Skip to contentSkip to conversation

FAILED: patch "[PATCH] gpu/buddy: bail out of try_harder when alignment cannot be" failed to apply to 6.12-stable tree

PATCH New [email protected] 2 participants 3 messages Jul 20 – Jul 23

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 56bc6384314fb9ae98975fb2af8b143097ede3dc
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072017-endless-bagging-0d2e@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 56bc6384314fb9ae98975fb2af8b143097ede3dc Mon Sep 17 00:00:00 2001
From: Arunpravin Paneer Selvam <[email protected]>
Date: Thu, 9 Jul 2026 18:40:50 +0530
Subject: [PATCH] gpu/buddy: bail out of try_harder when alignment cannot be
honoured
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The try_harder contiguous fallback could return a range whose start offset did not match the caller's min_block_size. When a candidate's start is misaligned, realign it: free the misaligned run and reallocate exactly @size at the next lower min_block_size boundary. This keeps the returned size unchanged with no surplus to trim, and rejects the request only when no aligned candidate fits.

v2: align misaligned candidates down to min_block_size instead of
bailing out, for both the RHS and LHS paths (Matthew).

Fixes 0a1844bf0b53 ("drm/buddy: Improve contiguous memory allocation")
Cc Matthew Auld <[email protected]>
Cc Christian König <[email protected]>
Cc Timur Kristóf <[email protected]>
drivers/gpu/buddy.c +46 -21
index eb1457376307..b12d3a2ac630 100644
@@ -1084,22 +1084,30 @@ static int __gpu_buddy_alloc_range(struct gpu_buddy *mm,
 			     blocks, total_allocated_on_err);
 }
 
+static int __alloc_contig_aligned_retry(struct gpu_buddy *mm,
+					u64 unaligned_offset,
+					u64 size,
+					u64 min_block_size,
+					struct list_head *blocks)
+{
+	u64 aligned_offset = round_down(unaligned_offset, min_block_size);
+
+	return __gpu_buddy_alloc_range(mm, aligned_offset, size, NULL, blocks);
+}
+
 static int __alloc_contig_try_harder(struct gpu_buddy *mm,
 				     u64 size,
 				     u64 min_block_size,
 				     struct list_head *blocks)
 {
-	u64 rhs_offset, lhs_offset, lhs_size, filled;
+	u64 rhs_offset, lhs_offset, filled;
 	struct gpu_buddy_block *block;
 	unsigned int tree, order;
-	LIST_HEAD(blocks_lhs);
-	unsigned long pages;
 	u64 modify_size;
 	int err;
 
 	modify_size = rounddown_pow_of_two(size);
-	pages = modify_size >> ilog2(mm->chunk_size);
-	order = fls(pages) - 1;
+	order = ilog2(modify_size) - ilog2(mm->chunk_size);
 	if (order == 0)
 		return -ENOSPC;
 
@@ -1115,31 +1123,48 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
 		while (iter) {
 			block = rbtree_get_free_block(iter);
 
-			/* Allocate blocks traversing RHS */
 			rhs_offset = gpu_buddy_block_offset(block);
+
+			/* Allocate blocks traversing RHS */
 			err =  __gpu_buddy_alloc_range(mm, rhs_offset, size,
 						       &filled, blocks);
-			if (!err || err != -ENOSPC)
+			if (err && err != -ENOSPC)
 				return err;
-
-			lhs_size = max((size - filled), min_block_size);
-			if (!IS_ALIGNED(lhs_size, min_block_size))
-				lhs_size = round_up(lhs_size, min_block_size);
-
-			/* Allocate blocks traversing LHS */
-			lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
-			err =  __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
-						       NULL, &blocks_lhs);
-			if (!err) {
-				list_splice(&blocks_lhs, blocks);
+			if (!err && IS_ALIGNED(rhs_offset, min_block_size))
 				return 0;
-			} else if (err != -ENOSPC) {
+			if (!err) {
+				/* Allocate the unaligned RHS offset using round_down */
+				gpu_buddy_free_list_internal(mm, blocks);
+				err = __alloc_contig_aligned_retry(mm, rhs_offset,
+								   size,
+								   min_block_size,
+								   blocks);
+				if (!err)
+					return 0;
+				if (err != -ENOSPC) {
+					gpu_buddy_free_list_internal(mm, blocks);
+					return err;
+				}
+				goto next;
+			}
+
+			if (size - filled > rhs_offset)
+				goto next;
+
+			lhs_offset = rhs_offset - (size - filled);
+
+			/* Allocate the unaligned LHS offset using round_down */
+			gpu_buddy_free_list_internal(mm, blocks);
+			err = __alloc_contig_aligned_retry(mm, lhs_offset, size,
+							   min_block_size, blocks);
+			if (!err)
+				return 0;
+			if (err != -ENOSPC) {
 				gpu_buddy_free_list_internal(mm, blocks);
 				return err;
 			}
-			/* Free blocks for the next iteration */
+next:
 			gpu_buddy_free_list_internal(mm, blocks);
-
 			iter = rb_prev(iter);
 		}
 	}
