Merge "msm: ADSPRPC: add profiling counters"

This commit is contained in:
Linux Build Service Account 2017-01-16 23:06:10 -08:00 committed by Gerrit - the friendly Code Review server
commit b27dee6e83
3 changed files with 167 additions and 3 deletions

View file

@ -70,6 +70,24 @@
#define FASTRPC_LINK_CONNECTED (0x3) #define FASTRPC_LINK_CONNECTED (0x3)
#define FASTRPC_LINK_DISCONNECTING (0x7) #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 int fastrpc_glink_open(int cid);
static void fastrpc_glink_close(void *chan, int cid); static void fastrpc_glink_close(void *chan, int cid);
@ -237,6 +255,18 @@ struct fastrpc_mmap {
uintptr_t attr; 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 fastrpc_file {
struct hlist_node hn; struct hlist_node hn;
spinlock_t hlock; spinlock_t hlock;
@ -246,11 +276,13 @@ struct fastrpc_file {
struct fastrpc_session_ctx *sctx; struct fastrpc_session_ctx *sctx;
struct fastrpc_session_ctx *secsctx; struct fastrpc_session_ctx *secsctx;
uint32_t mode; uint32_t mode;
uint32_t profile;
int tgid; int tgid;
int cid; int cid;
int ssrcount; int ssrcount;
int pd; int pd;
struct fastrpc_apps *apps; struct fastrpc_apps *apps;
struct fastrpc_perf perf;
}; };
static struct fastrpc_apps gfa; 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) static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
{ {
struct fastrpc_file *fl = buf == 0 ? 0 : buf->fl; 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++; ipage++;
} }
/* map ion buffers */ /* map ion buffers */
PERF(ctx->fl->profile, ctx->fl->perf.map,
for (i = 0; i < inbufs + outbufs; ++i) { for (i = 0; i < inbufs + outbufs; ++i) {
struct fastrpc_mmap *map = ctx->maps[i]; struct fastrpc_mmap *map = ctx->maps[i];
uint64_t buf = ptr_to_uint64(lpra[i].buf.pv); 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; rpra[i].buf.pv = buf;
} }
PERF_END);
/* copy non ion buffers */ /* copy non ion buffers */
PERF(ctx->fl->profile, ctx->fl->perf.copy,
rlen = copylen - metalen; rlen = copylen - metalen;
for (oix = 0; oix < inbufs + outbufs; ++oix) { for (oix = 0; oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix; 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; args = args + mlen;
rlen -= mlen; rlen -= mlen;
} }
PERF_END);
PERF(ctx->fl->profile, ctx->fl->perf.flush,
for (oix = 0; oix < inbufs + outbufs; ++oix) { for (oix = 0; oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix; int i = ctx->overps[oix]->raix;
struct fastrpc_mmap *map = ctx->maps[i]; 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), dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len)); uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
} }
PERF_END);
inh = inbufs + outbufs; inh = inbufs + outbufs;
for (i = 0; i < REMOTE_SCALARS_INHANDLES(sc); i++) { 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.pv = ptr_to_uint64(ctx->lpra[inh + i].buf.pv);
rpra[inh + i].buf.len = ctx->lpra[inh + i].buf.len; rpra[inh + i].buf.len = ctx->lpra[inh + i].buf.len;
rpra[inh + i].h = ctx->lpra[inh + i].h; 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); dmac_flush_range((char *)rpra, (char *)rpra + ctx->used);
PERF_END);
}
bail: bail:
return err; return err;
} }
@ -1390,7 +1445,10 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
int cid = fl->cid; int cid = fl->cid;
int interrupted = 0; int interrupted = 0;
int err = 0; int err = 0;
struct timespec invoket;
if (fl->profile)
getnstimeofday(&invoket);
if (!kernel) { if (!kernel) {
VERIFY(err, 0 == context_restore_interrupted(fl, inv, VERIFY(err, 0 == context_restore_interrupted(fl, inv,
&ctx)); &ctx));
@ -1409,19 +1467,30 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
goto bail; goto bail;
if (REMOTE_SCALARS_LENGTH(ctx->sc)) { if (REMOTE_SCALARS_LENGTH(ctx->sc)) {
PERF(fl->profile, fl->perf.getargs,
VERIFY(err, 0 == get_args(kernel, ctx)); VERIFY(err, 0 == get_args(kernel, ctx));
PERF_END);
if (err) if (err)
goto bail; goto bail;
} }
PERF(fl->profile, fl->perf.invargs,
inv_args_pre(ctx); inv_args_pre(ctx);
if (mode == FASTRPC_MODE_SERIAL) if (mode == FASTRPC_MODE_SERIAL)
inv_args(ctx); inv_args(ctx);
PERF_END);
PERF(fl->profile, fl->perf.link,
VERIFY(err, 0 == fastrpc_invoke_send(ctx, kernel, invoke->handle)); VERIFY(err, 0 == fastrpc_invoke_send(ctx, kernel, invoke->handle));
PERF_END);
if (err) if (err)
goto bail; goto bail;
PERF(fl->profile, fl->perf.invargs,
if (mode == FASTRPC_MODE_PARALLEL) if (mode == FASTRPC_MODE_PARALLEL)
inv_args(ctx); inv_args(ctx);
PERF_END);
wait: wait:
if (kernel) if (kernel)
wait_for_completion(&ctx->work); 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)); VERIFY(err, 0 == (err = ctx->retval));
if (err) if (err)
goto bail; goto bail;
PERF(fl->profile, fl->perf.putargs,
VERIFY(err, 0 == put_args(kernel, ctx, invoke->pra)); VERIFY(err, 0 == put_args(kernel, ctx, invoke->pra));
PERF_END);
if (err) if (err)
goto bail; goto bail;
bail: bail:
@ -1444,6 +1516,14 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
context_free(ctx); context_free(ctx);
if (fl->ssrcount != fl->apps->channel[cid].ssrcount) if (fl->ssrcount != fl->apps->channel[cid].ssrcount)
err = ECONNRESET; 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; return err;
} }
@ -2086,6 +2166,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->tgid = current->tgid; fl->tgid = current->tgid;
fl->apps = me; fl->apps = me;
fl->cid = cid; fl->cid = cid;
memset(&fl->perf, 0, sizeof(fl->perf));
VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0, VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0,
&fl->sctx)); &fl->sctx));
if (err) 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_mmap mmap;
struct fastrpc_ioctl_munmap munmap; struct fastrpc_ioctl_munmap munmap;
struct fastrpc_ioctl_init init; struct fastrpc_ioctl_init init;
struct fastrpc_ioctl_perf perf;
} p; } p;
void *param = (char *)ioctl_param; void *param = (char *)ioctl_param;
struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; 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: case FASTRPC_MODE_SERIAL:
fl->mode = (uint32_t)ioctl_param; fl->mode = (uint32_t)ioctl_param;
break; break;
case FASTRPC_MODE_PROFILE:
fl->profile = (uint32_t)ioctl_param;
break;
default: default:
err = -ENOTTY; err = -ENOTTY;
break; break;
} }
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: case FASTRPC_IOCTL_GETINFO:
VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info))); VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info)));
if (err) if (err)

