drm: implement top-down allocation method
authorArunpravin <Arunpravin.PaneerSelvam@amd.com>
Mon, 21 Feb 2022 16:45:49 +0000 (22:15 +0530)
committerChristian König <christian.koenig@amd.com>
Tue, 22 Feb 2022 12:02:24 +0000 (13:02 +0100)
Implemented a function which walk through the order list,
compares the offset and returns the maximum offset block,
this method is unpredictable in obtaining the high range
address blocks which depends on allocation and deallocation.
for instance, if driver requests address at a low specific
range, allocator traverses from the root block and splits
the larger blocks until it reaches the specific block and
in the process of splitting, lower orders in the freelist
are occupied with low range address blocks and for the
subsequent TOPDOWN memory request we may return the low
range blocks.To overcome this issue, we may go with the
below approach.

The other approach, sorting each order list entries in
ascending order and compares the last entry of each
order list in the freelist and return the max block.
This creates sorting overhead on every drm_buddy_free()
request and split up of larger blocks for a single page
request.

v2:
  - Fix alignment issues(Matthew Auld)
  - Remove unnecessary list_empty check(Matthew Auld)
  - merged the below patch to see the feature in action
     - add top-down alloc support to i915 driver

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220221164552.2434-2-Arunpravin.PaneerSelvam@amd.com
Signed-off-by: Christian König <christian.koenig@amd.com>
drivers/gpu/drm/drm_buddy.c
drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
include/drm/drm_buddy.h

index 1d801c88b286614753e299517302aeb8e13529e1..72ee3cd96a2436291fc9b0befe5479455fa5d3bb 100644 (file)
@@ -369,6 +369,26 @@ err_undo:
        return ERR_PTR(err);
 }
 
+static struct drm_buddy_block *
+get_maxblock(struct list_head *head)
+{
+       struct drm_buddy_block *max_block = NULL, *node;
+
+       max_block = list_first_entry_or_null(head,
+                                            struct drm_buddy_block,
+                                            link);
+       if (!max_block)
+               return NULL;
+
+       list_for_each_entry(node, head, link) {
+               if (drm_buddy_block_offset(node) >
+                   drm_buddy_block_offset(max_block))
+                       max_block = node;
+       }
+
+       return max_block;
+}
+
 static struct drm_buddy_block *
 alloc_from_freelist(struct drm_buddy *mm,
                    unsigned int order,
@@ -379,11 +399,17 @@ alloc_from_freelist(struct drm_buddy *mm,
        int err;
 
        for (i = order; i <= mm->max_order; ++i) {
-               block = list_first_entry_or_null(&mm->free_list[i],
-                                                struct drm_buddy_block,
-                                                link);
-               if (block)
-                       break;
+               if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
+                       block = get_maxblock(&mm->free_list[i]);
+                       if (block)
+                               break;
+               } else {
+                       block = list_first_entry_or_null(&mm->free_list[i],
+                                                        struct drm_buddy_block,
+                                                        link);
+                       if (block)
+                               break;
+               }
        }
 
        if (!block)
index a328a38fab07b09ed400f89b05d0371236626663..7f553cceb6c06680eab35e2d9a14317cf7d48f27 100644 (file)
@@ -53,6 +53,9 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
        INIT_LIST_HEAD(&bman_res->blocks);
        bman_res->mm = mm;
 
+       if (place->flags & TTM_PL_FLAG_TOPDOWN)
+               bman_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+
        if (place->fpfn || lpfn != man->size)
                bman_res->flags |= DRM_BUDDY_RANGE_ALLOCATION;
 
index 54f25a372f27d0933347818accc2a50222e84eeb..f0378fb48d06f3a580c17a5b908dd0391c97d6f2 100644 (file)
@@ -23,6 +23,7 @@
 })
 
 #define DRM_BUDDY_RANGE_ALLOCATION (1 << 0)
+#define DRM_BUDDY_TOPDOWN_ALLOCATION (1 << 1)
 
 struct drm_buddy_block {
 #define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)