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

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
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/tee_drv.h> #include <linux/tee_drv.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/workqueue.h>
#include "optee_private.h" #include "optee_private.h"
#include "optee_smc.h" #include "optee_smc.h"
#include "shm_pool.h" #include "shm_pool.h"
...@@ -218,6 +219,11 @@ static void optee_get_version(struct tee_device *teedev, ...@@ -218,6 +219,11 @@ static void optee_get_version(struct tee_device *teedev,
*vers = v; *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) static int optee_open(struct tee_context *ctx)
{ {
struct optee_context_data *ctxdata; struct optee_context_data *ctxdata;
...@@ -241,8 +247,18 @@ static int optee_open(struct tee_context *ctx) ...@@ -241,8 +247,18 @@ static int optee_open(struct tee_context *ctx)
kfree(ctxdata); kfree(ctxdata);
return -EBUSY; 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); mutex_init(&ctxdata->mutex);
INIT_LIST_HEAD(&ctxdata->sess_list); INIT_LIST_HEAD(&ctxdata->sess_list);
...@@ -296,8 +312,13 @@ static void optee_release(struct tee_context *ctx) ...@@ -296,8 +312,13 @@ static void optee_release(struct tee_context *ctx)
ctx->data = NULL; 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); optee_supp_release(&optee->supp);
}
} }
static const struct tee_driver_ops optee_ops = { static const struct tee_driver_ops optee_ops = {
...@@ -675,7 +696,7 @@ static int optee_probe(struct platform_device *pdev) ...@@ -675,7 +696,7 @@ static int optee_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, optee); platform_set_drvdata(pdev, optee);
rc = optee_enumerate_devices(); rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
if (rc) { if (rc) {
optee_remove(pdev); optee_remove(pdev);
return rc; return rc;
......
...@@ -11,18 +11,6 @@ ...@@ -11,18 +11,6 @@
#include <linux/uuid.h> #include <linux/uuid.h>
#include "optee_private.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) static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{ {
if (ver->impl_id == TEE_IMPL_ID_OPTEE) 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) ...@@ -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, 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; int ret = 0;
struct tee_ioctl_invoke_arg inv_arg; struct tee_ioctl_invoke_arg inv_arg;
...@@ -41,8 +30,7 @@ static int get_devices(struct tee_context *ctx, u32 session, ...@@ -41,8 +30,7 @@ static int get_devices(struct tee_context *ctx, u32 session,
memset(&inv_arg, 0, sizeof(inv_arg)); memset(&inv_arg, 0, sizeof(inv_arg));
memset(&param, 0, sizeof(param)); memset(&param, 0, sizeof(param));
/* Invoke PTA_CMD_GET_DEVICES function */ inv_arg.func = func;
inv_arg.func = PTA_CMD_GET_DEVICES;
inv_arg.session = session; inv_arg.session = session;
inv_arg.num_params = 4; inv_arg.num_params = 4;
...@@ -90,7 +78,7 @@ static int optee_register_device(const uuid_t *device_uuid) ...@@ -90,7 +78,7 @@ static int optee_register_device(const uuid_t *device_uuid)
return rc; return rc;
} }
int optee_enumerate_devices(void) static int __optee_enumerate_devices(u32 func)
{ {
const uuid_t pta_uuid = const uuid_t pta_uuid =
UUID_INIT(0x7011a688, 0xddde, 0x4053, UUID_INIT(0x7011a688, 0xddde, 0x4053,
...@@ -121,7 +109,7 @@ int optee_enumerate_devices(void) ...@@ -121,7 +109,7 @@ int optee_enumerate_devices(void)
goto out_ctx; 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) if (rc < 0 || !shm_size)
goto out_sess; goto out_sess;
...@@ -133,7 +121,7 @@ int optee_enumerate_devices(void) ...@@ -133,7 +121,7 @@ int optee_enumerate_devices(void)
goto out_sess; 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) if (rc < 0)
goto out_shm; goto out_shm;
...@@ -161,3 +149,8 @@ int optee_enumerate_devices(void) ...@@ -161,3 +149,8 @@ int optee_enumerate_devices(void)
return rc; return rc;
} }
int optee_enumerate_devices(u32 func)
{
return __optee_enumerate_devices(func);
}
...@@ -78,6 +78,9 @@ struct optee_supp { ...@@ -78,6 +78,9 @@ struct optee_supp {
* @memremaped_shm virtual address of memory in shared memory pool * @memremaped_shm virtual address of memory in shared memory pool
* @sec_caps: secure world capabilities defined by * @sec_caps: secure world capabilities defined by
* OPTEE_SMC_SEC_CAP_* in optee_smc.h * 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 optee {
struct tee_device *supp_teedev; struct tee_device *supp_teedev;
...@@ -89,6 +92,9 @@ struct optee { ...@@ -89,6 +92,9 @@ struct optee {
struct tee_shm_pool *pool; struct tee_shm_pool *pool;
void *memremaped_shm; void *memremaped_shm;
u32 sec_caps; u32 sec_caps;
bool scan_bus_done;
struct workqueue_struct *scan_bus_wq;
struct work_struct scan_bus_work;
}; };
struct optee_session { struct optee_session {
...@@ -173,7 +179,9 @@ void optee_free_pages_list(void *array, size_t num_entries); ...@@ -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, void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
size_t page_offset); 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 * Small helpers
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment