1*d6e29083SAmirreza Zarrabi // SPDX-License-Identifier: GPL-2.0-only 2*d6e29083SAmirreza Zarrabi /* 3*d6e29083SAmirreza Zarrabi * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4*d6e29083SAmirreza Zarrabi */ 5*d6e29083SAmirreza Zarrabi 6*d6e29083SAmirreza Zarrabi #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7*d6e29083SAmirreza Zarrabi 8*d6e29083SAmirreza Zarrabi #include <linux/slab.h> 9*d6e29083SAmirreza Zarrabi #include <linux/uaccess.h> 10*d6e29083SAmirreza Zarrabi 11*d6e29083SAmirreza Zarrabi #include "qcomtee.h" 12*d6e29083SAmirreza Zarrabi 13*d6e29083SAmirreza Zarrabi /** 14*d6e29083SAmirreza Zarrabi * DOC: User Objects aka Supplicants 15*d6e29083SAmirreza Zarrabi * 16*d6e29083SAmirreza Zarrabi * Any userspace process with access to the TEE device file can behave as a 17*d6e29083SAmirreza Zarrabi * supplicant by creating a user object. Any TEE parameter of type OBJREF with 18*d6e29083SAmirreza Zarrabi * %QCOMTEE_OBJREF_FLAG_USER flag set is considered a user object. 19*d6e29083SAmirreza Zarrabi * 20*d6e29083SAmirreza Zarrabi * A supplicant uses qcomtee_user_object_select() (i.e. TEE_IOC_SUPPL_RECV) to 21*d6e29083SAmirreza Zarrabi * receive a QTEE user object request and qcomtee_user_object_submit() 22*d6e29083SAmirreza Zarrabi * (i.e. TEE_IOC_SUPPL_SEND) to submit a response. QTEE expects to receive the 23*d6e29083SAmirreza Zarrabi * response, including OB and OO in a specific order in the message; parameters 24*d6e29083SAmirreza Zarrabi * submitted with qcomtee_user_object_submit() should maintain this order. 25*d6e29083SAmirreza Zarrabi */ 26*d6e29083SAmirreza Zarrabi 27*d6e29083SAmirreza Zarrabi /** 28*d6e29083SAmirreza Zarrabi * struct qcomtee_user_object - User object. 29*d6e29083SAmirreza Zarrabi * @object: &struct qcomtee_object representing the user object. 30*d6e29083SAmirreza Zarrabi * @ctx: context for which the user object is defined. 31*d6e29083SAmirreza Zarrabi * @object_id: object ID in @ctx. 32*d6e29083SAmirreza Zarrabi * @notify: notify on release. 33*d6e29083SAmirreza Zarrabi * 34*d6e29083SAmirreza Zarrabi * Any object managed in userspace is represented by this struct. 35*d6e29083SAmirreza Zarrabi * If @notify is set, a notification message is sent back to userspace 36*d6e29083SAmirreza Zarrabi * upon release. 37*d6e29083SAmirreza Zarrabi */ 38*d6e29083SAmirreza Zarrabi struct qcomtee_user_object { 39*d6e29083SAmirreza Zarrabi struct qcomtee_object object; 40*d6e29083SAmirreza Zarrabi struct tee_context *ctx; 41*d6e29083SAmirreza Zarrabi u64 object_id; 42*d6e29083SAmirreza Zarrabi bool notify; 43*d6e29083SAmirreza Zarrabi }; 44*d6e29083SAmirreza Zarrabi 45*d6e29083SAmirreza Zarrabi #define to_qcomtee_user_object(o) \ 46*d6e29083SAmirreza Zarrabi container_of((o), struct qcomtee_user_object, object) 47*d6e29083SAmirreza Zarrabi 48*d6e29083SAmirreza Zarrabi static struct qcomtee_object_operations qcomtee_user_object_ops; 49*d6e29083SAmirreza Zarrabi 50*d6e29083SAmirreza Zarrabi /* Is it a user object? */ 51*d6e29083SAmirreza Zarrabi int is_qcomtee_user_object(struct qcomtee_object *object) 52*d6e29083SAmirreza Zarrabi { 53*d6e29083SAmirreza Zarrabi return object != NULL_QCOMTEE_OBJECT && 54*d6e29083SAmirreza Zarrabi typeof_qcomtee_object(object) == QCOMTEE_OBJECT_TYPE_CB && 55*d6e29083SAmirreza Zarrabi object->ops == &qcomtee_user_object_ops; 56*d6e29083SAmirreza Zarrabi } 57*d6e29083SAmirreza Zarrabi 58*d6e29083SAmirreza Zarrabi /* Set the user object's 'notify on release' flag. */ 59*d6e29083SAmirreza Zarrabi void qcomtee_user_object_set_notify(struct qcomtee_object *object, bool notify) 60*d6e29083SAmirreza Zarrabi { 61*d6e29083SAmirreza Zarrabi if (is_qcomtee_user_object(object)) 62*d6e29083SAmirreza Zarrabi to_qcomtee_user_object(object)->notify = notify; 63*d6e29083SAmirreza Zarrabi } 64*d6e29083SAmirreza Zarrabi 65*d6e29083SAmirreza Zarrabi /* Supplicant Requests: */ 66*d6e29083SAmirreza Zarrabi 67*d6e29083SAmirreza Zarrabi /** 68*d6e29083SAmirreza Zarrabi * enum qcomtee_req_state - Current state of request. 69*d6e29083SAmirreza Zarrabi * @QCOMTEE_REQ_QUEUED: Request is waiting for supplicant. 70*d6e29083SAmirreza Zarrabi * @QCOMTEE_REQ_PROCESSING: Request has been picked by the supplicant. 71*d6e29083SAmirreza Zarrabi * @QCOMTEE_REQ_PROCESSED: Response has been submitted for the request. 72*d6e29083SAmirreza Zarrabi */ 73*d6e29083SAmirreza Zarrabi enum qcomtee_req_state { 74*d6e29083SAmirreza Zarrabi QCOMTEE_REQ_QUEUED = 1, 75*d6e29083SAmirreza Zarrabi QCOMTEE_REQ_PROCESSING, 76*d6e29083SAmirreza Zarrabi QCOMTEE_REQ_PROCESSED, 77*d6e29083SAmirreza Zarrabi }; 78*d6e29083SAmirreza Zarrabi 79*d6e29083SAmirreza Zarrabi /* User requests sent to supplicants. */ 80*d6e29083SAmirreza Zarrabi struct qcomtee_ureq { 81*d6e29083SAmirreza Zarrabi enum qcomtee_req_state state; 82*d6e29083SAmirreza Zarrabi 83*d6e29083SAmirreza Zarrabi /* User Request: */ 84*d6e29083SAmirreza Zarrabi int req_id; 85*d6e29083SAmirreza Zarrabi u64 object_id; 86*d6e29083SAmirreza Zarrabi u32 op; 87*d6e29083SAmirreza Zarrabi struct qcomtee_arg *args; 88*d6e29083SAmirreza Zarrabi int errno; 89*d6e29083SAmirreza Zarrabi 90*d6e29083SAmirreza Zarrabi struct list_head node; 91*d6e29083SAmirreza Zarrabi struct completion c; /* Completion for whoever wait. */ 92*d6e29083SAmirreza Zarrabi }; 93*d6e29083SAmirreza Zarrabi 94*d6e29083SAmirreza Zarrabi /* 95*d6e29083SAmirreza Zarrabi * Placeholder for a PROCESSING request in qcomtee_context.reqs_idr. 96*d6e29083SAmirreza Zarrabi * 97*d6e29083SAmirreza Zarrabi * If the thread that calls qcomtee_object_invoke() dies and the supplicant 98*d6e29083SAmirreza Zarrabi * is processing the request, replace the entry in qcomtee_context.reqs_idr 99*d6e29083SAmirreza Zarrabi * with empty_ureq. This ensures that (1) the req_id remains busy and is not 100*d6e29083SAmirreza Zarrabi * reused, and (2) the supplicant fails to submit the response and performs 101*d6e29083SAmirreza Zarrabi * the necessary rollback. 102*d6e29083SAmirreza Zarrabi */ 103*d6e29083SAmirreza Zarrabi static struct qcomtee_ureq empty_ureq = { .state = QCOMTEE_REQ_PROCESSING }; 104*d6e29083SAmirreza Zarrabi 105*d6e29083SAmirreza Zarrabi /* Enqueue a user request for a context and assign a request ID. */ 106*d6e29083SAmirreza Zarrabi static int ureq_enqueue(struct qcomtee_context_data *ctxdata, 107*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *ureq) 108*d6e29083SAmirreza Zarrabi { 109*d6e29083SAmirreza Zarrabi int ret; 110*d6e29083SAmirreza Zarrabi 111*d6e29083SAmirreza Zarrabi guard(mutex)(&ctxdata->reqs_lock); 112*d6e29083SAmirreza Zarrabi /* Supplicant is dying. */ 113*d6e29083SAmirreza Zarrabi if (ctxdata->released) 114*d6e29083SAmirreza Zarrabi return -ENODEV; 115*d6e29083SAmirreza Zarrabi 116*d6e29083SAmirreza Zarrabi /* Allocate an ID and queue the request. */ 117*d6e29083SAmirreza Zarrabi ret = idr_alloc(&ctxdata->reqs_idr, ureq, 0, 0, GFP_KERNEL); 118*d6e29083SAmirreza Zarrabi if (ret < 0) 119*d6e29083SAmirreza Zarrabi return ret; 120*d6e29083SAmirreza Zarrabi 121*d6e29083SAmirreza Zarrabi ureq->req_id = ret; 122*d6e29083SAmirreza Zarrabi ureq->state = QCOMTEE_REQ_QUEUED; 123*d6e29083SAmirreza Zarrabi list_add_tail(&ureq->node, &ctxdata->reqs_list); 124*d6e29083SAmirreza Zarrabi 125*d6e29083SAmirreza Zarrabi return 0; 126*d6e29083SAmirreza Zarrabi } 127*d6e29083SAmirreza Zarrabi 128*d6e29083SAmirreza Zarrabi /** 129*d6e29083SAmirreza Zarrabi * ureq_dequeue() - Dequeue a user request from a context. 130*d6e29083SAmirreza Zarrabi * @ctxdata: context data for a context to dequeue the request. 131*d6e29083SAmirreza Zarrabi * @req_id: ID of the request to be dequeued. 132*d6e29083SAmirreza Zarrabi * 133*d6e29083SAmirreza Zarrabi * It dequeues a user request and releases its request ID. 134*d6e29083SAmirreza Zarrabi * 135*d6e29083SAmirreza Zarrabi * Context: The caller should hold &qcomtee_context_data->reqs_lock. 136*d6e29083SAmirreza Zarrabi * Return: Returns the user request associated with this ID; otherwise, NULL. 137*d6e29083SAmirreza Zarrabi */ 138*d6e29083SAmirreza Zarrabi static struct qcomtee_ureq *ureq_dequeue(struct qcomtee_context_data *ctxdata, 139*d6e29083SAmirreza Zarrabi int req_id) 140*d6e29083SAmirreza Zarrabi { 141*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *ureq; 142*d6e29083SAmirreza Zarrabi 143*d6e29083SAmirreza Zarrabi ureq = idr_remove(&ctxdata->reqs_idr, req_id); 144*d6e29083SAmirreza Zarrabi if (ureq == &empty_ureq || !ureq) 145*d6e29083SAmirreza Zarrabi return NULL; 146*d6e29083SAmirreza Zarrabi 147*d6e29083SAmirreza Zarrabi list_del(&ureq->node); 148*d6e29083SAmirreza Zarrabi 149*d6e29083SAmirreza Zarrabi return ureq; 150*d6e29083SAmirreza Zarrabi } 151*d6e29083SAmirreza Zarrabi 152*d6e29083SAmirreza Zarrabi /** 153*d6e29083SAmirreza Zarrabi * ureq_select() - Select the next request in a context. 154*d6e29083SAmirreza Zarrabi * @ctxdata: context data for a context to pop a request. 155*d6e29083SAmirreza Zarrabi * @ubuf_size: size of the available buffer for UBUF parameters. 156*d6e29083SAmirreza Zarrabi * @num_params: number of entries for the TEE parameter array. 157*d6e29083SAmirreza Zarrabi * 158*d6e29083SAmirreza Zarrabi * It checks if @num_params is large enough to fit the next request arguments. 159*d6e29083SAmirreza Zarrabi * It checks if @ubuf_size is large enough to fit IB buffer arguments. 160*d6e29083SAmirreza Zarrabi * 161*d6e29083SAmirreza Zarrabi * Context: The caller should hold &qcomtee_context_data->reqs_lock. 162*d6e29083SAmirreza Zarrabi * Return: On success, returns a request; 163*d6e29083SAmirreza Zarrabi * on failure, returns NULL and ERR_PTR. 164*d6e29083SAmirreza Zarrabi */ 165*d6e29083SAmirreza Zarrabi static struct qcomtee_ureq *ureq_select(struct qcomtee_context_data *ctxdata, 166*d6e29083SAmirreza Zarrabi size_t ubuf_size, int num_params) 167*d6e29083SAmirreza Zarrabi { 168*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *req, *ureq = NULL; 169*d6e29083SAmirreza Zarrabi struct qcomtee_arg *u; 170*d6e29083SAmirreza Zarrabi int i; 171*d6e29083SAmirreza Zarrabi 172*d6e29083SAmirreza Zarrabi /* Find the a queued request. */ 173*d6e29083SAmirreza Zarrabi list_for_each_entry(req, &ctxdata->reqs_list, node) { 174*d6e29083SAmirreza Zarrabi if (req->state == QCOMTEE_REQ_QUEUED) { 175*d6e29083SAmirreza Zarrabi ureq = req; 176*d6e29083SAmirreza Zarrabi break; 177*d6e29083SAmirreza Zarrabi } 178*d6e29083SAmirreza Zarrabi } 179*d6e29083SAmirreza Zarrabi 180*d6e29083SAmirreza Zarrabi if (!ureq) 181*d6e29083SAmirreza Zarrabi return NULL; 182*d6e29083SAmirreza Zarrabi 183*d6e29083SAmirreza Zarrabi u = ureq->args; 184*d6e29083SAmirreza Zarrabi /* (1) Is there enough TEE parameters? */ 185*d6e29083SAmirreza Zarrabi if (num_params < qcomtee_args_len(u)) 186*d6e29083SAmirreza Zarrabi return ERR_PTR(-EINVAL); 187*d6e29083SAmirreza Zarrabi /* (2) Is there enough space to pass input buffers? */ 188*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_buffer(i, u) { 189*d6e29083SAmirreza Zarrabi ubuf_size = size_sub(ubuf_size, u[i].b.size); 190*d6e29083SAmirreza Zarrabi if (ubuf_size == SIZE_MAX) 191*d6e29083SAmirreza Zarrabi return ERR_PTR(-EINVAL); 192*d6e29083SAmirreza Zarrabi 193*d6e29083SAmirreza Zarrabi ubuf_size = round_down(ubuf_size, 8); 194*d6e29083SAmirreza Zarrabi } 195*d6e29083SAmirreza Zarrabi 196*d6e29083SAmirreza Zarrabi return ureq; 197*d6e29083SAmirreza Zarrabi } 198*d6e29083SAmirreza Zarrabi 199*d6e29083SAmirreza Zarrabi /* Gets called when the user closes the device. */ 200*d6e29083SAmirreza Zarrabi void qcomtee_requests_destroy(struct qcomtee_context_data *ctxdata) 201*d6e29083SAmirreza Zarrabi { 202*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *req, *ureq; 203*d6e29083SAmirreza Zarrabi 204*d6e29083SAmirreza Zarrabi guard(mutex)(&ctxdata->reqs_lock); 205*d6e29083SAmirreza Zarrabi /* So ureq_enqueue() refuses new requests from QTEE. */ 206*d6e29083SAmirreza Zarrabi ctxdata->released = true; 207*d6e29083SAmirreza Zarrabi /* ureqs in reqs_list are in QUEUED or PROCESSING (!= empty_ureq) state. */ 208*d6e29083SAmirreza Zarrabi list_for_each_entry_safe(ureq, req, &ctxdata->reqs_list, node) { 209*d6e29083SAmirreza Zarrabi ureq_dequeue(ctxdata, ureq->req_id); 210*d6e29083SAmirreza Zarrabi 211*d6e29083SAmirreza Zarrabi if (ureq->op != QCOMTEE_MSG_OBJECT_OP_RELEASE) { 212*d6e29083SAmirreza Zarrabi ureq->state = QCOMTEE_REQ_PROCESSED; 213*d6e29083SAmirreza Zarrabi ureq->errno = -ENODEV; 214*d6e29083SAmirreza Zarrabi 215*d6e29083SAmirreza Zarrabi complete(&ureq->c); 216*d6e29083SAmirreza Zarrabi } else { 217*d6e29083SAmirreza Zarrabi kfree(ureq); 218*d6e29083SAmirreza Zarrabi } 219*d6e29083SAmirreza Zarrabi } 220*d6e29083SAmirreza Zarrabi } 221*d6e29083SAmirreza Zarrabi 222*d6e29083SAmirreza Zarrabi /* User Object API. */ 223*d6e29083SAmirreza Zarrabi 224*d6e29083SAmirreza Zarrabi /* User object dispatcher. */ 225*d6e29083SAmirreza Zarrabi static int qcomtee_user_object_dispatch(struct qcomtee_object_invoke_ctx *oic, 226*d6e29083SAmirreza Zarrabi struct qcomtee_object *object, u32 op, 227*d6e29083SAmirreza Zarrabi struct qcomtee_arg *args) 228*d6e29083SAmirreza Zarrabi { 229*d6e29083SAmirreza Zarrabi struct qcomtee_user_object *uo = to_qcomtee_user_object(object); 230*d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = uo->ctx->data; 231*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *ureq __free(kfree) = NULL; 232*d6e29083SAmirreza Zarrabi int errno; 233*d6e29083SAmirreza Zarrabi 234*d6e29083SAmirreza Zarrabi ureq = kzalloc(sizeof(*ureq), GFP_KERNEL); 235*d6e29083SAmirreza Zarrabi if (!ureq) 236*d6e29083SAmirreza Zarrabi return -ENOMEM; 237*d6e29083SAmirreza Zarrabi 238*d6e29083SAmirreza Zarrabi init_completion(&ureq->c); 239*d6e29083SAmirreza Zarrabi ureq->object_id = uo->object_id; 240*d6e29083SAmirreza Zarrabi ureq->op = op; 241*d6e29083SAmirreza Zarrabi ureq->args = args; 242*d6e29083SAmirreza Zarrabi 243*d6e29083SAmirreza Zarrabi /* Queue the request. */ 244*d6e29083SAmirreza Zarrabi if (ureq_enqueue(ctxdata, ureq)) 245*d6e29083SAmirreza Zarrabi return -ENODEV; 246*d6e29083SAmirreza Zarrabi /* Wakeup supplicant to process it. */ 247*d6e29083SAmirreza Zarrabi complete(&ctxdata->req_c); 248*d6e29083SAmirreza Zarrabi 249*d6e29083SAmirreza Zarrabi /* 250*d6e29083SAmirreza Zarrabi * Wait for the supplicant to process the request. Wait as KILLABLE 251*d6e29083SAmirreza Zarrabi * in case the supplicant and invoke thread are both running from the 252*d6e29083SAmirreza Zarrabi * same process, the supplicant crashes, or the shutdown sequence 253*d6e29083SAmirreza Zarrabi * starts with supplicant dies first; otherwise, it stuck indefinitely. 254*d6e29083SAmirreza Zarrabi * 255*d6e29083SAmirreza Zarrabi * If the supplicant processes long-running requests, also use 256*d6e29083SAmirreza Zarrabi * TASK_FREEZABLE to allow the device to safely suspend if needed. 257*d6e29083SAmirreza Zarrabi */ 258*d6e29083SAmirreza Zarrabi if (!wait_for_completion_state(&ureq->c, 259*d6e29083SAmirreza Zarrabi TASK_KILLABLE | TASK_FREEZABLE)) { 260*d6e29083SAmirreza Zarrabi errno = ureq->errno; 261*d6e29083SAmirreza Zarrabi if (!errno) 262*d6e29083SAmirreza Zarrabi oic->data = no_free_ptr(ureq); 263*d6e29083SAmirreza Zarrabi } else { 264*d6e29083SAmirreza Zarrabi enum qcomtee_req_state prev_state; 265*d6e29083SAmirreza Zarrabi 266*d6e29083SAmirreza Zarrabi errno = -ENODEV; 267*d6e29083SAmirreza Zarrabi 268*d6e29083SAmirreza Zarrabi scoped_guard(mutex, &ctxdata->reqs_lock) { 269*d6e29083SAmirreza Zarrabi prev_state = ureq->state; 270*d6e29083SAmirreza Zarrabi /* Replace with empty_ureq to keep req_id reserved. */ 271*d6e29083SAmirreza Zarrabi if (prev_state == QCOMTEE_REQ_PROCESSING) { 272*d6e29083SAmirreza Zarrabi list_del(&ureq->node); 273*d6e29083SAmirreza Zarrabi idr_replace(&ctxdata->reqs_idr, 274*d6e29083SAmirreza Zarrabi &empty_ureq, ureq->req_id); 275*d6e29083SAmirreza Zarrabi 276*d6e29083SAmirreza Zarrabi /* Remove as supplicant has never seen this request. */ 277*d6e29083SAmirreza Zarrabi } else if (prev_state == QCOMTEE_REQ_QUEUED) { 278*d6e29083SAmirreza Zarrabi ureq_dequeue(ctxdata, ureq->req_id); 279*d6e29083SAmirreza Zarrabi } 280*d6e29083SAmirreza Zarrabi } 281*d6e29083SAmirreza Zarrabi 282*d6e29083SAmirreza Zarrabi /* Supplicant did some work, do not discard it. */ 283*d6e29083SAmirreza Zarrabi if (prev_state == QCOMTEE_REQ_PROCESSED) { 284*d6e29083SAmirreza Zarrabi errno = ureq->errno; 285*d6e29083SAmirreza Zarrabi if (!errno) 286*d6e29083SAmirreza Zarrabi oic->data = no_free_ptr(ureq); 287*d6e29083SAmirreza Zarrabi } 288*d6e29083SAmirreza Zarrabi } 289*d6e29083SAmirreza Zarrabi 290*d6e29083SAmirreza Zarrabi return errno; 291*d6e29083SAmirreza Zarrabi } 292*d6e29083SAmirreza Zarrabi 293*d6e29083SAmirreza Zarrabi /* Gets called after submitting the dispatcher response. */ 294*d6e29083SAmirreza Zarrabi static void qcomtee_user_object_notify(struct qcomtee_object_invoke_ctx *oic, 295*d6e29083SAmirreza Zarrabi struct qcomtee_object *unused_object, 296*d6e29083SAmirreza Zarrabi int err) 297*d6e29083SAmirreza Zarrabi { 298*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *ureq = oic->data; 299*d6e29083SAmirreza Zarrabi struct qcomtee_arg *u = ureq->args; 300*d6e29083SAmirreza Zarrabi int i; 301*d6e29083SAmirreza Zarrabi 302*d6e29083SAmirreza Zarrabi /* 303*d6e29083SAmirreza Zarrabi * If err, there was a transport issue, and QTEE did not receive the 304*d6e29083SAmirreza Zarrabi * response for the dispatcher. Release the callback object created for 305*d6e29083SAmirreza Zarrabi * QTEE, in addition to the copies of objects kept for the drivers. 306*d6e29083SAmirreza Zarrabi */ 307*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_object(i, u) { 308*d6e29083SAmirreza Zarrabi if (err && 309*d6e29083SAmirreza Zarrabi (typeof_qcomtee_object(u[i].o) == QCOMTEE_OBJECT_TYPE_CB)) 310*d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 311*d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 312*d6e29083SAmirreza Zarrabi } 313*d6e29083SAmirreza Zarrabi 314*d6e29083SAmirreza Zarrabi kfree(ureq); 315*d6e29083SAmirreza Zarrabi } 316*d6e29083SAmirreza Zarrabi 317*d6e29083SAmirreza Zarrabi static void qcomtee_user_object_release(struct qcomtee_object *object) 318*d6e29083SAmirreza Zarrabi { 319*d6e29083SAmirreza Zarrabi struct qcomtee_user_object *uo = to_qcomtee_user_object(object); 320*d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = uo->ctx->data; 321*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *ureq; 322*d6e29083SAmirreza Zarrabi 323*d6e29083SAmirreza Zarrabi /* RELEASE does not require any argument. */ 324*d6e29083SAmirreza Zarrabi static struct qcomtee_arg args[] = { { .type = QCOMTEE_ARG_TYPE_INV } }; 325*d6e29083SAmirreza Zarrabi 326*d6e29083SAmirreza Zarrabi if (!uo->notify) 327*d6e29083SAmirreza Zarrabi goto out_no_notify; 328*d6e29083SAmirreza Zarrabi 329*d6e29083SAmirreza Zarrabi ureq = kzalloc(sizeof(*ureq), GFP_KERNEL); 330*d6e29083SAmirreza Zarrabi if (!ureq) 331*d6e29083SAmirreza Zarrabi goto out_no_notify; 332*d6e29083SAmirreza Zarrabi 333*d6e29083SAmirreza Zarrabi /* QUEUE a release request: */ 334*d6e29083SAmirreza Zarrabi ureq->object_id = uo->object_id; 335*d6e29083SAmirreza Zarrabi ureq->op = QCOMTEE_MSG_OBJECT_OP_RELEASE; 336*d6e29083SAmirreza Zarrabi ureq->args = args; 337*d6e29083SAmirreza Zarrabi if (ureq_enqueue(ctxdata, ureq)) { 338*d6e29083SAmirreza Zarrabi kfree(ureq); 339*d6e29083SAmirreza Zarrabi /* Ignore the notification if it cannot be queued. */ 340*d6e29083SAmirreza Zarrabi goto out_no_notify; 341*d6e29083SAmirreza Zarrabi } 342*d6e29083SAmirreza Zarrabi 343*d6e29083SAmirreza Zarrabi complete(&ctxdata->req_c); 344*d6e29083SAmirreza Zarrabi 345*d6e29083SAmirreza Zarrabi out_no_notify: 346*d6e29083SAmirreza Zarrabi teedev_ctx_put(uo->ctx); 347*d6e29083SAmirreza Zarrabi kfree(uo); 348*d6e29083SAmirreza Zarrabi } 349*d6e29083SAmirreza Zarrabi 350*d6e29083SAmirreza Zarrabi static struct qcomtee_object_operations qcomtee_user_object_ops = { 351*d6e29083SAmirreza Zarrabi .release = qcomtee_user_object_release, 352*d6e29083SAmirreza Zarrabi .notify = qcomtee_user_object_notify, 353*d6e29083SAmirreza Zarrabi .dispatch = qcomtee_user_object_dispatch, 354*d6e29083SAmirreza Zarrabi }; 355*d6e29083SAmirreza Zarrabi 356*d6e29083SAmirreza Zarrabi /** 357*d6e29083SAmirreza Zarrabi * qcomtee_user_param_to_object() - OBJREF parameter to &struct qcomtee_object. 358*d6e29083SAmirreza Zarrabi * @object: object returned. 359*d6e29083SAmirreza Zarrabi * @param: TEE parameter. 360*d6e29083SAmirreza Zarrabi * @ctx: context in which the conversion should happen. 361*d6e29083SAmirreza Zarrabi * 362*d6e29083SAmirreza Zarrabi * @param is an OBJREF with %QCOMTEE_OBJREF_FLAG_USER flags. 363*d6e29083SAmirreza Zarrabi * 364*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 365*d6e29083SAmirreza Zarrabi */ 366*d6e29083SAmirreza Zarrabi int qcomtee_user_param_to_object(struct qcomtee_object **object, 367*d6e29083SAmirreza Zarrabi struct tee_param *param, 368*d6e29083SAmirreza Zarrabi struct tee_context *ctx) 369*d6e29083SAmirreza Zarrabi { 370*d6e29083SAmirreza Zarrabi struct qcomtee_user_object *user_object __free(kfree) = NULL; 371*d6e29083SAmirreza Zarrabi int err; 372*d6e29083SAmirreza Zarrabi 373*d6e29083SAmirreza Zarrabi user_object = kzalloc(sizeof(*user_object), GFP_KERNEL); 374*d6e29083SAmirreza Zarrabi if (!user_object) 375*d6e29083SAmirreza Zarrabi return -ENOMEM; 376*d6e29083SAmirreza Zarrabi 377*d6e29083SAmirreza Zarrabi user_object->ctx = ctx; 378*d6e29083SAmirreza Zarrabi user_object->object_id = param->u.objref.id; 379*d6e29083SAmirreza Zarrabi /* By default, always notify userspace upon release. */ 380*d6e29083SAmirreza Zarrabi user_object->notify = true; 381*d6e29083SAmirreza Zarrabi err = qcomtee_object_user_init(&user_object->object, 382*d6e29083SAmirreza Zarrabi QCOMTEE_OBJECT_TYPE_CB, 383*d6e29083SAmirreza Zarrabi &qcomtee_user_object_ops, "uo-%llu", 384*d6e29083SAmirreza Zarrabi param->u.objref.id); 385*d6e29083SAmirreza Zarrabi if (err) 386*d6e29083SAmirreza Zarrabi return err; 387*d6e29083SAmirreza Zarrabi /* Matching teedev_ctx_put() is in qcomtee_user_object_release(). */ 388*d6e29083SAmirreza Zarrabi teedev_ctx_get(ctx); 389*d6e29083SAmirreza Zarrabi 390*d6e29083SAmirreza Zarrabi *object = &no_free_ptr(user_object)->object; 391*d6e29083SAmirreza Zarrabi 392*d6e29083SAmirreza Zarrabi return 0; 393*d6e29083SAmirreza Zarrabi } 394*d6e29083SAmirreza Zarrabi 395*d6e29083SAmirreza Zarrabi /* Reverse what qcomtee_user_param_to_object() does. */ 396*d6e29083SAmirreza Zarrabi int qcomtee_user_param_from_object(struct tee_param *param, 397*d6e29083SAmirreza Zarrabi struct qcomtee_object *object, 398*d6e29083SAmirreza Zarrabi struct tee_context *ctx) 399*d6e29083SAmirreza Zarrabi { 400*d6e29083SAmirreza Zarrabi struct qcomtee_user_object *uo; 401*d6e29083SAmirreza Zarrabi 402*d6e29083SAmirreza Zarrabi uo = to_qcomtee_user_object(object); 403*d6e29083SAmirreza Zarrabi /* Ensure the object is in the same context as the caller. */ 404*d6e29083SAmirreza Zarrabi if (uo->ctx != ctx) 405*d6e29083SAmirreza Zarrabi return -EINVAL; 406*d6e29083SAmirreza Zarrabi 407*d6e29083SAmirreza Zarrabi param->u.objref.id = uo->object_id; 408*d6e29083SAmirreza Zarrabi param->u.objref.flags = QCOMTEE_OBJREF_FLAG_USER; 409*d6e29083SAmirreza Zarrabi 410*d6e29083SAmirreza Zarrabi /* User objects are valid in userspace; do not keep a copy. */ 411*d6e29083SAmirreza Zarrabi qcomtee_object_put(object); 412*d6e29083SAmirreza Zarrabi 413*d6e29083SAmirreza Zarrabi return 0; 414*d6e29083SAmirreza Zarrabi } 415*d6e29083SAmirreza Zarrabi 416*d6e29083SAmirreza Zarrabi /** 417*d6e29083SAmirreza Zarrabi * qcomtee_cb_params_from_args() - Convert QTEE arguments to TEE parameters. 418*d6e29083SAmirreza Zarrabi * @params: TEE parameters. 419*d6e29083SAmirreza Zarrabi * @u: QTEE arguments. 420*d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 421*d6e29083SAmirreza Zarrabi * @ubuf_addr: user buffer for arguments of type %QCOMTEE_ARG_TYPE_IB. 422*d6e29083SAmirreza Zarrabi * @ubuf_size: size of the user buffer. 423*d6e29083SAmirreza Zarrabi * @ctx: context in which the conversion should happen. 424*d6e29083SAmirreza Zarrabi * 425*d6e29083SAmirreza Zarrabi * It expects @params to have enough entries for @u. Entries in @params are of 426*d6e29083SAmirreza Zarrabi * %TEE_IOCTL_PARAM_ATTR_TYPE_NONE. 427*d6e29083SAmirreza Zarrabi * 428*d6e29083SAmirreza Zarrabi * Return: On success, returns the number of input parameters; 429*d6e29083SAmirreza Zarrabi * on failure, returns < 0. 430*d6e29083SAmirreza Zarrabi */ 431*d6e29083SAmirreza Zarrabi static int qcomtee_cb_params_from_args(struct tee_param *params, 432*d6e29083SAmirreza Zarrabi struct qcomtee_arg *u, int num_params, 433*d6e29083SAmirreza Zarrabi void __user *ubuf_addr, size_t ubuf_size, 434*d6e29083SAmirreza Zarrabi struct tee_context *ctx) 435*d6e29083SAmirreza Zarrabi { 436*d6e29083SAmirreza Zarrabi int i, np; 437*d6e29083SAmirreza Zarrabi void __user *uaddr; 438*d6e29083SAmirreza Zarrabi 439*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each(i, u) { 440*d6e29083SAmirreza Zarrabi switch (u[i].type) { 441*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_IB: 442*d6e29083SAmirreza Zarrabi params[i].attr = TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT; 443*d6e29083SAmirreza Zarrabi 444*d6e29083SAmirreza Zarrabi /* Underflow already checked in ureq_select(). */ 445*d6e29083SAmirreza Zarrabi ubuf_size = round_down(ubuf_size - u[i].b.size, 8); 446*d6e29083SAmirreza Zarrabi uaddr = (void __user *)(ubuf_addr + ubuf_size); 447*d6e29083SAmirreza Zarrabi 448*d6e29083SAmirreza Zarrabi params[i].u.ubuf.uaddr = uaddr; 449*d6e29083SAmirreza Zarrabi params[i].u.ubuf.size = u[i].b.size; 450*d6e29083SAmirreza Zarrabi if (copy_to_user(params[i].u.ubuf.uaddr, u[i].b.addr, 451*d6e29083SAmirreza Zarrabi u[i].b.size)) 452*d6e29083SAmirreza Zarrabi goto out_failed; 453*d6e29083SAmirreza Zarrabi 454*d6e29083SAmirreza Zarrabi break; 455*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_OB: 456*d6e29083SAmirreza Zarrabi params[i].attr = TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT; 457*d6e29083SAmirreza Zarrabi /* Let the user knows the maximum size QTEE expects. */ 458*d6e29083SAmirreza Zarrabi params[i].u.ubuf.size = u[i].b.size; 459*d6e29083SAmirreza Zarrabi 460*d6e29083SAmirreza Zarrabi break; 461*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_IO: 462*d6e29083SAmirreza Zarrabi params[i].attr = TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT; 463*d6e29083SAmirreza Zarrabi if (qcomtee_objref_from_arg(¶ms[i], &u[i], ctx)) 464*d6e29083SAmirreza Zarrabi goto out_failed; 465*d6e29083SAmirreza Zarrabi 466*d6e29083SAmirreza Zarrabi break; 467*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_OO: 468*d6e29083SAmirreza Zarrabi params[i].attr = 469*d6e29083SAmirreza Zarrabi TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT; 470*d6e29083SAmirreza Zarrabi 471*d6e29083SAmirreza Zarrabi break; 472*d6e29083SAmirreza Zarrabi default: /* Never get here! */ 473*d6e29083SAmirreza Zarrabi goto out_failed; 474*d6e29083SAmirreza Zarrabi } 475*d6e29083SAmirreza Zarrabi } 476*d6e29083SAmirreza Zarrabi 477*d6e29083SAmirreza Zarrabi return i; 478*d6e29083SAmirreza Zarrabi 479*d6e29083SAmirreza Zarrabi out_failed: 480*d6e29083SAmirreza Zarrabi /* Undo qcomtee_objref_from_arg(). */ 481*d6e29083SAmirreza Zarrabi for (np = i; np >= 0; np--) { 482*d6e29083SAmirreza Zarrabi if (params[np].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT) 483*d6e29083SAmirreza Zarrabi qcomtee_context_del_qtee_object(¶ms[np], ctx); 484*d6e29083SAmirreza Zarrabi } 485*d6e29083SAmirreza Zarrabi 486*d6e29083SAmirreza Zarrabi /* Release any IO objects not processed. */ 487*d6e29083SAmirreza Zarrabi for (; u[i].type; i++) { 488*d6e29083SAmirreza Zarrabi if (u[i].type == QCOMTEE_ARG_TYPE_IO) 489*d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 490*d6e29083SAmirreza Zarrabi } 491*d6e29083SAmirreza Zarrabi 492*d6e29083SAmirreza Zarrabi return -EINVAL; 493*d6e29083SAmirreza Zarrabi } 494*d6e29083SAmirreza Zarrabi 495*d6e29083SAmirreza Zarrabi /** 496*d6e29083SAmirreza Zarrabi * qcomtee_cb_params_to_args() - Convert TEE parameters to QTEE arguments. 497*d6e29083SAmirreza Zarrabi * @u: QTEE arguments. 498*d6e29083SAmirreza Zarrabi * @params: TEE parameters. 499*d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 500*d6e29083SAmirreza Zarrabi * @ctx: context in which the conversion should happen. 501*d6e29083SAmirreza Zarrabi * 502*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 503*d6e29083SAmirreza Zarrabi */ 504*d6e29083SAmirreza Zarrabi static int qcomtee_cb_params_to_args(struct qcomtee_arg *u, 505*d6e29083SAmirreza Zarrabi struct tee_param *params, int num_params, 506*d6e29083SAmirreza Zarrabi struct tee_context *ctx) 507*d6e29083SAmirreza Zarrabi { 508*d6e29083SAmirreza Zarrabi int i; 509*d6e29083SAmirreza Zarrabi 510*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each(i, u) { 511*d6e29083SAmirreza Zarrabi switch (u[i].type) { 512*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_IB: 513*d6e29083SAmirreza Zarrabi if (params[i].attr != 514*d6e29083SAmirreza Zarrabi TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT) 515*d6e29083SAmirreza Zarrabi goto out_failed; 516*d6e29083SAmirreza Zarrabi 517*d6e29083SAmirreza Zarrabi break; 518*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_OB: 519*d6e29083SAmirreza Zarrabi if (params[i].attr != 520*d6e29083SAmirreza Zarrabi TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT) 521*d6e29083SAmirreza Zarrabi goto out_failed; 522*d6e29083SAmirreza Zarrabi 523*d6e29083SAmirreza Zarrabi /* Client can not send more data than requested. */ 524*d6e29083SAmirreza Zarrabi if (params[i].u.ubuf.size > u[i].b.size) 525*d6e29083SAmirreza Zarrabi goto out_failed; 526*d6e29083SAmirreza Zarrabi 527*d6e29083SAmirreza Zarrabi if (copy_from_user(u[i].b.addr, params[i].u.ubuf.uaddr, 528*d6e29083SAmirreza Zarrabi params[i].u.ubuf.size)) 529*d6e29083SAmirreza Zarrabi goto out_failed; 530*d6e29083SAmirreza Zarrabi 531*d6e29083SAmirreza Zarrabi u[i].b.size = params[i].u.ubuf.size; 532*d6e29083SAmirreza Zarrabi 533*d6e29083SAmirreza Zarrabi break; 534*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_IO: 535*d6e29083SAmirreza Zarrabi if (params[i].attr != 536*d6e29083SAmirreza Zarrabi TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT) 537*d6e29083SAmirreza Zarrabi goto out_failed; 538*d6e29083SAmirreza Zarrabi 539*d6e29083SAmirreza Zarrabi break; 540*d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_OO: 541*d6e29083SAmirreza Zarrabi if (params[i].attr != 542*d6e29083SAmirreza Zarrabi TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT) 543*d6e29083SAmirreza Zarrabi goto out_failed; 544*d6e29083SAmirreza Zarrabi 545*d6e29083SAmirreza Zarrabi if (qcomtee_objref_to_arg(&u[i], ¶ms[i], ctx)) 546*d6e29083SAmirreza Zarrabi goto out_failed; 547*d6e29083SAmirreza Zarrabi 548*d6e29083SAmirreza Zarrabi break; 549*d6e29083SAmirreza Zarrabi default: /* Never get here! */ 550*d6e29083SAmirreza Zarrabi goto out_failed; 551*d6e29083SAmirreza Zarrabi } 552*d6e29083SAmirreza Zarrabi } 553*d6e29083SAmirreza Zarrabi 554*d6e29083SAmirreza Zarrabi return 0; 555*d6e29083SAmirreza Zarrabi 556*d6e29083SAmirreza Zarrabi out_failed: 557*d6e29083SAmirreza Zarrabi /* Undo qcomtee_objref_to_arg(). */ 558*d6e29083SAmirreza Zarrabi for (i--; i >= 0; i--) { 559*d6e29083SAmirreza Zarrabi if (u[i].type != QCOMTEE_ARG_TYPE_OO) 560*d6e29083SAmirreza Zarrabi continue; 561*d6e29083SAmirreza Zarrabi 562*d6e29083SAmirreza Zarrabi qcomtee_user_object_set_notify(u[i].o, false); 563*d6e29083SAmirreza Zarrabi if (typeof_qcomtee_object(u[i].o) == QCOMTEE_OBJECT_TYPE_CB) 564*d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 565*d6e29083SAmirreza Zarrabi 566*d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 567*d6e29083SAmirreza Zarrabi } 568*d6e29083SAmirreza Zarrabi 569*d6e29083SAmirreza Zarrabi return -EINVAL; 570*d6e29083SAmirreza Zarrabi } 571*d6e29083SAmirreza Zarrabi 572*d6e29083SAmirreza Zarrabi /** 573*d6e29083SAmirreza Zarrabi * qcomtee_user_object_select() - Select a request for a user object. 574*d6e29083SAmirreza Zarrabi * @ctx: context to look for a user object. 575*d6e29083SAmirreza Zarrabi * @params: parameters for @op. 576*d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 577*d6e29083SAmirreza Zarrabi * @uaddr: user buffer for output UBUF parameters. 578*d6e29083SAmirreza Zarrabi * @size: size of user buffer @uaddr. 579*d6e29083SAmirreza Zarrabi * @data: information for the selected request. 580*d6e29083SAmirreza Zarrabi * 581*d6e29083SAmirreza Zarrabi * @params is filled along with @data for the selected request. 582*d6e29083SAmirreza Zarrabi * 583*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 584*d6e29083SAmirreza Zarrabi */ 585*d6e29083SAmirreza Zarrabi int qcomtee_user_object_select(struct tee_context *ctx, 586*d6e29083SAmirreza Zarrabi struct tee_param *params, int num_params, 587*d6e29083SAmirreza Zarrabi void __user *uaddr, size_t size, 588*d6e29083SAmirreza Zarrabi struct qcomtee_user_object_request_data *data) 589*d6e29083SAmirreza Zarrabi { 590*d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 591*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *ureq; 592*d6e29083SAmirreza Zarrabi int ret; 593*d6e29083SAmirreza Zarrabi 594*d6e29083SAmirreza Zarrabi /* 595*d6e29083SAmirreza Zarrabi * Hold the reqs_lock not only for ureq_select() and updating the ureq 596*d6e29083SAmirreza Zarrabi * state to PROCESSING but for the entire duration of ureq access. 597*d6e29083SAmirreza Zarrabi * This prevents qcomtee_user_object_dispatch() from freeing 598*d6e29083SAmirreza Zarrabi * ureq while it is still in use, if client dies. 599*d6e29083SAmirreza Zarrabi */ 600*d6e29083SAmirreza Zarrabi 601*d6e29083SAmirreza Zarrabi while (1) { 602*d6e29083SAmirreza Zarrabi scoped_guard(mutex, &ctxdata->reqs_lock) { 603*d6e29083SAmirreza Zarrabi ureq = ureq_select(ctxdata, size, num_params); 604*d6e29083SAmirreza Zarrabi if (!ureq) 605*d6e29083SAmirreza Zarrabi goto wait_for_request; 606*d6e29083SAmirreza Zarrabi 607*d6e29083SAmirreza Zarrabi if (IS_ERR(ureq)) 608*d6e29083SAmirreza Zarrabi return PTR_ERR(ureq); 609*d6e29083SAmirreza Zarrabi 610*d6e29083SAmirreza Zarrabi /* Processing the request 'QUEUED -> PROCESSING'. */ 611*d6e29083SAmirreza Zarrabi ureq->state = QCOMTEE_REQ_PROCESSING; 612*d6e29083SAmirreza Zarrabi /* ''Prepare user request:'' */ 613*d6e29083SAmirreza Zarrabi data->id = ureq->req_id; 614*d6e29083SAmirreza Zarrabi data->object_id = ureq->object_id; 615*d6e29083SAmirreza Zarrabi data->op = ureq->op; 616*d6e29083SAmirreza Zarrabi ret = qcomtee_cb_params_from_args(params, ureq->args, 617*d6e29083SAmirreza Zarrabi num_params, uaddr, 618*d6e29083SAmirreza Zarrabi size, ctx); 619*d6e29083SAmirreza Zarrabi if (ret >= 0) 620*d6e29083SAmirreza Zarrabi goto done_request; 621*d6e29083SAmirreza Zarrabi 622*d6e29083SAmirreza Zarrabi /* Something is wrong with the request: */ 623*d6e29083SAmirreza Zarrabi ureq_dequeue(ctxdata, data->id); 624*d6e29083SAmirreza Zarrabi /* Send error to QTEE. */ 625*d6e29083SAmirreza Zarrabi ureq->state = QCOMTEE_REQ_PROCESSED; 626*d6e29083SAmirreza Zarrabi ureq->errno = ret; 627*d6e29083SAmirreza Zarrabi 628*d6e29083SAmirreza Zarrabi complete(&ureq->c); 629*d6e29083SAmirreza Zarrabi } 630*d6e29083SAmirreza Zarrabi 631*d6e29083SAmirreza Zarrabi continue; 632*d6e29083SAmirreza Zarrabi wait_for_request: 633*d6e29083SAmirreza Zarrabi /* Wait for a new QUEUED request. */ 634*d6e29083SAmirreza Zarrabi if (wait_for_completion_interruptible(&ctxdata->req_c)) 635*d6e29083SAmirreza Zarrabi return -ERESTARTSYS; 636*d6e29083SAmirreza Zarrabi } 637*d6e29083SAmirreza Zarrabi 638*d6e29083SAmirreza Zarrabi done_request: 639*d6e29083SAmirreza Zarrabi /* No one is waiting for the response. */ 640*d6e29083SAmirreza Zarrabi if (data->op == QCOMTEE_MSG_OBJECT_OP_RELEASE) { 641*d6e29083SAmirreza Zarrabi scoped_guard(mutex, &ctxdata->reqs_lock) 642*d6e29083SAmirreza Zarrabi ureq_dequeue(ctxdata, data->id); 643*d6e29083SAmirreza Zarrabi kfree(ureq); 644*d6e29083SAmirreza Zarrabi } 645*d6e29083SAmirreza Zarrabi 646*d6e29083SAmirreza Zarrabi data->np = ret; 647*d6e29083SAmirreza Zarrabi 648*d6e29083SAmirreza Zarrabi return 0; 649*d6e29083SAmirreza Zarrabi } 650*d6e29083SAmirreza Zarrabi 651*d6e29083SAmirreza Zarrabi /** 652*d6e29083SAmirreza Zarrabi * qcomtee_user_object_submit() - Submit a response for a user object. 653*d6e29083SAmirreza Zarrabi * @ctx: context to look for a user object. 654*d6e29083SAmirreza Zarrabi * @params: returned parameters. 655*d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 656*d6e29083SAmirreza Zarrabi * @req_id: request ID for the response. 657*d6e29083SAmirreza Zarrabi * @errno: result of user object invocation. 658*d6e29083SAmirreza Zarrabi * 659*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 660*d6e29083SAmirreza Zarrabi */ 661*d6e29083SAmirreza Zarrabi int qcomtee_user_object_submit(struct tee_context *ctx, 662*d6e29083SAmirreza Zarrabi struct tee_param *params, int num_params, 663*d6e29083SAmirreza Zarrabi int req_id, int errno) 664*d6e29083SAmirreza Zarrabi { 665*d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 666*d6e29083SAmirreza Zarrabi struct qcomtee_ureq *ureq; 667*d6e29083SAmirreza Zarrabi 668*d6e29083SAmirreza Zarrabi /* See comments for reqs_lock in qcomtee_user_object_select(). */ 669*d6e29083SAmirreza Zarrabi guard(mutex)(&ctxdata->reqs_lock); 670*d6e29083SAmirreza Zarrabi 671*d6e29083SAmirreza Zarrabi ureq = ureq_dequeue(ctxdata, req_id); 672*d6e29083SAmirreza Zarrabi if (!ureq) 673*d6e29083SAmirreza Zarrabi return -EINVAL; 674*d6e29083SAmirreza Zarrabi 675*d6e29083SAmirreza Zarrabi ureq->state = QCOMTEE_REQ_PROCESSED; 676*d6e29083SAmirreza Zarrabi 677*d6e29083SAmirreza Zarrabi if (!errno) 678*d6e29083SAmirreza Zarrabi ureq->errno = qcomtee_cb_params_to_args(ureq->args, params, 679*d6e29083SAmirreza Zarrabi num_params, ctx); 680*d6e29083SAmirreza Zarrabi else 681*d6e29083SAmirreza Zarrabi ureq->errno = errno; 682*d6e29083SAmirreza Zarrabi /* Return errno if qcomtee_cb_params_to_args() failed; otherwise 0. */ 683*d6e29083SAmirreza Zarrabi if (!errno && ureq->errno) 684*d6e29083SAmirreza Zarrabi errno = ureq->errno; 685*d6e29083SAmirreza Zarrabi else 686*d6e29083SAmirreza Zarrabi errno = 0; 687*d6e29083SAmirreza Zarrabi 688*d6e29083SAmirreza Zarrabi /* Send result to QTEE. */ 689*d6e29083SAmirreza Zarrabi complete(&ureq->c); 690*d6e29083SAmirreza Zarrabi 691*d6e29083SAmirreza Zarrabi return errno; 692*d6e29083SAmirreza Zarrabi } 693