Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 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>

authored by

Maxim Uvarov and committed by
Jens Wiklander
5f178bb7 58df195c

+44 -22
+24 -3
drivers/tee/optee/core.c
··· 17 17 #include <linux/tee_drv.h> 18 18 #include <linux/types.h> 19 19 #include <linux/uaccess.h> 20 + #include <linux/workqueue.h> 20 21 #include "optee_private.h" 21 22 #include "optee_smc.h" 22 23 #include "shm_pool.h" ··· 219 218 *vers = v; 220 219 } 221 220 221 + static void optee_bus_scan(struct work_struct *work) 222 + { 223 + WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP)); 224 + } 225 + 222 226 static int optee_open(struct tee_context *ctx) 223 227 { 224 228 struct optee_context_data *ctxdata; ··· 247 241 kfree(ctxdata); 248 242 return -EBUSY; 249 243 } 250 - } 251 244 245 + if (!optee->scan_bus_done) { 246 + INIT_WORK(&optee->scan_bus_work, optee_bus_scan); 247 + optee->scan_bus_wq = create_workqueue("optee_bus_scan"); 248 + if (!optee->scan_bus_wq) { 249 + kfree(ctxdata); 250 + return -ECHILD; 251 + } 252 + queue_work(optee->scan_bus_wq, &optee->scan_bus_work); 253 + optee->scan_bus_done = true; 254 + } 255 + } 252 256 mutex_init(&ctxdata->mutex); 253 257 INIT_LIST_HEAD(&ctxdata->sess_list); 254 258 ··· 312 296 313 297 ctx->data = NULL; 314 298 315 - if (teedev == optee->supp_teedev) 299 + if (teedev == optee->supp_teedev) { 300 + if (optee->scan_bus_wq) { 301 + destroy_workqueue(optee->scan_bus_wq); 302 + optee->scan_bus_wq = NULL; 303 + } 316 304 optee_supp_release(&optee->supp); 305 + } 317 306 } 318 307 319 308 static const struct tee_driver_ops optee_ops = { ··· 696 675 697 676 platform_set_drvdata(pdev, optee); 698 677 699 - rc = optee_enumerate_devices(); 678 + rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES); 700 679 if (rc) { 701 680 optee_remove(pdev); 702 681 return rc;
+11 -18
drivers/tee/optee/device.c
··· 11 11 #include <linux/uuid.h> 12 12 #include "optee_private.h" 13 13 14 - /* 15 - * Get device UUIDs 16 - * 17 - * [out] memref[0] Array of device UUIDs 18 - * 19 - * Return codes: 20 - * TEE_SUCCESS - Invoke command success 21 - * TEE_ERROR_BAD_PARAMETERS - Incorrect input param 22 - * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required 23 - */ 24 - #define PTA_CMD_GET_DEVICES 0x0 25 - 26 14 static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data) 27 15 { 28 16 if (ver->impl_id == TEE_IMPL_ID_OPTEE) ··· 20 32 } 21 33 22 34 static int get_devices(struct tee_context *ctx, u32 session, 23 - struct tee_shm *device_shm, u32 *shm_size) 35 + struct tee_shm *device_shm, u32 *shm_size, 36 + u32 func) 24 37 { 25 38 int ret = 0; 26 39 struct tee_ioctl_invoke_arg inv_arg; ··· 30 41 memset(&inv_arg, 0, sizeof(inv_arg)); 31 42 memset(&param, 0, sizeof(param)); 32 43 33 - /* Invoke PTA_CMD_GET_DEVICES function */ 34 - inv_arg.func = PTA_CMD_GET_DEVICES; 44 + inv_arg.func = func; 35 45 inv_arg.session = session; 36 46 inv_arg.num_params = 4; 37 47 ··· 78 90 return rc; 79 91 } 80 92 81 - int optee_enumerate_devices(void) 93 + static int __optee_enumerate_devices(u32 func) 82 94 { 83 95 const uuid_t pta_uuid = 84 96 UUID_INIT(0x7011a688, 0xddde, 0x4053, ··· 109 121 goto out_ctx; 110 122 } 111 123 112 - rc = get_devices(ctx, sess_arg.session, NULL, &shm_size); 124 + rc = get_devices(ctx, sess_arg.session, NULL, &shm_size, func); 113 125 if (rc < 0 || !shm_size) 114 126 goto out_sess; 115 127 ··· 121 133 goto out_sess; 122 134 } 123 135 124 - rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size); 136 + rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size, func); 125 137 if (rc < 0) 126 138 goto out_shm; 127 139 ··· 148 160 tee_client_close_context(ctx); 149 161 150 162 return rc; 163 + } 164 + 165 + int optee_enumerate_devices(u32 func) 166 + { 167 + return __optee_enumerate_devices(func); 151 168 }
+9 -1
drivers/tee/optee/optee_private.h
··· 78 78 * @memremaped_shm virtual address of memory in shared memory pool 79 79 * @sec_caps: secure world capabilities defined by 80 80 * OPTEE_SMC_SEC_CAP_* in optee_smc.h 81 + * @scan_bus_done flag if device registation was already done. 82 + * @scan_bus_wq workqueue to scan optee bus and register optee drivers 83 + * @scan_bus_work workq to scan optee bus and register optee drivers 81 84 */ 82 85 struct optee { 83 86 struct tee_device *supp_teedev; ··· 92 89 struct tee_shm_pool *pool; 93 90 void *memremaped_shm; 94 91 u32 sec_caps; 92 + bool scan_bus_done; 93 + struct workqueue_struct *scan_bus_wq; 94 + struct work_struct scan_bus_work; 95 95 }; 96 96 97 97 struct optee_session { ··· 179 173 void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages, 180 174 size_t page_offset); 181 175 182 - int optee_enumerate_devices(void); 176 + #define PTA_CMD_GET_DEVICES 0x0 177 + #define PTA_CMD_GET_DEVICES_SUPP 0x1 178 + int optee_enumerate_devices(u32 func); 183 179 184 180 /* 185 181 * Small helpers