Merge "msm: adsprpc: API to get DSP capability"
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index becb445..038d061 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -17,7 +17,6 @@
#include <linux/completion.h>
#include <linux/pagemap.h>
#include <linux/mm.h>
-#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/cdev.h>
@@ -32,7 +31,6 @@
#include <soc/qcom/service-notifier.h>
#include <soc/qcom/service-locator.h>
#include <linux/scatterlist.h>
-#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/of.h>
@@ -51,6 +49,8 @@
#include <soc/qcom/ramdump.h>
#include <linux/debugfs.h>
#include <linux/pm_qos.h>
+#include <linux/stat.h>
+
#define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C
#define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
#define TZ_PIL_AUTH_QDSP6_PROC 1
@@ -106,8 +106,9 @@
#define FASTRPC_GLINK_INTENT_NUM (16)
#define PERF_KEYS \
- "count:flush:map:copy:glink:getargs:putargs:invalidate:invoke:tid:ptr"
-#define FASTRPC_STATIC_HANDLE_KERNEL (1)
+ "count:flush:map:copy:rpmsg:getargs:putargs:invalidate:invoke:tid:ptr"
+#define FASTRPC_STATIC_HANDLE_PROCESS_GROUP (1)
+#define FASTRPC_STATIC_HANDLE_DSP_UTILITIES (2)
#define FASTRPC_STATIC_HANDLE_LISTENER (3)
#define FASTRPC_STATIC_HANDLE_MAX (20)
#define FASTRPC_LATENCY_CTRL_ENB (1)
@@ -285,6 +286,11 @@
void *link_notify_handle;
};
+struct fastrpc_dsp_capabilities {
+ uint32_t is_cached; //! Flag if dsp attributes are cached
+ uint32_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
+};
+
struct fastrpc_channel_ctx {
char *name;
char *subsys;
@@ -309,6 +315,7 @@
struct fastrpc_glink_info link;
/* Indicates, if channel is restricted to secure node only */
int secure;
+ struct fastrpc_dsp_capabilities dsp_cap_kernel;
};
struct fastrpc_apps {
@@ -2066,10 +2073,13 @@
getnstimeofday(&invoket);
if (!kernel) {
- VERIFY(err, invoke->handle != FASTRPC_STATIC_HANDLE_KERNEL);
+ VERIFY(err, invoke->handle !=
+ FASTRPC_STATIC_HANDLE_PROCESS_GROUP);
+ VERIFY(err, invoke->handle !=
+ FASTRPC_STATIC_HANDLE_DSP_UTILITIES);
if (err) {
- pr_err("adsprpc: ERROR: %s: user application %s trying to send a kernel RPC message to channel %d",
- __func__, current->comm, cid);
+ pr_err("adsprpc: ERROR: %s: user application %s trying to send a kernel RPC message to channel %d, handle 0x%x\n",
+ __func__, current->comm, cid, invoke->handle);
goto bail;
}
}
@@ -2204,7 +2214,7 @@
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
- ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@@ -2299,7 +2309,7 @@
ra[5].buf.len = sizeof(inbuf.siglen);
fds[5] = 0;
- ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(6, 4, 0);
if (uproc->attrs)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 6, 0);
@@ -2385,7 +2395,7 @@
ra[2].buf.pv = (void *)pages;
ra[2].buf.len = sizeof(*pages);
fds[2] = 0;
- ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(8, 3, 0);
ioctl.inv.pra = ra;
@@ -2421,6 +2431,119 @@
return err;
}
+static int fastrpc_get_info_from_dsp(struct fastrpc_file *fl,
+ uint32_t *dsp_attr, uint32_t dsp_attr_size,
+ uint32_t domain)
+{
+ int err = 0, dsp_cap_buff_size, dsp_support = 0;
+ struct fastrpc_ioctl_invoke_crc ioctl;
+ remote_arg_t ra[2];
+ struct fastrpc_apps *me = &gfa;
+
+ // Querying device about DSP support
+ switch (domain) {
+ case ADSP_DOMAIN_ID:
+ case SDSP_DOMAIN_ID:
+ case CDSP_DOMAIN_ID:
+ if (me->channel[domain].issubsystemup)
+ dsp_support = 1;
+ break;
+ case MDSP_DOMAIN_ID:
+ //Modem not supported for fastRPC
+ break;
+ default:
+ dsp_support = 0;
+ break;
+ }
+ dsp_attr[0] = dsp_support;
+
+ if (dsp_support == 0) {
+ err = -ENOTCONN;
+ goto bail;
+ }
+
+ err = fastrpc_channel_open(fl);
+ if (err)
+ goto bail;
+
+ dsp_cap_buff_size = dsp_attr_size - sizeof(uint32_t);
+ ra[0].buf.pv = (void *)&dsp_cap_buff_size;
+ ra[0].buf.len = sizeof(dsp_cap_buff_size);
+ ra[1].buf.pv = (void *)(&dsp_attr[1]);
+ ra[1].buf.len = dsp_cap_buff_size * sizeof(uint32_t);
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_DSP_UTILITIES;
+ ioctl.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 1);
+ ioctl.inv.pra = ra;
+ ioctl.fds = NULL;
+ ioctl.attrs = NULL;
+ ioctl.crc = NULL;
+ fl->pd = 1;
+
+ err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl);
+bail:
+
+ if (err)
+ pr_err("adsprpc: %s: %s: could not obtain dsp information, err val 0x%x\n",
+ current->comm, __func__, err);
+ return err;
+}
+
+static int fastrpc_get_info_from_kernel(
+ struct fastrpc_ioctl_dsp_capabilities *dsp_cap,
+ struct fastrpc_file *fl)
+{
+ int err = 0;
+ uint32_t domain_support;
+ uint32_t domain = dsp_cap->domain;
+
+ if (!gcinfo[domain].dsp_cap_kernel.is_cached) {
+ /*
+ * Information not on kernel, query device for information
+ * and cache on kernel
+ */
+ err = fastrpc_get_info_from_dsp(fl, dsp_cap->dsp_attributes,
+ sizeof(dsp_cap->dsp_attributes),
+ domain);
+ if (err)
+ goto bail;
+
+ domain_support = dsp_cap->dsp_attributes[0];
+ switch (domain_support) {
+ case 0:
+ memset(dsp_cap->dsp_attributes, 0,
+ sizeof(dsp_cap->dsp_attributes));
+ memset(&gcinfo[domain].dsp_cap_kernel.dsp_attributes,
+ 0, sizeof(dsp_cap->dsp_attributes));
+ break;
+ case 1:
+ memcpy(&gcinfo[domain].dsp_cap_kernel.dsp_attributes,
+ dsp_cap->dsp_attributes,
+ sizeof(dsp_cap->dsp_attributes));
+ break;
+ default:
+ err = -1;
+ /*
+ * Reset is_cached flag to 0 so subsequent calls
+ * can try to query dsp again
+ */
+ gcinfo[domain].dsp_cap_kernel.is_cached = 0;
+ pr_warn("adsprpc: %s: %s: returned bad domain support value %d\n",
+ current->comm,
+ __func__,
+ domain_support);
+ goto bail;
+ }
+ gcinfo[domain].dsp_cap_kernel.is_cached = 1;
+ } else {
+ // Information on Kernel, pass it to user
+ memcpy(dsp_cap->dsp_attributes,
+ &gcinfo[domain].dsp_cap_kernel.dsp_attributes,
+ sizeof(dsp_cap->dsp_attributes));
+ }
+bail:
+ return err;
+}
+
static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
{
int err = 0;
@@ -2440,7 +2563,7 @@
tgid = fl->tgid;
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
- ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@@ -2486,7 +2609,7 @@
ra[2].buf.pv = (void *)&routargs;
ra[2].buf.len = sizeof(routargs);
- ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
if (fl->apps->compat)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(4, 2, 1);
else
@@ -2547,7 +2670,7 @@
ra[1].buf.pv = (void *)&routargs;
ra[1].buf.len = sizeof(routargs);
- ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(9, 1, 1);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@@ -2609,7 +2732,7 @@
ra[0].buf.pv = (void *)&inargs;
ra[0].buf.len = sizeof(inargs);
- ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
if (fl->apps->compat)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(5, 1, 0);
else
@@ -3739,6 +3862,26 @@
return err;
}
+static int fastrpc_get_dsp_info(struct fastrpc_ioctl_dsp_capabilities *dsp_cap,
+ void *param, struct fastrpc_file *fl)
+{
+ int err = 0;
+
+ K_COPY_FROM_USER(err, 0, dsp_cap, param,
+ sizeof(struct fastrpc_ioctl_dsp_capabilities));
+ VERIFY(err, dsp_cap->domain < NUM_CHANNELS);
+ if (err)
+ goto bail;
+
+ err = fastrpc_get_info_from_kernel(dsp_cap, fl);
+ if (err)
+ goto bail;
+ K_COPY_TO_USER(err, 0, param, dsp_cap,
+ sizeof(struct fastrpc_ioctl_dsp_capabilities));
+bail:
+ return err;
+}
+
static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param)
{
@@ -3752,6 +3895,7 @@
struct fastrpc_ioctl_init_attrs init;
struct fastrpc_ioctl_perf perf;
struct fastrpc_ioctl_control cp;
+ struct fastrpc_ioctl_dsp_capabilities dsp_cap;
} p;
union {
struct fastrpc_ioctl_mmap mmap;
@@ -3962,7 +4106,9 @@
if (err)
goto bail;
break;
-
+ case FASTRPC_IOCTL_GET_DSP_INFO:
+ err = fastrpc_get_dsp_info(&p.dsp_cap, param, fl);
+ break;
default:
err = -ENOTTY;
pr_info("bad ioctl: %d\n", ioctl_num);
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 3b54243..3d72ad2 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -43,6 +43,8 @@
_IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64)
#define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \
_IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64)
+#define COMPAT_FASTRPC_IOCTL_GET_DSP_INFO \
+ _IOWR('R', 16, struct compat_fastrpc_ioctl_dsp_capabilities)
struct compat_remote_buf {
compat_uptr_t pv; /* buffer pointer */
@@ -151,6 +153,11 @@
};
};
+struct compat_fastrpc_ioctl_dsp_capabilities {
+ compat_uint_t domain; /* DSP domain to query capabilities */
+ compat_uint_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
+};
+
static int compat_get_fastrpc_ioctl_invoke(
struct compat_fastrpc_ioctl_invoke_crc __user *inv32,
struct fastrpc_ioctl_invoke_crc __user **inva,
@@ -389,6 +396,53 @@
return err;
}
+static int compat_put_fastrpc_ioctl_get_dsp_info(
+ struct compat_fastrpc_ioctl_dsp_capabilities __user *info32,
+ struct fastrpc_ioctl_dsp_capabilities __user *info)
+{
+ compat_uint_t u;
+ int err, ii;
+
+ for (ii = 0, err = 0; ii < FASTRPC_MAX_DSP_ATTRIBUTES; ii++) {
+ err |= get_user(u, &info->dsp_attributes[ii]);
+ err |= put_user(u, &info32->dsp_attributes[ii]);
+ }
+
+ return err;
+}
+
+
+
+static int compat_fastrpc_get_dsp_info(struct file *filp,
+ unsigned long arg)
+{
+ struct compat_fastrpc_ioctl_dsp_capabilities __user *info32;
+ struct fastrpc_ioctl_dsp_capabilities __user *info;
+ compat_uint_t u;
+ long ret;
+ int err = 0;
+
+ info32 = compat_ptr(arg);
+ VERIFY(err, NULL != (info = compat_alloc_user_space(
+ sizeof(*info))));
+ if (err)
+ return -EFAULT;
+
+ err = get_user(u, &info32->domain);
+ err |= put_user(u, &info->domain);
+ if (err)
+ return err;
+
+ ret = filp->f_op->unlocked_ioctl(filp,
+ FASTRPC_IOCTL_GET_DSP_INFO,
+ (unsigned long)info);
+ if (ret)
+ return ret;
+
+ err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
+ return err;
+}
+
long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -588,6 +642,8 @@
err |= put_user(u, &perf32->numkeys);
return err;
}
+ case COMPAT_FASTRPC_IOCTL_GET_DSP_INFO:
+ return compat_fastrpc_get_dsp_info(filp, arg);
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 24fad76..067c2c1 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,8 @@
#define FASTRPC_IOCTL_INVOKE_CRC _IOWR('R', 11, struct fastrpc_ioctl_invoke_crc)
#define FASTRPC_IOCTL_CONTROL _IOWR('R', 12, struct fastrpc_ioctl_control)
#define FASTRPC_IOCTL_MUNMAP_FD _IOWR('R', 13, struct fastrpc_ioctl_munmap_fd)
+#define FASTRPC_IOCTL_GET_DSP_INFO \
+ _IOWR('R', 16, struct fastrpc_ioctl_dsp_capabilities)
#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
@@ -269,6 +271,12 @@
};
};
+#define FASTRPC_MAX_DSP_ATTRIBUTES (7)
+struct fastrpc_ioctl_dsp_capabilities {
+ uint32_t domain; //! DSP domain to query capabilities
+ uint32_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
+};
+
struct smq_null_invoke {
uint64_t ctx; /* invoke caller context */
uint32_t handle; /* handle to invoke */