maintainer
#1 lore raw

PATCH 1/2 gpu: Move DRM buddy allocator one level up (part two)

From: Joel Fernandes <[email protected]>

[ Upstream commit ba110db8e1bc206c13fd7d985e79b033f53bfdea ]

Move the DRM buddy allocator one level up so that it can be used by GPU drivers (example, nova-core) that have usecases other than DRM (such as VFIO vGPU support). Modify the API, structures and Kconfigs to use "gpu_buddy" terminology. Adapt the drivers and tests to use the new API.

The commit cannot be split due to bisectability, however no functional change is intended. Verified by running K-UNIT tests and build tested various configurations.

[airlied: I've split this into two so git can find copies easier. I've also just nuked drm_random library, that stuff needs to be done elsewhere and only the buddy tests seem to be using it].

Stable-dep-of: 56bc6384314f ("gpu/buddy: bail out of try_harder when alignment cannot be honoured")

---
 Documentation/gpu/drm-mm.rst                  |   10 +-
 drivers/gpu/Kconfig                           |   13 +
 drivers/gpu/Makefile                          |    3 +-
 drivers/gpu/buddy.c                           | 1322 +++++++++++++++++
 drivers/gpu/drm/Kconfig                       |    6 +-
 drivers/gpu/drm/Makefile                      |    1 -
 .../gpu/drm/amd/amdgpu/amdgpu_res_cursor.h    |   12 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c  |   77 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h  |   18 +-
 drivers/gpu/drm/drm_buddy.c                   | 1279 +---------------
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |    2 +-
 drivers/gpu/drm/i915/i915_scatterlist.c       |   10 +-
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c |   55 +-
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.h |    4 +-
 .../drm/i915/selftests/intel_memory_region.c  |   20 +-
 drivers/gpu/drm/tests/Makefile                |    1 -
 drivers/gpu/drm/tests/drm_exec_test.c         |    2 -
 drivers/gpu/drm/tests/drm_mm_test.c           |    2 -
 .../gpu/drm/ttm/tests/ttm_bo_validate_test.c  |    4 +-
 drivers/gpu/drm/ttm/tests/ttm_mock_manager.c  |   18 +-
 drivers/gpu/drm/ttm/tests/ttm_mock_manager.h  |    4 +-
 drivers/gpu/drm/xe/xe_res_cursor.h            |   34 +-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.c          |   73 +-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h    |    4 +-
 drivers/gpu/tests/Makefile                    |    4 +
 .../gpu_buddy_test.c}                         |  316 ++--
 .../lib/drm_random.c => tests/gpu_random.c}   |   18 +-
 .../lib/drm_random.h => tests/gpu_random.h}   |   18 +-
 drivers/video/Kconfig                         |    1 +
 include/drm/drm_buddy.h                       |  174 +--
 include/linux/gpu_buddy.h                     |  188 +++
 31 files changed, 1903 insertions(+), 1790 deletions(-)
 create mode 100644 drivers/gpu/Kconfig
 create mode 100644 drivers/gpu/buddy.c
 create mode 100644 drivers/gpu/tests/Makefile
 rename drivers/gpu/{drm/tests/drm_buddy_test.c => tests/gpu_buddy_test.c} (70%)
 rename drivers/gpu/{drm/lib/drm_random.c => tests/gpu_random.c} (58%)
 rename drivers/gpu/{drm/lib/drm_random.h => tests/gpu_random.h} (53%)
 create mode 100644 include/linux/gpu_buddy.h
Documentation/gpu/drm-mm.rst +8 -2
index d55751cad67cf9..8e0d31230b29b5 100644
@@ -509,8 +509,14 @@ DRM GPUVM Function References
 DRM Buddy Allocator
 ===================
 
-DRM Buddy Function References
------------------------------
+Buddy Allocator Function References (GPU buddy)
+-----------------------------------------------
+
+.. kernel-doc:: drivers/gpu/buddy.c
+   :export:
+
+DRM Buddy Specific Logging Function References
+----------------------------------------------
 
 .. kernel-doc:: drivers/gpu/drm/drm_buddy.c
    :export:
