Skip to contentSkip to conversation

FAILED: patch "[PATCH] gpu/buddy: bail out of try_harder when alignment cannot be" failed to apply to 6.18-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.18-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.18.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-ranging-tableware-042e@gregkh' --subject-prefix 'PATCH 6.18.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 +-
 MAINTAINERS                                   |   13 +
 drivers/gpu/Kconfig                           |   13 +
 drivers/gpu/Makefile                          |    3 +-
 drivers/gpu/buddy.c                           | 1322 +++++++++++++++++
 drivers/gpu/drm/Kconfig                       |    5 +-
 drivers/gpu/drm/Kconfig.debug                 |    1 -
 drivers/gpu/drm/Makefile                      |    1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c       |    2 +-
 .../gpu/drm/amd/amdgpu/amdgpu_res_cursor.h    |   12 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c  |   79 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h  |   20 +-
 drivers/gpu/drm/drm_buddy.c                   | 1278 +---------------
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |    3 +-
 drivers/gpu/drm/i915/i915_scatterlist.c       |   10 +-
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c |   59 +-
 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_svm.c                   |   12 +-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.c          |   71 +-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h    |    4 +-
 drivers/gpu/tests/Makefile                    |    4 +
 .../gpu_buddy_test.c}                         |  358 ++---
 .../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                       |  165 +-
 include/linux/gpu_buddy.h                     |  177 +++
 35 files changed, 1934 insertions(+), 1814 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} (66%)
 rename drivers/gpu/{drm/lib/drm_random.c => tests/gpu_random.c} (59%)
 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:
MAINTAINERS +13 -0
index cbfe2a7dd993fd..d27beeb0d9b8d3 100644
@@ -8656,6 +8656,19 @@ T:	git https://gitlab.freedesktop.org/drm/misc/kernel.git
 F:	drivers/gpu/drm/ttm/
 F:	include/drm/ttm/
 
+GPU BUDDY ALLOCATOR
+M:	Matthew Auld <[email protected]>
+M:	Arun Pravin <[email protected]>
+R:	Christian Koenig <[email protected]>
+L:	[email protected]
+S:	Maintained
+T:	git https://gitlab.freedesktop.org/drm/misc/kernel.git
+F:	drivers/gpu/drm_buddy.c
+F:	drivers/gpu/buddy.c
+F:	drivers/gpu/tests/gpu_buddy_test.c
+F:	include/linux/gpu_buddy.h
+F:	include/drm/drm_buddy.h
+
 DRM AUTOMATED TESTING
 M:	Helen Koike <[email protected]>
 M:	Vignesh Raman <[email protected]>
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 36a54d45663030..5cd54d06e26270 100644
@@ -2,7 +2,8 @@
 # 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_NOVA_CORE)		+= nova-core/
+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 -4
index ed85d0ceee3ba5..4b0228c88f496a 100644
@@ -220,6 +220,7 @@ config DRM_GPUSVM
 config DRM_BUDDY
 	tristate
 	depends on DRM
+	select GPU_BUDDY
 	help
 	  A page based buddy allocator
 
@@ -416,10 +417,6 @@ config DRM_HYPERV
 config DRM_PANEL_BACKLIGHT_QUIRKS
 	tristate
 
-config DRM_LIB_RANDOM
-	bool
-	default n
-
 config DRM_PRIVACY_SCREEN
 	bool
 	default n
drivers/gpu/drm/Kconfig.debug +0 -1
index 05dc43c0b8c5af..3b7886865335a3 100644
@@ -69,7 +69,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 DRM_SYSFB_HELPER
 	select PRIME_NUMBERS
 	default KUNIT_ALL_TESTS
drivers/gpu/drm/Makefile +0 -1
index b248e64587ed40..82cd30cf6cb2d7 100644
@@ -77,7 +77,6 @@ drm-$(CONFIG_DRM_CLIENT) += \
 	drm_client.o \
 	drm_client_event.o \
 	drm_client_modeset.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_ras.c +1 -1
index e9ed1a3b135cc4..9df691364a18c2 100644
@@ -5416,7 +5416,7 @@ int amdgpu_ras_add_critical_region(struct amdgpu_device *adev,
 	struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
 	struct amdgpu_vram_mgr_resource *vres;
 	struct ras_critical_region *region;
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	int ret = 0;
 
 	if (!bo || !bo->tbo.resource)
drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h +6 -6
index be2e56ce1355ec..8908d9e08a3043 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;
@@ -125,7 +125,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;
 
@@ -146,7 +146,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);
@@ -175,7 +175,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 +40 -39

259 lines not on this page · raw message

drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +10 -10
index 5f5fd9a911c268..429a21a2e9b236 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;
@@ -57,19 +57,19 @@ struct amdgpu_vram_mgr_resource {
 	struct amdgpu_vres_task task;
 };
 
-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 *
@@ -82,8 +82,8 @@ static inline void amdgpu_vram_mgr_set_cleared(struct ttm_resource *res)
 {
 	struct amdgpu_vram_mgr_resource *ares = to_amdgpu_vram_mgr_resource(res);
 
-	WARN_ON(ares->flags & DRM_BUDDY_CLEARED);
-	ares->flags |= DRM_BUDDY_CLEARED;
+	WARN_ON(ares->flags & GPU_BUDDY_CLEARED);
+	ares->flags |= GPU_BUDDY_CLEARED;
 }
 
 int amdgpu_vram_mgr_query_address_block_info(struct amdgpu_vram_mgr *mgr,
drivers/gpu/drm/drm_buddy.c +10 -1268

1,227 lines not on this page · raw message

drivers/gpu/drm/i915/gem/i915_gem_ttm.c +2 -1
index 3d53c54eb48fe0..d17695ae0a31c9 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 +30 -29

59 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 7b856b5090f9a3..8307390943a2f3 100644

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

drivers/gpu/drm/tests/Makefile +0 -1
index c0e952293ad021..524310241e16d3 100644

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

drivers/gpu/drm/tests/drm_exec_test.c +0 -2
index 3a20c788c51f89..2fc47f3b463b7e 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 1bcc67977f4879..3cbdc8101b7c6b 100644

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

drivers/gpu/drm/ttm/tests/ttm_mock_manager.c +9 -9
index d7eb6471f2edad..a9c233f982f676 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 4e00008b708176..5f4ab08c068694 100644

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

drivers/gpu/drm/xe/xe_svm.c +6 -6
index 65452c20609ed8..800eb209b2cdc2 100644

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

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

71 lines not on this page · raw message

drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h +2 -2
index 1144f9232ebbba..674a846f99862e 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 +179 -179

358 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 59%
rename from drivers/gpu/drm/lib/drm_random.c
rename to drivers/gpu/tests/gpu_random.c
index 0e9dba1ef4af51..6356372f7e52ed 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 9f827260a89db9..b68cf344826445 100644

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

drivers/video/Kconfig +1 -0
index d51777df12d164..0adb1e2fa53382 100644

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

include/drm/drm_buddy.h +6 -159

165 lines not on this page · raw message

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

177 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