Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@xxxxxxx>
---
drivers/gpu/drm/drm_buddy.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 72f52f293249..98d7ec359b08 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -641,6 +641,7 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm,
unsigned int min_order, order;
unsigned long pages;
LIST_HEAD(allocated);
+ u64 cur_size;
int err;
if (size < mm->chunk_size)
@@ -665,6 +666,11 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm,
if (start + size == end)
return __drm_buddy_alloc_range(mm, start, size, blocks);
+ cur_size = size;
+
+ if (!IS_ALIGNED(size, min_page_size))
+ size = round_up(size, min_page_size);
+
pages = size >> ilog2(mm->chunk_size);
order = fls(pages) - 1;
min_order = ilog2(min_page_size) - ilog2(mm->chunk_size);
@@ -702,6 +708,31 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm,
break;
} while (1);
+
+ /*
+ * If size value rounded up to min_page_size, trim the last block
+ * to the required size
+ */
+ if (cur_size != size) {
+ struct drm_buddy_block *trim_block;
+ LIST_HEAD(trim_list);
+ u64 required_size;
+
+ trim_block = list_last_entry(&allocated, typeof(*trim_block), link);
+ list_move_tail(&trim_block->link, &trim_list);
+ /*
+ * Compute the required_size value by subtracting the last block size
+ * with (aligned size - original size)
+ */
+ required_size = drm_buddy_block_size(mm, trim_block) - (size - cur_size);
+
+ drm_buddy_block_trim(mm,
+ required_size,
+ &trim_list);
+
+ list_splice_tail(&trim_list, &allocated);
+ }
+
list_splice_tail(&allocated, blocks);
return 0;
base-commit: ec57376fba5abc0e571617ff88e2ade7970c2e4b