drm: Introduce drm_mm_create_block()
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 15 Nov 2012 11:32:16 +0000 (11:32 +0000)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 30 Nov 2012 22:20:09 +0000 (23:20 +0100)
To be used later by i915 to preallocate exact blocks of space from the
range manager.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Dave Airlie <airlied@redhat.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/drm_mm.c
include/drm/drm_mm.h

index 0761a03cdbb2d4f0af455097d1c09d3710c2749f..bd203b61a72b32d1f20a35da758873ba61393f32 100644 (file)
@@ -161,6 +161,56 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
        }
 }
 
+struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
+                                       unsigned long start,
+                                       unsigned long size,
+                                       bool atomic)
+{
+       struct drm_mm_node *hole, *node;
+       unsigned long end = start + size;
+
+       list_for_each_entry(hole, &mm->hole_stack, hole_stack) {
+               unsigned long hole_start;
+               unsigned long hole_end;
+
+               BUG_ON(!hole->hole_follows);
+               hole_start = drm_mm_hole_node_start(hole);
+               hole_end = drm_mm_hole_node_end(hole);
+
+               if (hole_start > start || hole_end < end)
+                       continue;
+
+               node = drm_mm_kmalloc(mm, atomic);
+               if (unlikely(node == NULL))
+                       return NULL;
+
+               node->start = start;
+               node->size = size;
+               node->mm = mm;
+               node->allocated = 1;
+
+               INIT_LIST_HEAD(&node->hole_stack);
+               list_add(&node->node_list, &hole->node_list);
+
+               if (start == hole_start) {
+                       hole->hole_follows = 0;
+                       list_del_init(&hole->hole_stack);
+               }
+
+               node->hole_follows = 0;
+               if (end != hole_end) {
+                       list_add(&node->hole_stack, &mm->hole_stack);
+                       node->hole_follows = 1;
+               }
+
+               return node;
+       }
+
+       WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size);
+       return NULL;
+}
+EXPORT_SYMBOL(drm_mm_create_block);
+
 struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
                                             unsigned long size,
                                             unsigned alignment,
index 06d7f798a08c547c3dfbd3ed3139c33b86c26c0b..4020f9661c3c1459eade32de367128584cff0e8d 100644 (file)
@@ -102,6 +102,10 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
 /*
  * Basic range manager support (drm_mm.c)
  */
+extern struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
+                                              unsigned long start,
+                                              unsigned long size,
+                                              bool atomic);
 extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
                                                    unsigned long size,
                                                    unsigned alignment,