summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_buddy.c
diff options
context:
space:
mode:
authorArunpravin <Arunpravin.PaneerSelvam@amd.com>2022-02-21 19:45:49 +0300
committerChristian König <christian.koenig@amd.com>2022-02-22 15:02:24 +0300
commit476e4063022787b5720758239ee4c22fa2495e82 (patch)
treec93f0db35bd080b4efcc230c76485dfe106a1856 /drivers/gpu/drm/drm_buddy.c
parentafea229fe10282da14595870b44f82792451dfb2 (diff)
downloadlinux-476e4063022787b5720758239ee4c22fa2495e82.tar.xz
drm: implement top-down allocation method
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>
Diffstat (limited to 'drivers/gpu/drm/drm_buddy.c')
-rw-r--r--drivers/gpu/drm/drm_buddy.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 1d801c88b286..72ee3cd96a24 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -370,6 +370,26 @@ err_undo:
}
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,
unsigned long flags)
@@ -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)