msm: ADSPRPC: add support for fastrpc control interface
Add fastrpc control interface for QoS voting to reduce remote
call overhead outliers.
Change-Id: Ib9ff3553c583d0b5274c33bc8d029790b093f640
Acked-by: Viswanatham Paduchuri <vpaduchu@qti.qualcomm.com>
Signed-off-by: Tharun Kumar Merugu <mtharu@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
index 9b1b9ee..b0db996 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
@@ -12,6 +12,7 @@
Optional properties:
- qcom,fastrpc-glink: Flag to use glink instead of smd for IPC
+- qcom,rpc-latency-us: FastRPC QoS latency vote
Optional subnodes:
- qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context
@@ -26,6 +27,7 @@
qcom,msm_fastrpc {
compatible = "qcom,msm-fastrpc-adsp";
qcom,fastrpc-glink;
+ qcom,rpc-latency-us = <2343>;
qcom,msm_fastrpc_compute_cb_1 {
compatible = "qcom,msm-fastrpc-compute-cb";
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index d1e01bd..72d6d09 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -45,7 +45,7 @@
#include "adsprpc_compat.h"
#include "adsprpc_shared.h"
#include <linux/debugfs.h>
-
+#include <linux/pm_qos.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
@@ -73,6 +73,7 @@
#define PERF_KEYS "count:flush:map:copy:glink:getargs:putargs:invalidate:invoke"
#define FASTRPC_STATIC_HANDLE_LISTENER (3)
#define FASTRPC_STATIC_HANDLE_MAX (20)
+#define FASTRPC_LATENCY_CTRL_ENB (1)
#define PERF_END (void)0
@@ -235,6 +236,7 @@
spinlock_t hlock;
struct ion_client *client;
struct device *dev;
+ unsigned int latency;
};
struct fastrpc_mmap {
@@ -288,6 +290,8 @@
struct fastrpc_apps *apps;
struct fastrpc_perf perf;
struct dentry *debugfs_file;
+ struct pm_qos_request pm_qos_req;
+ int qos_request;
};
static struct fastrpc_apps gfa;
@@ -1923,6 +1927,8 @@
struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
if (fl) {
+ if (fl->qos_request && pm_qos_request_active(&fl->pm_qos_req))
+ pm_qos_remove_request(&fl->pm_qos_req);
if (fl->debugfs_file != NULL)
debugfs_remove(fl->debugfs_file);
fastrpc_file_free(fl);
@@ -2225,6 +2231,7 @@
if (debugfs_file != NULL)
fl->debugfs_file = debugfs_file;
memset(&fl->perf, 0, sizeof(fl->perf));
+ fl->qos_request = 0;
filp->private_data = fl;
spin_lock(&me->hlock);
hlist_add_head(&fl->hn, &me->drivers);
@@ -2260,6 +2267,41 @@
return err;
}
+static int fastrpc_internal_control(struct fastrpc_file *fl,
+ struct fastrpc_ioctl_control *cp)
+{
+ int err = 0;
+ int latency;
+
+ VERIFY(err, !IS_ERR_OR_NULL(fl) && !IS_ERR_OR_NULL(fl->apps));
+ if (err)
+ goto bail;
+ VERIFY(err, !IS_ERR_OR_NULL(cp));
+ if (err)
+ goto bail;
+
+ switch (cp->req) {
+ case FASTRPC_CONTROL_LATENCY:
+ latency = cp->lp.enable == FASTRPC_LATENCY_CTRL_ENB ?
+ fl->apps->latency : PM_QOS_DEFAULT_VALUE;
+ VERIFY(err, latency != 0);
+ if (err)
+ goto bail;
+ if (!fl->qos_request) {
+ pm_qos_add_request(&fl->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY, latency);
+ fl->qos_request = 1;
+ } else
+ pm_qos_update_request(&fl->pm_qos_req, latency);
+ break;
+ default:
+ err = -ENOTTY;
+ break;
+ }
+bail:
+ return err;
+}
+
static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param)
{
@@ -2269,6 +2311,7 @@
struct fastrpc_ioctl_munmap munmap;
struct fastrpc_ioctl_init_attrs init;
struct fastrpc_ioctl_perf perf;
+ struct fastrpc_ioctl_control cp;
} p;
void *param = (char *)ioctl_param;
struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
@@ -2368,6 +2411,15 @@
if (err)
goto bail;
break;
+ case FASTRPC_IOCTL_CONTROL:
+ VERIFY(err, 0 == copy_from_user(&p.cp, (void __user *)param,
+ sizeof(p.cp)));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp)));
+ if (err)
+ goto bail;
+ break;
case FASTRPC_IOCTL_GETINFO:
VERIFY(err, 0 == copy_from_user(&info, param, sizeof(info)));
if (err)
@@ -2563,6 +2615,10 @@
return 0;
}
+ err = of_property_read_u32(dev->of_node, "qcom,rpc-latency-us",
+ &me->latency);
+ if (err)
+ me->latency = 0;
VERIFY(err, !of_platform_populate(pdev->dev.of_node,
fastrpc_match_table,
NULL, &pdev->dev));
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 078b4d9..21ad3f9 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -11,7 +11,6 @@
* GNU General Public License for more details.
*
*/
-
#include <linux/compat.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
@@ -38,6 +37,8 @@
_IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
#define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
_IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
+#define COMPAT_FASTRPC_IOCTL_CONTROL \
+ _IOWR('R', 12, struct compat_fastrpc_ioctl_control)
struct compat_remote_buf {
compat_uptr_t pv; /* buffer pointer */
@@ -108,6 +109,19 @@
compat_uptr_t keys;
};
+#define FASTRPC_CONTROL_LATENCY (1)
+struct compat_fastrpc_ctrl_latency {
+ compat_uint_t enable; /* latency control enable */
+ compat_uint_t level; /* level of control */
+};
+
+struct compat_fastrpc_ioctl_control {
+ compat_uint_t req;
+ union {
+ struct compat_fastrpc_ctrl_latency lp;
+ };
+};
+
static int compat_get_fastrpc_ioctl_invoke(
struct compat_fastrpc_ioctl_invoke_crc __user *inv32,
struct fastrpc_ioctl_invoke_crc __user **inva,
@@ -236,6 +250,25 @@
return err;
}
+static int compat_get_fastrpc_ioctl_control(
+ struct compat_fastrpc_ioctl_control __user *ctrl32,
+ struct fastrpc_ioctl_control __user *ctrl)
+{
+ compat_uptr_t p;
+ int err;
+
+ err = get_user(p, &ctrl32->req);
+ err |= put_user(p, &ctrl->req);
+ if (p == FASTRPC_CONTROL_LATENCY) {
+ err |= get_user(p, &ctrl32->lp.enable);
+ err |= put_user(p, &ctrl->lp.enable);
+ err |= get_user(p, &ctrl32->lp.level);
+ err |= put_user(p, &ctrl->lp.level);
+ }
+
+ return err;
+}
+
static int compat_get_fastrpc_ioctl_init(
struct compat_fastrpc_ioctl_init_attrs __user *init32,
struct fastrpc_ioctl_init_attrs __user *init,
@@ -385,6 +418,24 @@
case FASTRPC_IOCTL_SETMODE:
return filp->f_op->unlocked_ioctl(filp, cmd,
(unsigned long)compat_ptr(arg));
+ case COMPAT_FASTRPC_IOCTL_CONTROL:
+ {
+ struct compat_fastrpc_ioctl_control __user *ctrl32;
+ struct fastrpc_ioctl_control __user *ctrl;
+
+ ctrl32 = compat_ptr(arg);
+ VERIFY(err, NULL != (ctrl = compat_alloc_user_space(
+ sizeof(*ctrl))));
+ if (err)
+ return -EFAULT;
+ VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
+ ctrl));
+ if (err)
+ return err;
+ err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL,
+ (unsigned long)ctrl);
+ return err;
+ }
case COMPAT_FASTRPC_IOCTL_GETPERF:
{
struct compat_fastrpc_ioctl_perf __user *perf32;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 0441451..9f964d2 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -28,6 +28,7 @@
#define FASTRPC_IOCTL_GETPERF _IOWR('R', 9, struct fastrpc_ioctl_perf)
#define FASTRPC_IOCTL_INIT_ATTRS _IOWR('R', 10, struct fastrpc_ioctl_init_attrs)
#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_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
@@ -205,6 +206,19 @@
uintptr_t __user keys;
};
+#define FASTRPC_CONTROL_LATENCY (1)
+struct fastrpc_ctrl_latency {
+ uint32_t enable; //!latency control enable
+ uint32_t level; //!level of control
+};
+
+struct fastrpc_ioctl_control {
+ uint32_t req;
+ union {
+ struct fastrpc_ctrl_latency lp;
+ };
+};
+
struct smq_null_invoke {
uint64_t ctx; /* invoke caller context */
uint32_t handle; /* handle to invoke */