optee: enable support for multi-stage bus enumeration
authorMaxim Uvarov <maxim.uvarov@linaro.org>
Thu, 18 Jun 2020 13:52:50 +0000 (16:52 +0300)
committerJens Wiklander <jens.wiklander@linaro.org>
Fri, 10 Jul 2020 07:41:53 +0000 (09:41 +0200)
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: Maxim Uvarov <maxim.uvarov@linaro.org>
Suggested-by: Sumit Garg <sumit.garg@linaro.org>
Suggested-by: Arnd Bergmann <arnd@linaro.org>
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Acked-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Sumit Garg <sumit.garg@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
drivers/tee/optee/core.c
drivers/tee/optee/device.c
drivers/tee/optee/optee_private.h

index 99698b8..b373b1b 100644 (file)
@@ -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,8 +312,13 @@ 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 = {
@@ -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;
index e91b7db..7a897d5 100644 (file)
 #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);
+}
index d9c5037..8b71839 100644 (file)
@@ -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