diff options
author | Konsta Holtta <kholtta@nvidia.com> | 2013-08-30 10:16:41 +0300 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-27 12:51:52 -0700 |
commit | 41797576db9434854211956abe9cc56ad79f2a9c (patch) | |
tree | 300e2fd63a532fdc75b15652b54321a33efb0fd0 /lib | |
parent | 9a725a610d02715b098e20936b1f3103cfffe755 (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.c | 108 |
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: |