diff options
author | Jon Medhurst <tixy@linaro.org> | 2017-04-11 17:30:58 +0100 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2017-04-11 17:30:58 +0100 |
commit | 71afea5c1f09e8aca8d5adeb166f47416d6c5daa (patch) | |
tree | 412ea236d2ac3a8bc5eefda20aff10c0e5f26c20 | |
parent | 457349a00449a9554151368e1dbdecf64c847219 (diff) | |
parent | cecbf98dc56b51bf2b3055ad9e53f43e30e93939 (diff) |
Merge branch '4.4-armlt' into lsk-4.4-armltlsk-4.4-armlt-20170411
25 files changed, 277 insertions, 311 deletions
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index a2f2e1472b85..c0b1035279f8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -713,6 +713,9 @@ dtb-$(CONFIG_ARCH_VERSATILE) += \ versatile-pb.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += \ fvp-base-aemv8a-aemv8a.dtb \ + juno.dtb \ + juno-r1.dtb \ + juno-r2.dtb \ vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \ diff --git a/arch/arm/boot/dts/juno-base.dtsi b/arch/arm/boot/dts/juno-base.dtsi new file mode 120000 index 000000000000..5bf5772d7718 --- /dev/null +++ b/arch/arm/boot/dts/juno-base.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-base.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-clocks.dtsi b/arch/arm/boot/dts/juno-clocks.dtsi new file mode 120000 index 000000000000..d26c206771d4 --- /dev/null +++ b/arch/arm/boot/dts/juno-clocks.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-clocks.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-motherboard.dtsi b/arch/arm/boot/dts/juno-motherboard.dtsi new file mode 120000 index 000000000000..a4e1f71b8533 --- /dev/null +++ b/arch/arm/boot/dts/juno-motherboard.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-motherboard.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-r1.dts b/arch/arm/boot/dts/juno-r1.dts new file mode 120000 index 000000000000..f0bf74937285 --- /dev/null +++ b/arch/arm/boot/dts/juno-r1.dts @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-r1.dts
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-r2.dts b/arch/arm/boot/dts/juno-r2.dts new file mode 120000 index 000000000000..aba7e1fac440 --- /dev/null +++ b/arch/arm/boot/dts/juno-r2.dts @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-r2.dts
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-sched-energy.dtsi b/arch/arm/boot/dts/juno-sched-energy.dtsi new file mode 120000 index 000000000000..3508c8b8438f --- /dev/null +++ b/arch/arm/boot/dts/juno-sched-energy.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-sched-energy.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno.dts b/arch/arm/boot/dts/juno.dts new file mode 120000 index 000000000000..186e53545ef2 --- /dev/null +++ b/arch/arm/boot/dts/juno.dts @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno.dts
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno_r2-sched-energy.dtsi b/arch/arm/boot/dts/juno_r2-sched-energy.dtsi new file mode 120000 index 000000000000..0d000be54a83 --- /dev/null +++ b/arch/arm/boot/dts/juno_r2-sched-energy.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno_r2-sched-energy.dtsi
\ No newline at end of file diff --git a/arch/arm64/boot/dts/arm/fvp-base-aemv8a-aemv8a.dts b/arch/arm64/boot/dts/arm/fvp-base-aemv8a-aemv8a.dts index eb9d35a61243..c88dc9a62585 100644 --- a/arch/arm64/boot/dts/arm/fvp-base-aemv8a-aemv8a.dts +++ b/arch/arm64/boot/dts/arm/fvp-base-aemv8a-aemv8a.dts @@ -9,7 +9,7 @@ / { model = "FVP_Base_AEMv8A-AEMv8A"; - compatible = "arm,fvp-base,aemv8a-aemv8a", "arm,fvp-base", "arm,vexpress"; + compatible = "arm,fvp-base,aemv8a-aemv8a", "arm,fvp-base"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts index 041190329365..ea4b2ddb10d0 100644 --- a/arch/arm64/boot/dts/arm/juno-r1.dts +++ b/arch/arm64/boot/dts/arm/juno-r1.dts @@ -13,7 +13,7 @@ / { model = "ARM Juno development board (r1)"; - compatible = "arm,juno-r1", "arm,juno", "arm,vexpress"; + compatible = "arm,juno-r1", "arm,juno"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts index 6334049dec04..b07c7f9c1797 100644 --- a/arch/arm64/boot/dts/arm/juno-r2.dts +++ b/arch/arm64/boot/dts/arm/juno-r2.dts @@ -13,7 +13,7 @@ / { model = "ARM Juno development board (r2)"; - compatible = "arm,juno-r2", "arm,juno", "arm,vexpress"; + compatible = "arm,juno-r2", "arm,juno"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts index c5425a4365ef..5c7a0270413b 100644 --- a/arch/arm64/boot/dts/arm/juno.dts +++ b/arch/arm64/boot/dts/arm/juno.dts @@ -13,7 +13,7 @@ / { model = "ARM Juno development board (r0)"; - compatible = "arm,juno", "arm,vexpress"; + compatible = "arm,juno"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index aa435cb06a21..6c0e0a5fe447 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -141,6 +141,8 @@ static int hdlcd_crtc_colour_set(struct hdlcd_drm_private *hdlcd, { unsigned int depth, bpp; unsigned int default_color = 0x00000000; + bool swap_red_blue = false; + u32 hbi; struct simplefb_format *format = NULL; int i; @@ -175,7 +177,16 @@ static int hdlcd_crtc_colour_set(struct hdlcd_drm_private *hdlcd, * pixel is outside the visible frame area or when there is a * buffer underrun. */ - if(!config_enabled(CONFIG_ARM)) { + if (of_property_read_u32(of_root, "arm,hbi", &hbi) == 0) { + /* + * This is a hack to swap read and blue when building for some + * Versatile Express CoreTiles because they seem to be wired up + * differently. + */ + if (hbi == 0x249) /* TC2 */ + swap_red_blue = true; + } + if(!swap_red_blue) { hdlcd_write(hdlcd, HDLCD_REG_RED_SELECT, default_color | format->red.offset | (format->red.length & 0xf) << 8); hdlcd_write(hdlcd, HDLCD_REG_GREEN_SELECT, default_color | diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 97fad0e2f90a..f7b7b404c990 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -25,12 +25,19 @@ struct optee_call_waiter { struct list_head list_node; struct completion c; - bool completed; }; static void optee_cq_wait_init(struct optee_call_queue *cq, struct optee_call_waiter *w) { + /* + * We're preparing to make a call to secure world. In case we can't + * allocate a thread in secure world we'll end up waiting in + * optee_cq_wait_for_completion(). + * + * Normally if there's no contention in secure world the call will + * complete and we can cleanup directly with optee_cq_wait_final(). + */ mutex_lock(&cq->mutex); /* @@ -39,7 +46,6 @@ static void optee_cq_wait_init(struct optee_call_queue *cq, * returns busy and another thread just exited and try to complete * someone. */ - w->completed = false; init_completion(&w->c); list_add_tail(&w->list_node, &cq->waiters); @@ -55,7 +61,6 @@ static void optee_cq_wait_for_completion(struct optee_call_queue *cq, /* Move to end of list to get out of the way for other waiters */ list_del(&w->list_node); - w->completed = false; reinit_completion(&w->c); list_add_tail(&w->list_node, &cq->waiters); @@ -67,9 +72,8 @@ static void optee_cq_complete_one(struct optee_call_queue *cq) struct optee_call_waiter *w; list_for_each_entry(w, &cq->waiters, list_node) { - if (!w->completed) { + if (!completion_done(&w->c)) { complete(&w->c); - w->completed = true; break; } } @@ -78,17 +82,26 @@ static void optee_cq_complete_one(struct optee_call_queue *cq) static void optee_cq_wait_final(struct optee_call_queue *cq, struct optee_call_waiter *w) { + /* + * We're done with the call to secure world. The thread in secure + * world that was used for this call is now available for some + * other task to use. + */ mutex_lock(&cq->mutex); /* Get out of the list */ list_del(&w->list_node); + /* Wake up one eventual waiting task */ optee_cq_complete_one(cq); + /* - * If we're completed we've got a completion that some other task - * could have used instead. + * If we're completed we've got a completion from another task that + * was just done with its call to secure world. Since yet another + * thread now is available in secure world wake up another eventual + * waiting task. */ - if (w->completed) + if (completion_done(&w->c)) optee_cq_complete_one(cq); mutex_unlock(&cq->mutex); @@ -206,7 +219,6 @@ int optee_open_session(struct tee_context *ctx, struct tee_shm *shm; struct optee_msg_arg *msg_arg; phys_addr_t msg_parg; - struct optee_msg_param *msg_param; struct optee_session *sess = NULL; /* +2 for the meta parameters added below */ @@ -216,21 +228,20 @@ int optee_open_session(struct tee_context *ctx, msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION; msg_arg->cancel_id = arg->cancel_id; - msg_param = OPTEE_MSG_GET_PARAMS(msg_arg); /* * Initialize and add the meta parameters needed when opening a * session. */ - msg_param[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | - OPTEE_MSG_ATTR_META; - msg_param[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | - OPTEE_MSG_ATTR_META; - memcpy(&msg_param[0].u.value, arg->uuid, sizeof(arg->uuid)); - memcpy(&msg_param[1].u.value, arg->uuid, sizeof(arg->clnt_uuid)); - msg_param[1].u.value.c = arg->clnt_login; - - rc = optee_to_msg_param(msg_param + 2, arg->num_params, param); + msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | + OPTEE_MSG_ATTR_META; + msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | + OPTEE_MSG_ATTR_META; + memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid)); + memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid)); + msg_arg->params[1].u.value.c = arg->clnt_login; + + rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param); if (rc) goto out; @@ -255,7 +266,7 @@ int optee_open_session(struct tee_context *ctx, kfree(sess); } - if (optee_from_msg_param(param, arg->num_params, msg_param + 2)) { + if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) { arg->ret = TEEC_ERROR_COMMUNICATION; arg->ret_origin = TEEC_ORIGIN_COMMS; /* Close session again to avoid leakage */ @@ -308,7 +319,6 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_shm *shm; struct optee_msg_arg *msg_arg; phys_addr_t msg_parg; - struct optee_msg_param *msg_param; struct optee_session *sess; int rc; @@ -326,9 +336,8 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, msg_arg->func = arg->func; msg_arg->session = arg->session; msg_arg->cancel_id = arg->cancel_id; - msg_param = OPTEE_MSG_GET_PARAMS(msg_arg); - rc = optee_to_msg_param(msg_param, arg->num_params, param); + rc = optee_to_msg_param(msg_arg->params, arg->num_params, param); if (rc) goto out; @@ -337,7 +346,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } - if (optee_from_msg_param(param, arg->num_params, msg_param)) { + if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } @@ -401,7 +410,7 @@ void optee_enable_shm_cache(struct optee *optee) } /** - * optee_enable_shm_cache() - Disables caching of some shared memory allocation + * optee_disable_shm_cache() - Disables caching of some shared memory allocation * in OP-TEE * @optee: main service struct */ diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index b4fe7713b2fb..58169e519422 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -11,6 +11,10 @@ * GNU General Public License for more details. * */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/arm-smccc.h> #include <linux/errno.h> #include <linux/io.h> #include <linux/module.h> @@ -326,9 +330,8 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, * point of view) or not, is_smp() returns the the information * needed, but can't be called directly from here. */ -#ifndef CONFIG_SMP - a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR; -#endif + if (!IS_ENABLED(CONFIG_SMP) || nr_cpu_ids == 1) + a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR; invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, a1, 0, 0, 0, 0, 0, 0, &res.smccc); @@ -341,8 +344,7 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, } static struct tee_shm_pool * -optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn, - void __iomem **ioremaped_shm) +optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) { union { struct arm_smccc_res smccc; @@ -354,18 +356,18 @@ optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn, size_t size; phys_addr_t begin; phys_addr_t end; - void __iomem *va; + void *va; struct tee_shm_pool_mem_info priv_info; struct tee_shm_pool_mem_info dmabuf_info; invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); if (res.result.status != OPTEE_SMC_RETURN_OK) { - dev_info(dev, "shm service not available\n"); + pr_info("shm service not available\n"); return ERR_PTR(-ENOENT); } if (res.result.settings != OPTEE_SMC_SHM_CACHED) { - dev_err(dev, "only normal cached shared memory supported\n"); + pr_err("only normal cached shared memory supported\n"); return ERR_PTR(-EINVAL); } @@ -375,13 +377,13 @@ optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn, size = end - begin; if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) { - dev_err(dev, "too small shared memory area\n"); + pr_err("too small shared memory area\n"); return ERR_PTR(-EINVAL); } - va = ioremap_cache(paddr, size); + va = memremap(paddr, size, MEMREMAP_WB); if (!va) { - dev_err(dev, "shared memory ioremap failed\n"); + pr_err("shared memory ioremap failed\n"); return ERR_PTR(-EINVAL); } vaddr = (unsigned long)va; @@ -393,97 +395,112 @@ optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn, dmabuf_info.paddr = paddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; dmabuf_info.size = size - OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; - pool = tee_shm_pool_alloc_res_mem(dev, &priv_info, &dmabuf_info); + pool = tee_shm_pool_alloc_res_mem(&priv_info, &dmabuf_info); if (IS_ERR(pool)) { - iounmap(va); + memunmap(va); goto out; } - *ioremaped_shm = va; + *memremaped_shm = va; out: return pool; } -static int get_invoke_func(struct device *dev, optee_invoke_fn **invoke_fn) +/* Simple wrapper functions to be able to use a function pointer */ +static void optee_smccc_smc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res) +{ + arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res); +} + +static void optee_smccc_hvc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res) +{ + arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res); +} + +static optee_invoke_fn *get_invoke_func(struct device_node *np) { - struct device_node *np = dev->of_node; const char *method; - dev_info(dev, "probing for conduit method from DT.\n"); + pr_info("probing for conduit method from DT.\n"); if (of_property_read_string(np, "method", &method)) { - dev_warn(dev, "missing \"method\" property\n"); - return -ENXIO; + pr_warn("missing \"method\" property\n"); + return ERR_PTR(-ENXIO); } - if (!strcmp("hvc", method)) { - *invoke_fn = arm_smccc_hvc; - } else if (!strcmp("smc", method)) { - *invoke_fn = arm_smccc_smc; - } else { - dev_warn(dev, "invalid \"method\" property: %s\n", method); - return -EINVAL; - } - return 0; + if (!strcmp("hvc", method)) + return optee_smccc_hvc; + else if (!strcmp("smc", method)) + return optee_smccc_smc; + + pr_warn("invalid \"method\" property: %s\n", method); + return ERR_PTR(-EINVAL); } -static int optee_probe(struct platform_device *pdev) +static struct optee *optee_probe(struct device_node *np) { optee_invoke_fn *invoke_fn; struct tee_shm_pool *pool; struct optee *optee = NULL; - void __iomem *ioremaped_shm = NULL; + void *memremaped_shm = NULL; struct tee_device *teedev; u32 sec_caps; int rc; - rc = get_invoke_func(&pdev->dev, &invoke_fn); - if (rc) - return rc; + invoke_fn = get_invoke_func(np); + if (IS_ERR(invoke_fn)) + return (void *)invoke_fn; if (!optee_msg_api_uid_is_optee_api(invoke_fn)) { - dev_warn(&pdev->dev, "api uid mismatch\n"); - return -EINVAL; + pr_warn("api uid mismatch\n"); + return ERR_PTR(-EINVAL); } if (!optee_msg_api_revision_is_compatible(invoke_fn)) { - dev_warn(&pdev->dev, "api revision mismatch\n"); - return -EINVAL; + pr_warn("api revision mismatch\n"); + return ERR_PTR(-EINVAL); } if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) { - dev_warn(&pdev->dev, "capabilities mismatch\n"); - return -EINVAL; + pr_warn("capabilities mismatch\n"); + return ERR_PTR(-EINVAL); } /* * We have no other option for shared memory, if secure world * doesn't have any reserved memory we can use we can't continue. */ - if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVERED_SHM)) - return -EINVAL; + if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM)) + return ERR_PTR(-EINVAL); - pool = optee_config_shm_ioremap(&pdev->dev, invoke_fn, &ioremaped_shm); + pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm); if (IS_ERR(pool)) - return PTR_ERR(pool); + return (void *)pool; - optee = devm_kzalloc(&pdev->dev, sizeof(*optee), GFP_KERNEL); + optee = kzalloc(sizeof(*optee), GFP_KERNEL); if (!optee) { rc = -ENOMEM; goto err; } - optee->dev = &pdev->dev; optee->invoke_fn = invoke_fn; - teedev = tee_device_alloc(&optee_desc, &pdev->dev, pool, optee); + teedev = tee_device_alloc(&optee_desc, NULL, pool, optee); if (IS_ERR(teedev)) { rc = PTR_ERR(teedev); goto err; } optee->teedev = teedev; - teedev = tee_device_alloc(&optee_supp_desc, &pdev->dev, pool, optee); + teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee); if (IS_ERR(teedev)) { rc = PTR_ERR(teedev); goto err; @@ -502,15 +519,13 @@ static int optee_probe(struct platform_device *pdev) INIT_LIST_HEAD(&optee->call_queue.waiters); optee_wait_queue_init(&optee->wait_queue); optee_supp_init(&optee->supp); - optee->ioremaped_shm = ioremaped_shm; + optee->memremaped_shm = memremaped_shm; optee->pool = pool; - platform_set_drvdata(pdev, optee); - optee_enable_shm_cache(optee); - dev_info(&pdev->dev, "initialized driver\n"); - return 0; + pr_info("initialized driver\n"); + return optee; err: if (optee) { /* @@ -520,18 +535,17 @@ err: */ tee_device_unregister(optee->supp_teedev); tee_device_unregister(optee->teedev); + kfree(optee); } if (pool) tee_shm_pool_free(pool); - if (ioremaped_shm) - iounmap(ioremaped_shm); - return rc; + if (memremaped_shm) + memunmap(memremaped_shm); + return ERR_PTR(rc); } -static int optee_remove(struct platform_device *pdev) +static void optee_remove(struct optee *optee) { - struct optee *optee = platform_get_drvdata(pdev); - /* * Ask OP-TEE to free all cached shared memory objects to decrease * reference counters and also avoid wild pointers in secure world @@ -547,13 +561,13 @@ static int optee_remove(struct platform_device *pdev) tee_device_unregister(optee->teedev); tee_shm_pool_free(optee->pool); - if (optee->ioremaped_shm) - iounmap(optee->ioremaped_shm); + if (optee->memremaped_shm) + memunmap(optee->memremaped_shm); optee_wait_queue_exit(&optee->wait_queue); optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); - return 0; + kfree(optee); } static const struct of_device_id optee_match[] = { @@ -561,33 +575,43 @@ static const struct of_device_id optee_match[] = { {}, }; -static struct platform_driver optee_driver = { - .driver = { - .name = DRIVER_NAME, - .of_match_table = optee_match, - }, - .probe = optee_probe, - .remove = optee_remove, -}; +static struct optee *optee_svc; static int __init optee_driver_init(void) { - struct device_node *node; + struct device_node *fw_np; + struct device_node *np; + struct optee *optee; - /* - * Preferred path is /firmware/optee, but it's the matching that - * matters. - */ - for_each_matching_node(node, optee_match) - of_platform_device_create(node, NULL, NULL); + /* Node is supposed to be below /firmware */ + fw_np = of_find_node_by_name(NULL, "firmware"); + if (!fw_np) + return -ENODEV; + + np = of_find_matching_node(fw_np, optee_match); + of_node_put(fw_np); + if (!np) + return -ENODEV; + + optee = optee_probe(np); + of_node_put(np); + + if (IS_ERR(optee)) + return PTR_ERR(optee); - return platform_driver_register(&optee_driver); + optee_svc = optee; + + return 0; } module_init(optee_driver_init); static void __exit optee_driver_exit(void) { - platform_driver_unregister(&optee_driver); + struct optee *optee = optee_svc; + + optee_svc = NULL; + if (optee) + optee_remove(optee); } module_exit(optee_driver_exit); diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index 3c0a91213610..dd7a06ee0462 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -194,29 +194,9 @@ struct optee_msg_arg { u32 ret_origin; u32 num_params; - /* - * this struct is 8 byte aligned since the 'struct optee_msg_param' - * which follows requires 8 byte alignment. - * - * Commented out element used to visualize the layout dynamic part - * of the struct. This field is not available at all if - * num_params == 0. - * - * params is accessed through the macro OPTEE_MSG_GET_PARAMS - * - * struct optee_msg_param params[num_params]; - */ -} __aligned(8); - -/** - * OPTEE_MSG_GET_PARAMS - return pointer to struct optee_msg_param * - * - * @x: Pointer to a struct optee_msg_arg - * - * Returns a pointer to the params[] inside a struct optee_msg_arg. - */ -#define OPTEE_MSG_GET_PARAMS(x) \ - (struct optee_msg_param *)(((struct optee_msg_arg *)(x)) + 1) + /* num_params tells the actual number of element in params */ + struct optee_msg_param params[0]; +}; /** * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg @@ -281,8 +261,6 @@ struct optee_msg_arg { * Returns revision in 2 32-bit words in the same way as * OPTEE_MSG_CALLS_REVISION described above. */ -#define OPTEE_MSG_OS_OPTEE_REVISION_MAJOR 1 -#define OPTEE_MSG_OS_OPTEE_REVISION_MINOR 0 #define OPTEE_MSG_FUNCID_GET_OS_REVISION 0x0001 /* @@ -371,7 +349,12 @@ struct optee_msg_arg { #define OPTEE_MSG_RPC_CMD_GET_TIME 3 /* - * Wait queue primitive, helper for secure world to implement a wait queue + * Wait queue primitive, helper for secure world to implement a wait queue. + * + * If secure world need to wait for a secure world mutex it issues a sleep + * request instead of spinning in secure world. Conversely is a wakeup + * request issued when a secure world mutex with a thread waiting thread is + * unlocked. * * Waiting on a key * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 807f74c41319..c374cd594314 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -89,25 +89,23 @@ struct optee_supp { * struct optee - main service struct * @supp_teedev: supplicant device * @teedev: client device - * @dev: probed device * @invoke_fn: function to issue smc or hvc * @call_queue: queue of threads waiting to call @invoke_fn * @wait_queue: queue of threads from secure world waiting for a * secure world sync object * @supp: supplicant synchronization struct for RPC to supplicant * @pool: shared memory pool - * @ioremaped_shm virtual address of memory in shared memory pool + * @memremaped_shm virtual address of memory in shared memory pool */ struct optee { struct tee_device *supp_teedev; struct tee_device *teedev; - struct device *dev; optee_invoke_fn *invoke_fn; struct optee_call_queue call_queue; struct optee_wait_queue wait_queue; struct optee_supp supp; struct tee_shm_pool *pool; - void __iomem *ioremaped_shm; + void *memremaped_shm; }; struct optee_session { diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index d470d450b182..13b7c98cdf25 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -219,7 +219,7 @@ struct optee_smc_get_shm_config_result { /* Normal world works as a uniprocessor system */ #define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR BIT(0) /* Secure world has reserved shared memory for normal world to use */ -#define OPTEE_SMC_SEC_CAP_HAVE_RESERVERED_SHM BIT(0) +#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM BIT(0) /* Secure world can communicate via previously unregistered shared memory */ #define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM BIT(1) #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 0b9c1a2accd0..8c1ab49c83c3 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -11,6 +11,10 @@ * GNU General Public License for more details. * */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/delay.h> #include <linux/device.h> #include <linux/sched.h> #include <linux/slab.h> @@ -37,19 +41,17 @@ void optee_wait_queue_exit(struct optee_wait_queue *priv) static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg) { - struct optee_msg_param *params; struct timespec64 ts; if (arg->num_params != 1) goto bad; - params = OPTEE_MSG_GET_PARAMS(arg); - if ((params->attr & OPTEE_MSG_ATTR_TYPE_MASK) != + if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) != OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT) goto bad; getnstimeofday64(&ts); - params->u.value.a = ts.tv_sec; - params->u.value.b = ts.tv_nsec; + arg->params[0].u.value.a = ts.tv_sec; + arg->params[0].u.value.b = ts.tv_nsec; arg->ret = TEEC_SUCCESS; return; @@ -102,22 +104,19 @@ static void wq_wakeup(struct optee_wait_queue *wq, u32 key) static void handle_rpc_func_cmd_wq(struct optee *optee, struct optee_msg_arg *arg) { - struct optee_msg_param *params; - if (arg->num_params != 1) goto bad; - params = OPTEE_MSG_GET_PARAMS(arg); - if ((params->attr & OPTEE_MSG_ATTR_TYPE_MASK) != + if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) goto bad; - switch (params->u.value.a) { + switch (arg->params[0].u.value.a) { case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP: - wq_sleep(&optee->wait_queue, params->u.value.b); + wq_sleep(&optee->wait_queue, arg->params[0].u.value.b); break; case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP: - wq_wakeup(&optee->wait_queue, params->u.value.b); + wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b); break; default: goto bad; @@ -131,24 +130,22 @@ bad: static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg) { - struct optee_msg_param *params; u32 msec_to_wait; if (arg->num_params != 1) goto bad; - params = OPTEE_MSG_GET_PARAMS(arg); - if ((params->attr & OPTEE_MSG_ATTR_TYPE_MASK) != + if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) goto bad; - msec_to_wait = params->u.value.a; + msec_to_wait = arg->params[0].u.value.a; /* set task's state to interruptible sleep */ set_current_state(TASK_INTERRUPTIBLE); /* take a nap */ - schedule_timeout(msecs_to_jiffies(msec_to_wait)); + msleep(msec_to_wait); arg->ret = TEEC_SUCCESS; return; @@ -160,7 +157,6 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee_msg_arg *arg) { struct tee_param *params; - struct optee_msg_param *msg_params = OPTEE_MSG_GET_PARAMS(arg); arg->ret_origin = TEEC_ORIGIN_COMMS; @@ -171,14 +167,14 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx, return; } - if (optee_from_msg_param(params, arg->num_params, msg_params)) { + if (optee_from_msg_param(params, arg->num_params, arg->params)) { arg->ret = TEEC_ERROR_BAD_PARAMETERS; goto out; } arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params); - if (optee_to_msg_param(msg_params, arg->num_params, params)) + if (optee_to_msg_param(arg->params, arg->num_params, params)) arg->ret = TEEC_ERROR_BAD_PARAMETERS; out: kfree(params); @@ -210,7 +206,6 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz) static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, struct optee_msg_arg *arg) { - struct optee_msg_param *params = OPTEE_MSG_GET_PARAMS(arg); phys_addr_t pa; struct tee_shm *shm; size_t sz; @@ -219,20 +214,20 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, arg->ret_origin = TEEC_ORIGIN_COMMS; if (!arg->num_params || - params->attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { + arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { arg->ret = TEEC_ERROR_BAD_PARAMETERS; return; } for (n = 1; n < arg->num_params; n++) { - if (params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE) { + if (arg->params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE) { arg->ret = TEEC_ERROR_BAD_PARAMETERS; return; } } - sz = params->u.value.b; - switch (params->u.value.a) { + sz = arg->params[0].u.value.b; + switch (arg->params[0].u.value.a) { case OPTEE_MSG_RPC_SHM_TYPE_APPL: shm = cmd_alloc_suppl(ctx, sz); break; @@ -254,10 +249,10 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, goto bad; } - params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; - params[0].u.tmem.buf_ptr = pa; - params[0].u.tmem.size = sz; - params[0].u.tmem.shm_ref = (unsigned long)shm; + arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; + arg->params[0].u.tmem.buf_ptr = pa; + arg->params[0].u.tmem.size = sz; + arg->params[0].u.tmem.shm_ref = (unsigned long)shm; arg->ret = TEEC_SUCCESS; return; bad: @@ -292,19 +287,18 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm) static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, struct optee_msg_arg *arg) { - struct optee_msg_param *params = OPTEE_MSG_GET_PARAMS(arg); struct tee_shm *shm; arg->ret_origin = TEEC_ORIGIN_COMMS; if (arg->num_params != 1 || - params->attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { + arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { arg->ret = TEEC_ERROR_BAD_PARAMETERS; return; } - shm = (struct tee_shm *)(unsigned long)params->u.value.b; - switch (params->u.value.a) { + shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b; + switch (arg->params[0].u.value.a) { case OPTEE_MSG_RPC_SHM_TYPE_APPL: cmd_free_suppl(ctx, shm); break; @@ -324,8 +318,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, arg = tee_shm_get_va(shm, 0); if (IS_ERR(arg)) { - dev_err(optee->dev, "%s: tee_shm_get_va %p failed\n", - __func__, shm); + pr_err("%s: tee_shm_get_va %p failed\n", __func__, shm); return; } @@ -395,8 +388,8 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param) handle_rpc_func_cmd(ctx, optee, shm); break; default: - dev_warn(optee->dev, "Unknown RPC func 0x%x\n", - (u32)OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)); + pr_warn("Unknown RPC func 0x%x\n", + (u32)OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)); break; } diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 204521003350..ac34acd7bb93 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -157,9 +157,9 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params, break; case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: - params[n].u.value.a = ip.u.value.a; - params[n].u.value.b = ip.u.value.b; - params[n].u.value.c = ip.u.value.c; + params[n].u.value.a = ip.a; + params[n].u.value.b = ip.b; + params[n].u.value.c = ip.c; break; case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: @@ -172,12 +172,12 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params, * count. It's the callers responibility to do * tee_shm_put() on all resolved pointers. */ - shm = tee_shm_get_from_id(ctx, ip.u.memref.shm_id); + shm = tee_shm_get_from_id(ctx, ip.c); if (IS_ERR(shm)) return PTR_ERR(shm); - params[n].u.memref.shm_offs = ip.u.memref.shm_offs; - params[n].u.memref.size = ip.u.memref.size; + params[n].u.memref.shm_offs = ip.a; + params[n].u.memref.size = ip.b; params[n].u.memref.shm = shm; break; default: @@ -200,14 +200,14 @@ static int params_to_user(struct tee_ioctl_param __user *uparams, switch (p->attr) { case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: - if (put_user(p->u.value.a, &up->u.value.a) || - put_user(p->u.value.b, &up->u.value.b) || - put_user(p->u.value.c, &up->u.value.c)) + if (put_user(p->u.value.a, &up->a) || + put_user(p->u.value.b, &up->b) || + put_user(p->u.value.c, &up->c)) return -EFAULT; break; case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: - if (put_user((u64)p->u.memref.size, &up->u.memref.size)) + if (put_user((u64)p->u.memref.size, &up->b)) return -EFAULT; default: break; @@ -251,7 +251,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx, return -EINVAL; uarg = (struct tee_ioctl_open_session_arg __user *)(unsigned long) - buf.buf_ptr; + buf.buf_ptr; if (copy_from_user(&arg, uarg, sizeof(arg))) return -EFAULT; @@ -263,7 +263,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx, GFP_KERNEL); if (!params) return -ENOMEM; - uparams = (struct tee_ioctl_param __user *)(uarg + 1); + uparams = uarg->params; rc = params_from_user(ctx, params, arg.num_params, uparams); if (rc) goto out; @@ -322,7 +322,8 @@ static int tee_ioctl_invoke(struct tee_context *ctx, buf.buf_len < sizeof(struct tee_ioctl_invoke_arg)) return -EINVAL; - uarg = (struct tee_ioctl_invoke_arg __user *)(unsigned long)buf.buf_ptr; + uarg = (struct tee_ioctl_invoke_arg __user *)(unsigned long) + buf.buf_ptr; if (copy_from_user(&arg, uarg, sizeof(arg))) return -EFAULT; @@ -334,7 +335,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx, GFP_KERNEL); if (!params) return -ENOMEM; - uparams = (struct tee_ioctl_param __user *)(uarg + 1); + uparams = uarg->params; rc = params_from_user(ctx, params, arg.num_params, uparams); if (rc) goto out; @@ -406,24 +407,26 @@ static int params_to_supp(struct tee_context *ctx, switch (p->attr) { case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: - ip.u.value.a = p->u.value.a; - ip.u.value.b = p->u.value.b; - ip.u.value.c = p->u.value.c; + ip.a = p->u.value.a; + ip.b = p->u.value.b; + ip.c = p->u.value.c; break; case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: - ip.u.memref.size = p->u.memref.size; + ip.b = p->u.memref.size; if (!p->u.memref.shm) { - ip.u.memref.shm_offs = 0; - ip.u.memref.shm_id = -1; + ip.a = 0; + ip.c = (u64)-1; /* invalid shm id */ break; } - ip.u.memref.shm_offs = p->u.memref.shm_offs; - ip.u.memref.shm_id = p->u.memref.shm->id; + ip.a = p->u.memref.shm_offs; + ip.c = p->u.memref.shm->id; break; default: - memset(&ip.u, 0, sizeof(ip.u)); + ip.a = 0; + ip.b = 0; + ip.c = 0; break; } @@ -441,7 +444,6 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx, struct tee_ioctl_buf_data buf; struct tee_iocl_supp_recv_arg __user *uarg; struct tee_param *params; - struct tee_ioctl_param __user *uparams; u32 num_params; u32 func; @@ -456,7 +458,7 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx, return -EINVAL; uarg = (struct tee_iocl_supp_recv_arg __user *)(unsigned long) - buf.buf_ptr; + buf.buf_ptr; if (get_user(num_params, &uarg->num_params)) return -EFAULT; @@ -477,8 +479,7 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx, goto out; } - uparams = (struct tee_ioctl_param __user *)(uarg + 1); - rc = params_to_supp(ctx, uparams, num_params, params); + rc = params_to_supp(ctx, uarg->params, num_params, params); out: kfree(params); return rc; @@ -505,9 +506,9 @@ static int params_from_supp(struct tee_param *params, size_t num_params, case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: /* Only out and in/out values can be updated */ - p->u.value.a = ip.u.value.a; - p->u.value.b = ip.u.value.b; - p->u.value.c = ip.u.value.c; + p->u.value.a = ip.a; + p->u.value.b = ip.b; + p->u.value.c = ip.c; break; case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: @@ -520,7 +521,7 @@ static int params_from_supp(struct tee_param *params, size_t num_params, */ p->u.memref.shm = NULL; p->u.memref.shm_offs = 0; - p->u.memref.size = ip.u.memref.size; + p->u.memref.size = ip.b; break; default: memset(&p->u, 0, sizeof(p->u)); @@ -537,7 +538,6 @@ static int tee_ioctl_supp_send(struct tee_context *ctx, struct tee_ioctl_buf_data buf; struct tee_iocl_supp_send_arg __user *uarg; struct tee_param *params; - struct tee_ioctl_param __user *uparams; u32 num_params; u32 ret; @@ -553,7 +553,7 @@ static int tee_ioctl_supp_send(struct tee_context *ctx, return -EINVAL; uarg = (struct tee_iocl_supp_send_arg __user *)(unsigned long) - buf.buf_ptr; + buf.buf_ptr; if (get_user(ret, &uarg->ret) || get_user(num_params, &uarg->num_params)) return -EFAULT; @@ -565,8 +565,7 @@ static int tee_ioctl_supp_send(struct tee_context *ctx, if (!params) return -ENOMEM; - uparams = (struct tee_ioctl_param __user *)(uarg + 1); - rc = params_from_supp(params, num_params, uparams); + rc = params_from_supp(params, num_params, uarg->params); if (rc) goto out; @@ -619,6 +618,7 @@ static void tee_release_device(struct device *dev) clear_bit(teedev->id, dev_mask); spin_unlock(&driver_lock); mutex_destroy(&teedev->mutex); + idr_destroy(&teedev->idr); kfree(teedev); } @@ -646,7 +646,7 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, if (!teedesc || !teedesc->name || !teedesc->ops || !teedesc->ops->get_version || !teedesc->ops->open || - !teedesc->ops->release || !dev || !pool) + !teedesc->ops->release || !pool) return ERR_PTR(-EINVAL); teedev = kzalloc(sizeof(*teedev), GFP_KERNEL); @@ -696,6 +696,7 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, teedev->num_users = 1; init_completion(&teedev->c_no_users); mutex_init(&teedev->mutex); + idr_init(&teedev->idr); teedev->desc = teedesc; teedev->pool = pool; @@ -704,8 +705,8 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, err_devt: unregister_chrdev_region(teedev->dev.devt, 1); err: - dev_err(dev, "could not register %s driver\n", - teedesc->flags & TEE_DESC_PRIVILEGED ? "privileged" : "client"); + pr_err("could not register %s driver\n", + teedesc->flags & TEE_DESC_PRIVILEGED ? "privileged" : "client"); if (teedev && teedev->id < TEE_NUM_DEVICES) { spin_lock(&driver_lock); clear_bit(teedev->id, dev_mask); @@ -749,14 +750,9 @@ int tee_device_register(struct tee_device *teedev) { int rc; - /* - * If the teedev already is registered, don't do it again. It's - * obviously an error to try to register twice, but if we return - * an error we'll force the driver to remove the teedev. - */ if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) { dev_err(&teedev->dev, "attempt to register twice\n"); - return 0; + return -EINVAL; } rc = cdev_add(&teedev->cdev, teedev->dev.devt, 1); diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 9fd501c8e22e..0be1e3e93bee 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -309,7 +309,8 @@ int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa) EXPORT_SYMBOL_GPL(tee_shm_get_pa); /** - * tee_shm_get_from_id() - Find shared memory object and increase referece count + * tee_shm_get_from_id() - Find shared memory object and increase reference + * count * @ctx: Context owning the shared memory * @id: Id of shared memory object * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c index 3cb0ad0ce99f..fb4f8522a526 100644 --- a/drivers/tee/tee_shm_pool.c +++ b/drivers/tee/tee_shm_pool.c @@ -90,7 +90,6 @@ static int pool_res_mem_mgr_init(struct tee_shm_pool_mgr *mgr, /** * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved * memory range - * @dev: Device allocating the pool * @priv_info: Information for driver private shared memory pool * @dmabuf_info: Information for dma-buf shared memory pool * @@ -102,8 +101,7 @@ static int pool_res_mem_mgr_init(struct tee_shm_pool_mgr *mgr, * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. */ struct tee_shm_pool * -tee_shm_pool_alloc_res_mem(struct device *dev, - struct tee_shm_pool_mem_info *priv_info, +tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, struct tee_shm_pool_mem_info *dmabuf_info) { struct tee_shm_pool *pool = NULL; @@ -135,7 +133,7 @@ tee_shm_pool_alloc_res_mem(struct device *dev, return pool; err: if (ret == -ENOMEM) - dev_err(dev, "can't allocate memory for res_mem shared memory pool\n"); + pr_err("%s: can't allocate memory for res_mem shared memory pool\n", __func__); if (pool && pool->private_mgr.private_data) gen_pool_destroy(pool->private_mgr.private_data); kfree(pool); diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index f5d5f455660c..0f175b8f6456 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -164,7 +164,6 @@ struct tee_shm_pool_mem_info { /** * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved * memory range - * @dev: Device allocating the pool * @priv_info: Information for driver private shared memory pool * @dmabuf_info: Information for dma-buf shared memory pool * @@ -176,8 +175,7 @@ struct tee_shm_pool_mem_info { * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. */ struct tee_shm_pool * -tee_shm_pool_alloc_res_mem(struct device *dev, - struct tee_shm_pool_mem_info *priv_info, +tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info, struct tee_shm_pool_mem_info *dmabuf_info); /** @@ -268,7 +266,8 @@ int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa); int tee_shm_get_id(struct tee_shm *shm); /** - * tee_shm_get_from_id() - Find shared memory object and increase referece count + * tee_shm_get_from_id() - Find shared memory object and increase reference + * count * @ctx: Context owning the shared memory * @id: Id of shared memory object * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index ddc476e3c16b..370d8845ab21 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -165,54 +165,28 @@ struct tee_ioctl_buf_data { #define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6 /** - * struct tee_ioctl_param_memref - memory reference - * @shm_offs: Offset into the shared memory object - * @size: Size of the buffer - * @shm_id: Shared memory identifier - * - * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an - * identifier representing the shared memory object. A memref can reference - * a part of a shared memory by specifying an offset (@shm_offs) and @size - * of the object. To supply the entire shared memory object set @shm_offs - * to 0 and @size to the previously returned size of the object. - */ -struct tee_ioctl_param_memref { - __u64 shm_offs; - __u64 size; - __s64 shm_id; -}; - -/** - * struct tee_ioctl_param_value - values - * @a: first value - * @b: second value - * @c: third value - * - * Value parameters are passed unchecked to the destination - */ -struct tee_ioctl_param_value { - __u64 a; - __u64 b; - __u64 c; -}; - -/** * struct tee_ioctl_param - parameter * @attr: attributes - * @memref: a memory reference - * @value: a value + * @a: if a memref, offset into the shared memory object, else a value parameter + * @b: if a memref, size of the buffer, else a value parameter + * @c: if a memref, shared memory identifier, else a value parameter * * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in * the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE * indicates that none of the members are used. + * + * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an + * identifier representing the shared memory object. A memref can reference + * a part of a shared memory by specifying an offset (@a) and size (@b) of + * the object. To supply the entire shared memory object set the offset + * (@a) to 0 and size (@b) to the previously returned size of the object. */ struct tee_ioctl_param { __u64 attr; - union { - struct tee_ioctl_param_memref memref; - struct tee_ioctl_param_value value; - } u; + __u64 a; + __u64 b; + __u64 c; }; #define TEE_IOCTL_UUID_LEN 16 @@ -237,17 +211,9 @@ struct tee_ioctl_open_session_arg { __u32 ret; __u32 ret_origin; __u32 num_params; - /* - * this struct is 8 byte aligned since the 'struct tee_ioctl_param' - * which follows requires 8 byte alignment. - * - * Commented out element used to visualize the layout dynamic part - * of the struct. This field is not available at all if - * num_params == 0. - * - * struct tee_ioctl_param params[num_params]; - */ -} __aligned(8); + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; /** * TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application @@ -276,17 +242,9 @@ struct tee_ioctl_invoke_arg { __u32 ret; __u32 ret_origin; __u32 num_params; - /* - * this struct is 8 byte aligned since the 'struct tee_ioctl_param' - * which follows requires 8 byte alignment. - * - * Commented out element used to visualize the layout dynamic part - * of the struct. This field is not available at all if - * num_params == 0. - * - * struct tee_ioctl_param params[num_params]; - */ -} __aligned(8); + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; /** * TEE_IOC_INVOKE - Invokes a function in a Trusted Application @@ -339,17 +297,9 @@ struct tee_ioctl_close_session_arg { struct tee_iocl_supp_recv_arg { __u32 func; __u32 num_params; - /* - * this struct is 8 byte aligned since the 'struct tee_ioctl_param' - * which follows requires 8 byte alignment. - * - * Commented out element used to visualize the layout dynamic part - * of the struct. This field is not available at all if - * num_params == 0. - * - * struct tee_ioctl_param params[num_params]; - */ -} __aligned(8); + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; /** * TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function @@ -368,17 +318,10 @@ struct tee_iocl_supp_recv_arg { struct tee_iocl_supp_send_arg { __u32 ret; __u32 num_params; - /* - * this struct is 8 byte aligned since the 'struct tee_ioctl_param' - * which follows requires 8 byte alignment. - * - * Commented out element used to visualize the layout dynamic part - * of the struct. This field is not available at all if - * num_params == 0. - * - * struct tee_ioctl_param params[num_params]; - */ -} __aligned(8); + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + /** * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function * |