OSDN Git Service

msm: ADSPRPC: add profiling counters
authorSathish Ambley <sathishambley@codeaurora.org>
Thu, 12 Jan 2017 00:11:01 +0000 (16:11 -0800)
committerSathish Ambley <sathishambley@codeaurora.org>
Tue, 17 Jan 2017 00:05:12 +0000 (16:05 -0800)
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>
drivers/char/adsprpc.c
drivers/char/adsprpc_compat.c
drivers/char/adsprpc_shared.h

index 896bd6e..82caf98 100644 (file)
 #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)
index 1e5649a..a224ba7 100644 (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
  * 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;
        }
index 4fc9396..9b24e2d 100644 (file)
@@ -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 */