aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tee/optee/call.c')
-rw-r--r--drivers/tee/optee/call.c59
1 files changed, 34 insertions, 25 deletions
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 @@
25struct optee_call_waiter { 25struct optee_call_waiter {
26 struct list_head list_node; 26 struct list_head list_node;
27 struct completion c; 27 struct completion c;
28 bool completed;
29}; 28};
30 29
31static void optee_cq_wait_init(struct optee_call_queue *cq, 30static void optee_cq_wait_init(struct optee_call_queue *cq,
32 struct optee_call_waiter *w) 31 struct optee_call_waiter *w)
33{ 32{
33 /*
34 * We're preparing to make a call to secure world. In case we can't
35 * allocate a thread in secure world we'll end up waiting in
36 * optee_cq_wait_for_completion().
37 *
38 * Normally if there's no contention in secure world the call will
39 * complete and we can cleanup directly with optee_cq_wait_final().
40 */
34 mutex_lock(&cq->mutex); 41 mutex_lock(&cq->mutex);
35 42
36 /* 43 /*
@@ -39,7 +46,6 @@ static void optee_cq_wait_init(struct optee_call_queue *cq,
39 * returns busy and another thread just exited and try to complete 46 * returns busy and another thread just exited and try to complete
40 * someone. 47 * someone.
41 */ 48 */
42 w->completed = false;
43 init_completion(&w->c); 49 init_completion(&w->c);
44 list_add_tail(&w->list_node, &cq->waiters); 50 list_add_tail(&w->list_node, &cq->waiters);
45 51
@@ -55,7 +61,6 @@ static void optee_cq_wait_for_completion(struct optee_call_queue *cq,
55 61
56 /* Move to end of list to get out of the way for other waiters */ 62 /* Move to end of list to get out of the way for other waiters */
57 list_del(&w->list_node); 63 list_del(&w->list_node);
58 w->completed = false;
59 reinit_completion(&w->c); 64 reinit_completion(&w->c);
60 list_add_tail(&w->list_node, &cq->waiters); 65 list_add_tail(&w->list_node, &cq->waiters);
61 66
@@ -67,9 +72,8 @@ static void optee_cq_complete_one(struct optee_call_queue *cq)
67 struct optee_call_waiter *w; 72 struct optee_call_waiter *w;
68 73
69 list_for_each_entry(w, &cq->waiters, list_node) { 74 list_for_each_entry(w, &cq->waiters, list_node) {
70 if (!w->completed) { 75 if (!completion_done(&w->c)) {
71 complete(&w->c); 76 complete(&w->c);
72 w->completed = true;
73 break; 77 break;
74 } 78 }
75 } 79 }
@@ -78,17 +82,26 @@ static void optee_cq_complete_one(struct optee_call_queue *cq)
78static void optee_cq_wait_final(struct optee_call_queue *cq, 82static void optee_cq_wait_final(struct optee_call_queue *cq,
79 struct optee_call_waiter *w) 83 struct optee_call_waiter *w)
80{ 84{
85 /*
86 * We're done with the call to secure world. The thread in secure
87 * world that was used for this call is now available for some
88 * other task to use.
89 */
81 mutex_lock(&cq->mutex); 90 mutex_lock(&cq->mutex);
82 91
83 /* Get out of the list */ 92 /* Get out of the list */
84 list_del(&w->list_node); 93 list_del(&w->list_node);
85 94
95 /* Wake up one eventual waiting task */
86 optee_cq_complete_one(cq); 96 optee_cq_complete_one(cq);
97
87 /* 98 /*
88 * If we're completed we've got a completion that some other task 99 * If we're completed we've got a completion from another task that
89 * could have used instead. 100 * was just done with its call to secure world. Since yet another
101 * thread now is available in secure world wake up another eventual
102 * waiting task.
90 */ 103 */
91 if (w->completed) 104 if (completion_done(&w->c))
92 optee_cq_complete_one(cq); 105 optee_cq_complete_one(cq);
93 106
94 mutex_unlock(&cq->mutex); 107 mutex_unlock(&cq->mutex);
@@ -206,7 +219,6 @@ int optee_open_session(struct tee_context *ctx,
206 struct tee_shm *shm; 219 struct tee_shm *shm;
207 struct optee_msg_arg *msg_arg; 220 struct optee_msg_arg *msg_arg;
208 phys_addr_t msg_parg; 221 phys_addr_t msg_parg;
209 struct optee_msg_param *msg_param;
210 struct optee_session *sess = NULL; 222 struct optee_session *sess = NULL;
211 223
212 /* +2 for the meta parameters added below */ 224 /* +2 for the meta parameters added below */
@@ -216,21 +228,20 @@ int optee_open_session(struct tee_context *ctx,
216 228
217 msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION; 229 msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
218 msg_arg->cancel_id = arg->cancel_id; 230 msg_arg->cancel_id = arg->cancel_id;
219 msg_param = OPTEE_MSG_GET_PARAMS(msg_arg);
220 231
221 /* 232 /*
222 * Initialize and add the meta parameters needed when opening a 233 * Initialize and add the meta parameters needed when opening a
223 * session. 234 * session.
224 */ 235 */
225 msg_param[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | 236 msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
226 OPTEE_MSG_ATTR_META; 237 OPTEE_MSG_ATTR_META;
227 msg_param[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | 238 msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
228 OPTEE_MSG_ATTR_META; 239 OPTEE_MSG_ATTR_META;
229 memcpy(&msg_param[0].u.value, arg->uuid, sizeof(arg->uuid)); 240 memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
230 memcpy(&msg_param[1].u.value, arg->uuid, sizeof(arg->clnt_uuid)); 241 memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
231 msg_param[1].u.value.c = arg->clnt_login; 242 msg_arg->params[1].u.value.c = arg->clnt_login;
232 243
233 rc = optee_to_msg_param(msg_param + 2, arg->num_params, param); 244 rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
234 if (rc) 245 if (rc)
235 goto out; 246 goto out;
236 247
@@ -255,7 +266,7 @@ int optee_open_session(struct tee_context *ctx,
255 kfree(sess); 266 kfree(sess);
256 } 267 }
257 268
258 if (optee_from_msg_param(param, arg->num_params, msg_param + 2)) { 269 if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
259 arg->ret = TEEC_ERROR_COMMUNICATION; 270 arg->ret = TEEC_ERROR_COMMUNICATION;
260 arg->ret_origin = TEEC_ORIGIN_COMMS; 271 arg->ret_origin = TEEC_ORIGIN_COMMS;
261 /* Close session again to avoid leakage */ 272 /* Close session again to avoid leakage */
@@ -308,7 +319,6 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
308 struct tee_shm *shm; 319 struct tee_shm *shm;
309 struct optee_msg_arg *msg_arg; 320 struct optee_msg_arg *msg_arg;
310 phys_addr_t msg_parg; 321 phys_addr_t msg_parg;
311 struct optee_msg_param *msg_param;
312 struct optee_session *sess; 322 struct optee_session *sess;
313 int rc; 323 int rc;
314 324
@@ -326,9 +336,8 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
326 msg_arg->func = arg->func; 336 msg_arg->func = arg->func;
327 msg_arg->session = arg->session; 337 msg_arg->session = arg->session;
328 msg_arg->cancel_id = arg->cancel_id; 338 msg_arg->cancel_id = arg->cancel_id;
329 msg_param = OPTEE_MSG_GET_PARAMS(msg_arg);
330 339
331 rc = optee_to_msg_param(msg_param, arg->num_params, param); 340 rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
332 if (rc) 341 if (rc)
333 goto out; 342 goto out;
334 343
@@ -337,7 +346,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
337 msg_arg->ret_origin = TEEC_ORIGIN_COMMS; 346 msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
338 } 347 }
339 348
340 if (optee_from_msg_param(param, arg->num_params, msg_param)) { 349 if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
341 msg_arg->ret = TEEC_ERROR_COMMUNICATION; 350 msg_arg->ret = TEEC_ERROR_COMMUNICATION;
342 msg_arg->ret_origin = TEEC_ORIGIN_COMMS; 351 msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
343 } 352 }
@@ -401,7 +410,7 @@ void optee_enable_shm_cache(struct optee *optee)
401} 410}
402 411
403/** 412/**
404 * optee_enable_shm_cache() - Disables caching of some shared memory allocation 413 * optee_disable_shm_cache() - Disables caching of some shared memory allocation
405 * in OP-TEE 414 * in OP-TEE
406 * @optee: main service struct 415 * @optee: main service struct
407 */ 416 */