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. Adding a 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. With this change, DSP always sends a glink response which will get ignored if polling mode didn't time out. Signed-off-by: Ekansh Gupta <quic_ekangupt@xxxxxxxxxxx> --- drivers/misc/fastrpc.c | 50 +++++++++++++++++++++++++++++++++++++ include/uapi/misc/fastrpc.h | 10 +++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index e4bb01bad7fb..296ddae0ef7c 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -111,6 +111,8 @@ #define FASTRPC_RSP_VERSION2 2 /* Early wake up poll completion number received from remoteproc */ #define FASTRPC_EARLY_WAKEUP_POLL (0xabbccdde) +/* Poll response number from remote processor for call completion */ +#define FASTRPC_POLL_RESPONSE (0xdecaf) /* timeout in us for polling until memory barrier */ #define FASTRPC_POLL_TIME_MEM_UPDATE (500) /* timeout in us for busy polling after early response from remoteproc */ @@ -418,11 +420,15 @@ struct fastrpc_user { struct fastrpc_buf *init_mem; u32 profile; + /* Threads poll for specified timeout and fall back to glink wait */ + u32 poll_timeout; int tgid; int pd; bool is_secure_dev; bool is_unsigned_pd; bool sharedcb; + /* If set, threads will poll for DSP response instead of glink wait */ + bool poll_mode; char *servloc_name; /* Lock for lists */ spinlock_t lock; @@ -1398,6 +1404,11 @@ static int poll_for_remote_response(struct fastrpc_invoke_ctx *ctx, u32 timeout) /* Remote processor sent early response */ err = 0; break; + } else if (*poll == FASTRPC_POLL_RESPONSE) { + err = 0; + ctx->is_work_done = true; + ctx->retval = 0; + break; } if (j == FASTRPC_POLL_TIME_MEM_UPDATE) { /* make sure that all poll memory writes by DSP are seen by CPU */ @@ -1475,6 +1486,15 @@ static void fastrpc_wait_for_completion(struct fastrpc_invoke_ctx *ctx, if (*ptr_interrupted || ctx->is_work_done) return; break; + case POLL_MODE: + err = poll_for_remote_response(ctx, ctx->fl->poll_timeout); + + /* If polling timed out, move to normal response state */ + if (err) + ctx->rsp_flags = NORMAL_RESPONSE; + else + *ptr_interrupted = 0; + break; default: *ptr_interrupted = -EBADR; dev_err(ctx->fl->sctx->dev, "unsupported response type:0x%x\n", ctx->rsp_flags); @@ -2176,6 +2196,33 @@ static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp) return err; } +static int fastrpc_manage_poll_mode(struct fastrpc_user *fl, u32 enable, u32 timeout) +{ + const unsigned int MAX_POLL_TIMEOUT_US = 10000; + + if ((fl->cctx->domain_id != CDSP_DOMAIN_ID) || (fl->pd != USER_PD)) { + dev_err(&fl->cctx->rpdev->dev, "poll mode only allowed for dynamic CDSP process\n"); + return -EPERM; + } + if (timeout > MAX_POLL_TIMEOUT_US) { + dev_err(&fl->cctx->rpdev->dev, "poll timeout %u is greater than max allowed value %u\n", + timeout, MAX_POLL_TIMEOUT_US); + return -EBADMSG; + } + spin_lock(&fl->lock); + if (enable) { + fl->poll_mode = true; + fl->poll_timeout = timeout; + } else { + fl->poll_mode = false; + fl->poll_timeout = 0; + } + spin_unlock(&fl->lock); + dev_info(&fl->cctx->rpdev->dev, "updated poll mode to %d, timeout %u\n", enable, timeout); + + return 0; +} + static int fastrpc_internal_control(struct fastrpc_user *fl, struct fastrpc_internal_control *cp) { @@ -2190,6 +2237,9 @@ static int fastrpc_internal_control(struct fastrpc_user *fl, case FASTRPC_CONTROL_SMMU: fl->sharedcb = cp->smmu.sharedcb; break; + case FASTRPC_CONTROL_RPC_POLL: + err = fastrpc_manage_poll_mode(fl, cp->lp.enable, cp->lp.latency); + break; default: err = -EBADRQC; break; diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h index d29188e43b21..b4959cc4d254 100644 --- a/include/uapi/misc/fastrpc.h +++ b/include/uapi/misc/fastrpc.h @@ -182,9 +182,17 @@ struct fastrpc_ctrl_smmu { u32 sharedcb; /* Set to SMMU share context bank */ }; +struct fastrpc_ctrl_latency { + u32 enable; /* latency control enable */ + u32 latency; /* latency request in us */ +}; + struct fastrpc_internal_control { u32 req; - struct fastrpc_ctrl_smmu smmu; + union { + struct fastrpc_ctrl_smmu smmu; + struct fastrpc_ctrl_latency lp; + }; }; enum fastrpc_perfkeys { -- 2.17.0