@@ -109,6 +109,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 */
@@ -380,10 +382,14 @@ 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 sharedcb;
+ /* If set, threads will poll for DSP response instead of glink wait */
+ bool poll_mode;
/* Lock for lists */
spinlock_t lock;
/* lock for allocations */
@@ -1374,6 +1380,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 (jj == FASTRPC_POLL_TIME_MEM_UPDATE) {
/* Wait for DSP to finish updating poll memory */
@@ -1449,6 +1460,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);
@@ -2065,6 +2085,32 @@ 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)
{
@@ -2079,6 +2125,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;
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@quicinc.com> --- drivers/misc/fastrpc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)