drivers/gpu/Kconfig new file +13 -0
new file mode 100644
index 00000000000000..ebb2ad4b7ea0bb
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config GPU_BUDDY
+       bool
+       help
+         A page based buddy allocator for GPU memory.
+
+config GPU_BUDDY_KUNIT_TEST
+       tristate "KUnit tests for GPU buddy allocator" if !KUNIT_ALL_TESTS
+       depends on GPU_BUDDY && KUNIT
+       default KUNIT_ALL_TESTS
+       help
+         KUnit tests for the GPU buddy allocator.
drivers/gpu/Makefile +2 -1
index 8997f0096545e2..0b5b739b110a45 100644
@@ -2,6 +2,7 @@
 # drm/tegra depends on host1x, so if both drivers are built-in care must be
 # taken to initialize them in the correct order. Link order is the only way
 # to ensure this currently.
-obj-y			+= host1x/ drm/ vga/
+obj-y			+= host1x/ drm/ vga/ tests/
 obj-$(CONFIG_IMX_IPUV3_CORE)	+= ipu-v3/
 obj-$(CONFIG_TRACE_GPU_MEM)		+= trace/
+obj-$(CONFIG_GPU_BUDDY)		+= buddy.o
drivers/gpu/buddy.c new file +1322 -0

1,322 lines not on this page · raw message

drivers/gpu/drm/Kconfig +1 -5
index 0dd0d996e53e9a..62b9fdae96ddbf 100644
@@ -85,7 +85,6 @@ config DRM_KUNIT_TEST
 	select DRM_EXPORT_FOR_TESTS if m
 	select DRM_GEM_SHMEM_HELPER
 	select DRM_KUNIT_TEST_HELPERS
-	select DRM_LIB_RANDOM
 	select PRIME_NUMBERS
 	default KUNIT_ALL_TESTS
 	help
@@ -325,6 +324,7 @@ config DRM_GPUVM
 config DRM_BUDDY
 	tristate
 	depends on DRM
+	select GPU_BUDDY
 	help
 	  A page based buddy allocator
 
@@ -507,10 +507,6 @@ config DRM_EXPORT_FOR_TESTS
 config DRM_PANEL_BACKLIGHT_QUIRKS
 	tristate
 
-config DRM_LIB_RANDOM
-	bool
-	default n
-
 config DRM_PRIVACY_SCREEN
 	bool
 	default n
drivers/gpu/drm/Makefile +0 -1
index f4a5edf746d2d6..4a899e75a25cf8 100644
@@ -75,7 +75,6 @@ drm-y := \
 	drm_vblank_work.o \
 	drm_vma_manager.o \
 	drm_writeback.o
-drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_PANEL) += drm_panel.o
 drm-$(CONFIG_OF) += drm_of.o
drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h +6 -6
index 50fcd86e1033b8..aee50e7fb4208e 100644
@@ -55,7 +55,7 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
 				    uint64_t start, uint64_t size,
 				    struct amdgpu_res_cursor *cur)
 {
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	struct list_head *head, *next;
 	struct drm_mm_node *node;
 
@@ -71,7 +71,7 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
 		head = &to_amdgpu_vram_mgr_resource(res)->blocks;
 
 		block = list_first_entry_or_null(head,
-						 struct drm_buddy_block,
+						 struct gpu_buddy_block,
 						 link);
 		if (!block)
 			goto fallback;
@@ -81,7 +81,7 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
 
 			next = block->link.next;
 			if (next != head)
-				block = list_entry(next, struct drm_buddy_block, link);
+				block = list_entry(next, struct gpu_buddy_block, link);
 		}
 
 		cur->start = amdgpu_vram_mgr_block_start(block) + start;
