drm/nouveau: allow a nouveau_mm to be created with holes
authorBen Skeggs <bskeggs@redhat.com>
Fri, 24 Jun 2011 00:23:20 +0000 (10:23 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 20 Sep 2011 06:04:00 +0000 (16:04 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_mm.c
drivers/gpu/drm/nouveau/nouveau_mm.h

index 75b5dd93a32f894555c368ea40517b34270d651c..b29ffb3d1408c6686f09c499c13e0d1a8f7fe05a 100644 (file)
@@ -129,21 +129,25 @@ nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc,
 int
 nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
 {
-       struct nouveau_mm_node *heap;
+       struct nouveau_mm_node *node;
+
+       if (block) {
+               mutex_init(&mm->mutex);
+               INIT_LIST_HEAD(&mm->nodes);
+               INIT_LIST_HEAD(&mm->free);
+               mm->block_size = block;
+               mm->heap_nodes = 0;
+       }
 
-       heap = kzalloc(sizeof(*heap), GFP_KERNEL);
-       if (!heap)
+       node = kzalloc(sizeof(*node), GFP_KERNEL);
+       if (!node)
                return -ENOMEM;
-       heap->offset = roundup(offset, block);
-       heap->length = rounddown(offset + length, block) - heap->offset;
-
-       mutex_init(&mm->mutex);
-       mm->block_size = block;
-       INIT_LIST_HEAD(&mm->nodes);
-       INIT_LIST_HEAD(&mm->free);
+       node->offset = roundup(offset, mm->block_size);
+       node->length = rounddown(offset + length, mm->block_size) - node->offset;
 
-       list_add(&heap->nl_entry, &mm->nodes);
-       list_add(&heap->fl_entry, &mm->free);
+       list_add_tail(&node->nl_entry, &mm->nodes);
+       list_add_tail(&node->fl_entry, &mm->free);
+       mm->heap_nodes++;
        return 0;
 }
 
@@ -152,15 +156,18 @@ nouveau_mm_fini(struct nouveau_mm *mm)
 {
        struct nouveau_mm_node *node, *heap =
                list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry);
-
-       if (!list_is_singular(&mm->nodes)) {
-               printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
-               list_for_each_entry(node, &mm->nodes, nl_entry) {
-                       printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
-                              node->type, node->offset, node->length);
+       int nodes = 0;
+
+       list_for_each_entry(node, &mm->nodes, nl_entry) {
+               if (nodes++ == mm->heap_nodes) {
+                       printk(KERN_ERR "nouveau_mm in use at destroy time!\n");
+                       list_for_each_entry(node, &mm->nodes, nl_entry) {
+                               printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
+                                      node->type, node->offset, node->length);
+                       }
+                       WARN_ON(1);
+                       return -EBUSY;
                }
-               WARN_ON(1);
-               return -EBUSY;
        }
 
        kfree(heap);
index b8fe9088b9ed940779a2e54a0c311402fb1c2236..57a600c35c95a49bd878741a34ce5c9453abbb6e 100644 (file)
@@ -42,6 +42,7 @@ struct nouveau_mm {
        struct mutex mutex;
 
        u32 block_size;
+       int heap_nodes;
 };
 
 int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);