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/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));