@@ -124,7 +124,7 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
  */
 static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
 {
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	struct drm_mm_node *node;
 	struct list_head *next;
 
@@ -145,7 +145,7 @@ static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
 		block = cur->node;
 
 		next = block->link.next;
-		block = list_entry(next, struct drm_buddy_block, link);
+		block = list_entry(next, struct gpu_buddy_block, link);
 
 		cur->node = block;
 		cur->start = amdgpu_vram_mgr_block_start(block);
@@ -173,7 +173,7 @@ static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
  */
 static inline bool amdgpu_res_cleared(struct amdgpu_res_cursor *cur)
 {
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 
 	switch (cur->mem_type) {
 	case TTM_PL_VRAM:
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +39 -38

251 lines not on this page · raw message

drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +9 -9
index b256cbc2bc2708..3afa344a2f5384 100644
@@ -24,11 +24,11 @@
 #ifndef __AMDGPU_VRAM_MGR_H__
 #define __AMDGPU_VRAM_MGR_H__
 
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
 
 struct amdgpu_vram_mgr {
 	struct ttm_resource_manager manager;
-	struct drm_buddy mm;
+	struct gpu_buddy mm;
 	/* protects access to buffer objects */
 	struct mutex lock;
 	struct list_head reservations_pending;
@@ -43,19 +43,19 @@ struct amdgpu_vram_mgr_resource {
 	unsigned long flags;
 };
 
-static inline u64 amdgpu_vram_mgr_block_start(struct drm_buddy_block *block)
+static inline u64 amdgpu_vram_mgr_block_start(struct gpu_buddy_block *block)
 {
-	return drm_buddy_block_offset(block);
+	return gpu_buddy_block_offset(block);
 }
 
-static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block)
+static inline u64 amdgpu_vram_mgr_block_size(struct gpu_buddy_block *block)
 {
-	return (u64)PAGE_SIZE << drm_buddy_block_order(block);
+	return (u64)PAGE_SIZE << gpu_buddy_block_order(block);
 }
 
-static inline bool amdgpu_vram_mgr_is_cleared(struct drm_buddy_block *block)
+static inline bool amdgpu_vram_mgr_is_cleared(struct gpu_buddy_block *block)
 {
-	return drm_buddy_block_is_clear(block);
+	return gpu_buddy_block_is_clear(block);
 }
 
 static inline struct amdgpu_vram_mgr_resource *
@@ -66,7 +66,7 @@ to_amdgpu_vram_mgr_resource(struct ttm_resource *res)
 
 static inline void amdgpu_vram_mgr_set_cleared(struct ttm_resource *res)
 {
-	to_amdgpu_vram_mgr_resource(res)->flags |= DRM_BUDDY_CLEARED;
+	to_amdgpu_vram_mgr_resource(res)->flags |= GPU_BUDDY_CLEARED;
 }
 
 #endif
drivers/gpu/drm/drm_buddy.c +13 -1266

1,265 lines not on this page · raw message

drivers/gpu/drm/i915/gem/i915_gem_ttm.c +1 -1
index ed610931f15110..ecb10c2db5a066 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/i915/i915_scatterlist.c +5 -5
index 4d830740946da3..6a34dae13769e8 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +28 -27

55 lines not on this page · raw message

drivers/gpu/drm/i915/i915_ttm_buddy_manager.h +2 -2
index d6462071283039..1cff018c1689af 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/i915/selftests/intel_memory_region.c +10 -10
index f08f6674911eec..518887a5584c43 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/tests/Makefile +0 -1
index 56dab563abd7a7..3d09bfbfb30a84 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/tests/drm_exec_test.c +0 -2
index d6c4dd1194a0eb..c1f7a747752fea 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/tests/drm_mm_test.c +0 -2
index 6174d092902082..99744322ed1a25 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c +2 -2
index 1adf18481ea057..7b86da22a1a5cb 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/ttm/tests/ttm_mock_manager.c +9 -9
index f6d1c8a2845dd5..8b2d979a87077c 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/ttm/tests/ttm_mock_manager.h +2 -2
index e4c95f86a4670a..08710756fd8e0f 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/xe/xe_res_cursor.h +17 -17
index dca374b6521c2d..cbc76747021e59 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +37 -36

73 lines not on this page · raw message

drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h +2 -2
index 2d75cf1262893f..4aafe9b4a3bdfc 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/tests/Makefile new file +4 -0
new file mode 100644
index 00000000000000..4183e6e2de4511

Lines of this file are not shown. View the raw message.

drivers/gpu/tests/gpu_buddy_test.c renamed from drivers/gpu/drm/tests/drm_buddy_test.c +158 -158

316 lines not on this page · raw message

drivers/gpu/tests/gpu_random.c renamed from drivers/gpu/drm/lib/drm_random.c +9 -9
similarity index 58%
rename from drivers/gpu/drm/lib/drm_random.c
rename to drivers/gpu/tests/gpu_random.c
index 31b5a3e219114f..5a78a361686f46 100644

Lines of this file are not shown. View the raw message.

drivers/gpu/tests/gpu_random.h renamed from drivers/gpu/drm/lib/drm_random.h +9 -9
similarity index 53%
rename from drivers/gpu/drm/lib/drm_random.h
rename to drivers/gpu/tests/gpu_random.h
index 5543bf0474bc4e..c3caf120a9c937 100644

Lines of this file are not shown. View the raw message.

drivers/video/Kconfig +1 -0
index 44c9ef1435a2d2..c03c455dbdebbc 100644

Lines of this file are not shown. View the raw message.

include/drm/drm_buddy.h +6 -168

174 lines not on this page · raw message

include/linux/gpu_buddy.h new file +188 -0

188 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.53.0

Part of the diff is not shown here. View the raw message.

maintainer
#2 lore raw

PATCH 2/2 gpu/buddy: bail out of try_harder when alignment cannot be honoured

From: Arunpravin Paneer Selvam <[email protected]>

[ Upstream commit 56bc6384314fb9ae98975fb2af8b143097ede3dc ]

The try_harder contiguous fallback could return a range whose start offset did not match the caller's min_block_size. When a candidate's start is misaligned, realign it: free the misaligned run and reallocate exactly @size at the next lower min_block_size boundary. This keeps the returned size unchanged with no surplus to trim, and rejects the request only when no aligned candidate fits.

v2: align misaligned candidates down to min_block_size instead of
bailing out, for both the RHS and LHS paths (Matthew).

---
 drivers/gpu/buddy.c | 63 +++++++++++++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 19 deletions(-)
drivers/gpu/buddy.c +44 -19
index 603c59a2013a00..bf5920bd225803 100644
@@ -901,22 +901,30 @@ static int __gpu_buddy_alloc_range(struct gpu_buddy *mm,
 			     blocks, total_allocated_on_err);
 }
 
+static int __alloc_contig_aligned_retry(struct gpu_buddy *mm,
+					u64 unaligned_offset,
+					u64 size,
+					u64 min_block_size,
+					struct list_head *blocks)
+{
+	u64 aligned_offset = round_down(unaligned_offset, min_block_size);
+
+	return __gpu_buddy_alloc_range(mm, aligned_offset, size, NULL, blocks);
+}
+
 static int __alloc_contig_try_harder(struct gpu_buddy *mm,
 				     u64 size,
 				     u64 min_block_size,
 				     struct list_head *blocks)
 {
-	u64 rhs_offset, lhs_offset, lhs_size, filled;
+	u64 rhs_offset, lhs_offset, filled;
 	struct gpu_buddy_block *block;
 	unsigned int tree, order;
-	LIST_HEAD(blocks_lhs);
-	unsigned long pages;
 	u64 modify_size;
 	int err;
 
 	modify_size = rounddown_pow_of_two(size);
-	pages = modify_size >> ilog2(mm->chunk_size);
-	order = fls(pages) - 1;
+	order = ilog2(modify_size) - ilog2(mm->chunk_size);
 	if (order == 0)
 		return -ENOSPC;
 
@@ -932,31 +940,48 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
 		while (iter) {
 			block = rbtree_get_free_block(iter);
 
-			/* Allocate blocks traversing RHS */
 			rhs_offset = gpu_buddy_block_offset(block);
+
+			/* Allocate blocks traversing RHS */
 			err =  __gpu_buddy_alloc_range(mm, rhs_offset, size,
 						       &filled, blocks);
-			if (!err || err != -ENOSPC)
+			if (err && err != -ENOSPC)
 				return err;
+			if (!err && IS_ALIGNED(rhs_offset, min_block_size))
+				return 0;
+			if (!err) {
+				/* Allocate the unaligned RHS offset using round_down */
+				gpu_buddy_free_list_internal(mm, blocks);
+				err = __alloc_contig_aligned_retry(mm, rhs_offset,
+								   size,
+								   min_block_size,
+								   blocks);
+				if (!err)
+					return 0;
+				if (err != -ENOSPC) {
+					gpu_buddy_free_list_internal(mm, blocks);
+					return err;
+				}
+				goto next;
+			}
 
-			lhs_size = max((size - filled), min_block_size);
-			if (!IS_ALIGNED(lhs_size, min_block_size))
-				lhs_size = round_up(lhs_size, min_block_size);
+			if (size - filled > rhs_offset)
+				goto next;
 
-			/* Allocate blocks traversing LHS */
-			lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
-			err =  __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
-						       NULL, &blocks_lhs);
-			if (!err) {
-				list_splice(&blocks_lhs, blocks);
+			lhs_offset = rhs_offset - (size - filled);
+
+			/* Allocate the unaligned LHS offset using round_down */
+			gpu_buddy_free_list_internal(mm, blocks);
+			err = __alloc_contig_aligned_retry(mm, lhs_offset, size,
+							   min_block_size, blocks);
+			if (!err)
 				return 0;
-			} else if (err != -ENOSPC) {
+			if (err != -ENOSPC) {
 				gpu_buddy_free_list_internal(mm, blocks);
 				return err;
 			}
-			/* Free blocks for the next iteration */
+next:
 			gpu_buddy_free_list_internal(mm, blocks);
-
 			iter = rb_prev(iter);
 		}
 	}
Signature · 1 line
2.53.0