aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core/core
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-12 14:48:28 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-09-15 22:22:13 +1000
commitd7bda18c9102b65078c132fd7d7ffd835058f021 (patch)
tree936a1812a017665ca04de5f98a5e893905501251 /drivers/gpu/drm/nouveau/core/core
parentdrm/nouveau/core/mm: modify test for if building a mm with holes in it (diff)
downloadlinux-dev-d7bda18c9102b65078c132fd7d7ffd835058f021.tar.xz
linux-dev-d7bda18c9102b65078c132fd7d7ffd835058f021.zip
drm/nouveau/core/mm: dump mm when trying to tear one down that still has allocations
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/core')
-rw-r--r--drivers/gpu/drm/nouveau/core/core/mm.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c
index cdd0c9ad0eff..8a77a8bf9cc0 100644
--- a/drivers/gpu/drm/nouveau/core/core/mm.c
+++ b/drivers/gpu/drm/nouveau/core/core/mm.c
@@ -28,6 +28,24 @@
#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \
list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry)
+static void
+nouveau_mm_dump(struct nouveau_mm *mm, const char *header)
+{
+ struct nouveau_mm_node *node;
+
+ printk(KERN_ERR "nouveau: %s\n", header);
+ printk(KERN_ERR "nouveau: node list:\n");
+ list_for_each_entry(node, &mm->nodes, nl_entry) {
+ printk(KERN_ERR "nouveau: \t%08x %08x %d\n",
+ node->offset, node->length, node->type);
+ }
+ printk(KERN_ERR "nouveau: free list:\n");
+ list_for_each_entry(node, &mm->free, fl_entry) {
+ printk(KERN_ERR "nouveau: \t%08x %08x %d\n",
+ node->offset, node->length, node->type);
+ }
+}
+
void
nouveau_mm_free(struct nouveau_mm *mm, struct nouveau_mm_node **pthis)
{
@@ -239,18 +257,23 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
int
nouveau_mm_fini(struct nouveau_mm *mm)
{
- if (nouveau_mm_initialised(mm)) {
- struct nouveau_mm_node *node, *heap =
- list_first_entry(&mm->nodes, typeof(*heap), nl_entry);
- int nodes = 0;
+ struct nouveau_mm_node *node, *temp;
+ int nodes = 0;
- list_for_each_entry(node, &mm->nodes, nl_entry) {
- if (WARN_ON(nodes++ == mm->heap_nodes))
- return -EBUSY;
- }
+ if (!nouveau_mm_initialised(mm))
+ return 0;
- kfree(heap);
+ list_for_each_entry(node, &mm->nodes, nl_entry) {
+ if (++nodes > mm->heap_nodes) {
+ nouveau_mm_dump(mm, "mm not clean!");
+ return -EBUSY;
+ }
}
+ list_for_each_entry_safe(node, temp, &mm->nodes, nl_entry) {
+ list_del(&node->nl_entry);
+ kfree(node);
+ }
+ mm->heap_nodes = 0;
return 0;
}