|
22 | 22 | #include <linux/firmware/qcom/qcom_scm.h> |
23 | 23 | #include <uapi/misc/fastrpc.h> |
24 | 24 | #include <linux/of_reserved_mem.h> |
| 25 | +#include <linux/compiler.h> |
| 26 | +#include <linux/iopoll.h> |
25 | 27 |
|
26 | 28 | #define ADSP_DOMAIN_ID (0) |
27 | 29 | #define MDSP_DOMAIN_ID (1) |
|
37 | 39 | #define FASTRPC_CTX_MAX (256) |
38 | 40 | #define FASTRPC_INIT_HANDLE 1 |
39 | 41 | #define FASTRPC_DSP_UTILITIES_HANDLE 2 |
| 42 | +#define FASTRPC_MAX_STATIC_HANDLE (20) |
40 | 43 | #define FASTRPC_CTXID_MASK (0xFF00) |
41 | 44 | #define INIT_FILELEN_MAX (2 * 1024 * 1024) |
42 | 45 | #define INIT_FILE_NAMELEN_MAX (128) |
|
105 | 108 |
|
106 | 109 | #define miscdev_to_fdevice(d) container_of(d, struct fastrpc_device, miscdev) |
107 | 110 |
|
| 111 | +/* Poll response number from remote processor for call completion */ |
| 112 | +#define FASTRPC_POLL_RESPONSE (0xdecaf) |
| 113 | + |
| 114 | +/* Polling mode timeout limit */ |
| 115 | +#define FASTRPC_POLL_MAX_TIMEOUT_US (10000) |
| 116 | + |
| 117 | +/* Response types supported for RPC calls */ |
| 118 | +enum fastrpc_response_flags { |
| 119 | + /* normal job completion glink response */ |
| 120 | + NORMAL_RESPONSE = 0, |
| 121 | + /* process updates poll memory instead of glink response */ |
| 122 | + POLL_MODE = 1, |
| 123 | +}; |
| 124 | + |
108 | 125 | struct fastrpc_phy_page { |
109 | 126 | u64 addr; /* physical address */ |
110 | 127 | u64 size; /* size of contiguous region */ |
@@ -235,8 +252,14 @@ struct fastrpc_invoke_ctx { |
235 | 252 | u32 sc; |
236 | 253 | u64 *fdlist; |
237 | 254 | u32 *crc; |
| 255 | + /* Poll memory that DSP updates */ |
| 256 | + u32 *poll; |
238 | 257 | u64 ctxid; |
239 | 258 | u64 msg_sz; |
| 259 | + /* work done status flag */ |
| 260 | + bool is_work_done; |
| 261 | + /* response flags from remote processor */ |
| 262 | + enum fastrpc_response_flags rsp_flags; |
240 | 263 | struct kref refcount; |
241 | 264 | struct list_head node; /* list of ctxs */ |
242 | 265 | struct completion work; |
@@ -891,7 +914,8 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) |
891 | 914 | sizeof(struct fastrpc_invoke_buf) + |
892 | 915 | sizeof(struct fastrpc_phy_page)) * ctx->nscalars + |
893 | 916 | sizeof(u64) * FASTRPC_MAX_FDLIST + |
894 | | - sizeof(u32) * FASTRPC_MAX_CRCLIST; |
| 917 | + sizeof(u32) * FASTRPC_MAX_CRCLIST + |
| 918 | + sizeof(u32); |
895 | 919 |
|
896 | 920 | return size; |
897 | 921 | } |
@@ -987,6 +1011,8 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) |
987 | 1011 | list = fastrpc_invoke_buf_start(rpra, ctx->nscalars); |
988 | 1012 | pages = fastrpc_phy_page_start(list, ctx->nscalars); |
989 | 1013 | ctx->fdlist = (u64 *)(pages + ctx->nscalars); |
| 1014 | + ctx->crc = (u32 *)(ctx->fdlist + FASTRPC_MAX_FDLIST); |
| 1015 | + ctx->poll = (u32 *)(ctx->crc + FASTRPC_MAX_CRCLIST); |
990 | 1016 | args = (uintptr_t)ctx->buf->virt + metalen; |
991 | 1017 | rlen = pkt_size - metalen; |
992 | 1018 | ctx->rpra = rpra; |
@@ -1155,6 +1181,83 @@ static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx, |
1155 | 1181 |
|
1156 | 1182 | } |
1157 | 1183 |
|
| 1184 | +static inline u32 fastrpc_poll_op(void *p) |
| 1185 | +{ |
| 1186 | + struct fastrpc_invoke_ctx *ctx = p; |
| 1187 | + |
| 1188 | + dma_rmb(); |
| 1189 | + return READ_ONCE(*ctx->poll); |
| 1190 | +} |
| 1191 | + |
| 1192 | +static int poll_for_remote_response(struct fastrpc_invoke_ctx *ctx) |
| 1193 | +{ |
| 1194 | + u32 val; |
| 1195 | + int ret; |
| 1196 | + |
| 1197 | + /* |
| 1198 | + * Poll until DSP writes FASTRPC_POLL_RESPONSE into *ctx->poll |
| 1199 | + * or until another path marks the work done. |
| 1200 | + */ |
| 1201 | + ret = read_poll_timeout_atomic(fastrpc_poll_op, val, |
| 1202 | + (val == FASTRPC_POLL_RESPONSE) || |
| 1203 | + ctx->is_work_done, 1, |
| 1204 | + FASTRPC_POLL_MAX_TIMEOUT_US, false, ctx); |
| 1205 | + |
| 1206 | + if (!ret && val == FASTRPC_POLL_RESPONSE) { |
| 1207 | + ctx->is_work_done = true; |
| 1208 | + ctx->retval = 0; |
| 1209 | + } |
| 1210 | + |
| 1211 | + if (ret == -ETIMEDOUT) |
| 1212 | + ret = -EIO; |
| 1213 | + |
| 1214 | + return ret; |
| 1215 | +} |
| 1216 | + |
| 1217 | +static inline int fastrpc_wait_for_response(struct fastrpc_invoke_ctx *ctx, |
| 1218 | + u32 kernel) |
| 1219 | +{ |
| 1220 | + int err = 0; |
| 1221 | + |
| 1222 | + if (kernel) { |
| 1223 | + if (!wait_for_completion_timeout(&ctx->work, 10 * HZ)) |
| 1224 | + err = -ETIMEDOUT; |
| 1225 | + } else { |
| 1226 | + err = wait_for_completion_interruptible(&ctx->work); |
| 1227 | + } |
| 1228 | + |
| 1229 | + return err; |
| 1230 | +} |
| 1231 | + |
| 1232 | +static int fastrpc_wait_for_completion(struct fastrpc_invoke_ctx *ctx, |
| 1233 | + u32 kernel) |
| 1234 | +{ |
| 1235 | + int err; |
| 1236 | + |
| 1237 | + do { |
| 1238 | + switch (ctx->rsp_flags) { |
| 1239 | + case NORMAL_RESPONSE: |
| 1240 | + err = fastrpc_wait_for_response(ctx, kernel); |
| 1241 | + if (err || ctx->is_work_done) |
| 1242 | + return err; |
| 1243 | + break; |
| 1244 | + case POLL_MODE: |
| 1245 | + err = poll_for_remote_response(ctx); |
| 1246 | + /* If polling timed out, move to normal response mode */ |
| 1247 | + if (err) |
| 1248 | + ctx->rsp_flags = NORMAL_RESPONSE; |
| 1249 | + break; |
| 1250 | + default: |
| 1251 | + err = -EBADR; |
| 1252 | + dev_dbg(ctx->fl->sctx->dev, |
| 1253 | + "unsupported response type:0x%x\n", ctx->rsp_flags); |
| 1254 | + break; |
| 1255 | + } |
| 1256 | + } while (!ctx->is_work_done); |
| 1257 | + |
| 1258 | + return err; |
| 1259 | +} |
| 1260 | + |
1158 | 1261 | static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, |
1159 | 1262 | u32 handle, u32 sc, |
1160 | 1263 | struct fastrpc_invoke_args *args) |
@@ -1190,16 +1293,19 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, |
1190 | 1293 | if (err) |
1191 | 1294 | goto bail; |
1192 | 1295 |
|
1193 | | - if (kernel) { |
1194 | | - if (!wait_for_completion_timeout(&ctx->work, 10 * HZ)) |
1195 | | - err = -ETIMEDOUT; |
1196 | | - } else { |
1197 | | - err = wait_for_completion_interruptible(&ctx->work); |
1198 | | - } |
| 1296 | + if (handle > FASTRPC_MAX_STATIC_HANDLE && fl->pd == USER_PD) |
| 1297 | + ctx->rsp_flags = POLL_MODE; |
1199 | 1298 |
|
| 1299 | + err = fastrpc_wait_for_completion(ctx, kernel); |
1200 | 1300 | if (err) |
1201 | 1301 | goto bail; |
1202 | 1302 |
|
| 1303 | + if (!ctx->is_work_done) { |
| 1304 | + err = -ETIMEDOUT; |
| 1305 | + dev_dbg(fl->sctx->dev, "Invalid workdone state for handle 0x%x, sc 0x%x\n", |
| 1306 | + handle, sc); |
| 1307 | + goto bail; |
| 1308 | + } |
1203 | 1309 | /* make sure that all memory writes by DSP are seen by CPU */ |
1204 | 1310 | dma_rmb(); |
1205 | 1311 | /* populate all the output buffers with results */ |
@@ -2462,6 +2568,7 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, |
2462 | 2568 |
|
2463 | 2569 | ctx->retval = rsp->retval; |
2464 | 2570 | complete(&ctx->work); |
| 2571 | + ctx->is_work_done = true; |
2465 | 2572 |
|
2466 | 2573 | /* |
2467 | 2574 | * The DMA buffer associated with the context cannot be freed in |
|
0 commit comments