summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSathish Ambley <sathishambley@codeaurora.org>2017-01-11 16:11:01 -0800
committerSathish Ambley <sathishambley@codeaurora.org>2017-01-16 16:05:12 -0800
commitdf3c528a5943d5c0b47720760df55c80f8e0d3a5 (patch)
tree738d13fa78a7d89c5a22fe0819ab5f68916b5ee3 /drivers
parente83e4c14e91799f39990016fd8ba7f1628ad5ffa (diff)
msm: ADSPRPC: add profiling counters
Added profiling counters for measuring RPC performance and by default profiling is disabled. Change-Id: I6a79dde638e751998ac37948f826639a161ff4a2 Acked-by: Viswanatham Paduchuri <vpaduchu@qti.qualcomm.com> Signed-off-by: Sathish Ambley <sathishambley@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/adsprpc.c110
-rw-r--r--drivers/char/adsprpc_compat.c49
-rw-r--r--drivers/char/adsprpc_shared.h11
3 files changed, 167 insertions, 3 deletions
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 896bd6ec90f6..82caf98491fa 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -70,6 +70,24 @@
#define FASTRPC_LINK_CONNECTED (0x3)
#define FASTRPC_LINK_DISCONNECTING (0x7)
+#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 PERF_END (void)0
+
+#define PERF(enb, cnt, ff) \
+ {\
+ struct timespec startT = {0};\
+ if (enb) {\
+ getnstimeofday(&startT);\
+ } \
+ ff ;\
+ if (enb) {\
+ cnt += getnstimediff(&startT);\
+ } \
+ }
+
static int fastrpc_glink_open(int cid);
static void fastrpc_glink_close(void *chan, int cid);
@@ -237,6 +255,18 @@ struct fastrpc_mmap {
uintptr_t attr;
};
+struct fastrpc_perf {
+ int64_t count;
+ int64_t flush;
+ int64_t map;
+ int64_t copy;
+ int64_t link;
+ int64_t getargs;
+ int64_t putargs;
+ int64_t invargs;
+ int64_t invoke;
+};
+
struct fastrpc_file {
struct hlist_node hn;
spinlock_t hlock;
@@ -246,11 +276,13 @@ struct fastrpc_file {
struct fastrpc_session_ctx *sctx;
struct fastrpc_session_ctx *secsctx;
uint32_t mode;
+ uint32_t profile;
int tgid;
int cid;
int ssrcount;
int pd;
struct fastrpc_apps *apps;
+ struct fastrpc_perf perf;
};
static struct fastrpc_apps gfa;
@@ -286,6 +318,17 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
},
};
+static inline int64_t getnstimediff(struct timespec *start)
+{
+ int64_t ns;
+ struct timespec ts, b;
+
+ getnstimeofday(&ts);
+ b = timespec_sub(ts, *start);
+ ns = timespec_to_ns(&b);
+ return ns;
+}
+
static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
{
struct fastrpc_file *fl = buf == 0 ? 0 : buf->fl;
@@ -1075,6 +1118,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
ipage++;
}
/* map ion buffers */
+ PERF(ctx->fl->profile, ctx->fl->perf.map,
for (i = 0; i < inbufs + outbufs; ++i) {
struct fastrpc_mmap *map = ctx->maps[i];
uint64_t buf = ptr_to_uint64(lpra[i].buf.pv);
@@ -1110,7 +1154,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
}
rpra[i].buf.pv = buf;
}
+ PERF_END);
+
/* copy non ion buffers */
+ PERF(ctx->fl->profile, ctx->fl->perf.copy,
rlen = copylen - metalen;
for (oix = 0; oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix;
@@ -1146,7 +1193,9 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
args = args + mlen;
rlen -= mlen;
}
+ PERF_END);
+ PERF(ctx->fl->profile, ctx->fl->perf.flush,
for (oix = 0; oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix;
struct fastrpc_mmap *map = ctx->maps[i];
@@ -1163,14 +1212,20 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
}
+ PERF_END);
+
inh = inbufs + outbufs;
for (i = 0; i < REMOTE_SCALARS_INHANDLES(sc); i++) {
rpra[inh + i].buf.pv = ptr_to_uint64(ctx->lpra[inh + i].buf.pv);
rpra[inh + i].buf.len = ctx->lpra[inh + i].buf.len;
rpra[inh + i].h = ctx->lpra[inh + i].h;
}
- if (!ctx->fl->sctx->smmu.coherent)
+
+ if (!ctx->fl->sctx->smmu.coherent) {
+ PERF(ctx->fl->profile, ctx->fl->perf.flush,
dmac_flush_range((char *)rpra, (char *)rpra + ctx->used);
+ PERF_END);
+ }
bail:
return err;
}
@@ -1390,7 +1445,10 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
int cid = fl->cid;
int interrupted = 0;
int err = 0;
+ struct timespec invoket;
+ if (fl->profile)
+ getnstimeofday(&invoket);
if (!kernel) {
VERIFY(err, 0 == context_restore_interrupted(fl, inv,
&ctx));
@@ -1409,19 +1467,30 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
goto bail;
if (REMOTE_SCALARS_LENGTH(ctx->sc)) {
+ PERF(fl->profile, fl->perf.getargs,
VERIFY(err, 0 == get_args(kernel, ctx));
+ PERF_END);
if (err)
goto bail;
}
+ PERF(fl->profile, fl->perf.invargs,
inv_args_pre(ctx);
if (mode == FASTRPC_MODE_SERIAL)
inv_args(ctx);
+ PERF_END);
+
+ PERF(fl->profile, fl->perf.link,
VERIFY(err, 0 == fastrpc_invoke_send(ctx, kernel, invoke->handle));
+ PERF_END);
+
if (err)
goto bail;
+
+ PERF(fl->profile, fl->perf.invargs,
if (mode == FASTRPC_MODE_PARALLEL)
inv_args(ctx);
+ PERF_END);
wait:
if (kernel)
wait_for_completion(&ctx->work);
@@ -1434,7 +1503,10 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
VERIFY(err, 0 == (err = ctx->retval));
if (err)
goto bail;
+
+ PERF(fl->profile, fl->perf.putargs,
VERIFY(err, 0 == put_args(kernel, ctx, invoke->pra));
+ PERF_END);
if (err)
goto bail;
bail:
@@ -1444,6 +1516,14 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
context_free(ctx);
if (fl->ssrcount != fl->apps->channel[cid].ssrcount)
err = ECONNRESET;
+
+ if (fl->profile && !interrupted) {
+ if (invoke->handle != FASTRPC_STATIC_HANDLE_LISTENER)
+ fl->perf.invoke += getnstimediff(&invoket);
+ if (!(invoke->handle >= 0 &&
+ invoke->handle <= FASTRPC_STATIC_HANDLE_MAX))
+ fl->perf.count++;
+ }
return err;
}
@@ -2086,6 +2166,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->tgid = current->tgid;
fl->apps = me;
fl->cid = cid;
+ memset(&fl->perf, 0, sizeof(fl->perf));
+
VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0,
&fl->sctx));
if (err)
@@ -2156,6 +2238,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
struct fastrpc_ioctl_mmap mmap;
struct fastrpc_ioctl_munmap munmap;
struct fastrpc_ioctl_init init;
+ struct fastrpc_ioctl_perf perf;
} p;
void *param = (char *)ioctl_param;
struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
@@ -2211,11 +2294,36 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
case FASTRPC_MODE_SERIAL:
fl->mode = (uint32_t)ioctl_param;
break;
+ case FASTRPC_MODE_PROFILE:
+ fl->profile = (uint32_t)ioctl_param;
+ break;
default:
err = -ENOTTY;
break;
}
break;
+ case FASTRPC_IOCTL_GETPERF:
+ VERIFY(err, 0 == copy_from_user(&p.perf,
+ param, sizeof(p.perf)));
+ if (err)
+ goto bail;
+ p.perf.numkeys = sizeof(struct fastrpc_perf)/sizeof(int64_t);
+ if (p.perf.keys) {
+ char *keys = PERF_KEYS;
+
+ VERIFY(err, 0 == copy_to_user((char *)p.perf.keys,
+ keys, strlen(keys)+1));
+ if (err)
+ goto bail;
+ }
+ if (p.perf.data) {
+ VERIFY(err, 0 == copy_to_user((int64_t *)p.perf.data,
+ &fl->perf, sizeof(fl->perf)));
+ }
+ VERIFY(err, 0 == copy_to_user(param, &p.perf, sizeof(p.perf)));
+ if (err)
+ goto bail;
+ break;
case FASTRPC_IOCTL_GETINFO:
VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info)));
if (err)
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 1e5649a8d4c4..a224ba7ed3e4 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, 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 @@
_IOWR('R', 6, struct compat_fastrpc_ioctl_init)
#define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
_IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
+#define COMPAT_FASTRPC_IOCTL_GETPERF \
+ _IOWR('R', 9, struct compat_fastrpc_ioctl_perf)
struct compat_remote_buf {
compat_uptr_t pv; /* buffer pointer */
@@ -83,6 +85,12 @@ struct compat_fastrpc_ioctl_init {
compat_int_t memfd; /* ION fd for the mem */
};
+struct compat_fastrpc_ioctl_perf { /* kernel performance data */
+ compat_uptr_t data;
+ compat_int_t numkeys;
+ compat_uptr_t keys;
+};
+
static int compat_get_fastrpc_ioctl_invoke(
struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
struct fastrpc_ioctl_invoke_attrs __user **inva,
@@ -222,6 +230,21 @@ static int compat_get_fastrpc_ioctl_munmap(
return err;
}
+static int compat_get_fastrpc_ioctl_perf(
+ struct compat_fastrpc_ioctl_perf __user *perf32,
+ struct fastrpc_ioctl_perf __user *perf)
+{
+ compat_uptr_t p;
+ int err;
+
+ err = get_user(p, &perf32->data);
+ err |= put_user(p, &perf->data);
+ err |= get_user(p, &perf32->keys);
+ err |= put_user(p, &perf->keys);
+
+ return err;
+}
+
static int compat_get_fastrpc_ioctl_init(
struct compat_fastrpc_ioctl_init __user *init32,
struct fastrpc_ioctl_init __user *init)
@@ -356,6 +379,30 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
case FASTRPC_IOCTL_SETMODE:
return filp->f_op->unlocked_ioctl(filp, cmd,
(unsigned long)compat_ptr(arg));
+ case COMPAT_FASTRPC_IOCTL_GETPERF:
+ {
+ struct compat_fastrpc_ioctl_perf __user *perf32;
+ struct fastrpc_ioctl_perf *perf;
+ compat_uint_t u;
+ long ret;
+
+ perf32 = compat_ptr(arg);
+ VERIFY(err, NULL != (perf = compat_alloc_user_space(
+ sizeof(*perf))));
+ if (err)
+ return -EFAULT;
+ VERIFY(err, 0 == compat_get_fastrpc_ioctl_perf(perf32,
+ perf));
+ if (err)
+ return err;
+ ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETPERF,
+ (unsigned long)perf);
+ if (ret)
+ return ret;
+ err = get_user(u, &perf->numkeys);
+ err |= put_user(u, &perf32->numkeys);
+ return err;
+ }
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 4fc9396bfd3a..9b24e2da489f 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -25,6 +25,7 @@
#define FASTRPC_IOCTL_INVOKE_ATTRS \
_IOWR('R', 7, struct fastrpc_ioctl_invoke_attrs)
#define FASTRPC_IOCTL_GETINFO _IOWR('R', 8, uint32_t)
+#define FASTRPC_IOCTL_GETPERF _IOWR('R', 9, struct fastrpc_ioctl_perf)
#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
@@ -45,6 +46,9 @@
/* Driver should operate in serial mode with the co-processor */
#define FASTRPC_MODE_SERIAL 1
+/* Driver should operate in profile mode with the co-processor */
+#define FASTRPC_MODE_PROFILE 2
+
/* INIT a new process or attach to guestos */
#define FASTRPC_INIT_ATTACH 0
#define FASTRPC_INIT_CREATE 1
@@ -159,7 +163,6 @@ struct fastrpc_ioctl_munmap {
ssize_t size; /* size */
};
-
struct fastrpc_ioctl_mmap {
int fd; /* ion fd */
uint32_t flags; /* flags for dsp to map with */
@@ -168,6 +171,12 @@ struct fastrpc_ioctl_mmap {
uintptr_t vaddrout; /* dsps virtual address */
};
+struct fastrpc_ioctl_perf { /* kernel performance data */
+ uintptr_t __user data;
+ uint32_t numkeys;
+ uintptr_t __user keys;
+};
+
struct smq_null_invoke {
uint64_t ctx; /* invoke caller context */
uint32_t handle; /* handle to invoke */