From 09efec338c3782d717cc4ee130d0bb964db59615 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Thu, 6 Nov 2025 09:25:34 +0530 Subject: [PATCH] Add poll mode support for improved fastrpc performance 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. With polling mode support fastRPC driver can 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. Steps to enable polling mode: ** Remote control structure **: typedef enum remote_rpc_latency_flags { RPC_DISABLE_QOS = 0, RPC_PM_QOS, RPC_ADAPTIVE_QOS, RPC_POLL_QOS, } remote_rpc_control_latency_t; struct remote_rpc_control_latency { remote_rpc_control_latency_t enable; uint32_t latency; }; ** Application code **: struct remote_rpc_control_latency data; data.enable = RPC_POLL_QOS; err = remote_handle64_control(h, DSPRPC_CONTROL_LATENCY, (void*)&data, sizeof(data)); Signed-off-by: Ekansh Gupta --- inc/fastrpc_ioctl.h | 9 +++++++++ src/fastrpc_apps_user.c | 31 +++++++++++++------------------ src/fastrpc_ioctl.c | 9 +++++++++ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/inc/fastrpc_ioctl.h b/inc/fastrpc_ioctl.h index 779d0345..0a1b1ba0 100644 --- a/inc/fastrpc_ioctl.h +++ b/inc/fastrpc_ioctl.h @@ -24,6 +24,7 @@ #define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_ioctl_init_create_static) #define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_ioctl_mem_map) #define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_ioctl_mem_unmap) +#define FASTRPC_IOCTL_SET_OPTION _IOWR('R', 12, struct fastrpc_ioctl_set_option) #define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability) #define ADSPRPC_DEVICE "/dev/fastrpc-adsp" @@ -99,6 +100,8 @@ #ifndef FASTRPC_MAX_DSP_ATTRIBUTES_FALLBACK #define FASTRPC_MAX_DSP_ATTRIBUTES_FALLBACK 1 #endif +/* Set option IOCTL request ID to enable poll mode */ +#define FASTRPC_POLL_MODE 1 struct fastrpc_invoke_args { __u64 ptr; /* pointer to invoke address*/ @@ -166,6 +169,12 @@ struct fastrpc_ioctl_mem_unmap { __s32 reserved[5]; }; +struct fastrpc_ioctl_set_option { + __u32 req; /* request id */ + __u32 value; /* value */ + __s32 reserved[6]; +}; + struct fastrpc_ioctl_capability { __u32 domain; /* domain of the PD*/ __u32 attribute_id; /* attribute id*/ diff --git a/src/fastrpc_apps_user.c b/src/fastrpc_apps_user.c index 6de574a5..1f9e9c3f 100644 --- a/src/fastrpc_apps_user.c +++ b/src/fastrpc_apps_user.c @@ -2040,11 +2040,10 @@ static int manage_adaptive_qos(int domain, uint32_t enable) { return nErr; } -static int manage_poll_qos(int domain, remote_handle64 h, uint32_t enable, - uint32_t latency) { +static int manage_poll_qos(int domain, remote_handle64 h, uint32_t enable) { int nErr = AEE_SUCCESS, dev = -1; const unsigned int MAX_POLL_TIMEOUT = 10000; - struct fastrpc_ctrl_latency lp = {0}; + struct fastrpc_ioctl_set_option op = {0}; /* Handle will be -1 in non-domains invocation. Create DSP session if * necessary */ @@ -2058,13 +2057,10 @@ static int manage_poll_qos(int domain, remote_handle64 h, uint32_t enable, * already */ VERIFYC((hlist) && (-1 != (dev = hlist[domain].dev)), AEE_ERPC); - // Max poll timeout allowed is 10 ms - VERIFYC(latency < MAX_POLL_TIMEOUT, AEE_EBADPARM); - /* Update polling mode in kernel */ - lp.enable = enable; - lp.latency = latency; - nErr = ioctl_control(dev, DSPRPC_RPC_POLL, &lp); + op.req = FASTRPC_POLL_MODE; + op.value = enable; + nErr = ioctl_control(dev, FASTRPC_POLL_MODE, &op); if (nErr) { nErr = convert_kernel_to_user_error(nErr, errno); goto bail; @@ -2073,22 +2069,21 @@ static int manage_poll_qos(int domain, remote_handle64 h, uint32_t enable, /* Update polling mode in DSP */ if (h == INVALID_HANDLE) { VERIFY(AEE_SUCCESS == - (nErr = adsp_current_process_poll_mode(enable, latency))); + (nErr = adsp_current_process_poll_mode(enable, MAX_POLL_TIMEOUT))); } else { remote_handle64 handle = get_adsp_current_process1_handle(domain); VERIFY(AEE_SUCCESS == - (nErr = adsp_current_process1_poll_mode(handle, enable, latency))); + (nErr = adsp_current_process1_poll_mode(handle, enable, MAX_POLL_TIMEOUT))); } FARF(ALWAYS, - "%s: poll mode updated to %u for domain %d, handle 0x%" PRIx64 - " for timeout %u\n", - __func__, enable, domain, h, latency); + "%s: poll mode updated to %u for domain %d, handle 0x%" PRIx64 "\n", + __func__, enable, domain, h); bail: if (nErr) { FARF(ERROR, "Error 0x%x (errno %d): %s failed for domain %d, handle 0x%" PRIx64 - ", enable %u, timeout %u (%s)\n", - nErr, errno, __func__, domain, h, enable, latency, strerror(errno)); + ", enable %u (%s)\n", + nErr, errno, __func__, domain, h, enable, strerror(errno)); } return nErr; } @@ -2309,7 +2304,7 @@ int remote_handle_control_domain(int domain, remote_handle64 h, uint32_t req, VERIFY(AEE_SUCCESS == (nErr = manage_pm_qos(domain, h, RPC_DISABLE_QOS, lp->latency))); VERIFY(AEE_SUCCESS == - (nErr = manage_poll_qos(domain, h, RPC_DISABLE_QOS, lp->latency))); + (nErr = manage_poll_qos(domain, h, 0))); /* Error ignored, currently meeting qos requirement is optional. Consider * to error out in later targets */ fastrpc_set_qos_latency(domain, h, FASTRPC_QOS_MAX_LATENCY_USEC); @@ -2338,7 +2333,7 @@ int remote_handle_control_domain(int domain, remote_handle64 h, uint32_t req, } case RPC_POLL_QOS: { VERIFY(AEE_SUCCESS == - (nErr = manage_poll_qos(domain, h, RPC_POLL_QOS, lp->latency))); + (nErr = manage_poll_qos(domain, h, 1))); /* * Poll QoS option also enables PM QoS to enable early response from DSP diff --git a/src/fastrpc_ioctl.c b/src/fastrpc_ioctl.c index e0329e13..efbbd0a7 100644 --- a/src/fastrpc_ioctl.c +++ b/src/fastrpc_ioctl.c @@ -211,6 +211,15 @@ int ioctl_setmode(int dev, int mode) { } int ioctl_control(int dev, int req, void *c) { + int ioErr = AEE_SUCCESS; + struct fastrpc_ioctl_set_option opt = {0}; + + if (req == FASTRPC_POLL_MODE) { + opt = *(struct fastrpc_ioctl_set_option *)c; + ioErr = ioctl(dev, FASTRPC_IOCTL_SET_OPTION, &opt); + + return ioErr; + } return AEE_EUNSUPPORTED; }