Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 68 additions & 23 deletions drivers/misc/fastrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ struct fastrpc_invoke_ctx {
bool is_work_done;
/* response flags from remote processor */
enum fastrpc_response_flags rsp_flags;
/* process updates poll memory instead of glink response */
bool is_polled;
struct kref refcount;
struct list_head node; /* list of ctxs */
struct completion work;
Expand Down Expand Up @@ -304,6 +306,7 @@ struct fastrpc_channel_ctx {
bool secure;
bool unsigned_support;
u64 dma_mask;
bool poll_mode_supported;
};

struct fastrpc_device {
Expand All @@ -325,6 +328,8 @@ struct fastrpc_user {
int client_id;
int pd;
bool is_secure_dev;
/* Flags poll mode state */
bool poll_mode;
/* Lock for lists */
spinlock_t lock;
/* lock for allocations */
Expand Down Expand Up @@ -1268,28 +1273,15 @@ static int fastrpc_wait_for_completion(struct fastrpc_invoke_ctx *ctx,
{
int err;

do {
switch (ctx->rsp_flags) {
case NORMAL_RESPONSE:
err = fastrpc_wait_for_response(ctx, kernel);
if (err || ctx->is_work_done)
return err;
break;
case POLL_MODE:
err = poll_for_remote_response(ctx);
/* If polling timed out, move to normal response mode */
if (err)
ctx->rsp_flags = NORMAL_RESPONSE;
break;
default:
err = -EBADR;
dev_dbg(ctx->fl->sctx->dev,
"unsupported response type:0x%x\n", ctx->rsp_flags);
break;
}
} while (!ctx->is_work_done);
if (ctx->is_polled) {
err = poll_for_remote_response(ctx);
if (!err)
return 0;
/* If polling timed out or failed, move to normal response mode */
ctx->is_polled = false;
}

return err;
return fastrpc_wait_for_response(ctx, kernel);
}

static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
Expand Down Expand Up @@ -1327,8 +1319,13 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
if (err)
goto bail;

if (handle > FASTRPC_MAX_STATIC_HANDLE && fl->pd == USER_PD)
ctx->rsp_flags = POLL_MODE;
/*
* Set message context as polled if the call is for a user PD
* dynamic module and user has enabled poll mode.
*/
if (handle > FASTRPC_MAX_STATIC_HANDLE && fl->pd == USER_PD &&
fl->poll_mode)
ctx->is_polled = true;

err = fastrpc_wait_for_completion(ctx, kernel);
if (err)
Expand Down Expand Up @@ -1891,6 +1888,33 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap,
return 0;
}

static int fastrpc_set_option(struct fastrpc_user *fl, char __user *argp)
{
struct fastrpc_ioctl_set_option opt = { 0 };
int i;

if (copy_from_user(&opt, argp, sizeof(opt)))
return -EFAULT;

for (i = 0; i < ARRAY_SIZE(opt.reserved); i++) {
if (opt.reserved[i] != 0)
return -EINVAL;
}

if (opt.request_id != FASTRPC_POLL_MODE)
return -EINVAL;

if (opt.value) {
if (!fl->cctx->poll_mode_supported)
return -EOPNOTSUPP;
fl->poll_mode = true;
} else {
fl->poll_mode = false;
}

return 0;
}

static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp)
{
struct fastrpc_ioctl_capability cap = {0};
Expand Down Expand Up @@ -2254,6 +2278,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
case FASTRPC_IOCTL_MEM_UNMAP:
err = fastrpc_req_mem_unmap(fl, argp);
break;
case FASTRPC_IOCTL_SET_OPTION:
err = fastrpc_set_option(fl, argp);
break;
case FASTRPC_IOCTL_GET_DSP_INFO:
err = fastrpc_get_dsp_info(fl, argp);
break;
Expand Down Expand Up @@ -2400,6 +2427,21 @@ static int fastrpc_get_domain_id(const char *domain)
return -EINVAL;
}

/*
* Exception list for legacy platforms whose DSP firmware supports
* FastRPC polling mode.
*
* NOTE: This list is intentionally closed.
* Do NOT add new platforms here. New SoCs must advertise polling mode
* support via their soc_data.
*/

static const char *const fastrpc_poll_supported_machines[] = {
"qcom,milos", "qcom,qcs8300", "qcom,sa8775p", "qcom,sar2130p",
"qcom,sm8450", "qcom,sm8550", "qcom,sm8650", "qcom,sm8750",
"qcom,x1e80100", "qcom,x1p42100", NULL,
};

static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
{
struct device *rdev = &rpdev->dev;
Expand Down Expand Up @@ -2471,6 +2513,9 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
data->secure = secure_dsp;

data->poll_mode_supported =
of_machine_compatible_match(fastrpc_poll_supported_machines);

switch (domain_id) {
case ADSP_DOMAIN_ID:
case MDSP_DOMAIN_ID:
Expand Down
25 changes: 25 additions & 0 deletions include/uapi/misc/fastrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static)
#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map)
#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_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)

/**
Expand Down Expand Up @@ -67,6 +68,24 @@ enum fastrpc_proc_attr {
/* Fastrpc attribute for memory protection of buffers */
#define FASTRPC_ATTR_SECUREMAP (1)

/**
* FASTRPC_POLL_MODE - Enable/disable poll mode for FastRPC invocations
*
* Poll mode is an optimization that allows the CPU to poll shared memory
* for completion instead of waiting for an interrupt-based response.
* This reduces latency for fast-completing operations.
*
* Restrictions:
* - Only supported for USER_PD (User Protection Domain)
* - Only applies to dynamic modules (handle > 20)
* - Static modules always use interrupt-based completion
*
* Values:
* - 0: Disable poll mode (use interrupt-based completion)
* - 1: Enable poll mode (poll shared memory for completion)
*/
#define FASTRPC_POLL_MODE (1)

struct fastrpc_invoke_args {
__u64 ptr;
__u64 length;
Expand Down Expand Up @@ -133,6 +152,12 @@ struct fastrpc_mem_unmap {
__s32 reserved[5];
};

struct fastrpc_ioctl_set_option {
__u32 request_id; /* Request type (e.g., FASTRPC_POLL_MODE) */
__u32 value; /* Request-specific value */
__s32 reserved[6];
};

struct fastrpc_ioctl_capability {
__u32 unused; /* deprecated, ignored by the kernel */
__u32 attribute_id;
Expand Down