@@ -573,7 +573,7 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx)
static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
struct fastrpc_user *user, u32 kernel, u32 sc,
- struct fastrpc_invoke_args *args)
+ struct fastrpc_enhanced_invoke *invoke)
{
struct fastrpc_channel_ctx *cctx = user->cctx;
struct fastrpc_invoke_ctx *ctx = NULL;
@@ -604,7 +604,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
kfree(ctx);
return ERR_PTR(-ENOMEM);
}
- ctx->args = args;
+ ctx->args = (struct fastrpc_invoke_args *)invoke->inv.args;
fastrpc_get_buff_overlaps(ctx);
}
@@ -1133,12 +1133,12 @@ static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx,
}
static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
- u32 handle, u32 sc,
- struct fastrpc_invoke_args *args)
+ struct fastrpc_enhanced_invoke *invoke)
{
struct fastrpc_invoke_ctx *ctx = NULL;
struct fastrpc_buf *buf, *b;
-
+ struct fastrpc_invoke *inv = &invoke->inv;
+ u32 handle, sc;
int err = 0;
if (!fl->sctx)
@@ -1147,12 +1147,14 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
if (!fl->cctx->rpdev)
return -EPIPE;
+ handle = inv->handle;
+ sc = inv->sc;
if (handle == FASTRPC_INIT_HANDLE && !kernel) {
dev_warn_ratelimited(fl->sctx->dev, "user app trying to send a kernel RPC message (%d)\n", handle);
return -EPERM;
}
- ctx = fastrpc_context_alloc(fl, kernel, sc, args);
+ ctx = fastrpc_context_alloc(fl, kernel, sc, invoke);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
@@ -1238,6 +1240,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
{
struct fastrpc_init_create_static init;
struct fastrpc_invoke_args *args;
+ struct fastrpc_enhanced_invoke ioctl;
struct fastrpc_phy_page pages[1];
char *name;
int err;
@@ -1246,7 +1249,6 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
u32 namelen;
u32 pageslen;
} inbuf;
- u32 sc;
args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
if (!args)
@@ -1313,10 +1315,11 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
args[2].length = sizeof(*pages);
args[2].fd = -1;
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_STATIC, 3, 0);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_STATIC, 3, 0);
+ ioctl.inv.args = (__u64)args;
- err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
- sc, args);
+ err = fastrpc_internal_invoke(fl, true, &ioctl);
if (err)
goto err_invoke;
@@ -1356,6 +1359,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
{
struct fastrpc_init_create init;
struct fastrpc_invoke_args *args;
+ struct fastrpc_enhanced_invoke ioctl;
struct fastrpc_phy_page pages[1];
struct fastrpc_map *map = NULL;
struct fastrpc_buf *imem = NULL;
@@ -1369,7 +1373,6 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
u32 attrs;
u32 siglen;
} inbuf;
- u32 sc;
bool unsigned_module = false;
args = kcalloc(FASTRPC_CREATE_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
@@ -1443,12 +1446,13 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
args[5].length = sizeof(inbuf.siglen);
args[5].fd = -1;
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
if (init.attrs)
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 4, 0);
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 4, 0);
+ ioctl.inv.args = (__u64)args;
- err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
- sc, args);
+ err = fastrpc_internal_invoke(fl, true, &ioctl);
if (err)
goto err_invoke;
@@ -1500,17 +1504,19 @@ static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx,
static int fastrpc_release_current_dsp_process(struct fastrpc_user *fl)
{
struct fastrpc_invoke_args args[1];
+ struct fastrpc_enhanced_invoke ioctl;
int tgid = 0;
- u32 sc;
tgid = fl->tgid;
args[0].ptr = (u64)(uintptr_t) &tgid;
args[0].length = sizeof(tgid);
args[0].fd = -1;
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_RELEASE, 1, 0);
- return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
- sc, &args[0]);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_RELEASE, 1, 0);
+ ioctl.inv.args = (__u64)args;
+
+ return fastrpc_internal_invoke(fl, true, &ioctl);
}
static int fastrpc_device_release(struct inode *inode, struct file *file)
@@ -1646,22 +1652,25 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)
static int fastrpc_init_attach(struct fastrpc_user *fl, int pd)
{
struct fastrpc_invoke_args args[1];
+ struct fastrpc_enhanced_invoke ioctl;
int tgid = fl->tgid;
- u32 sc;
args[0].ptr = (u64)(uintptr_t) &tgid;
args[0].length = sizeof(tgid);
args[0].fd = -1;
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_ATTACH, 1, 0);
fl->pd = pd;
- return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
- sc, &args[0]);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_ATTACH, 1, 0);
+ ioctl.inv.args = (__u64)args;
+
+ return fastrpc_internal_invoke(fl, true, &ioctl);
}
static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp)
{
struct fastrpc_invoke_args *args = NULL;
+ struct fastrpc_enhanced_invoke ioctl;
struct fastrpc_invoke inv;
u32 nscalars;
int err;
@@ -1683,16 +1692,70 @@ static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp)
}
}
- err = fastrpc_internal_invoke(fl, false, inv.handle, inv.sc, args);
+ ioctl.inv = inv;
+ ioctl.inv.args = (__u64)args;
+
+ err = fastrpc_internal_invoke(fl, false, &ioctl);
kfree(args);
return err;
}
+static int fastrpc_multimode_invoke(struct fastrpc_user *fl, char __user *argp)
+{
+ struct fastrpc_enhanced_invoke einv;
+ struct fastrpc_invoke_args *args = NULL;
+ struct fastrpc_ioctl_multimode_invoke invoke;
+ u32 nscalars;
+ int err, i;
+
+ if (copy_from_user(&invoke, argp, sizeof(invoke)))
+ return -EFAULT;
+
+ for (i = 0; i < 8; i++) {
+ if (invoke.reserved[i] != 0)
+ return -EINVAL;
+ }
+ if (invoke.rsvd != 0)
+ return -EINVAL;
+
+ switch (invoke.req) {
+ case FASTRPC_INVOKE:
+ /* nscalars is truncated here to max supported value */
+ if (copy_from_user(&einv, (void __user *)(uintptr_t)invoke.invparam,
+ invoke.size))
+ return -EFAULT;
+ for (i = 0; i < 8; i++) {
+ if (einv.reserved[i] != 0)
+ return -EINVAL;
+ }
+ nscalars = REMOTE_SCALARS_LENGTH(einv.inv.sc);
+ if (nscalars) {
+ args = kcalloc(nscalars, sizeof(*args), GFP_KERNEL);
+ if (!args)
+ return -ENOMEM;
+ if (copy_from_user(args, (void __user *)(uintptr_t)einv.inv.args,
+ nscalars * sizeof(*args))) {
+ kfree(args);
+ return -EFAULT;
+ }
+ }
+ einv.inv.args = (__u64)args;
+ err = fastrpc_internal_invoke(fl, false, &einv);
+ kfree(args);
+ break;
+ default:
+ err = -ENOTTY;
+ break;
+ }
+ return err;
+}
+
static int fastrpc_get_info_from_dsp(struct fastrpc_user *fl, uint32_t *dsp_attr_buf,
uint32_t dsp_attr_buf_len)
{
struct fastrpc_invoke_args args[2] = { 0 };
+ struct fastrpc_enhanced_invoke ioctl;
/* Capability filled in userspace */
dsp_attr_buf[0] = 0;
@@ -1705,8 +1768,11 @@ static int fastrpc_get_info_from_dsp(struct fastrpc_user *fl, uint32_t *dsp_attr
args[1].fd = -1;
fl->pd = USER_PD;
- return fastrpc_internal_invoke(fl, true, FASTRPC_DSP_UTILITIES_HANDLE,
- FASTRPC_SCALARS(0, 1, 1), args);
+ ioctl.inv.handle = FASTRPC_DSP_UTILITIES_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(0, 1, 1);
+ ioctl.inv.args = (__u64)args;
+
+ return fastrpc_internal_invoke(fl, true, &ioctl);
}
static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap,
@@ -1793,10 +1859,10 @@ static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp)
static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf *buf)
{
struct fastrpc_invoke_args args[1] = { [0] = { 0 } };
+ struct fastrpc_enhanced_invoke ioctl;
struct fastrpc_munmap_req_msg req_msg;
struct device *dev = fl->sctx->dev;
int err;
- u32 sc;
req_msg.pgid = fl->tgid;
req_msg.size = buf->size;
@@ -1805,9 +1871,11 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf *
args[0].ptr = (u64) (uintptr_t) &req_msg;
args[0].length = sizeof(req_msg);
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MUNMAP, 1, 0);
- err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc,
- &args[0]);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MUNMAP, 1, 0);
+ ioctl.inv.args = (__u64)args;
+
+ err = fastrpc_internal_invoke(fl, true, &ioctl);
if (!err) {
dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr);
spin_lock(&fl->lock);
@@ -1851,6 +1919,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
{
struct fastrpc_invoke_args args[3] = { [0 ... 2] = { 0 } };
+ struct fastrpc_enhanced_invoke ioctl;
struct fastrpc_buf *buf = NULL;
struct fastrpc_mmap_req_msg req_msg;
struct fastrpc_mmap_rsp_msg rsp_msg;
@@ -1858,7 +1927,6 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
struct fastrpc_req_mmap req;
struct device *dev = fl->sctx->dev;
int err;
- u32 sc;
if (copy_from_user(&req, argp, sizeof(req)))
return -EFAULT;
@@ -1901,9 +1969,11 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
args[2].ptr = (u64) (uintptr_t) &rsp_msg;
args[2].length = sizeof(rsp_msg);
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MMAP, 2, 1);
- err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc,
- &args[0]);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MMAP, 2, 1);
+ ioctl.inv.args = (__u64)args;
+
+ err = fastrpc_internal_invoke(fl, true, &ioctl);
if (err) {
dev_err(dev, "mmap error (len 0x%08llx)\n", buf->size);
goto err_invoke;
@@ -1951,10 +2021,10 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
static int fastrpc_req_mem_unmap_impl(struct fastrpc_user *fl, struct fastrpc_mem_unmap *req)
{
struct fastrpc_invoke_args args[1] = { [0] = { 0 } };
+ struct fastrpc_enhanced_invoke ioctl;
struct fastrpc_map *map = NULL, *iter, *m;
struct fastrpc_mem_unmap_req_msg req_msg = { 0 };
int err = 0;
- u32 sc;
struct device *dev = fl->sctx->dev;
spin_lock(&fl->lock);
@@ -1980,9 +2050,11 @@ static int fastrpc_req_mem_unmap_impl(struct fastrpc_user *fl, struct fastrpc_me
args[0].ptr = (u64) (uintptr_t) &req_msg;
args[0].length = sizeof(req_msg);
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MEM_UNMAP, 1, 0);
- err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc,
- &args[0]);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MEM_UNMAP, 1, 0);
+ ioctl.inv.args = (__u64)args;
+
+ err = fastrpc_internal_invoke(fl, true, &ioctl);
fastrpc_map_put(map);
if (err)
dev_err(dev, "unmmap\tpt fd = %d, 0x%09llx error\n", map->fd, map->raddr);
@@ -2003,6 +2075,7 @@ static int fastrpc_req_mem_unmap(struct fastrpc_user *fl, char __user *argp)
static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
{
struct fastrpc_invoke_args args[4] = { [0 ... 3] = { 0 } };
+ struct fastrpc_enhanced_invoke ioctl;
struct fastrpc_mem_map_req_msg req_msg = { 0 };
struct fastrpc_mmap_rsp_msg rsp_msg = { 0 };
struct fastrpc_mem_unmap req_unmap = { 0 };
@@ -2011,7 +2084,6 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
struct device *dev = fl->sctx->dev;
struct fastrpc_map *map = NULL;
int err;
- u32 sc;
if (copy_from_user(&req, argp, sizeof(req)))
return -EFAULT;
@@ -2047,8 +2119,11 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
args[3].ptr = (u64) (uintptr_t) &rsp_msg;
args[3].length = sizeof(rsp_msg);
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MEM_MAP, 3, 1);
- err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, &args[0]);
+ ioctl.inv.handle = FASTRPC_INIT_HANDLE;
+ ioctl.inv.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MEM_MAP, 3, 1);
+ ioctl.inv.args = (__u64)args;
+
+ err = fastrpc_internal_invoke(fl, true, &ioctl);
if (err) {
dev_err(dev, "mem mmap error, fd %d, vaddr %llx, size %lld\n",
req.fd, req.vaddrin, map->size);
@@ -2088,6 +2163,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
case FASTRPC_IOCTL_INVOKE:
err = fastrpc_invoke(fl, argp);
break;
+ case FASTRPC_IOCTL_MULTIMODE_INVOKE:
+ err = fastrpc_multimode_invoke(fl, argp);
+ break;
case FASTRPC_IOCTL_INIT_ATTACH:
err = fastrpc_init_attach(fl, ROOT_PD);
break;
@@ -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_MULTIMODE_INVOKE _IOWR('R', 12, struct fastrpc_ioctl_multimode_invoke)
#define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability)
/**
@@ -80,6 +81,31 @@ struct fastrpc_invoke {
__u64 args;
};
+struct fastrpc_enhanced_invoke {
+ struct fastrpc_invoke inv;
+ __u64 crc;
+ __u64 perf_kernel;
+ __u64 perf_dsp;
+ __u32 reserved[8]; /* keeping reserved bits for new requirements */
+};
+
+struct fastrpc_ioctl_multimode_invoke {
+ __u32 req;
+ __u32 rsvd; /* padding field */
+ __u64 invparam;
+ __u64 size;
+ __u32 reserved[8]; /* keeping reserved bits for new requirements */
+};
+
+enum fastrpc_multimode_invoke_type {
+ FASTRPC_INVOKE = 1,
+ FASTRPC_INVOKE_ENHANCED = 2,
+ FASTRPC_INVOKE_CONTROL = 3,
+ FASTRPC_INVOKE_DSPSIGNAL = 4,
+ FASTRPC_INVOKE_NOTIF = 5,
+ FASTRPC_INVOKE_MULTISESSION = 6,
+};
+
struct fastrpc_init_create {
__u32 filelen; /* elf file length */
__s32 filefd; /* fd for the file */