diff options
Diffstat (limited to 'drivers/char/adsprpc.c')
| -rw-r--r-- | drivers/char/adsprpc.c | 110 |
1 files changed, 109 insertions, 1 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) |
