Commit 5f178bb7 authored by Maxim Uvarov's avatar Maxim Uvarov Committed by Jens Wiklander
Browse files

optee: enable support for multi-stage bus enumeration



Some drivers (like ftpm) can operate only after tee-supplicant
runs because of tee-supplicant provides things like storage
services (rpmb, shm).  This patch splits probe of non tee-supplicant
dependable drivers to the early stage, and after tee-supplicant run
probe other drivers.

Signed-off-by: default avatarMaxim Uvarov <maxim.uvarov@linaro.org>
Suggested-by: default avatarSumit Garg <sumit.garg@linaro.org>
Suggested-by: default avatarArnd Bergmann <arnd@linaro.org>
Reviewed-by: default avatarSumit Garg <sumit.garg@linaro.org>
Acked-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: default avatarSumit Garg <sumit.garg@linaro.org>
Signed-off-by: default avatarJens Wiklander <jens.wiklander@linaro.org>
parent 58df195c
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/tee_drv.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
#include "optee_private.h"
#include "optee_smc.h"
#include "shm_pool.h"
@@ -218,6 +219,11 @@ static void optee_get_version(struct tee_device *teedev,
	*vers = v;
}

static void optee_bus_scan(struct work_struct *work)
{
	WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP));
}

static int optee_open(struct tee_context *ctx)
{
	struct optee_context_data *ctxdata;
@@ -241,8 +247,18 @@ static int optee_open(struct tee_context *ctx)
			kfree(ctxdata);
			return -EBUSY;
		}
	}

		if (!optee->scan_bus_done) {
			INIT_WORK(&optee->scan_bus_work, optee_bus_scan);
			optee->scan_bus_wq = create_workqueue("optee_bus_scan");
			if (!optee->scan_bus_wq) {
				kfree(ctxdata);
				return -ECHILD;
			}
			queue_work(optee->scan_bus_wq, &optee->scan_bus_work);
			optee->scan_bus_done = true;
		}
	}
	mutex_init(&ctxdata->mutex);
	INIT_LIST_HEAD(&ctxdata->sess_list);

@@ -296,9 +312,14 @@ static void optee_release(struct tee_context *ctx)

	ctx->data = NULL;

	if (teedev == optee->supp_teedev)
	if (teedev == optee->supp_teedev) {
		if (optee->scan_bus_wq) {
			destroy_workqueue(optee->scan_bus_wq);
			optee->scan_bus_wq = NULL;
		}
		optee_supp_release(&optee->supp);
	}
}

static const struct tee_driver_ops optee_ops = {
	.get_version = optee_get_version,
@@ -675,7 +696,7 @@ static int optee_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, optee);

	rc = optee_enumerate_devices();
	rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
	if (rc) {
		optee_remove(pdev);
		return rc;
+11 −18
Original line number Diff line number Diff line
@@ -11,18 +11,6 @@
#include <linux/uuid.h>
#include "optee_private.h"

/*
 * Get device UUIDs
 *
 * [out]     memref[0]        Array of device UUIDs
 *
 * Return codes:
 * TEE_SUCCESS - Invoke command success
 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
 * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required
 */
#define PTA_CMD_GET_DEVICES		0x0

static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{
	if (ver->impl_id == TEE_IMPL_ID_OPTEE)
@@ -32,7 +20,8 @@ static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
}

static int get_devices(struct tee_context *ctx, u32 session,
		       struct tee_shm *device_shm, u32 *shm_size)
		       struct tee_shm *device_shm, u32 *shm_size,
		       u32 func)
{
	int ret = 0;
	struct tee_ioctl_invoke_arg inv_arg;
@@ -41,8 +30,7 @@ static int get_devices(struct tee_context *ctx, u32 session,
	memset(&inv_arg, 0, sizeof(inv_arg));
	memset(&param, 0, sizeof(param));

	/* Invoke PTA_CMD_GET_DEVICES function */
	inv_arg.func = PTA_CMD_GET_DEVICES;
	inv_arg.func = func;
	inv_arg.session = session;
	inv_arg.num_params = 4;

@@ -90,7 +78,7 @@ static int optee_register_device(const uuid_t *device_uuid)
	return rc;
}

int optee_enumerate_devices(void)
static int __optee_enumerate_devices(u32 func)
{
	const uuid_t pta_uuid =
		UUID_INIT(0x7011a688, 0xddde, 0x4053,
@@ -121,7 +109,7 @@ int optee_enumerate_devices(void)
		goto out_ctx;
	}

	rc = get_devices(ctx, sess_arg.session, NULL, &shm_size);
	rc = get_devices(ctx, sess_arg.session, NULL, &shm_size, func);
	if (rc < 0 || !shm_size)
		goto out_sess;

@@ -133,7 +121,7 @@ int optee_enumerate_devices(void)
		goto out_sess;
	}

	rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size);
	rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size, func);
	if (rc < 0)
		goto out_shm;

@@ -161,3 +149,8 @@ out_ctx:

	return rc;
}

int optee_enumerate_devices(u32 func)
{
	return  __optee_enumerate_devices(func);
}
+9 −1
Original line number Diff line number Diff line
@@ -78,6 +78,9 @@ struct optee_supp {
 * @memremaped_shm	virtual address of memory in shared memory pool
 * @sec_caps:		secure world capabilities defined by
 *			OPTEE_SMC_SEC_CAP_* in optee_smc.h
 * @scan_bus_done	flag if device registation was already done.
 * @scan_bus_wq		workqueue to scan optee bus and register optee drivers
 * @scan_bus_work	workq to scan optee bus and register optee drivers
 */
struct optee {
	struct tee_device *supp_teedev;
@@ -89,6 +92,9 @@ struct optee {
	struct tee_shm_pool *pool;
	void *memremaped_shm;
	u32 sec_caps;
	bool   scan_bus_done;
	struct workqueue_struct *scan_bus_wq;
	struct work_struct scan_bus_work;
};

struct optee_session {
@@ -173,7 +179,9 @@ void optee_free_pages_list(void *array, size_t num_entries);
void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
			   size_t page_offset);

int optee_enumerate_devices(void);
#define PTA_CMD_GET_DEVICES		0x0
#define PTA_CMD_GET_DEVICES_SUPP	0x1
int optee_enumerate_devices(u32 func);

/*
 * Small helpers