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 | 50 +++++++++++++++++++++++++++++++++++++
include/uapi/misc/fastrpc.h | 10 +++++++-
2 files changed, 59 insertions(+), 1 deletion(-)
@@ -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;
@@ -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 {