Skip to content

Commit 844e24f

Browse files
ekanshibuKomal-Bajaj
authored andcommitted
FROMLIST: misc: fastrpc: Add polling mode support for fastRPC driver
For any remote call to DSP, after sending an invocation message, fastRPC driver waits for glink response and during this time the CPU can go into low power modes. This adds latency to overall fastrpc call as CPU wakeup and scheduling latencies are included. Add polling mode support with which fastRPC driver will poll continuously on a memory after sending a message to remote subsystem which will eliminate CPU wakeup and scheduling latencies and reduce fastRPC overhead. Poll mode can be enabled by user by using FASTRPC_IOCTL_SET_OPTION ioctl request with FASTRPC_POLL_MODE request id. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ekansh Gupta <[email protected]>
1 parent 3672410 commit 844e24f

File tree

2 files changed

+141
-7
lines changed

2 files changed

+141
-7
lines changed

drivers/misc/fastrpc.c

Lines changed: 132 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <linux/firmware/qcom/qcom_scm.h>
2323
#include <uapi/misc/fastrpc.h>
2424
#include <linux/of_reserved_mem.h>
25+
#include <linux/compiler.h>
26+
#include <linux/iopoll.h>
2527
#include <linux/bitfield.h>
2628

2729
#define ADSP_DOMAIN_ID (0)
@@ -38,6 +40,7 @@
3840
#define FASTRPC_CTX_MAX (256)
3941
#define FASTRPC_INIT_HANDLE 1
4042
#define FASTRPC_DSP_UTILITIES_HANDLE 2
43+
#define FASTRPC_MAX_STATIC_HANDLE (20)
4144
#define FASTRPC_CTXID_MASK GENMASK(15, 8)
4245
#define INIT_FILELEN_MAX (2 * 1024 * 1024)
4346
#define INIT_FILE_NAMELEN_MAX (128)
@@ -106,6 +109,12 @@
106109

107110
#define miscdev_to_fdevice(d) container_of(d, struct fastrpc_device, miscdev)
108111

112+
/* Poll response number from remote processor for call completion */
113+
#define FASTRPC_POLL_RESPONSE (0xdecaf)
114+
115+
/* Polling mode timeout limit */
116+
#define FASTRPC_POLL_MAX_TIMEOUT_US (10000)
117+
109118
struct fastrpc_phy_page {
110119
u64 addr; /* physical address */
111120
u64 size; /* size of contiguous region */
@@ -236,8 +245,14 @@ struct fastrpc_invoke_ctx {
236245
u32 sc;
237246
u64 *fdlist;
238247
u32 *crc;
248+
/* Poll memory that DSP updates */
249+
u32 *poll;
239250
u64 ctxid;
240251
u64 msg_sz;
252+
/* work done status flag */
253+
bool is_work_done;
254+
/* process updates poll memory instead of glink response */
255+
bool is_polled;
241256
struct kref refcount;
242257
struct list_head node; /* list of ctxs */
243258
struct completion work;
@@ -301,6 +316,8 @@ struct fastrpc_user {
301316
int client_id;
302317
int pd;
303318
bool is_secure_dev;
319+
/* Flags poll mode state */
320+
bool poll_mode;
304321
/* Lock for lists */
305322
spinlock_t lock;
306323
/* lock for allocations */
@@ -894,7 +911,8 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx)
894911
sizeof(struct fastrpc_invoke_buf) +
895912
sizeof(struct fastrpc_phy_page)) * ctx->nscalars +
896913
sizeof(u64) * FASTRPC_MAX_FDLIST +
897-
sizeof(u32) * FASTRPC_MAX_CRCLIST;
914+
sizeof(u32) * FASTRPC_MAX_CRCLIST +
915+
sizeof(u32);
898916

899917
return size;
900918
}
@@ -990,6 +1008,7 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx)
9901008
list = fastrpc_invoke_buf_start(rpra, ctx->nscalars);
9911009
pages = fastrpc_phy_page_start(list, ctx->nscalars);
9921010
ctx->fdlist = (u64 *)(pages + ctx->nscalars);
1011+
ctx->poll = (u32 *)(ctx->fdlist + FASTRPC_MAX_FDLIST + FASTRPC_MAX_CRCLIST);
9931012
args = (uintptr_t)ctx->buf->virt + metalen;
9941013
rlen = pkt_size - metalen;
9951014
ctx->rpra = rpra;
@@ -1158,6 +1177,75 @@ static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx,
11581177

11591178
}
11601179

