OSDN Git Service

msm: ADSPRPC: Expose information about open devices
authorSathish Ambley <sathishambley@codeaurora.org>
Thu, 19 Jan 2017 18:32:55 +0000 (10:32 -0800)
committerGerrit - the friendly Code Review server <code-review@localhost>
Mon, 23 Jan 2017 05:35:53 +0000 (21:35 -0800)
Using Debugfs virtual file system to make debug information available
to userspace. A directory called adsprpc is created in debugfs root
directory and a debugfs file is created in this directory for every
device open in the fastrpc driver.

Change-Id: Ie944424e30ddc810ff29116481d63b266c47c037
Acked-by: Vishnu Karthik <vikarthi@qti.qualcomm.com>
Signed-off-by: Sathish Ambley <sathishambley@codeaurora.org>
drivers/char/adsprpc.c

index 03429b1..230856c 100644 (file)
@@ -48,6 +48,7 @@
 #include "adsprpc_compat.h"
 #include "adsprpc_shared.h"
 #include <soc/qcom/ramdump.h>
+#include <linux/debugfs.h>
 
 #define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C
 #define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
@@ -55,6 +56,7 @@
 #define ADSP_MMAP_HEAP_ADDR 4
 #define FASTRPC_ENOSUCH 39
 #define VMID_SSC_Q6     5
+#define DEBUGFS_SIZE 1024
 
 #define RPC_TIMEOUT    (5 * HZ)
 #define BALIGN         128
@@ -90,6 +92,8 @@
 
 static int fastrpc_glink_open(int cid);
 static void fastrpc_glink_close(void *chan, int cid);
+static struct dentry *debugfs_root;
+static struct dentry *debugfs_global_file;
 
 static inline uint64_t buf_page_start(uint64_t buf)
 {
@@ -283,6 +287,7 @@ struct fastrpc_file {
        int pd;
        struct fastrpc_apps *apps;
        struct fastrpc_perf perf;
+       struct dentry *debugfs_file;
 };
 
 static struct fastrpc_apps gfa;
@@ -2042,6 +2047,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
        struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
 
        if (fl) {
+               if (fl->debugfs_file != NULL)
+                       debugfs_remove(fl->debugfs_file);
                fastrpc_file_free(fl);
                file->private_data = 0;
        }
@@ -2158,9 +2165,124 @@ bail:
        return err;
 }
 