View file

@ -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 * 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 * 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) _IOWR('R', 6, struct compat_fastrpc_ioctl_init)
#define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \ #define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
_IOWR('R', 7, struct 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 { struct compat_remote_buf {
compat_uptr_t pv; /* buffer pointer */ compat_uptr_t pv; /* buffer pointer */
@ -83,6 +85,12 @@ struct compat_fastrpc_ioctl_init {
compat_int_t memfd; /* ION fd for the mem */ 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( static int compat_get_fastrpc_ioctl_invoke(
struct compat_fastrpc_ioctl_invoke_attrs __user *inv32, struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
struct fastrpc_ioctl_invoke_attrs __user **inva, struct fastrpc_ioctl_invoke_attrs __user **inva,
@ -222,6 +230,21 @@ static int compat_get_fastrpc_ioctl_munmap(
return err; 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( static int compat_get_fastrpc_ioctl_init(
struct compat_fastrpc_ioctl_init __user *init32, struct compat_fastrpc_ioctl_init __user *init32,
struct fastrpc_ioctl_init __user *init) 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: case FASTRPC_IOCTL_SETMODE:
return filp->f_op->unlocked_ioctl(filp, cmd, return filp->f_op->unlocked_ioctl(filp, cmd,
(unsigned long)compat_ptr(arg)); (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: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }

View file

@ -25,6 +25,7 @@
#define FASTRPC_IOCTL_INVOKE_ATTRS \ #define FASTRPC_IOCTL_INVOKE_ATTRS \
_IOWR('R', 7, struct fastrpc_ioctl_invoke_attrs) _IOWR('R', 7, struct fastrpc_ioctl_invoke_attrs)
#define FASTRPC_IOCTL_GETINFO _IOWR('R', 8, uint32_t) #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_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
@ -45,6 +46,9 @@
/* Driver should operate in serial mode with the co-processor */ /* Driver should operate in serial mode with the co-processor */
#define FASTRPC_MODE_SERIAL 1 #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 */ /* INIT a new process or attach to guestos */
#define FASTRPC_INIT_ATTACH 0 #define FASTRPC_INIT_ATTACH 0
#define FASTRPC_INIT_CREATE 1 #define FASTRPC_INIT_CREATE 1
@ -159,7 +163,6 @@ struct fastrpc_ioctl_munmap {
ssize_t size; /* size */ ssize_t size; /* size */
}; };
struct fastrpc_ioctl_mmap { struct fastrpc_ioctl_mmap {
int fd; /* ion fd */ int fd; /* ion fd */
uint32_t flags; /* flags for dsp to map with */ uint32_t flags; /* flags for dsp to map with */
@ -168,6 +171,12 @@ struct fastrpc_ioctl_mmap {
uintptr_t vaddrout; /* dsps virtual address */ 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 { struct smq_null_invoke {
uint64_t ctx; /* invoke caller context */ uint64_t ctx; /* invoke caller context */
uint32_t handle; /* handle to invoke */ uint32_t handle; /* handle to invoke */