From df3c528a5943d5c0b47720760df55c80f8e0d3a5 Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Wed, 11 Jan 2017 16:11:01 -0800 Subject: 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 Signed-off-by: Sathish Ambley --- drivers/char/adsprpc.c | 110 +++++++++++++++++++++++++++++++++++++++++- drivers/char/adsprpc_compat.c | 49 ++++++++++++++++++- drivers/char/adsprpc_shared.h | 11 ++++- 3 files changed, 167 insertions(+), 3 deletions(-) (limited to 'drivers') 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 */ -- cgit v1.2.3