+static int fastrpc_debugfs_open(struct inode *inode, struct file *filp)
+{
+       filp->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
+                                        size_t count, loff_t *position)
+{
+       struct fastrpc_file *fl = filp->private_data;
+       struct hlist_node *n;
+       struct fastrpc_buf *buf = 0;
+       struct fastrpc_mmap *map = 0;
+       struct smq_invoke_ctx *ictx = 0;
+       struct fastrpc_channel_ctx *chan;
+       struct fastrpc_session_ctx *sess;
+       unsigned int len = 0;
+       int i, j, ret = 0;
+       char *fileinfo = NULL;
+
+       fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL);
+       if (!fileinfo)
+               goto bail;
+       if (fl == NULL) {
+               for (i = 0; i < NUM_CHANNELS; i++) {
+                       chan = &gcinfo[i];
+                       len += scnprintf(fileinfo + len,
+                                       DEBUGFS_SIZE - len, "%s\n\n",
+                                       chan->name);
+                       len += scnprintf(fileinfo + len,
+                                       DEBUGFS_SIZE - len, "%s %d\n",
+                                       "sesscount:", chan->sesscount);
+                       for (j = 0; j < chan->sesscount; j++) {
+                               sess = &chan->session[j];
+                               len += scnprintf(fileinfo + len,
+                                               DEBUGFS_SIZE - len,
+                                               "%s%d\n\n", "SESSION", j);
+                               len += scnprintf(fileinfo + len,
+                                               DEBUGFS_SIZE - len,
+                                               "%s %d\n", "sid:",
+                                               sess->smmu.cb);
+                               len += scnprintf(fileinfo + len,
+                                               DEBUGFS_SIZE - len,
+                                               "%s %d\n", "SECURE:",
+                                               sess->smmu.secure);
+                       }
+               }
+       } else {
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                               "%s %d\n\n",
+                               "PROCESS_ID:", fl->tgid);
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                               "%s %d\n\n",
+                               "CHANNEL_ID:", fl->cid);
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                               "%s %d\n\n",
+                               "SSRCOUNT:", fl->ssrcount);
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                               "%s\n",
+                               "LIST OF BUFS:");
+               spin_lock(&fl->hlock);
+               hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
+                       len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                                               "%s %p %s %p %s %llx\n", "buf:",
+                                               buf, "buf->virt:", buf->virt,
+                                               "buf->phys:", buf->phys);
+               }
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                                       "\n%s\n",
+                                       "LIST OF MAPS:");
+               hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
+                       len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                                               "%s %p %s %lx %s %llx\n",
+                                               "map:", map,
+                                               "map->va:", map->va,
+                                               "map->phys:", map->phys);
+               }
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                                       "\n%s\n",
+                                       "LIST OF PENDING SMQCONTEXTS:");
+               hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) {
+                       len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                                               "%s %p %s %u %s %u %s %u\n",
+                                               "smqcontext:", ictx,
+                                               "sc:", ictx->sc,
+                                               "tid:", ictx->pid,
+                                               "handle", ictx->rpra->h);
+               }
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                                       "\n%s\n",
+                                       "LIST OF INTERRUPTED SMQCONTEXTS:");
+               hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) {
+               len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+                                       "%s %p %s %u %s %u %s %u\n",
+                                       "smqcontext:", ictx,
+                                       "sc:", ictx->sc,
+                                       "tid:", ictx->pid,
+                                       "handle", ictx->rpra->h);
+               }
+               spin_unlock(&fl->hlock);
+       }
+       if (len > DEBUGFS_SIZE)
+               len = DEBUGFS_SIZE;
+       ret = simple_read_from_buffer(buffer, count, position, fileinfo, len);
+       kfree(fileinfo);
+bail:
+       return ret;
+}
+
+static const struct file_operations debugfs_fops = {
+       .open = fastrpc_debugfs_open,
+       .read = fastrpc_debugfs_read,
+};
+
 static int fastrpc_device_open(struct inode *inode, struct file *filp)
 {
        int cid = MINOR(inode->i_rdev);
+       struct dentry *debugfs_file;
        int err = 0;
        struct fastrpc_apps *me = &gfa;
        struct fastrpc_file *fl = 0;
@@ -2173,6 +2295,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
 
        mutex_lock(&me->smd_mutex);
 
+       debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root,
+                                               fl, &debugfs_fops);
        context_list_ctor(&fl->clst);
        spin_lock_init(&fl->hlock);
        INIT_HLIST_HEAD(&fl->maps);
@@ -2181,6 +2305,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
        fl->tgid = current->tgid;
        fl->apps = me;
        fl->cid = cid;
+       if (debugfs_file != NULL)
+               fl->debugfs_file = debugfs_file;
        memset(&fl->perf, 0, sizeof(fl->perf));
 
        VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0,
@@ -2496,6 +2622,8 @@ static int fastrpc_cb_probe(struct device *dev)
        sess->dev = dev;
        sess->smmu.enabled = 1;
        chan->sesscount++;
+       debugfs_global_file = debugfs_create_file("global", 0644, debugfs_root,
+                                                       NULL, &debugfs_fops);
 bail:
        return err;
 }
@@ -2706,6 +2834,7 @@ static int __init fastrpc_device_init(void)
        VERIFY(err, !IS_ERR_OR_NULL(me->client));
        if (err)
                goto device_create_bail;
+       debugfs_root = debugfs_create_dir("adsprpc", NULL);
        return 0;
 device_create_bail:
        for (i = 0; i < NUM_CHANNELS; i++) {
@@ -2744,6 +2873,7 @@ static void __exit fastrpc_device_exit(void)
        cdev_del(&me->cdev);
        unregister_chrdev_region(me->dev_no, NUM_CHANNELS);
        ion_client_destroy(me->client);
+       debugfs_remove_recursive(debugfs_root);
 }
 
 late_initcall(fastrpc_device_init);