Merge "msm: ADSPRPC: add profiling counters"
This commit is contained in:
commit
b27dee6e83
3 changed files with 167 additions and 3 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue