summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrishna Reddy <vdumpa@nvidia.com>2011-08-04 15:14:49 -0700
committerVarun Colbert <vcolbert@nvidia.com>2011-08-08 11:15:41 -0700
commit0ce7bbcb97b05efe22c8b1ba18fef3336a3577cf (patch)
treed47574269da81cda19d457890eeaca3f667f8321
parent43619db4bdc6705359034068634d0f946e35cb4e (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.h1
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c114
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c16
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"