diff options
Diffstat (limited to 'drivers/tee/optee/call.c')
-rw-r--r-- | drivers/tee/optee/call.c | 59 |
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 @@ | |||
25 | struct optee_call_waiter { | 25 | struct 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 | ||
31 | static void optee_cq_wait_init(struct optee_call_queue *cq, | 30 | static 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) | |||
78 | static void optee_cq_wait_final(struct optee_call_queue *cq, | 82 | static 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 | */ |