1180+
static inline u32 fastrpc_poll_op(void *p)
1181+
{
1182+
struct fastrpc_invoke_ctx *ctx = p;
1183+
1184+
dma_rmb();
1185+
return READ_ONCE(*ctx->poll);
1186+
}
1187+
1188+
static int poll_for_remote_response(struct fastrpc_invoke_ctx *ctx)
1189+
{
1190+
u32 val;
1191+
int ret;
1192+
1193+
/*
1194+
* Poll until DSP writes FASTRPC_POLL_RESPONSE into *ctx->poll
1195+
* or until another path marks the work done.
1196+
*/
1197+
ret = read_poll_timeout_atomic(fastrpc_poll_op, val,
1198+
(val == FASTRPC_POLL_RESPONSE) ||
1199+
ctx->is_work_done, 1,
1200+
FASTRPC_POLL_MAX_TIMEOUT_US, false, ctx);
1201+
1202+
if (!ret && val == FASTRPC_POLL_RESPONSE) {
1203+
ctx->is_work_done = true;
1204+
ctx->retval = 0;
1205+
}
1206+
1207+
if (ret == -ETIMEDOUT)
1208+
ret = -EIO;
1209+
1210+
return ret;
1211+
}
1212+
1213+
static inline int fastrpc_wait_for_response(struct fastrpc_invoke_ctx *ctx,
1214+
u32 kernel)
1215+
{
1216+
int err = 0;
1217+
1218+
if (kernel) {
1219+
if (!wait_for_completion_timeout(&ctx->work, 10 * HZ))
1220+
err = -ETIMEDOUT;
1221+
} else {
1222+
err = wait_for_completion_interruptible(&ctx->work);
1223+
}
1224+
1225+
return err;
1226+
}
1227+
1228+
static int fastrpc_wait_for_completion(struct fastrpc_invoke_ctx *ctx,
1229+
u32 kernel)
1230+
{
1231+
int err;
1232+
1233+
do {
1234+
if (ctx->is_polled) {
1235+
err = poll_for_remote_response(ctx);
1236+
/* If polling timed out, move to normal response mode */
1237+
if (err)
1238+
ctx->is_polled = false;
1239+
} else {
1240+
err = fastrpc_wait_for_response(ctx, kernel);
1241+
if (err)
1242+
return err;
1243+
}
1244+
} while (!ctx->is_work_done);
1245+
1246+
return err;
1247+
}
1248+
11611249
static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
11621250
u32 handle, u32 sc,
11631251
struct fastrpc_invoke_args *args)
@@ -1193,16 +1281,25 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
11931281
if (err)
11941282
goto bail;
11951283

1196-
if (kernel) {
1197-
if (!wait_for_completion_timeout(&ctx->work, 10 * HZ))
1198-
err = -ETIMEDOUT;
1199-
} else {
1200-
err = wait_for_completion_interruptible(&ctx->work);
1201-
}
1284+
/*
1285+
* Set message context as polled if the call is for a user PD
1286+
* dynamic module and user has enabled poll mode.
1287+
*/
1288+
if (handle > FASTRPC_MAX_STATIC_HANDLE && fl->pd == USER_PD &&
1289+
fl->poll_mode)
1290+
ctx->is_polled = true;
1291+
1292+
err = fastrpc_wait_for_completion(ctx, kernel);
12021293

12031294
if (err)
12041295
goto bail;
12051296

1297+
if (!ctx->is_work_done) {
1298+
err = -ETIMEDOUT;
1299+
dev_dbg(fl->sctx->dev, "Invalid workdone state for handle 0x%x, sc 0x%x\n",
1300+
handle, sc);
1301+
goto bail;
1302+
}
12061303
/* make sure that all memory writes by DSP are seen by CPU */
12071304
dma_rmb();
12081305
/* populate all the output buffers with results */
@@ -1780,6 +1877,30 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap,
17801877
return 0;
17811878
}
17821879

1880+
static int fastrpc_set_option(struct fastrpc_user *fl, char __user *argp)
1881+
{
1882+
struct fastrpc_ioctl_set_option opt = {0};
1883+
int i;
1884+
1885+
if (copy_from_user(&opt, argp, sizeof(opt)))
1886+
return -EFAULT;
1887+
1888+
for (i = 0; i < ARRAY_SIZE(opt.reserved); i++) {
1889+
if (opt.reserved[i] != 0)
1890+
return -EINVAL;
1891+
}
1892+
1893+
if (opt.req != FASTRPC_POLL_MODE)
1894+
return -EINVAL;
1895+
1896+
if (opt.value)
1897+
fl->poll_mode = true;
1898+
else
1899+
fl->poll_mode = false;
1900+
1901+
return 0;
1902+
}
1903+
17831904
static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp)
17841905
{
17851906
struct fastrpc_ioctl_capability cap = {0};
@@ -2134,6 +2255,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
21342255
case FASTRPC_IOCTL_MEM_UNMAP:
21352256
err = fastrpc_req_mem_unmap(fl, argp);
21362257
break;
2258+
case FASTRPC_IOCTL_SET_OPTION:
2259+
err = fastrpc_set_option(fl, argp);
2260+
break;
21372261
case FASTRPC_IOCTL_GET_DSP_INFO:
21382262
err = fastrpc_get_dsp_info(fl, argp);
21392263
break;
@@ -2465,6 +2589,7 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
24652589

24662590
ctx->retval = rsp->retval;
24672591
complete(&ctx->work);
2592+
ctx->is_work_done = true;
24682593

24692594
/*
24702595
* The DMA buffer associated with the context cannot be freed in

include/uapi/misc/fastrpc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static)
1717
#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map)
1818
#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap)
19+
#define FASTRPC_IOCTL_SET_OPTION _IOWR('R', 12, struct fastrpc_ioctl_set_option)
1920
#define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability)
2021

2122
/**
@@ -66,6 +67,8 @@ enum fastrpc_proc_attr {
6667

6768
/* Fastrpc attribute for memory protection of buffers */
6869
#define FASTRPC_ATTR_SECUREMAP (1)
70+
/* Set option request ID to enable poll mode */
71+
#define FASTRPC_POLL_MODE (1)
6972

7073
struct fastrpc_invoke_args {
7174
__u64 ptr;
@@ -133,6 +136,12 @@ struct fastrpc_mem_unmap {
133136
__s32 reserved[5];
134137
};
135138

139+
struct fastrpc_ioctl_set_option {
140+
__u32 req; /* request id */
141+
__u32 value; /* value */
142+
__s32 reserved[6];
143+
};
144+
136145
struct fastrpc_ioctl_capability {
137146
__u32 unused; /* deprecated, ignored by the kernel */
138147
__u32 attribute_id;

0 commit comments

Comments
 (0)