summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKonsta Holtta <kholtta@nvidia.com>2013-08-30 10:16:41 +0300
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-27 12:51:52 -0700
commit41797576db9434854211956abe9cc56ad79f2a9c (patch)
tree300e2fd63a532fdc75b15652b54321a33efb0fd0 /lib
parent9a725a610d02715b098e20936b1f3103cfffe755 (diff)
dma-debug: dump buffers and mappings via debugfs
Export via debugfs the debug-dma infrastructure's data about allocated mappings, and architecture specific information about possible mappings. Bug 1173494 Change-Id: I6c64364dad69f83fd301a89938fe184dde33806a Signed-off-by: Konsta Holtta <kholtta@nvidia.com> Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com> Reviewed-on: http://git-master/r/268384 GVS: Gerrit_Virtual_Submit Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/dma-debug.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index cc42171ff462..554352eeae2e 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -659,6 +659,111 @@ out_unlock:
return count;
}
+char *__weak debug_dma_platformdata(struct device *dev)
+{
+ /* empty string by default */
+ static char buf[1];
+
+ return buf;
+}
+
+static inline void seq_print_ip_sym(struct seq_file *s, unsigned long ip)
+{
+ seq_printf(s, "[<%p>] %pS\n", (void *)ip, (void *)ip);
+}
+
+void seq_print_trace(struct seq_file *s, struct stack_trace *trace)
+{
+ int i;
+
+ if (WARN_ON(!trace->entries))
+ return;
+
+ for (i = trace->skip; i < trace->nr_entries; i++)
+ seq_print_ip_sym(s, trace->entries[i]);
+}
+
+/*
+ * Print all map entries just in the order they are stored. We assume that the
+ * user will be able to parse this later anyway. Detailed output includes stack
+ * traces of allocations.
+ */
+void seq_print_dma_mappings(struct seq_file *s, int detail)
+{
+ int idx;
+
+ for (idx = 0; idx < HASH_SIZE; idx++) {
+ struct hash_bucket *bucket = &dma_entry_hash[idx];
+ struct dma_debug_entry *entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bucket->lock, flags);
+
+ list_for_each_entry(entry, &bucket->list, list) {
+ seq_printf(s,
+ " %s %s idx %d P=%llx D=%llx L=%llx %s A=%s\n",
+ dev_name(entry->dev),
+ type2name[entry->type], idx,
+ (u64)entry->paddr,
+ entry->dev_addr, entry->size,
+ dir2name[entry->direction],
+ debug_dma_platformdata(entry->dev));
+
+ if (detail)
+ seq_print_trace(s, &entry->stacktrace);
+ }
+
+ spin_unlock_irqrestore(&bucket->lock, flags);
+ }
+}
+
+void __weak dma_debugfs_platform_info(struct dentry *dent)
+{
+}
+
+static int _dump_allocs(struct seq_file *s, void *data)
+{
+ int detail = (int)s->private;
+
+ seq_print_dma_mappings(s, detail);
+ return 0;
+}
+
+#define DEFINE_DEBUGFS(__name, __func, __data) \
+static int __name ## _open(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, __func, __data); \
+} \
+static const struct file_operations __name ## _fops = { \
+ .open = __name ## _open, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+}
+
+DEFINE_DEBUGFS(_dump_allocs, _dump_allocs, NULL);
+DEFINE_DEBUGFS(_dump_allocs_detail, _dump_allocs, (void *)1);
+#undef DEFINE_DEBUGFS
+
+static int map_dump_debug_fs_init(void)
+{
+#define CREATE_FILE(name) \
+ debugfs_create_file(#name, S_IRUGO, \
+ dma_debug_dent, NULL, \
+ &_##name##_fops)
+
+ if (!CREATE_FILE(dump_allocs))
+ return -ENOMEM;
+
+ if (!CREATE_FILE(dump_allocs_detail))
+ return -ENOMEM;
+
+#undef CREATE_FILE
+
+ dma_debugfs_platform_info(dma_debug_dent);
+ return 0;
+}
+
static const struct file_operations filter_fops = {
.read = filter_read,
.write = filter_write,
@@ -713,6 +818,9 @@ static int dma_debug_fs_init(void)
if (!filter_dent)
goto out_err;
+ if (map_dump_debug_fs_init())
+ goto out_err;
+
return 0;
out_err: