diff options
author | Krishna Reddy <vdumpa@nvidia.com> | 2011-08-04 15:14:49 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-08-08 11:15:41 -0700 |
commit | 0ce7bbcb97b05efe22c8b1ba18fef3336a3577cf (patch) | |
tree | d47574269da81cda19d457890eeaca3f667f8321 | |
parent | 43619db4bdc6705359034068634d0f946e35cb4e (diff) |
video: tegra: nvmap: Add debugfs for iovmm allocations.
Change-Id: Ic50111924d7adf7838926cb534bbf841b7e8003a
Reviewed-on: http://git-master/r/45358
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.h | 1 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_dev.c | 114 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_handle.c | 16 |
3 files changed, 117 insertions, 14 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap.h b/drivers/video/tegra/nvmap/nvmap.h index 8bc70a920b16..8798949354d4 100644 --- a/drivers/video/tegra/nvmap/nvmap.h +++ b/drivers/video/tegra/nvmap/nvmap.h @@ -114,6 +114,7 @@ struct nvmap_client { bool super; atomic_t count; struct task_struct *task; + struct list_head list; struct nvmap_carveout_commit carveout_commit[0]; }; diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c index 1ebb1f4dcf82..d30100d3625c 100644 --- a/drivers/video/tegra/nvmap/nvmap_dev.c +++ b/drivers/video/tegra/nvmap/nvmap_dev.c @@ -79,6 +79,8 @@ struct nvmap_device { struct nvmap_carveout_node *heaps; int nr_carveouts; struct nvmap_share iovmm_master; + struct list_head clients; + spinlock_t clients_lock; }; struct nvmap_device *nvmap_dev; @@ -652,6 +654,9 @@ struct nvmap_client *nvmap_create_client(struct nvmap_device *dev, mutex_init(&client->ref_lock); atomic_set(&client->count, 1); + spin_lock(&dev->clients_lock); + list_add(&client->list, &dev->clients); + spin_unlock(&dev->clients_lock); return client; } @@ -699,6 +704,9 @@ static void destroy_client(struct nvmap_client *client) if (client->task) put_task_struct(client->task); + spin_lock(&client->dev->clients_lock); + list_del(&client->list); + spin_unlock(&client->dev->clients_lock); kfree(client); } @@ -956,17 +964,18 @@ static void client_stringify(struct nvmap_client *client, struct seq_file *s) { char task_comm[TASK_COMM_LEN]; if (!client->task) { - seq_printf(s, "%-16s %16s %8u", client->name, "kernel", 0); + seq_printf(s, "%-18s %18s %8u", client->name, "kernel", 0); return; } get_task_comm(task_comm, client->task); - seq_printf(s, "%-16s %16s %8u", client->name, task_comm, + seq_printf(s, "%-18s %18s %8u", client->name, task_comm, client->task->pid); } static void allocations_stringify(struct nvmap_client *client, struct seq_file *s) { + unsigned long base = 0; struct rb_node *n = rb_first(&client->handle_refs); for (; n != NULL; n = rb_next(n)) { @@ -974,9 +983,12 @@ static void allocations_stringify(struct nvmap_client *client, rb_entry(n, struct nvmap_handle_ref, node); struct nvmap_handle *handle = ref->handle; if (handle->alloc && !handle->heap_pgalloc) { - seq_printf(s, "%-16s %-16s %8lx %10u\n", "", "", + seq_printf(s, "%-18s %-18s %8lx %10u\n", "", "", (unsigned long)(handle->carveout->base), handle->size); + } else if (handle->alloc && handle->heap_pgalloc) { + seq_printf(s, "%-18s %-18s %8lx %10u\n", "", "", + base, handle->size); } } } @@ -989,6 +1001,10 @@ static int nvmap_debug_allocations_show(struct seq_file *s, void *unused) unsigned int total = 0; spin_lock_irqsave(&node->clients_lock, flags); + seq_printf(s, "%-18s %18s %8s %10s\n", "CLIENT", "PROCESS", "PID", + "SIZE"); + seq_printf(s, "%-18s %18s %8s %10s\n", "", "", + "BASE", "SIZE"); list_for_each_entry(commit, &node->clients, list) { struct nvmap_client *client = get_client_from_carveout_commit(node, commit); @@ -998,7 +1014,7 @@ static int nvmap_debug_allocations_show(struct seq_file *s, void *unused) seq_printf(s, "\n"); total += commit->commit; } - seq_printf(s, "%-16s %-16s %8u %10u\n", "total", "", 0, total); + seq_printf(s, "%-18s %-18s %8u %10u\n", "total", "", 0, total); spin_unlock_irqrestore(&node->clients_lock, flags); return 0; @@ -1025,6 +1041,8 @@ static int nvmap_debug_clients_show(struct seq_file *s, void *unused) unsigned int total = 0; spin_lock_irqsave(&node->clients_lock, flags); + seq_printf(s, "%-18s %18s %8s %10s\n", "CLIENT", "PROCESS", "PID", + "SIZE"); list_for_each_entry(commit, &node->clients, list) { struct nvmap_client *client = get_client_from_carveout_commit(node, commit); @@ -1032,7 +1050,7 @@ static int nvmap_debug_clients_show(struct seq_file *s, void *unused) seq_printf(s, " %10u\n", commit->commit); total += commit->commit; } - seq_printf(s, "%-16s %-16s %8u %10u\n", "total", "", 0, total); + seq_printf(s, "%-18s %18s %8u %10u\n", "total", "", 0, total); spin_unlock_irqrestore(&node->clients_lock, flags); return 0; @@ -1050,6 +1068,80 @@ static struct file_operations debug_clients_fops = { .release = single_release, }; +static int nvmap_debug_iovmm_clients_show(struct seq_file *s, void *unused) +{ + unsigned long flags; + unsigned int total = 0; + struct nvmap_client *client; + struct nvmap_device *dev = s->private; + + spin_lock_irqsave(&dev->clients_lock, flags); + seq_printf(s, "%-18s %18s %8s %10s\n", "CLIENT", "PROCESS", "PID", + "SIZE"); + list_for_each_entry(client, &dev->clients, list) { + client_stringify(client, s); + seq_printf(s, " %10u\n", atomic_read(&client->iovm_commit)); + total += atomic_read(&client->iovm_commit); + } + seq_printf(s, "%-18s %18s %8u %10u\n", "total", "", 0, total); + spin_unlock_irqrestore(&dev->clients_lock, flags); + + return 0; +} + +static int nvmap_debug_iovmm_clients_open(struct inode *inode, + struct file *file) +{ + return single_open(file, nvmap_debug_iovmm_clients_show, + inode->i_private); +} + +static const struct file_operations debug_iovmm_clients_fops = { + .open = nvmap_debug_iovmm_clients_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int nvmap_debug_iovmm_allocations_show(struct seq_file *s, void *unused) +{ + unsigned long flags; + unsigned int total = 0; + struct nvmap_client *client; + struct nvmap_device *dev = s->private; + + spin_lock_irqsave(&dev->clients_lock, flags); + seq_printf(s, "%-18s %18s %8s %10s\n", "CLIENT", "PROCESS", "PID", + "SIZE"); + seq_printf(s, "%-18s %18s %8s %10s\n", "", "", + "BASE", "SIZE"); + list_for_each_entry(client, &dev->clients, list) { + client_stringify(client, s); + seq_printf(s, " %10u\n", atomic_read(&client->iovm_commit)); + allocations_stringify(client, s); + seq_printf(s, "\n"); + total += atomic_read(&client->iovm_commit); + } + seq_printf(s, "%-18s %-18s %8u %10u\n", "total", "", 0, total); + spin_unlock_irqrestore(&dev->clients_lock, flags); + + return 0; +} + +static int nvmap_debug_iovmm_allocations_open(struct inode *inode, + struct file *file) +{ + return single_open(file, nvmap_debug_iovmm_allocations_show, + inode->i_private); +} + +static const struct file_operations debug_iovmm_allocations_fops = { + .open = nvmap_debug_iovmm_allocations_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int nvmap_probe(struct platform_device *pdev) { struct nvmap_platform_data *plat = pdev->dev.platform_data; @@ -1112,6 +1204,8 @@ static int nvmap_probe(struct platform_device *pdev) spin_lock_init(&dev->ptelock); spin_lock_init(&dev->handle_lock); + INIT_LIST_HEAD(&dev->clients); + spin_lock_init(&dev->clients_lock); for (i = 0; i < NVMAP_NUM_PTES; i++) { unsigned long addr; @@ -1204,6 +1298,16 @@ static int nvmap_probe(struct platform_device *pdev) } } } + if (!IS_ERR_OR_NULL(nvmap_debug_root)) { + struct dentry *iovmm_root = + debugfs_create_dir("iovmm", nvmap_debug_root); + if (!IS_ERR_OR_NULL(iovmm_root)) { + debugfs_create_file("clients", 0664, iovmm_root, + dev, &debug_iovmm_clients_fops); + debugfs_create_file("allocations", 0664, iovmm_root, + dev, &debug_iovmm_allocations_fops); + } + } platform_set_drvdata(pdev, dev); nvmap_dev = dev; diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index 9bb2731a9b43..6f9935cfdab7 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -269,11 +269,10 @@ static void alloc_handle(struct nvmap_client *client, /* increment the committed IOVM space prior to allocation * to avoid race conditions with other threads simultaneously * allocating. */ - if (!client->super) - commit = atomic_add_return(reserved, - &client->iovm_commit); + commit = atomic_add_return(reserved, + &client->iovm_commit); - if (commit < client->iovm_limit) + if (commit < client->iovm_limit || client->super) ret = handle_page_alloc(client, h, false); else ret = -ENOMEM; @@ -282,8 +281,7 @@ static void alloc_handle(struct nvmap_client *client, h->heap_pgalloc = true; h->alloc = true; } else { - if (!client->super) - atomic_sub(reserved, &client->iovm_commit); + atomic_sub(reserved, &client->iovm_commit); } } else if (type & NVMAP_HEAP_SYSMEM) { @@ -441,7 +439,7 @@ void nvmap_free_handle_id(struct nvmap_client *client, unsigned long id) pins = atomic_read(&ref->pin); rb_erase(&ref->node, &client->handle_refs); - if (h->alloc && h->heap_pgalloc && !h->pgalloc.contig && !client->super) + if (h->alloc && h->heap_pgalloc && !h->pgalloc.contig) atomic_sub(h->size, &client->iovm_commit); if (h->alloc && !h->heap_pgalloc) { @@ -571,10 +569,10 @@ struct nvmap_handle_ref *nvmap_duplicate_handle_id(struct nvmap_client *client, /* verify that adding this handle to the process' access list * won't exceed the IOVM limit */ - if (h->heap_pgalloc && !h->pgalloc.contig && !client->super) { + if (h->heap_pgalloc && !h->pgalloc.contig) { int oc; oc = atomic_add_return(h->size, &client->iovm_commit); - if (oc > client->iovm_limit) { + if (oc > client->iovm_limit && !client->super) { atomic_sub(h->size, &client->iovm_commit); nvmap_handle_put(h); nvmap_err(client, "duplicating %p in %s over-commits" |