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 "qcomtee.h" 9*d6e29083SAmirreza Zarrabi 10*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_1_0 0x00010000U /* Maj: 0x0001, Min: 0x0000. */ 11*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_1_1 0x00010001U /* Maj: 0x0001, Min: 0x0001. */ 12*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_1_2 0x00010002U /* Maj: 0x0001, Min: 0x0002. */ 13*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_CURRENT QCOMTEE_ASYNC_VERSION_1_2 14*d6e29083SAmirreza Zarrabi 15*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_MAJOR(n) upper_16_bits(n) 16*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_MINOR(n) lower_16_bits(n) 17*d6e29083SAmirreza Zarrabi 18*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR \ 19*d6e29083SAmirreza Zarrabi QCOMTEE_ASYNC_VERSION_MAJOR(QCOMTEE_ASYNC_VERSION_CURRENT) 20*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_VERSION_CURRENT_MINOR \ 21*d6e29083SAmirreza Zarrabi QCOMTEE_ASYNC_VERSION_MINOR(QCOMTEE_ASYNC_VERSION_CURRENT) 22*d6e29083SAmirreza Zarrabi 23*d6e29083SAmirreza Zarrabi /** 24*d6e29083SAmirreza Zarrabi * struct qcomtee_async_msg_hdr - Asynchronous message header format. 25*d6e29083SAmirreza Zarrabi * @version: current async protocol version of the remote endpoint. 26*d6e29083SAmirreza Zarrabi * @op: async operation. 27*d6e29083SAmirreza Zarrabi * 28*d6e29083SAmirreza Zarrabi * @version specifies the endpoint's (QTEE or driver) supported async protocol. 29*d6e29083SAmirreza Zarrabi * For example, if QTEE sets @version to %QCOMTEE_ASYNC_VERSION_1_1, QTEE 30*d6e29083SAmirreza Zarrabi * handles operations supported in %QCOMTEE_ASYNC_VERSION_1_1 or 31*d6e29083SAmirreza Zarrabi * %QCOMTEE_ASYNC_VERSION_1_0. @op determines the message format. 32*d6e29083SAmirreza Zarrabi */ 33*d6e29083SAmirreza Zarrabi struct qcomtee_async_msg_hdr { 34*d6e29083SAmirreza Zarrabi u32 version; 35*d6e29083SAmirreza Zarrabi u32 op; 36*d6e29083SAmirreza Zarrabi }; 37*d6e29083SAmirreza Zarrabi 38*d6e29083SAmirreza Zarrabi /* Size of an empty async message. */ 39*d6e29083SAmirreza Zarrabi #define QCOMTEE_ASYNC_MSG_ZERO sizeof(struct qcomtee_async_msg_hdr) 40*d6e29083SAmirreza Zarrabi 41*d6e29083SAmirreza Zarrabi /** 42*d6e29083SAmirreza Zarrabi * struct qcomtee_async_release_msg - Release asynchronous message. 43*d6e29083SAmirreza Zarrabi * @hdr: message header as &struct qcomtee_async_msg_hdr. 44*d6e29083SAmirreza Zarrabi * @counts: number of objects in @object_ids. 45*d6e29083SAmirreza Zarrabi * @object_ids: array of object IDs that should be released. 46*d6e29083SAmirreza Zarrabi * 47*d6e29083SAmirreza Zarrabi * Available in Maj = 0x0001, Min >= 0x0000. 48*d6e29083SAmirreza Zarrabi */ 49*d6e29083SAmirreza Zarrabi struct qcomtee_async_release_msg { 50*d6e29083SAmirreza Zarrabi struct qcomtee_async_msg_hdr hdr; 51*d6e29083SAmirreza Zarrabi u32 counts; 52*d6e29083SAmirreza Zarrabi u32 object_ids[] __counted_by(counts); 53*d6e29083SAmirreza Zarrabi }; 54*d6e29083SAmirreza Zarrabi 55*d6e29083SAmirreza Zarrabi /** 56*d6e29083SAmirreza Zarrabi * qcomtee_get_async_buffer() - Get the start of the asynchronous message. 57*d6e29083SAmirreza Zarrabi * @oic: context used for the current invocation. 58*d6e29083SAmirreza Zarrabi * @async_buffer: return buffer to extract from or fill in async messages. 59*d6e29083SAmirreza Zarrabi * 60*d6e29083SAmirreza Zarrabi * If @oic is used for direct object invocation, the whole outbound buffer 61*d6e29083SAmirreza Zarrabi * is available for the async message. If @oic is used for a callback request, 62*d6e29083SAmirreza Zarrabi * the tail of the outbound buffer (after the callback request message) is 63*d6e29083SAmirreza Zarrabi * available for the async message. 64*d6e29083SAmirreza Zarrabi * 65*d6e29083SAmirreza Zarrabi * The start of the async buffer is aligned, see qcomtee_msg_offset_align(). 66*d6e29083SAmirreza Zarrabi */ 67*d6e29083SAmirreza Zarrabi static void qcomtee_get_async_buffer(struct qcomtee_object_invoke_ctx *oic, 68*d6e29083SAmirreza Zarrabi struct qcomtee_buffer *async_buffer) 69*d6e29083SAmirreza Zarrabi { 70*d6e29083SAmirreza Zarrabi struct qcomtee_msg_callback *msg; 71*d6e29083SAmirreza Zarrabi unsigned int offset; 72*d6e29083SAmirreza Zarrabi int i; 73*d6e29083SAmirreza Zarrabi 74*d6e29083SAmirreza Zarrabi if (!(oic->flags & QCOMTEE_OIC_FLAG_BUSY)) { 75*d6e29083SAmirreza Zarrabi /* The outbound buffer is empty. Using the whole buffer. */ 76*d6e29083SAmirreza Zarrabi offset = 0; 77*d6e29083SAmirreza Zarrabi } else { 78*d6e29083SAmirreza Zarrabi msg = (struct qcomtee_msg_callback *)oic->out_msg.addr; 79*d6e29083SAmirreza Zarrabi 80*d6e29083SAmirreza Zarrabi /* Start offset in a message for buffer arguments. */ 81*d6e29083SAmirreza Zarrabi offset = qcomtee_msg_buffer_args(struct qcomtee_msg_callback, 82*d6e29083SAmirreza Zarrabi qcomtee_msg_args(msg)); 83*d6e29083SAmirreza Zarrabi 84*d6e29083SAmirreza Zarrabi /* Add size of IB arguments. */ 85*d6e29083SAmirreza Zarrabi qcomtee_msg_for_each_input_buffer(i, msg) 86*d6e29083SAmirreza Zarrabi offset += qcomtee_msg_offset_align(msg->args[i].b.size); 87*d6e29083SAmirreza Zarrabi 88*d6e29083SAmirreza Zarrabi /* Add size of OB arguments. */ 89*d6e29083SAmirreza Zarrabi qcomtee_msg_for_each_output_buffer(i, msg) 90*d6e29083SAmirreza Zarrabi offset += qcomtee_msg_offset_align(msg->args[i].b.size); 91*d6e29083SAmirreza Zarrabi } 92*d6e29083SAmirreza Zarrabi 93*d6e29083SAmirreza Zarrabi async_buffer->addr = oic->out_msg.addr + offset; 94*d6e29083SAmirreza Zarrabi async_buffer->size = oic->out_msg.size - offset; 95*d6e29083SAmirreza Zarrabi } 96*d6e29083SAmirreza Zarrabi 97*d6e29083SAmirreza Zarrabi /** 98*d6e29083SAmirreza Zarrabi * async_release() - Process QTEE async release requests. 99*d6e29083SAmirreza Zarrabi * @oic: context used for the current invocation. 100*d6e29083SAmirreza Zarrabi * @msg: async message for object release. 101*d6e29083SAmirreza Zarrabi * @size: size of the async buffer available. 102*d6e29083SAmirreza Zarrabi * 103*d6e29083SAmirreza Zarrabi * Return: Size of the outbound buffer used when processing @msg. 104*d6e29083SAmirreza Zarrabi */ 105*d6e29083SAmirreza Zarrabi static size_t async_release(struct qcomtee_object_invoke_ctx *oic, 106*d6e29083SAmirreza Zarrabi struct qcomtee_async_msg_hdr *async_msg, 107*d6e29083SAmirreza Zarrabi size_t size) 108*d6e29083SAmirreza Zarrabi { 109*d6e29083SAmirreza Zarrabi struct qcomtee_async_release_msg *msg; 110*d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 111*d6e29083SAmirreza Zarrabi int i; 112*d6e29083SAmirreza Zarrabi 113*d6e29083SAmirreza Zarrabi msg = (struct qcomtee_async_release_msg *)async_msg; 114*d6e29083SAmirreza Zarrabi 115*d6e29083SAmirreza Zarrabi for (i = 0; i < msg->counts; i++) { 116*d6e29083SAmirreza Zarrabi object = qcomtee_idx_erase(oic, msg->object_ids[i]); 117*d6e29083SAmirreza Zarrabi qcomtee_object_put(object); 118*d6e29083SAmirreza Zarrabi } 119*d6e29083SAmirreza Zarrabi 120*d6e29083SAmirreza Zarrabi return struct_size(msg, object_ids, msg->counts); 121*d6e29083SAmirreza Zarrabi } 122*d6e29083SAmirreza Zarrabi 123*d6e29083SAmirreza Zarrabi /** 124*d6e29083SAmirreza Zarrabi * qcomtee_fetch_async_reqs() - Fetch and process asynchronous messages. 125*d6e29083SAmirreza Zarrabi * @oic: context used for the current invocation. 126*d6e29083SAmirreza Zarrabi * 127*d6e29083SAmirreza Zarrabi * Calls handlers to process the requested operations in the async message. 128*d6e29083SAmirreza Zarrabi * Currently, only supports async release requests. 129*d6e29083SAmirreza Zarrabi */ 130*d6e29083SAmirreza Zarrabi void qcomtee_fetch_async_reqs(struct qcomtee_object_invoke_ctx *oic) 131*d6e29083SAmirreza Zarrabi { 132*d6e29083SAmirreza Zarrabi struct qcomtee_async_msg_hdr *async_msg; 133*d6e29083SAmirreza Zarrabi struct qcomtee_buffer async_buffer; 134*d6e29083SAmirreza Zarrabi size_t consumed, used = 0; 135*d6e29083SAmirreza Zarrabi u16 major_ver; 136*d6e29083SAmirreza Zarrabi 137*d6e29083SAmirreza Zarrabi qcomtee_get_async_buffer(oic, &async_buffer); 138*d6e29083SAmirreza Zarrabi 139*d6e29083SAmirreza Zarrabi while (async_buffer.size - used > QCOMTEE_ASYNC_MSG_ZERO) { 140*d6e29083SAmirreza Zarrabi async_msg = (struct qcomtee_async_msg_hdr *)(async_buffer.addr + 141*d6e29083SAmirreza Zarrabi used); 142*d6e29083SAmirreza Zarrabi /* 143*d6e29083SAmirreza Zarrabi * QTEE assumes that the unused space of the async buffer is 144*d6e29083SAmirreza Zarrabi * zeroed; so if version is zero, the buffer is unused. 145*d6e29083SAmirreza Zarrabi */ 146*d6e29083SAmirreza Zarrabi if (async_msg->version == 0) 147*d6e29083SAmirreza Zarrabi goto out; 148*d6e29083SAmirreza Zarrabi 149*d6e29083SAmirreza Zarrabi major_ver = QCOMTEE_ASYNC_VERSION_MAJOR(async_msg->version); 150*d6e29083SAmirreza Zarrabi /* Major version mismatch is a compatibility break. */ 151*d6e29083SAmirreza Zarrabi if (major_ver != QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR) { 152*d6e29083SAmirreza Zarrabi pr_err("Async message version mismatch (%u != %u)\n", 153*d6e29083SAmirreza Zarrabi major_ver, QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR); 154*d6e29083SAmirreza Zarrabi 155*d6e29083SAmirreza Zarrabi goto out; 156*d6e29083SAmirreza Zarrabi } 157*d6e29083SAmirreza Zarrabi 158*d6e29083SAmirreza Zarrabi switch (async_msg->op) { 159*d6e29083SAmirreza Zarrabi case QCOMTEE_MSG_OBJECT_OP_RELEASE: 160*d6e29083SAmirreza Zarrabi consumed = async_release(oic, async_msg, 161*d6e29083SAmirreza Zarrabi async_buffer.size - used); 162*d6e29083SAmirreza Zarrabi break; 163*d6e29083SAmirreza Zarrabi default: 164*d6e29083SAmirreza Zarrabi pr_err("Unsupported async message %u\n", async_msg->op); 165*d6e29083SAmirreza Zarrabi goto out; 166*d6e29083SAmirreza Zarrabi } 167*d6e29083SAmirreza Zarrabi 168*d6e29083SAmirreza Zarrabi /* Supported operation but unable to parse the message. */ 169*d6e29083SAmirreza Zarrabi if (!consumed) { 170*d6e29083SAmirreza Zarrabi pr_err("Unable to parse async message for op %u\n", 171*d6e29083SAmirreza Zarrabi async_msg->op); 172*d6e29083SAmirreza Zarrabi goto out; 173*d6e29083SAmirreza Zarrabi } 174*d6e29083SAmirreza Zarrabi 175*d6e29083SAmirreza Zarrabi /* Next async message. */ 176*d6e29083SAmirreza Zarrabi used += qcomtee_msg_offset_align(consumed); 177*d6e29083SAmirreza Zarrabi } 178*d6e29083SAmirreza Zarrabi 179*d6e29083SAmirreza Zarrabi out: 180*d6e29083SAmirreza Zarrabi /* Reset the async buffer so async requests do not loop to QTEE. */ 181*d6e29083SAmirreza Zarrabi memzero_explicit(async_buffer.addr, async_buffer.size); 182*d6e29083SAmirreza Zarrabi } 183