aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2017-04-11 17:30:58 +0100
committerJon Medhurst <tixy@linaro.org>2017-04-11 17:30:58 +0100
commit71afea5c1f09e8aca8d5adeb166f47416d6c5daa (patch)
tree412ea236d2ac3a8bc5eefda20aff10c0e5f26c20
parent457349a00449a9554151368e1dbdecf64c847219 (diff)
parentcecbf98dc56b51bf2b3055ad9e53f43e30e93939 (diff)
Merge branch '4.4-armlt' into lsk-4.4-armltlsk-4.4-armlt-20170411
-rw-r--r--arch/arm/boot/dts/Makefile3
l---------arch/arm/boot/dts/juno-base.dtsi1
l---------arch/arm/boot/dts/juno-clocks.dtsi1
l---------arch/arm/boot/dts/juno-motherboard.dtsi1
l---------arch/arm/boot/dts/juno-r1.dts1
l---------arch/arm/boot/dts/juno-r2.dts1
l---------arch/arm/boot/dts/juno-sched-energy.dtsi1
l---------arch/arm/boot/dts/juno.dts1
l---------arch/arm/boot/dts/juno_r2-sched-energy.dtsi1
-rw-r--r--arch/arm64/boot/dts/arm/fvp-base-aemv8a-aemv8a.dts2
-rw-r--r--arch/arm64/boot/dts/arm/juno-r1.dts2
-rw-r--r--arch/arm64/boot/dts/arm/juno-r2.dts2
-rw-r--r--arch/arm64/boot/dts/arm/juno.dts2
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c13
-rw-r--r--drivers/tee/optee/call.c59
-rw-r--r--drivers/tee/optee/core.c180
-rw-r--r--drivers/tee/optee/optee_msg.h35
-rw-r--r--drivers/tee/optee/optee_private.h6
-rw-r--r--drivers/tee/optee/optee_smc.h2
-rw-r--r--drivers/tee/optee/rpc.c67
-rw-r--r--drivers/tee/tee_core.c84
-rw-r--r--drivers/tee/tee_shm.c3
-rw-r--r--drivers/tee/tee_shm_pool.c6
-rw-r--r--include/linux/tee_drv.h7
-rw-r--r--include/uapi/linux/tee.h107
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
*