summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2016-12-23 07:13:39 -0500
committerJens Wiklander <jens.wiklander@linaro.org>2017-11-29 04:37:13 -0500
commit1647a5ac175490d7dac2e74532e85b6197fc74e9 (patch)
tree9883ff54c1d697ddd0cd77c2c2dea7160ff4fdd7
parentf2aa97240c84b8f258710e297ba60048bd9c153e (diff)
optee: support asynchronous supplicant requests
Adds support for asynchronous supplicant requests, meaning that the supplicant can process several requests in parallel or block in a request for some time. Acked-by: Etienne Carriere <etienne.carriere@linaro.org> Tested-by: Etienne Carriere <etienne.carriere@linaro.org> (b2260 pager=y/n) Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
-rw-r--r--drivers/tee/optee/core.c11
-rw-r--r--drivers/tee/optee/optee_private.h43
-rw-r--r--drivers/tee/optee/rpc.c4
-rw-r--r--drivers/tee/optee/supp.c358
4 files changed, 243 insertions, 173 deletions
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 7952357df9c8..b7492da92567 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -187,12 +187,12 @@ static int optee_open(struct tee_context *ctx)
187 if (teedev == optee->supp_teedev) { 187 if (teedev == optee->supp_teedev) {
188 bool busy = true; 188 bool busy = true;
189 189
190 mutex_lock(&optee->supp.ctx_mutex); 190 mutex_lock(&optee->supp.mutex);
191 if (!optee->supp.ctx) { 191 if (!optee->supp.ctx) {
192 busy = false; 192 busy = false;
193 optee->supp.ctx = ctx; 193 optee->supp.ctx = ctx;
194 } 194 }
195 mutex_unlock(&optee->supp.ctx_mutex); 195 mutex_unlock(&optee->supp.mutex);
196 if (busy) { 196 if (busy) {
197 kfree(ctxdata); 197 kfree(ctxdata);
198 return -EBUSY; 198 return -EBUSY;
@@ -252,11 +252,8 @@ static void optee_release(struct tee_context *ctx)
252 252
253 ctx->data = NULL; 253 ctx->data = NULL;
254 254
255 if (teedev == optee->supp_teedev) { 255 if (teedev == optee->supp_teedev)
256 mutex_lock(&optee->supp.ctx_mutex); 256 optee_supp_release(&optee->supp);
257 optee->supp.ctx = NULL;
258 mutex_unlock(&optee->supp.ctx_mutex);
259 }
260} 257}
261 258
262static const struct tee_driver_ops optee_ops = { 259static const struct tee_driver_ops optee_ops = {
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index c374cd594314..3e7da187acbe 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -53,36 +53,24 @@ struct optee_wait_queue {
53 * @ctx the context of current connected supplicant. 53 * @ctx the context of current connected supplicant.
54 * if !NULL the supplicant device is available for use, 54 * if !NULL the supplicant device is available for use,
55 * else busy 55 * else busy
56 * @ctx_mutex: held while accessing @ctx 56 * @mutex: held while accessing content of this struct
57 * @func: supplicant function id to call 57 * @req_id: current request id if supplicant is doing synchronous
58 * @ret: call return value 58 * communication, else -1
59 * @num_params: number of elements in @param 59 * @reqs: queued request not yet retrieved by supplicant
60 * @param: parameters for @func 60 * @idr: IDR holding all requests currently being processed
61 * @req_posted: if true, a request has been posted to the supplicant 61 * by supplicant
62 * @supp_next_send: if true, next step is for supplicant to send response 62 * @reqs_c: completion used by supplicant when waiting for a
63 * @thrd_mutex: held by the thread doing a request to supplicant 63 * request to be queued.
64 * @supp_mutex: held by supplicant while operating on this struct
65 * @data_to_supp: supplicant is waiting on this for next request
66 * @data_from_supp: requesting thread is waiting on this to get the result
67 */ 64 */
68struct optee_supp { 65struct optee_supp {
66 /* Serializes access to this struct */
67 struct mutex mutex;
69 struct tee_context *ctx; 68 struct tee_context *ctx;
70 /* Serializes access of ctx */ 69
71 struct mutex ctx_mutex; 70 int req_id;
72 71 struct list_head reqs;
73 u32 func; 72 struct idr idr;
74 u32 ret; 73 struct completion reqs_c;
75 size_t num_params;
76 struct tee_param *param;
77
78 bool req_posted;
79 bool supp_next_send;
80 /* Serializes access to this struct for requesting thread */
81 struct mutex thrd_mutex;
82 /* Serializes access to this struct for supplicant threads */
83 struct mutex supp_mutex;
84 struct completion data_to_supp;
85 struct completion data_from_supp;
86}; 74};
87 75
88/** 76/**
@@ -142,6 +130,7 @@ int optee_supp_read(struct tee_context *ctx, void __user *buf, size_t len);
142int optee_supp_write(struct tee_context *ctx, void __user *buf, size_t len); 130int optee_supp_write(struct tee_context *ctx, void __user *buf, size_t len);
143void optee_supp_init(struct optee_supp *supp); 131void optee_supp_init(struct optee_supp *supp);
144void optee_supp_uninit(struct optee_supp *supp); 132void optee_supp_uninit(struct optee_supp *supp);
133void optee_supp_release(struct optee_supp *supp);
145 134
146int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params, 135int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
147 struct tee_param *param); 136 struct tee_param *param);
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
index cef417f4f4d2..c6df4317ca9f 100644
--- a/drivers/tee/optee/rpc.c
+++ b/drivers/tee/optee/rpc.c
@@ -192,10 +192,10 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
192 if (ret) 192 if (ret)
193 return ERR_PTR(-ENOMEM); 193 return ERR_PTR(-ENOMEM);
194 194
195 mutex_lock(&optee->supp.ctx_mutex); 195 mutex_lock(&optee->supp.mutex);
196 /* Increases count as secure world doesn't have a reference */ 196 /* Increases count as secure world doesn't have a reference */
197 shm = tee_shm_get_from_id(optee->supp.ctx, param.u.value.c); 197 shm = tee_shm_get_from_id(optee->supp.ctx, param.u.value.c);
198 mutex_unlock(&optee->supp.ctx_mutex); 198 mutex_unlock(&optee->supp.mutex);
199 return shm; 199 return shm;
200} 200}
201 201
diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
index 56aa8b929b8c..df35fc01fd3e 100644
--- a/drivers/tee/optee/supp.c
+++ b/drivers/tee/optee/supp.c
@@ -16,21 +16,61 @@
16#include <linux/uaccess.h> 16#include <linux/uaccess.h>
17#include "optee_private.h" 17#include "optee_private.h"
18 18
19struct optee_supp_req {
20 struct list_head link;
21
22 bool busy;
23 u32 func;
24 u32 ret;
25 size_t num_params;
26 struct tee_param *param;
27
28 struct completion c;
29};
30
19void optee_supp_init(struct optee_supp *supp) 31void optee_supp_init(struct optee_supp *supp)
20{ 32{
21 memset(supp, 0, sizeof(*supp)); 33 memset(supp, 0, sizeof(*supp));
22 mutex_init(&supp->ctx_mutex); 34 mutex_init(&supp->mutex);
23 mutex_init(&supp->thrd_mutex); 35 init_completion(&supp->reqs_c);
24 mutex_init(&supp->supp_mutex); 36 idr_init(&supp->idr);
25 init_completion(&supp->data_to_supp); 37 INIT_LIST_HEAD(&supp->reqs);
26 init_completion(&supp->data_from_supp); 38 supp->req_id = -1;
27} 39}
28 40
29void optee_supp_uninit(struct optee_supp *supp) 41void optee_supp_uninit(struct optee_supp *supp)
30{ 42{
31 mutex_destroy(&supp->ctx_mutex); 43 mutex_destroy(&supp->mutex);
32 mutex_destroy(&supp->thrd_mutex); 44 idr_destroy(&supp->idr);
33 mutex_destroy(&supp->supp_mutex); 45}
46
47void optee_supp_release(struct optee_supp *supp)
48{
49 int id;
50 struct optee_supp_req *req;
51 struct optee_supp_req *req_tmp;
52
53 mutex_lock(&supp->mutex);
54
55 /* Abort all request retrieved by supplicant */
56 idr_for_each_entry(&supp->idr, req, id) {
57 req->busy = false;
58 idr_remove(&supp->idr, id);
59 req->ret = TEEC_ERROR_COMMUNICATION;
60 complete(&req->c);
61 }
62
63 /* Abort all queued requests */
64 list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
65 list_del(&req->link);
66 req->ret = TEEC_ERROR_COMMUNICATION;
67 complete(&req->c);
68 }
69
70 supp->ctx = NULL;
71 supp->req_id = -1;
72
73 mutex_unlock(&supp->mutex);
34} 74}
35 75
36/** 76/**
@@ -44,53 +84,42 @@ void optee_supp_uninit(struct optee_supp *supp)
44 */ 84 */
45u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, 85u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
46 struct tee_param *param) 86 struct tee_param *param)
87
47{ 88{
48 bool interruptable;
49 struct optee *optee = tee_get_drvdata(ctx->teedev); 89 struct optee *optee = tee_get_drvdata(ctx->teedev);
50 struct optee_supp *supp = &optee->supp; 90 struct optee_supp *supp = &optee->supp;
91 struct optee_supp_req *req = kzalloc(sizeof(*req), GFP_KERNEL);
92 bool interruptable;
51 u32 ret; 93 u32 ret;
52 94
53 /* 95 if (!req)
54 * Other threads blocks here until we've copied our answer from 96 return TEEC_ERROR_OUT_OF_MEMORY;
55 * supplicant.
56 */
57 while (mutex_lock_interruptible(&supp->thrd_mutex)) {
58 /* See comment below on when the RPC can be interrupted. */
59 mutex_lock(&supp->ctx_mutex);
60 interruptable = !supp->ctx;
61 mutex_unlock(&supp->ctx_mutex);
62 if (interruptable)
63 return TEEC_ERROR_COMMUNICATION;
64 }
65 97
66 /* 98 init_completion(&req->c);
67 * We have exclusive access now since the supplicant at this 99 req->func = func;
68 * point is either doing a 100 req->num_params = num_params;
69 * wait_for_completion_interruptible(&supp->data_to_supp) or is in 101 req->param = param;
70 * userspace still about to do the ioctl() to enter
71 * optee_supp_recv() below.
72 */
73 102
74 supp->func = func; 103 /* Insert the request in the request list */
75 supp->num_params = num_params; 104 mutex_lock(&supp->mutex);
76 supp->param = param; 105 list_add_tail(&req->link, &supp->reqs);
77 supp->req_posted = true; 106 mutex_unlock(&supp->mutex);
78 107
79 /* Let supplicant get the data */ 108 /* Tell an eventual waiter there's a new request */
80 complete(&supp->data_to_supp); 109 complete(&supp->reqs_c);
81 110
82 /* 111 /*
83 * Wait for supplicant to process and return result, once we've 112 * Wait for supplicant to process and return result, once we've
84 * returned from wait_for_completion(data_from_supp) we have 113 * returned from wait_for_completion(&req->c) successfully we have
85 * exclusive access again. 114 * exclusive access again.
86 */ 115 */
87 while (wait_for_completion_interruptible(&supp->data_from_supp)) { 116 while (wait_for_completion_interruptible(&req->c)) {
88 mutex_lock(&supp->ctx_mutex); 117 mutex_lock(&supp->mutex);
89 interruptable = !supp->ctx; 118 interruptable = !supp->ctx;
90 if (interruptable) { 119 if (interruptable) {
91 /* 120 /*
92 * There's no supplicant available and since the 121 * There's no supplicant available and since the
93 * supp->ctx_mutex currently is held none can 122 * supp->mutex currently is held none can
94 * become available until the mutex released 123 * become available until the mutex released
95 * again. 124 * again.
96 * 125 *
@@ -101,28 +130,65 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
101 * will serve all requests in a timely manner and 130 * will serve all requests in a timely manner and
102 * interrupting then wouldn't make sense. 131 * interrupting then wouldn't make sense.
103 */ 132 */
104 supp->ret = TEEC_ERROR_COMMUNICATION; 133 interruptable = !req->busy;
105 init_completion(&supp->data_to_supp); 134 if (!req->busy)
135 list_del(&req->link);
106 } 136 }
107 mutex_unlock(&supp->ctx_mutex); 137 mutex_unlock(&supp->mutex);
108 if (interruptable) 138
139 if (interruptable) {
140 req->ret = TEEC_ERROR_COMMUNICATION;
109 break; 141 break;
142 }
110 } 143 }
111 144
112 ret = supp->ret; 145 ret = req->ret;
113 supp->param = NULL; 146 kfree(req);
114 supp->req_posted = false;
115
116 /* We're done, let someone else talk to the supplicant now. */
117 mutex_unlock(&supp->thrd_mutex);
118 147
119 return ret; 148 return ret;
120} 149}
121 150
122static int supp_check_recv_params(size_t num_params, struct tee_param *params) 151static struct optee_supp_req *supp_pop_entry(struct optee_supp *supp,
152 int num_params, int *id)
153{
154 struct optee_supp_req *req;
155
156 if (supp->req_id != -1) {
157 /*
158 * Supplicant should not mix synchronous and asnynchronous
159 * requests.
160 */
161 return ERR_PTR(-EINVAL);
162 }
163
164 if (list_empty(&supp->reqs))
165 return NULL;
166
167 req = list_first_entry(&supp->reqs, struct optee_supp_req, link);
168
169 if (num_params < req->num_params) {
170 /* Not enough room for parameters */
171 return ERR_PTR(-EINVAL);
172 }
173
174 *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
175 if (*id < 0)
176 return ERR_PTR(-ENOMEM);
177
178 list_del(&req->link);
179 req->busy = true;
180
181 return req;
182}
183
184static int supp_check_recv_params(size_t num_params, struct tee_param *params,
185 size_t *num_meta)
123{ 186{
124 size_t n; 187 size_t n;
125 188
189 if (!num_params)
190 return -EINVAL;
191
126 /* 192 /*
127 * If there's memrefs we need to decrease those as they where 193 * If there's memrefs we need to decrease those as they where
128 * increased earlier and we'll even refuse to accept any below. 194 * increased earlier and we'll even refuse to accept any below.
@@ -132,11 +198,20 @@ static int supp_check_recv_params(size_t num_params, struct tee_param *params)
132 tee_shm_put(params[n].u.memref.shm); 198 tee_shm_put(params[n].u.memref.shm);
133 199
134 /* 200 /*
135 * We only expect parameters as TEE_IOCTL_PARAM_ATTR_TYPE_NONE (0). 201 * We only expect parameters as TEE_IOCTL_PARAM_ATTR_TYPE_NONE with
202 * or without the TEE_IOCTL_PARAM_ATTR_META bit set.
136 */ 203 */
137 for (n = 0; n < num_params; n++) 204 for (n = 0; n < num_params; n++)
138 if (params[n].attr) 205 if (params[n].attr &&
206 params[n].attr != TEE_IOCTL_PARAM_ATTR_META)
139 return -EINVAL; 207 return -EINVAL;
208
209 /* At most we'll need one meta parameter so no need to check for more */
210 if (params->attr == TEE_IOCTL_PARAM_ATTR_META)
211 *num_meta = 1;
212 else
213 *num_meta = 0;
214
140 return 0; 215 return 0;
141} 216}
142 217
@@ -156,69 +231,99 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
156 struct tee_device *teedev = ctx->teedev; 231 struct tee_device *teedev = ctx->teedev;
157 struct optee *optee = tee_get_drvdata(teedev); 232 struct optee *optee = tee_get_drvdata(teedev);
158 struct optee_supp *supp = &optee->supp; 233 struct optee_supp *supp = &optee->supp;
234 struct optee_supp_req *req = NULL;
235 int id;
236 size_t num_meta;
159 int rc; 237 int rc;
160 238
161 rc = supp_check_recv_params(*num_params, param); 239 rc = supp_check_recv_params(*num_params, param, &num_meta);
162 if (rc) 240 if (rc)
163 return rc; 241 return rc;
164 242
165 /* 243 while (true) {
166 * In case two threads in one supplicant is calling this function 244 mutex_lock(&supp->mutex);
167 * simultaneously we need to protect the data with a mutex which 245 req = supp_pop_entry(supp, *num_params - num_meta, &id);
168 * we'll release before returning. 246 mutex_unlock(&supp->mutex);
169 */ 247
170 mutex_lock(&supp->supp_mutex); 248 if (req) {
249 if (IS_ERR(req))
250 return PTR_ERR(req);
251 break;
252 }
171 253
172 if (supp->supp_next_send) {
173 /* 254 /*
174 * optee_supp_recv() has been called again without 255 * If we didn't get a request we'll block in
175 * a optee_supp_send() in between. Supplicant has 256 * wait_for_completion() to avoid needless spinning.
176 * probably been restarted before it was able to 257 *
177 * write back last result. Abort last request and 258 * This is where supplicant will be hanging most of
178 * wait for a new. 259 * the time, let's make this interruptable so we
260 * can easily restart supplicant if needed.
179 */ 261 */
180 if (supp->req_posted) { 262 if (wait_for_completion_interruptible(&supp->reqs_c))
181 supp->ret = TEEC_ERROR_COMMUNICATION; 263 return -ERESTARTSYS;
182 supp->supp_next_send = false;
183 complete(&supp->data_from_supp);
184 }
185 } 264 }
186 265
187 /* 266 if (num_meta) {
188 * This is where supplicant will be hanging most of the 267 /*
189 * time, let's make this interruptable so we can easily 268 * tee-supplicant support meta parameters -> requsts can be
190 * restart supplicant if needed. 269 * processed asynchronously.
191 */ 270 */
192 if (wait_for_completion_interruptible(&supp->data_to_supp)) { 271 param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
193 rc = -ERESTARTSYS; 272 TEE_IOCTL_PARAM_ATTR_META;
194 goto out; 273 param->u.value.a = id;
274 param->u.value.b = 0;
275 param->u.value.c = 0;
276 } else {
277 mutex_lock(&supp->mutex);
278 supp->req_id = id;
279 mutex_unlock(&supp->mutex);
195 } 280 }
196 281
197 /* We have exlusive access to the data */ 282 *func = req->func;
283 *num_params = req->num_params + num_meta;
284 memcpy(param + num_meta, req->param,
285 sizeof(struct tee_param) * req->num_params);
198 286
199 if (*num_params < supp->num_params) { 287 return 0;
200 /* 288}
201 * Not enough room for parameters, tell supplicant 289
202 * it failed and abort last request. 290static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
203 */ 291 size_t num_params,
204 supp->ret = TEEC_ERROR_COMMUNICATION; 292 struct tee_param *param,
205 rc = -EINVAL; 293 size_t *num_meta)
206 complete(&supp->data_from_supp); 294{
207 goto out; 295 struct optee_supp_req *req;
296 int id;
297 size_t nm;
298 const u32 attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
299 TEE_IOCTL_PARAM_ATTR_META;
300
301 if (!num_params)
302 return ERR_PTR(-EINVAL);
303
304 if (supp->req_id == -1) {
305 if (param->attr != attr)
306 return ERR_PTR(-EINVAL);
307 id = param->u.value.a;
308 nm = 1;
309 } else {
310 id = supp->req_id;
311 nm = 0;
208 } 312 }
209 313
210 *func = supp->func; 314 req = idr_find(&supp->idr, id);
211 *num_params = supp->num_params; 315 if (!req)
212 memcpy(param, supp->param, 316 return ERR_PTR(-ENOENT);
213 sizeof(struct tee_param) * supp->num_params); 317
318 if ((num_params - nm) != req->num_params)
319 return ERR_PTR(-EINVAL);
214 320
215 /* Allow optee_supp_send() below to do its work */ 321 req->busy = false;
216 supp->supp_next_send = true; 322 idr_remove(&supp->idr, id);
323 supp->req_id = -1;
324 *num_meta = nm;
217 325
218 rc = 0; 326 return req;
219out:
220 mutex_unlock(&supp->supp_mutex);
221 return rc;
222} 327}
223 328
224/** 329/**
@@ -236,63 +341,42 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
236 struct tee_device *teedev = ctx->teedev; 341 struct tee_device *teedev = ctx->teedev;
237 struct optee *optee = tee_get_drvdata(teedev); 342 struct optee *optee = tee_get_drvdata(teedev);
238 struct optee_supp *supp = &optee->supp; 343 struct optee_supp *supp = &optee->supp;
344 struct optee_supp_req *req;
239 size_t n; 345 size_t n;
240 int rc = 0; 346 size_t num_meta;
241 347
242 /* 348 mutex_lock(&supp->mutex);
243 * We still have exclusive access to the data since that's how we 349 req = supp_pop_req(supp, num_params, param, &num_meta);
244 * left it when returning from optee_supp_read(). 350 mutex_unlock(&supp->mutex);
245 */
246 351
247 /* See comment on mutex in optee_supp_read() above */ 352 if (IS_ERR(req)) {
248 mutex_lock(&supp->supp_mutex); 353 /* Something is wrong, let supplicant restart. */
249 354 return PTR_ERR(req);
250 if (!supp->supp_next_send) {
251 /*
252 * Something strange is going on, supplicant shouldn't
253 * enter optee_supp_send() in this state
254 */
255 rc = -ENOENT;
256 goto out;
257 }
258
259 if (num_params != supp->num_params) {
260 /*
261 * Something is wrong, let supplicant restart. Next call to
262 * optee_supp_recv() will give an error to the requesting
263 * thread and release it.
264 */
265 rc = -EINVAL;
266 goto out;
267 } 355 }
268 356
269 /* Update out and in/out parameters */ 357 /* Update out and in/out parameters */
270 for (n = 0; n < num_params; n++) { 358 for (n = 0; n < req->num_params; n++) {
271 struct tee_param *p = supp->param + n; 359 struct tee_param *p = req->param + n;
272 360
273 switch (p->attr) { 361 switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
274 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: 362 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
275 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: 363 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
276 p->u.value.a = param[n].u.value.a; 364 p->u.value.a = param[n + num_meta].u.value.a;
277 p->u.value.b = param[n].u.value.b; 365 p->u.value.b = param[n + num_meta].u.value.b;
278 p->u.value.c = param[n].u.value.c; 366 p->u.value.c = param[n + num_meta].u.value.c;
279 break; 367 break;
280 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: 368 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
281 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: 369 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
282 p->u.memref.size = param[n].u.memref.size; 370 p->u.memref.size = param[n + num_meta].u.memref.size;
283 break; 371 break;
284 default: 372 default:
285 break; 373 break;
286 } 374 }
287 } 375 }
288 supp->ret = ret; 376 req->ret = ret;
289
290 /* Allow optee_supp_recv() above to do its work */
291 supp->supp_next_send = false;
292 377
293 /* Let the requesting thread continue */ 378 /* Let the requesting thread continue */
294 complete(&supp->data_from_supp); 379 complete(&req->c);
295out: 380
296 mutex_unlock(&supp->supp_mutex); 381 return 0;
297 return rc;
298} 382}