Archive-only list for patches
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	patches@lists.linux.dev, Joel Fernandes <joelagnelf@nvidia.com>,
	Dave Airlie <airlied@redhat.com>, Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.12 510/602] gpu: Move DRM buddy allocator one level up (part two)
Date: Thu, 30 Jul 2026 16:15:02 +0200	[thread overview]
Message-ID: <20260730141446.712461318@linuxfoundation.org> (raw)
In-Reply-To: <20260730141435.976815864@linuxfoundation.org>

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Joel Fernandes <joelagnelf@nvidia.com>

[ 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.

Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
[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].
Signed-off-by: Dave Airlie <airlied@redhat.com>
Stable-dep-of: 56bc6384314f ("gpu/buddy: bail out of try_harder when alignment cannot be honoured")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 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 
 drivers/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 
 drivers/gpu/drm/i915/selftests/intel_memory_region.c |   20 
 drivers/gpu/drm/lib/drm_random.c                     |   43 
 drivers/gpu/drm/lib/drm_random.h                     |   28 
 drivers/gpu/drm/tests/Makefile                       |    1 
 drivers/gpu/drm/tests/drm_buddy_test.c               |  778 -----------
 drivers/gpu/drm/tests/drm_exec_test.c                |    2 
 drivers/gpu/drm/tests/drm_mm_test.c                  |    2 
 drivers/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 
 drivers/gpu/tests/gpu_buddy_test.c                   |  778 +++++++++++
 drivers/gpu/tests/gpu_random.c                       |   43 
 drivers/gpu/tests/gpu_random.h                       |   28 
 drivers/video/Kconfig                                |    1 
 include/drm/drm_buddy.h                              |  174 --
 include/linux/gpu_buddy.h                            |  188 ++
 34 files changed, 2576 insertions(+), 2463 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

--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -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:
--- /dev/null
+++ b/drivers/gpu/Kconfig
@@ -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.
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -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
--- /dev/null
+++ b/drivers/gpu/buddy.c
@@ -0,0 +1,1322 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <kunit/test-bug.h>
+
+#include <linux/export.h>
+#include <linux/kmemleak.h>
+#include <linux/module.h>
+#include <linux/sizes.h>
+
+#include <linux/gpu_buddy.h>
+
+static struct kmem_cache *slab_blocks;
+
+static struct gpu_buddy_block *gpu_block_alloc(struct gpu_buddy *mm,
+					       struct gpu_buddy_block *parent,
+					       unsigned int order,
+					       u64 offset)
+{
+	struct gpu_buddy_block *block;
+
+	BUG_ON(order > GPU_BUDDY_MAX_ORDER);
+
+	block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
+	if (!block)
+		return NULL;
+
+	block->header = offset;
+	block->header |= order;
+	block->parent = parent;
+
+	RB_CLEAR_NODE(&block->rb);
+
+	BUG_ON(block->header & GPU_BUDDY_HEADER_UNUSED);
+	return block;
+}
+
+static void gpu_block_free(struct gpu_buddy *mm,
+			   struct gpu_buddy_block *block)
+{
+	kmem_cache_free(slab_blocks, block);
+}
+
+static enum gpu_buddy_free_tree
+get_block_tree(struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_is_clear(block) ?
+	       GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
+}
+
+static struct gpu_buddy_block *
+rbtree_get_free_block(const struct rb_node *node)
+{
+	return node ? rb_entry(node, struct gpu_buddy_block, rb) : NULL;
+}
+
+static struct gpu_buddy_block *
+rbtree_last_free_block(struct rb_root *root)
+{
+	return rbtree_get_free_block(rb_last(root));
+}
+
+static bool rbtree_is_empty(struct rb_root *root)
+{
+	return RB_EMPTY_ROOT(root);
+}
+
+static bool gpu_buddy_block_offset_less(const struct gpu_buddy_block *block,
+					const struct gpu_buddy_block *node)
+{
+	return gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node);
+}
+
+static bool rbtree_block_offset_less(struct rb_node *block,
+				     const struct rb_node *node)
+{
+	return gpu_buddy_block_offset_less(rbtree_get_free_block(block),
+					   rbtree_get_free_block(node));
+}
+
+static void rbtree_insert(struct gpu_buddy *mm,
+			  struct gpu_buddy_block *block,
+			  enum gpu_buddy_free_tree tree)
+{
+	rb_add(&block->rb,
+	       &mm->free_trees[tree][gpu_buddy_block_order(block)],
+	       rbtree_block_offset_less);
+}
+
+static void rbtree_remove(struct gpu_buddy *mm,
+			  struct gpu_buddy_block *block)
+{
+	unsigned int order = gpu_buddy_block_order(block);
+	enum gpu_buddy_free_tree tree;
+	struct rb_root *root;
+
+	tree = get_block_tree(block);
+	root = &mm->free_trees[tree][order];
+
+	rb_erase(&block->rb, root);
+	RB_CLEAR_NODE(&block->rb);
+}
+
+static void clear_reset(struct gpu_buddy_block *block)
+{
+	block->header &= ~GPU_BUDDY_HEADER_CLEAR;
+}
+
+static void mark_cleared(struct gpu_buddy_block *block)
+{
+	block->header |= GPU_BUDDY_HEADER_CLEAR;
+}
+
+static void mark_allocated(struct gpu_buddy *mm,
+			   struct gpu_buddy_block *block)
+{
+	block->header &= ~GPU_BUDDY_HEADER_STATE;
+	block->header |= GPU_BUDDY_ALLOCATED;
+
+	rbtree_remove(mm, block);
+}
+
+static void mark_free(struct gpu_buddy *mm,
+		      struct gpu_buddy_block *block)
+{
+	enum gpu_buddy_free_tree tree;
+
+	block->header &= ~GPU_BUDDY_HEADER_STATE;
+	block->header |= GPU_BUDDY_FREE;
+
+	tree = get_block_tree(block);
+	rbtree_insert(mm, block, tree);
+}
+
+static void mark_split(struct gpu_buddy *mm,
+		       struct gpu_buddy_block *block)
+{
+	block->header &= ~GPU_BUDDY_HEADER_STATE;
+	block->header |= GPU_BUDDY_SPLIT;
+
+	rbtree_remove(mm, block);
+}
+
+static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+	return s1 <= e2 && e1 >= s2;
+}
+
+static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+	return s1 <= s2 && e1 >= e2;
+}
+
+static struct gpu_buddy_block *
+__get_buddy(struct gpu_buddy_block *block)
+{
+	struct gpu_buddy_block *parent;
+
+	parent = block->parent;
+	if (!parent)
+		return NULL;
+
+	if (parent->left == block)
+		return parent->right;
+
+	return parent->left;
+}
+
+static unsigned int __gpu_buddy_free(struct gpu_buddy *mm,
+				     struct gpu_buddy_block *block,
+				     bool force_merge)
+{
+	struct gpu_buddy_block *parent;
+	unsigned int order;
+
+	while ((parent = block->parent)) {
+		struct gpu_buddy_block *buddy;
+
+		buddy = __get_buddy(block);
+
+		if (!gpu_buddy_block_is_free(buddy))
+			break;
+
+		if (!force_merge) {
+			/*
+			 * Check the block and its buddy clear state and exit
+			 * the loop if they both have the dissimilar state.
+			 */
+			if (gpu_buddy_block_is_clear(block) !=
+			    gpu_buddy_block_is_clear(buddy))
+				break;
+
+			if (gpu_buddy_block_is_clear(block))
+				mark_cleared(parent);
+		}
+
+		rbtree_remove(mm, buddy);
+		if (force_merge && gpu_buddy_block_is_clear(buddy))
+			mm->clear_avail -= gpu_buddy_block_size(mm, buddy);
+
+		gpu_block_free(mm, block);
+		gpu_block_free(mm, buddy);
+
+		block = parent;
+	}
+
+	order = gpu_buddy_block_order(block);
+	mark_free(mm, block);
+
+	return order;
+}
+
+static int __force_merge(struct gpu_buddy *mm,
+			 u64 start,
+			 u64 end,
+			 unsigned int min_order)
+{
+	unsigned int tree, order;
+	int i;
+
+	if (!min_order)
+		return -ENOMEM;
+
+	if (min_order > mm->max_order)
+		return -EINVAL;
+
+	for_each_free_tree(tree) {
+		for (i = min_order - 1; i >= 0; i--) {
+			struct rb_node *iter = rb_last(&mm->free_trees[tree][i]);
+
+			while (iter) {
+				struct gpu_buddy_block *block, *buddy;
+				u64 block_start, block_end;
+
+				block = rbtree_get_free_block(iter);
+				iter = rb_prev(iter);
+
+				if (!block || !block->parent)
+					continue;
+
+				block_start = gpu_buddy_block_offset(block);
+				block_end = block_start + gpu_buddy_block_size(mm, block) - 1;
+
+				if (!contains(start, end, block_start, block_end))
+					continue;
+
+				buddy = __get_buddy(block);
+				if (!gpu_buddy_block_is_free(buddy))
+					continue;
+
+				WARN_ON(gpu_buddy_block_is_clear(block) ==
+					gpu_buddy_block_is_clear(buddy));
+
+				/*
+				 * Advance to the next node when the current node is the buddy,
+				 * as freeing the block will also remove its buddy from the tree.
+				 */
+				if (iter == &buddy->rb)
+					iter = rb_prev(iter);
+
+				rbtree_remove(mm, block);
+				if (gpu_buddy_block_is_clear(block))
+					mm->clear_avail -= gpu_buddy_block_size(mm, block);
+
+				order = __gpu_buddy_free(mm, block, true);
+				if (order >= min_order)
+					return 0;
+			}
+		}
+	}
+
+	return -ENOMEM;
+}
+
+/**
+ * gpu_buddy_init - init memory manager
+ *
+ * @mm: GPU buddy manager to initialize
+ * @size: size in bytes to manage
+ * @chunk_size: minimum page size in bytes for our allocations
+ *
+ * Initializes the memory manager and its resources.
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size)
+{
+	unsigned int i, j, root_count = 0;
+	u64 offset = 0;
+
+	if (size < chunk_size)
+		return -EINVAL;
+
+	if (chunk_size < SZ_4K)
+		return -EINVAL;
+
+	if (!is_power_of_2(chunk_size))
+		return -EINVAL;
+
+	size = round_down(size, chunk_size);
+
+	mm->size = size;
+	mm->avail = size;
+	mm->clear_avail = 0;
+	mm->chunk_size = chunk_size;
+	mm->max_order = ilog2(size) - ilog2(chunk_size);
+
+	BUG_ON(mm->max_order > GPU_BUDDY_MAX_ORDER);
+
+	mm->free_trees = kmalloc_array(GPU_BUDDY_MAX_FREE_TREES,
+				       sizeof(*mm->free_trees),
+				       GFP_KERNEL);
+	if (!mm->free_trees)
+		return -ENOMEM;
+
+	for_each_free_tree(i) {
+		mm->free_trees[i] = kmalloc_array(mm->max_order + 1,
+						  sizeof(struct rb_root),
+						  GFP_KERNEL);
+		if (!mm->free_trees[i])
+			goto out_free_tree;
+
+		for (j = 0; j <= mm->max_order; ++j)
+			mm->free_trees[i][j] = RB_ROOT;
+	}
+
+	mm->n_roots = hweight64(size);
+
+	mm->roots = kmalloc_array(mm->n_roots,
+				  sizeof(struct gpu_buddy_block *),
+				  GFP_KERNEL);
+	if (!mm->roots)
+		goto out_free_tree;
+
+	/*
+	 * Split into power-of-two blocks, in case we are given a size that is
+	 * not itself a power-of-two.
+	 */
+	do {
+		struct gpu_buddy_block *root;
+		unsigned int order;
+		u64 root_size;
+
+		order = ilog2(size) - ilog2(chunk_size);
+		root_size = chunk_size << order;
+
+		root = gpu_block_alloc(mm, NULL, order, offset);
+		if (!root)
+			goto out_free_roots;
+
+		mark_free(mm, root);
+
+		BUG_ON(root_count > mm->max_order);
+		BUG_ON(gpu_buddy_block_size(mm, root) < chunk_size);
+
+		mm->roots[root_count] = root;
+
+		offset += root_size;
+		size -= root_size;
+		root_count++;
+	} while (size);
+
+	return 0;
+
+out_free_roots:
+	while (root_count--)
+		gpu_block_free(mm, mm->roots[root_count]);
+	kfree(mm->roots);
+out_free_tree:
+	while (i--)
+		kfree(mm->free_trees[i]);
+	kfree(mm->free_trees);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(gpu_buddy_init);
+
+/**
+ * gpu_buddy_fini - tear down the memory manager
+ *
+ * @mm: GPU buddy manager to free
+ *
+ * Cleanup memory manager resources and the freetree
+ */
+void gpu_buddy_fini(struct gpu_buddy *mm)
+{
+	u64 root_size, size, start;
+	unsigned int order;
+	int i;
+
+	size = mm->size;
+
+	for (i = 0; i < mm->n_roots; ++i) {
+		order = ilog2(size) - ilog2(mm->chunk_size);
+		start = gpu_buddy_block_offset(mm->roots[i]);
+		__force_merge(mm, start, start + size, order);
+
+		if (WARN_ON(!gpu_buddy_block_is_free(mm->roots[i])))
+			kunit_fail_current_test("buddy_fini() root");
+
+		gpu_block_free(mm, mm->roots[i]);
+
+		root_size = mm->chunk_size << order;
+		size -= root_size;
+	}
+
+	WARN_ON(mm->avail != mm->size);
+
+	for_each_free_tree(i)
+		kfree(mm->free_trees[i]);
+	kfree(mm->free_trees);
+	kfree(mm->roots);
+}
+EXPORT_SYMBOL(gpu_buddy_fini);
+
+static int split_block(struct gpu_buddy *mm,
+		       struct gpu_buddy_block *block)
+{
+	unsigned int block_order = gpu_buddy_block_order(block) - 1;
+	u64 offset = gpu_buddy_block_offset(block);
+
+	BUG_ON(!gpu_buddy_block_is_free(block));
+	BUG_ON(!gpu_buddy_block_order(block));
+
+	block->left = gpu_block_alloc(mm, block, block_order, offset);
+	if (!block->left)
+		return -ENOMEM;
+
+	block->right = gpu_block_alloc(mm, block, block_order,
+				       offset + (mm->chunk_size << block_order));
+	if (!block->right) {
+		gpu_block_free(mm, block->left);
+		return -ENOMEM;
+	}
+
+	mark_split(mm, block);
+
+	if (gpu_buddy_block_is_clear(block)) {
+		mark_cleared(block->left);
+		mark_cleared(block->right);
+		clear_reset(block);
+	}
+
+	mark_free(mm, block->left);
+	mark_free(mm, block->right);
+
+	return 0;
+}
+
+/**
+ * gpu_get_buddy - get buddy address
+ *
+ * @block: GPU buddy block
+ *
+ * Returns the corresponding buddy block for @block, or NULL
+ * if this is a root block and can't be merged further.
+ * Requires some kind of locking to protect against
+ * any concurrent allocate and free operations.
+ */
+struct gpu_buddy_block *
+gpu_get_buddy(struct gpu_buddy_block *block)
+{
+	return __get_buddy(block);
+}
+EXPORT_SYMBOL(gpu_get_buddy);
+
+/**
+ * gpu_buddy_reset_clear - reset blocks clear state
+ *
+ * @mm: GPU buddy manager
+ * @is_clear: blocks clear state
+ *
+ * Reset the clear state based on @is_clear value for each block
+ * in the freetree.
+ */
+void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear)
+{
+	enum gpu_buddy_free_tree src_tree, dst_tree;
+	u64 root_size, size, start;
+	unsigned int order;
+	int i;
+
+	size = mm->size;
+	for (i = 0; i < mm->n_roots; ++i) {
+		order = ilog2(size) - ilog2(mm->chunk_size);
+		start = gpu_buddy_block_offset(mm->roots[i]);
+		__force_merge(mm, start, start + size, order);
+
+		root_size = mm->chunk_size << order;
+		size -= root_size;
+	}
+
+	src_tree = is_clear ? GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE;
+	dst_tree = is_clear ? GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
+
+	for (i = 0; i <= mm->max_order; ++i) {
+		struct rb_root *root = &mm->free_trees[src_tree][i];
+		struct gpu_buddy_block *block, *tmp;
+
+		rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
+			rbtree_remove(mm, block);
+			if (is_clear) {
+				mark_cleared(block);
+				mm->clear_avail += gpu_buddy_block_size(mm, block);
+			} else {
+				clear_reset(block);
+				mm->clear_avail -= gpu_buddy_block_size(mm, block);
+			}
+
+			rbtree_insert(mm, block, dst_tree);
+		}
+	}
+}
+EXPORT_SYMBOL(gpu_buddy_reset_clear);
+
+/**
+ * gpu_buddy_free_block - free a block
+ *
+ * @mm: GPU buddy manager
+ * @block: block to be freed
+ */
+void gpu_buddy_free_block(struct gpu_buddy *mm,
+			  struct gpu_buddy_block *block)
+{
+	BUG_ON(!gpu_buddy_block_is_allocated(block));
+	mm->avail += gpu_buddy_block_size(mm, block);
+	if (gpu_buddy_block_is_clear(block))
+		mm->clear_avail += gpu_buddy_block_size(mm, block);
+
+	__gpu_buddy_free(mm, block, false);
+}
+EXPORT_SYMBOL(gpu_buddy_free_block);
+
+static void __gpu_buddy_free_list(struct gpu_buddy *mm,
+				  struct list_head *objects,
+				  bool mark_clear,
+				  bool mark_dirty)
+{
+	struct gpu_buddy_block *block, *on;
+
+	WARN_ON(mark_dirty && mark_clear);
+
+	list_for_each_entry_safe(block, on, objects, link) {
+		if (mark_clear)
+			mark_cleared(block);
+		else if (mark_dirty)
+			clear_reset(block);
+		gpu_buddy_free_block(mm, block);
+		cond_resched();
+	}
+	INIT_LIST_HEAD(objects);
+}
+
+static void gpu_buddy_free_list_internal(struct gpu_buddy *mm,
+					 struct list_head *objects)
+{
+	/*
+	 * Don't touch the clear/dirty bit, since allocation is still internal
+	 * at this point. For example we might have just failed part of the
+	 * allocation.
+	 */
+	__gpu_buddy_free_list(mm, objects, false, false);
+}
+
+/**
+ * gpu_buddy_free_list - free blocks
+ *
+ * @mm: GPU buddy manager
+ * @objects: input list head to free blocks
+ * @flags: optional flags like GPU_BUDDY_CLEARED
+ */
+void gpu_buddy_free_list(struct gpu_buddy *mm,
+			 struct list_head *objects,
+			 unsigned int flags)
+{
+	bool mark_clear = flags & GPU_BUDDY_CLEARED;
+
+	__gpu_buddy_free_list(mm, objects, mark_clear, !mark_clear);
+}
+EXPORT_SYMBOL(gpu_buddy_free_list);
+
+static bool block_incompatible(struct gpu_buddy_block *block, unsigned int flags)
+{
+	bool needs_clear = flags & GPU_BUDDY_CLEAR_ALLOCATION;
+
+	return needs_clear != gpu_buddy_block_is_clear(block);
+}
+
+static struct gpu_buddy_block *
+__alloc_range_bias(struct gpu_buddy *mm,
+		   u64 start, u64 end,
+		   unsigned int order,
+		   unsigned long flags,
+		   bool fallback)
+{
+	u64 req_size = mm->chunk_size << order;
+	struct gpu_buddy_block *block;
+	struct gpu_buddy_block *buddy;
+	LIST_HEAD(dfs);
+	int err;
+	int i;
+
+	end = end - 1;
+
+	for (i = 0; i < mm->n_roots; ++i)
+		list_add_tail(&mm->roots[i]->tmp_link, &dfs);
+
+	do {
+		u64 block_start;
+		u64 block_end;
+
+		block = list_first_entry_or_null(&dfs,
+						 struct gpu_buddy_block,
+						 tmp_link);
+		if (!block)
+			break;
+
+		list_del(&block->tmp_link);
+
+		if (gpu_buddy_block_order(block) < order)
+			continue;
+
+		block_start = gpu_buddy_block_offset(block);
+		block_end = block_start + gpu_buddy_block_size(mm, block) - 1;
+
+		if (!overlaps(start, end, block_start, block_end))
+			continue;
+
+		if (gpu_buddy_block_is_allocated(block))
+			continue;
+
+		if (block_start < start || block_end > end) {
+			u64 adjusted_start = max(block_start, start);
+			u64 adjusted_end = min(block_end, end);
+
+			if (round_down(adjusted_end + 1, req_size) <=
+			    round_up(adjusted_start, req_size))
+				continue;
+		}
+
+		if (!fallback && block_incompatible(block, flags))
+			continue;
+
+		if (contains(start, end, block_start, block_end) &&
+		    order == gpu_buddy_block_order(block)) {
+			/*
+			 * Find the free block within the range.
+			 */
+			if (gpu_buddy_block_is_free(block))
+				return block;
+
+			continue;
+		}
+
+		if (!gpu_buddy_block_is_split(block)) {
+			err = split_block(mm, block);
+			if (unlikely(err))
+				goto err_undo;
+		}
+
+		list_add(&block->right->tmp_link, &dfs);
+		list_add(&block->left->tmp_link, &dfs);
+	} while (1);
+
+	return ERR_PTR(-ENOSPC);
+
+err_undo:
+	/*
+	 * We really don't want to leave around a bunch of split blocks, since
+	 * bigger is better, so make sure we merge everything back before we
+	 * free the allocated blocks.
+	 */
+	buddy = __get_buddy(block);
+	if (buddy &&
+	    (gpu_buddy_block_is_free(block) &&
+	     gpu_buddy_block_is_free(buddy)))
+		__gpu_buddy_free(mm, block, false);
+	return ERR_PTR(err);
+}
+
+static struct gpu_buddy_block *
+__gpu_buddy_alloc_range_bias(struct gpu_buddy *mm,
+			     u64 start, u64 end,
+			     unsigned int order,
+			     unsigned long flags)
+{
+	struct gpu_buddy_block *block;
+	bool fallback = false;
+
+	block = __alloc_range_bias(mm, start, end, order,
+				   flags, fallback);
+	if (IS_ERR(block))
+		return __alloc_range_bias(mm, start, end, order,
+					  flags, !fallback);
+
+	return block;
+}
+
+static struct gpu_buddy_block *
+get_maxblock(struct gpu_buddy *mm,
+	     unsigned int order,
+	     enum gpu_buddy_free_tree tree)
+{
+	struct gpu_buddy_block *max_block = NULL, *block = NULL;
+	struct rb_root *root;
+	unsigned int i;
+
+	for (i = order; i <= mm->max_order; ++i) {
+		root = &mm->free_trees[tree][i];
+		block = rbtree_last_free_block(root);
+		if (!block)
+			continue;
+
+		if (!max_block) {
+			max_block = block;
+			continue;
+		}
+
+		if (gpu_buddy_block_offset(block) >
+		    gpu_buddy_block_offset(max_block)) {
+			max_block = block;
+		}
+	}
+
+	return max_block;
+}
+
+static struct gpu_buddy_block *
+alloc_from_freetree(struct gpu_buddy *mm,
+		    unsigned int order,
+		    unsigned long flags)
+{
+	struct gpu_buddy_block *block = NULL;
+	struct rb_root *root;
+	enum gpu_buddy_free_tree tree;
+	unsigned int tmp;
+	int err;
+
+	tree = (flags & GPU_BUDDY_CLEAR_ALLOCATION) ?
+		GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
+
+	if (flags & GPU_BUDDY_TOPDOWN_ALLOCATION) {
+		block = get_maxblock(mm, order, tree);
+		if (block)
+			/* Store the obtained block order */
+			tmp = gpu_buddy_block_order(block);
+	} else {
+		for (tmp = order; tmp <= mm->max_order; ++tmp) {
+			/* Get RB tree root for this order and tree */
+			root = &mm->free_trees[tree][tmp];
+			block = rbtree_last_free_block(root);
+			if (block)
+				break;
+		}
+	}
+
+	if (!block) {
+		/* Try allocating from the other tree */
+		tree = (tree == GPU_BUDDY_CLEAR_TREE) ?
+			GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE;
+
+		for (tmp = order; tmp <= mm->max_order; ++tmp) {
+			root = &mm->free_trees[tree][tmp];
+			block = rbtree_last_free_block(root);
+			if (block)
+				break;
+		}
+
+		if (!block)
+			return ERR_PTR(-ENOSPC);
+	}
+
+	BUG_ON(!gpu_buddy_block_is_free(block));
+
+	while (tmp != order) {
+		err = split_block(mm, block);
+		if (unlikely(err))
+			goto err_undo;
+
+		block = block->right;
+		tmp--;
+	}
+	return block;
+
+err_undo:
+	if (tmp != order)
+		__gpu_buddy_free(mm, block, false);
+	return ERR_PTR(err);
+}
+
+static int __alloc_range(struct gpu_buddy *mm,
+			 struct list_head *dfs,
+			 u64 start, u64 size,
+			 struct list_head *blocks,
+			 u64 *total_allocated_on_err)
+{
+	struct gpu_buddy_block *block;
+	struct gpu_buddy_block *buddy;
+	u64 total_allocated = 0;
+	LIST_HEAD(allocated);
+	u64 end;
+	int err;
+
+	end = start + size - 1;
+
+	do {
+		u64 block_start;
+		u64 block_end;
+
+		block = list_first_entry_or_null(dfs,
+						 struct gpu_buddy_block,
+						 tmp_link);
+		if (!block)
+			break;
+
+		list_del(&block->tmp_link);
+
+		block_start = gpu_buddy_block_offset(block);
+		block_end = block_start + gpu_buddy_block_size(mm, block) - 1;
+
+		if (!overlaps(start, end, block_start, block_end))
+			continue;
+
+		if (gpu_buddy_block_is_allocated(block)) {
+			err = -ENOSPC;
+			goto err_free;
+		}
+
+		if (contains(start, end, block_start, block_end)) {
+			if (gpu_buddy_block_is_free(block)) {
+				mark_allocated(mm, block);
+				total_allocated += gpu_buddy_block_size(mm, block);
+				mm->avail -= gpu_buddy_block_size(mm, block);
+				if (gpu_buddy_block_is_clear(block))
+					mm->clear_avail -= gpu_buddy_block_size(mm, block);
+				list_add_tail(&block->link, &allocated);
+				continue;
+			} else if (!mm->clear_avail) {
+				err = -ENOSPC;
+				goto err_free;
+			}
+		}
+
+		if (!gpu_buddy_block_is_split(block)) {
+			err = split_block(mm, block);
+			if (unlikely(err))
+				goto err_undo;
+		}
+
+		list_add(&block->right->tmp_link, dfs);
+		list_add(&block->left->tmp_link, dfs);
+	} while (1);
+
+	if (total_allocated < size) {
+		err = -ENOSPC;
+		goto err_free;
+	}
+
+	list_splice_tail(&allocated, blocks);
+
+	return 0;
+
+err_undo:
+	/*
+	 * We really don't want to leave around a bunch of split blocks, since
+	 * bigger is better, so make sure we merge everything back before we
+	 * free the allocated blocks.
+	 */
+	buddy = __get_buddy(block);
+	if (buddy &&
+	    (gpu_buddy_block_is_free(block) &&
+	     gpu_buddy_block_is_free(buddy)))
+		__gpu_buddy_free(mm, block, false);
+
+err_free:
+	if (err == -ENOSPC && total_allocated_on_err) {
+		list_splice_tail(&allocated, blocks);
+		*total_allocated_on_err = total_allocated;
+	} else {
+		gpu_buddy_free_list_internal(mm, &allocated);
+	}
+
+	return err;
+}
+
+static int __gpu_buddy_alloc_range(struct gpu_buddy *mm,
+				   u64 start,
+				   u64 size,
+				   u64 *total_allocated_on_err,
+				   struct list_head *blocks)
+{
+	LIST_HEAD(dfs);
+	int i;
+
+	for (i = 0; i < mm->n_roots; ++i)
+		list_add_tail(&mm->roots[i]->tmp_link, &dfs);
+
+	return __alloc_range(mm, &dfs, start, size,
+			     blocks, total_allocated_on_err);
+}
+
+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;
+	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;
+	if (order == 0)
+		return -ENOSPC;
+
+	for_each_free_tree(tree) {
+		struct rb_root *root;
+		struct rb_node *iter;
+
+		root = &mm->free_trees[tree][order];
+		if (rbtree_is_empty(root))
+			continue;
+
+		iter = rb_last(root);
+		while (iter) {
+			block = rbtree_get_free_block(iter);
+
+			/* Allocate blocks traversing RHS */
+			rhs_offset = gpu_buddy_block_offset(block);
+			err =  __gpu_buddy_alloc_range(mm, rhs_offset, size,
+						       &filled, blocks);
+			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);
+				return 0;
+			} else if (err != -ENOSPC) {
+				gpu_buddy_free_list_internal(mm, blocks);
+				return err;
+			}
+			/* Free blocks for the next iteration */
+			gpu_buddy_free_list_internal(mm, blocks);
+
+			iter = rb_prev(iter);
+		}
+	}
+
+	return -ENOSPC;
+}
+
+/**
+ * gpu_buddy_block_trim - free unused pages
+ *
+ * @mm: GPU buddy manager
+ * @start: start address to begin the trimming.
+ * @new_size: original size requested
+ * @blocks: Input and output list of allocated blocks.
+ * MUST contain single block as input to be trimmed.
+ * On success will contain the newly allocated blocks
+ * making up the @new_size. Blocks always appear in
+ * ascending order
+ *
+ * For contiguous allocation, we round up the size to the nearest
+ * power of two value, drivers consume *actual* size, so remaining
+ * portions are unused and can be optionally freed with this function
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int gpu_buddy_block_trim(struct gpu_buddy *mm,
+			 u64 *start,
+			 u64 new_size,
+			 struct list_head *blocks)
+{
+	struct gpu_buddy_block *parent;
+	struct gpu_buddy_block *block;
+	u64 block_start, block_end;
+	LIST_HEAD(dfs);
+	u64 new_start;
+	int err;
+
+	if (!list_is_singular(blocks))
+		return -EINVAL;
+
+	block = list_first_entry(blocks,
+				 struct gpu_buddy_block,
+				 link);
+
+	block_start = gpu_buddy_block_offset(block);
+	block_end = block_start + gpu_buddy_block_size(mm, block);
+
+	if (WARN_ON(!gpu_buddy_block_is_allocated(block)))
+		return -EINVAL;
+
+	if (new_size > gpu_buddy_block_size(mm, block))
+		return -EINVAL;
+
+	if (!new_size || !IS_ALIGNED(new_size, mm->chunk_size))
+		return -EINVAL;
+
+	if (new_size == gpu_buddy_block_size(mm, block))
+		return 0;
+
+	new_start = block_start;
+	if (start) {
+		new_start = *start;
+
+		if (new_start < block_start)
+			return -EINVAL;
+
+		if (!IS_ALIGNED(new_start, mm->chunk_size))
+			return -EINVAL;
+
+		if (range_overflows(new_start, new_size, block_end))
+			return -EINVAL;
+	}
+
+	list_del(&block->link);
+	mark_free(mm, block);
+	mm->avail += gpu_buddy_block_size(mm, block);
+	if (gpu_buddy_block_is_clear(block))
+		mm->clear_avail += gpu_buddy_block_size(mm, block);
+
+	/* Prevent recursively freeing this node */
+	parent = block->parent;
+	block->parent = NULL;
+
+	list_add(&block->tmp_link, &dfs);
+	err =  __alloc_range(mm, &dfs, new_start, new_size, blocks, NULL);
+	if (err) {
+		mark_allocated(mm, block);
+		mm->avail -= gpu_buddy_block_size(mm, block);
+		if (gpu_buddy_block_is_clear(block))
+			mm->clear_avail -= gpu_buddy_block_size(mm, block);
+		list_add(&block->link, blocks);
+	}
+
+	block->parent = parent;
+	return err;
+}
+EXPORT_SYMBOL(gpu_buddy_block_trim);
+
+static struct gpu_buddy_block *
+__gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
+			 u64 start, u64 end,
+			 unsigned int order,
+			 unsigned long flags)
+{
+	if (flags & GPU_BUDDY_RANGE_ALLOCATION)
+		/* Allocate traversing within the range */
+		return  __gpu_buddy_alloc_range_bias(mm, start, end,
+						     order, flags);
+	else
+		/* Allocate from freetree */
+		return alloc_from_freetree(mm, order, flags);
+}
+
+/**
+ * gpu_buddy_alloc_blocks - allocate power-of-two blocks
+ *
+ * @mm: GPU buddy manager to allocate from
+ * @start: start of the allowed range for this block
+ * @end: end of the allowed range for this block
+ * @size: size of the allocation in bytes
+ * @min_block_size: alignment of the allocation
+ * @blocks: output list head to add allocated blocks
+ * @flags: GPU_BUDDY_*_ALLOCATION flags
+ *
+ * alloc_range_bias() called on range limitations, which traverses
+ * the tree and returns the desired block.
+ *
+ * alloc_from_freetree() called when *no* range restrictions
+ * are enforced, which picks the block from the freetree.
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
+			   u64 start, u64 end, u64 size,
+			   u64 min_block_size,
+			   struct list_head *blocks,
+			   unsigned long flags)
+{
+	struct gpu_buddy_block *block = NULL;
+	u64 original_size, original_min_size;
+	unsigned int min_order, order;
+	LIST_HEAD(allocated);
+	unsigned long pages;
+	int err;
+
+	if (size < mm->chunk_size)
+		return -EINVAL;
+
+	if (min_block_size < mm->chunk_size)
+		return -EINVAL;
+
+	if (!is_power_of_2(min_block_size))
+		return -EINVAL;
+
+	if (!IS_ALIGNED(start | end | size, mm->chunk_size))
+		return -EINVAL;
+
+	if (end > mm->size)
+		return -EINVAL;
+
+	if (range_overflows(start, size, mm->size))
+		return -EINVAL;
+
+	/* Actual range allocation */
+	if (start + size == end) {
+		if (!IS_ALIGNED(start | end, min_block_size))
+			return -EINVAL;
+
+		return __gpu_buddy_alloc_range(mm, start, size, NULL, blocks);
+	}
+
+	original_size = size;
+	original_min_size = min_block_size;
+
+	/* Roundup the size to power of 2 */
+	if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) {
+		size = roundup_pow_of_two(size);
+		min_block_size = size;
+	/* Align size value to min_block_size */
+	} else if (!IS_ALIGNED(size, min_block_size)) {
+		size = round_up(size, min_block_size);
+	}
+
+	pages = size >> ilog2(mm->chunk_size);
+	order = fls(pages) - 1;
+	min_order = ilog2(min_block_size) - ilog2(mm->chunk_size);
+
+	if (order > mm->max_order || size > mm->size) {
+		if ((flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) &&
+		    !(flags & GPU_BUDDY_RANGE_ALLOCATION))
+			return __alloc_contig_try_harder(mm, original_size,
+							 original_min_size, blocks);
+
+		return -EINVAL;
+	}
+
+	do {
+		order = min(order, (unsigned int)fls(pages) - 1);
+		BUG_ON(order > mm->max_order);
+		BUG_ON(order < min_order);
+
+		do {
+			block = __gpu_buddy_alloc_blocks(mm, start,
+							 end,
+							 order,
+							 flags);
+			if (!IS_ERR(block))
+				break;
+
+			if (order-- == min_order) {
+				/* Try allocation through force merge method */
+				if (mm->clear_avail &&
+				    !__force_merge(mm, start, end, min_order)) {
+					block = __gpu_buddy_alloc_blocks(mm, start,
+									 end,
+									 min_order,
+									 flags);
+					if (!IS_ERR(block)) {
+						order = min_order;
+						break;
+					}
+				}
+
+				/*
+				 * Try contiguous block allocation through
+				 * try harder method.
+				 */
+				if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION &&
+				    !(flags & GPU_BUDDY_RANGE_ALLOCATION))
+					return __alloc_contig_try_harder(mm,
+									 original_size,
+									 original_min_size,
+									 blocks);
+				err = -ENOSPC;
+				goto err_free;
+			}
+		} while (1);
+
+		mark_allocated(mm, block);
+		mm->avail -= gpu_buddy_block_size(mm, block);
+		if (gpu_buddy_block_is_clear(block))
+			mm->clear_avail -= gpu_buddy_block_size(mm, block);
+		kmemleak_update_trace(block);
+		list_add_tail(&block->link, &allocated);
+
+		pages -= BIT(order);
+
+		if (!pages)
+			break;
+	} while (1);
+
+	/* Trim the allocated block to the required size */
+	if (!(flags & GPU_BUDDY_TRIM_DISABLE) &&
+	    original_size != size) {
+		struct list_head *trim_list;
+		LIST_HEAD(temp);
+		u64 trim_size;
+
+		trim_list = &allocated;
+		trim_size = original_size;
+
+		if (!list_is_singular(&allocated)) {
+			block = list_last_entry(&allocated, typeof(*block), link);
+			list_move(&block->link, &temp);
+			trim_list = &temp;
+			trim_size = gpu_buddy_block_size(mm, block) -
+				(size - original_size);
+		}
+
+		gpu_buddy_block_trim(mm,
+				     NULL,
+				     trim_size,
+				     trim_list);
+
+		if (!list_empty(&temp))
+			list_splice_tail(trim_list, &allocated);
+	}
+
+	list_splice_tail(&allocated, blocks);
+	return 0;
+
+err_free:
+	gpu_buddy_free_list_internal(mm, &allocated);
+	return err;
+}
+EXPORT_SYMBOL(gpu_buddy_alloc_blocks);
+
+/**
+ * gpu_buddy_block_print - print block information
+ *
+ * @mm: GPU buddy manager
+ * @block: GPU buddy block
+ */
+void gpu_buddy_block_print(struct gpu_buddy *mm,
+			   struct gpu_buddy_block *block)
+{
+	u64 start = gpu_buddy_block_offset(block);
+	u64 size = gpu_buddy_block_size(mm, block);
+
+	pr_info("%#018llx-%#018llx: %llu\n", start, start + size, size);
+}
+EXPORT_SYMBOL(gpu_buddy_block_print);
+
+/**
+ * gpu_buddy_print - print allocator state
+ *
+ * @mm: GPU buddy manager
+ * @p: GPU printer to use
+ */
+void gpu_buddy_print(struct gpu_buddy *mm)
+{
+	int order;
+
+	pr_info("chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n",
+		mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
+
+	for (order = mm->max_order; order >= 0; order--) {
+		struct gpu_buddy_block *block, *tmp;
+		struct rb_root *root;
+		u64 count = 0, free;
+		unsigned int tree;
+
+		for_each_free_tree(tree) {
+			root = &mm->free_trees[tree][order];
+
+			rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
+				BUG_ON(!gpu_buddy_block_is_free(block));
+				count++;
+			}
+		}
+
+		free = count * (mm->chunk_size << order);
+		if (free < SZ_1M)
+			pr_info("order-%2d free: %8llu KiB, blocks: %llu\n",
+				order, free >> 10, count);
+		else
+			pr_info("order-%2d free: %8llu MiB, blocks: %llu\n",
+				order, free >> 20, count);
+	}
+}
+EXPORT_SYMBOL(gpu_buddy_print);
+
+static void gpu_buddy_module_exit(void)
+{
+	kmem_cache_destroy(slab_blocks);
+}
+
+static int __init gpu_buddy_module_init(void)
+{
+	slab_blocks = KMEM_CACHE(gpu_buddy_block, 0);
+	if (!slab_blocks)
+		return -ENOMEM;
+
+	return 0;
+}
+
+module_init(gpu_buddy_module_init);
+module_exit(gpu_buddy_module_exit);
+
+MODULE_DESCRIPTION("GPU Buddy Allocator");
+MODULE_LICENSE("Dual MIT/GPL");
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -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
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -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
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
@@ -55,7 +55,7 @@ static inline void amdgpu_res_first(stru
 				    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(stru
 		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(stru
 
 			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 @@ fallback:
  */
 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(struc
 		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(struc
  */
 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:
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -24,6 +24,7 @@
 
 #include <linux/dma-mapping.h>
 #include <drm/ttm/ttm_range_manager.h>
+#include <drm/drm_buddy.h>
 
 #include "amdgpu.h"
 #include "amdgpu_vm.h"
@@ -52,15 +53,15 @@ to_amdgpu_device(struct amdgpu_vram_mgr
 	return container_of(mgr, struct amdgpu_device, mman.vram_mgr);
 }
 
-static inline struct drm_buddy_block *
+static inline struct gpu_buddy_block *
 amdgpu_vram_mgr_first_block(struct list_head *list)
 {
-	return list_first_entry_or_null(list, struct drm_buddy_block, link);
+	return list_first_entry_or_null(list, struct gpu_buddy_block, link);
 }
 
 static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head)
 {
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	u64 start, size;
 
 	block = amdgpu_vram_mgr_first_block(head);
@@ -71,7 +72,7 @@ static inline bool amdgpu_is_vram_mgr_bl
 		start = amdgpu_vram_mgr_block_start(block);
 		size = amdgpu_vram_mgr_block_size(block);
 
-		block = list_entry(block->link.next, struct drm_buddy_block, link);
+		block = list_entry(block->link.next, struct gpu_buddy_block, link);
 		if (start + size != amdgpu_vram_mgr_block_start(block))
 			return false;
 	}
@@ -81,7 +82,7 @@ static inline bool amdgpu_is_vram_mgr_bl
 
 static inline u64 amdgpu_vram_mgr_blocks_size(struct list_head *head)
 {
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	u64 size = 0;
 
 	list_for_each_entry(block, head, link)
@@ -254,7 +255,7 @@ const struct attribute_group amdgpu_vram
  * Calculate how many bytes of the DRM BUDDY block are inside visible VRAM
  */
 static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev,
-				    struct drm_buddy_block *block)
+				    struct gpu_buddy_block *block)
 {
 	u64 start = amdgpu_vram_mgr_block_start(block);
 	u64 end = start + amdgpu_vram_mgr_block_size(block);
@@ -279,7 +280,7 @@ u64 amdgpu_vram_mgr_bo_visible_size(stru
 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	struct ttm_resource *res = bo->tbo.resource;
 	struct amdgpu_vram_mgr_resource *vres = to_amdgpu_vram_mgr_resource(res);
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	u64 usage = 0;
 
 	if (amdgpu_gmc_vram_full_visible(&adev->gmc))
@@ -299,15 +300,15 @@ static void amdgpu_vram_mgr_do_reserve(s
 {
 	struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
 	struct amdgpu_device *adev = to_amdgpu_device(mgr);
-	struct drm_buddy *mm = &mgr->mm;
+	struct gpu_buddy *mm = &mgr->mm;
 	struct amdgpu_vram_reservation *rsv, *temp;
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	uint64_t vis_usage;
 
 	list_for_each_entry_safe(rsv, temp, &mgr->reservations_pending, blocks) {
-		if (drm_buddy_alloc_blocks(mm, rsv->start, rsv->start + rsv->size,
+		if (gpu_buddy_alloc_blocks(mm, rsv->start, rsv->start + rsv->size,
 					   rsv->size, mm->chunk_size, &rsv->allocated,
-					   DRM_BUDDY_RANGE_ALLOCATION))
+					   GPU_BUDDY_RANGE_ALLOCATION))
 			continue;
 
 		block = amdgpu_vram_mgr_first_block(&rsv->allocated);
@@ -460,8 +461,8 @@ static int amdgpu_vram_mgr_new(struct tt
 	struct amdgpu_vram_mgr_resource *vres;
 	u64 size, remaining_size, lpfn, fpfn;
 	unsigned int adjust_dcc_size = 0;
-	struct drm_buddy *mm = &mgr->mm;
-	struct drm_buddy_block *block;
+	struct gpu_buddy *mm = &mgr->mm;
+	struct gpu_buddy_block *block;
 	unsigned long pages_per_block;
 	int r;
 
@@ -503,17 +504,17 @@ static int amdgpu_vram_mgr_new(struct tt
 	INIT_LIST_HEAD(&vres->blocks);
 
 	if (place->flags & TTM_PL_FLAG_TOPDOWN)
-		vres->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+		vres->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
 
 	if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
-		vres->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+		vres->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;
 
 	if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CLEARED)
-		vres->flags |= DRM_BUDDY_CLEAR_ALLOCATION;
+		vres->flags |= GPU_BUDDY_CLEAR_ALLOCATION;
 
 	if (fpfn || lpfn != mgr->mm.size)
 		/* Allocate blocks in desired range */
-		vres->flags |= DRM_BUDDY_RANGE_ALLOCATION;
+		vres->flags |= GPU_BUDDY_RANGE_ALLOCATION;
 
 	if (bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC &&
 	    adev->gmc.gmc_funcs->get_dcc_alignment)
@@ -526,7 +527,7 @@ static int amdgpu_vram_mgr_new(struct tt
 		dcc_size = roundup_pow_of_two(vres->base.size + adjust_dcc_size);
 		remaining_size = (u64)dcc_size;
 
-		vres->flags |= DRM_BUDDY_TRIM_DISABLE;
+		vres->flags |= GPU_BUDDY_TRIM_DISABLE;
 	}
 
 	mutex_lock(&mgr->lock);
@@ -546,7 +547,7 @@ static int amdgpu_vram_mgr_new(struct tt
 
 		BUG_ON(min_block_size < mm->chunk_size);
 
-		r = drm_buddy_alloc_blocks(mm, fpfn,
+		r = gpu_buddy_alloc_blocks(mm, fpfn,
 					   lpfn,
 					   size,
 					   min_block_size,
@@ -555,7 +556,7 @@ static int amdgpu_vram_mgr_new(struct tt
 
 		if (unlikely(r == -ENOSPC) && pages_per_block == ~0ul &&
 		    !(place->flags & TTM_PL_FLAG_CONTIGUOUS)) {
-			vres->flags &= ~DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+			vres->flags &= ~GPU_BUDDY_CONTIGUOUS_ALLOCATION;
 			pages_per_block = max_t(u32, 2UL << (20UL - PAGE_SHIFT),
 						tbo->page_alignment);
 
@@ -572,7 +573,7 @@ static int amdgpu_vram_mgr_new(struct tt
 	}
 
 	if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && adjust_dcc_size) {
-		struct drm_buddy_block *dcc_block;
+		struct gpu_buddy_block *dcc_block;
 		unsigned long dcc_start;
 		u64 trim_start;
 
@@ -582,7 +583,7 @@ static int amdgpu_vram_mgr_new(struct tt
 			roundup((unsigned long)amdgpu_vram_mgr_block_start(dcc_block),
 				adjust_dcc_size);
 		trim_start = (u64)dcc_start;
-		drm_buddy_block_trim(mm, &trim_start,
+		gpu_buddy_block_trim(mm, &trim_start,
 				     (u64)vres->base.size,
 				     &vres->blocks);
 	}
@@ -620,7 +621,7 @@ static int amdgpu_vram_mgr_new(struct tt
 	return 0;
 
 error_free_blocks:
-	drm_buddy_free_list(mm, &vres->blocks, 0);
+	gpu_buddy_free_list(mm, &vres->blocks, 0);
 	mutex_unlock(&mgr->lock);
 error_fini:
 	ttm_resource_fini(man, &vres->base);
@@ -643,15 +644,15 @@ static void amdgpu_vram_mgr_del(struct t
 	struct amdgpu_vram_mgr_resource *vres = to_amdgpu_vram_mgr_resource(res);
 	struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
 	struct amdgpu_device *adev = to_amdgpu_device(mgr);
-	struct drm_buddy *mm = &mgr->mm;
-	struct drm_buddy_block *block;
+	struct gpu_buddy *mm = &mgr->mm;
+	struct gpu_buddy_block *block;
 	uint64_t vis_usage = 0;
 
 	mutex_lock(&mgr->lock);
 	list_for_each_entry(block, &vres->blocks, link)
 		vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
 
-	drm_buddy_free_list(mm, &vres->blocks, vres->flags);
+	gpu_buddy_free_list(mm, &vres->blocks, vres->flags);
 	amdgpu_vram_mgr_do_reserve(man);
 	mutex_unlock(&mgr->lock);
 
@@ -690,7 +691,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amd
 	if (!*sgt)
 		return -ENOMEM;
 
-	/* Determine the number of DRM_BUDDY blocks to export */
+	/* Determine the number of GPU_BUDDY blocks to export */
 	amdgpu_res_first(res, offset, length, &cursor);
 	while (cursor.remaining) {
 		num_entries++;
@@ -706,10 +707,10 @@ int amdgpu_vram_mgr_alloc_sgt(struct amd
 		sg->length = 0;
 
 	/*
-	 * Walk down DRM_BUDDY blocks to populate scatterlist nodes
-	 * @note: Use iterator api to get first the DRM_BUDDY block
+	 * Walk down GPU_BUDDY blocks to populate scatterlist nodes
+	 * @note: Use iterator api to get first the GPU_BUDDY block
 	 * and the number of bytes from it. Access the following
-	 * DRM_BUDDY block(s) if more buffer needs to exported
+	 * GPU_BUDDY block(s) if more buffer needs to exported
 	 */
 	amdgpu_res_first(res, offset, length, &cursor);
 	for_each_sgtable_sg((*sgt), sg, i) {
@@ -794,10 +795,10 @@ uint64_t amdgpu_vram_mgr_vis_usage(struc
 void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev)
 {
 	struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
-	struct drm_buddy *mm = &mgr->mm;
+	struct gpu_buddy *mm = &mgr->mm;
 
 	mutex_lock(&mgr->lock);
-	drm_buddy_reset_clear(mm, false);
+	gpu_buddy_reset_clear(mm, false);
 	mutex_unlock(&mgr->lock);
 }
 
@@ -817,7 +818,7 @@ static bool amdgpu_vram_mgr_intersects(s
 				       size_t size)
 {
 	struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res);
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 
 	/* Check each drm buddy block individually */
 	list_for_each_entry(block, &mgr->blocks, link) {
@@ -850,7 +851,7 @@ static bool amdgpu_vram_mgr_compatible(s
 				       size_t size)
 {
 	struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res);
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 
 	/* Check each drm buddy block individually */
 	list_for_each_entry(block, &mgr->blocks, link) {
@@ -879,7 +880,7 @@ static void amdgpu_vram_mgr_debug(struct
 				  struct drm_printer *printer)
 {
 	struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
-	struct drm_buddy *mm = &mgr->mm;
+	struct gpu_buddy *mm = &mgr->mm;
 	struct amdgpu_vram_reservation *rsv;
 
 	drm_printf(printer, "  vis usage:%llu\n",
@@ -938,7 +939,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_d
 	if (!adev->gmc.is_app_apu) {
 		man->func = &amdgpu_vram_mgr_func;
 
-		err = drm_buddy_init(&mgr->mm, man->size, PAGE_SIZE);
+		err = gpu_buddy_init(&mgr->mm, man->size, PAGE_SIZE);
 		if (err)
 			return err;
 	} else {
@@ -977,11 +978,11 @@ void amdgpu_vram_mgr_fini(struct amdgpu_
 		kfree(rsv);
 
 	list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) {
-		drm_buddy_free_list(&mgr->mm, &rsv->allocated, 0);
+		gpu_buddy_free_list(&mgr->mm, &rsv->allocated, 0);
 		kfree(rsv);
 	}
 	if (!adev->gmc.is_app_apu)
-		drm_buddy_fini(&mgr->mm);
+		gpu_buddy_fini(&mgr->mm);
 	mutex_unlock(&mgr->lock);
 
 	ttm_resource_manager_cleanup(man);
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
@@ -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_r
 
 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
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -3,1252 +3,16 @@
  * Copyright © 2021 Intel Corporation
  */
 
+#include <kunit/test-bug.h>
+
+#include <linux/export.h>
 #include <linux/kmemleak.h>
 #include <linux/module.h>
 #include <linux/sizes.h>
 
+#include <linux/gpu_buddy.h>
 #include <drm/drm_buddy.h>
-
-enum drm_buddy_free_tree {
-	DRM_BUDDY_CLEAR_TREE = 0,
-	DRM_BUDDY_DIRTY_TREE,
-	DRM_BUDDY_MAX_FREE_TREES,
-};
-
-static struct kmem_cache *slab_blocks;
-
-#define for_each_free_tree(tree) \
-	for ((tree) = 0; (tree) < DRM_BUDDY_MAX_FREE_TREES; (tree)++)
-
-static struct drm_buddy_block *drm_block_alloc(struct drm_buddy *mm,
-					       struct drm_buddy_block *parent,
-					       unsigned int order,
-					       u64 offset)
-{
-	struct drm_buddy_block *block;
-
-	BUG_ON(order > DRM_BUDDY_MAX_ORDER);
-
-	block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
-	if (!block)
-		return NULL;
-
-	block->header = offset;
-	block->header |= order;
-	block->parent = parent;
-
-	RB_CLEAR_NODE(&block->rb);
-
-	BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED);
-	return block;
-}
-
-static void drm_block_free(struct drm_buddy *mm,
-			   struct drm_buddy_block *block)
-{
-	kmem_cache_free(slab_blocks, block);
-}
-
-static enum drm_buddy_free_tree
-get_block_tree(struct drm_buddy_block *block)
-{
-	return drm_buddy_block_is_clear(block) ?
-	       DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
-}
-
-static struct drm_buddy_block *
-rbtree_get_free_block(const struct rb_node *node)
-{
-	return node ? rb_entry(node, struct drm_buddy_block, rb) : NULL;
-}
-
-static struct drm_buddy_block *
-rbtree_last_free_block(struct rb_root *root)
-{
-	return rbtree_get_free_block(rb_last(root));
-}
-
-static bool rbtree_is_empty(struct rb_root *root)
-{
-	return RB_EMPTY_ROOT(root);
-}
-
-static bool drm_buddy_block_offset_less(const struct drm_buddy_block *block,
-					const struct drm_buddy_block *node)
-{
-	return drm_buddy_block_offset(block) < drm_buddy_block_offset(node);
-}
-
-static bool rbtree_block_offset_less(struct rb_node *block,
-				     const struct rb_node *node)
-{
-	return drm_buddy_block_offset_less(rbtree_get_free_block(block),
-					   rbtree_get_free_block(node));
-}
-
-static void rbtree_insert(struct drm_buddy *mm,
-			  struct drm_buddy_block *block,
-			  enum drm_buddy_free_tree tree)
-{
-	rb_add(&block->rb,
-	       &mm->free_trees[tree][drm_buddy_block_order(block)],
-	       rbtree_block_offset_less);
-}
-
-static void rbtree_remove(struct drm_buddy *mm,
-			  struct drm_buddy_block *block)
-{
-	unsigned int order = drm_buddy_block_order(block);
-	enum drm_buddy_free_tree tree;
-	struct rb_root *root;
-
-	tree = get_block_tree(block);
-	root = &mm->free_trees[tree][order];
-
-	rb_erase(&block->rb, root);
-	RB_CLEAR_NODE(&block->rb);
-}
-
-static void clear_reset(struct drm_buddy_block *block)
-{
-	block->header &= ~DRM_BUDDY_HEADER_CLEAR;
-}
-
-static void mark_cleared(struct drm_buddy_block *block)
-{
-	block->header |= DRM_BUDDY_HEADER_CLEAR;
-}
-
-static void mark_allocated(struct drm_buddy *mm,
-			   struct drm_buddy_block *block)
-{
-	block->header &= ~DRM_BUDDY_HEADER_STATE;
-	block->header |= DRM_BUDDY_ALLOCATED;
-
-	rbtree_remove(mm, block);
-}
-
-static void mark_free(struct drm_buddy *mm,
-		      struct drm_buddy_block *block)
-{
-	enum drm_buddy_free_tree tree;
-
-	block->header &= ~DRM_BUDDY_HEADER_STATE;
-	block->header |= DRM_BUDDY_FREE;
-
-	tree = get_block_tree(block);
-	rbtree_insert(mm, block, tree);
-}
-
-static void mark_split(struct drm_buddy *mm,
-		       struct drm_buddy_block *block)
-{
-	block->header &= ~DRM_BUDDY_HEADER_STATE;
-	block->header |= DRM_BUDDY_SPLIT;
-
-	rbtree_remove(mm, block);
-}
-
-static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
-{
-	return s1 <= e2 && e1 >= s2;
-}
-
-static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
-{
-	return s1 <= s2 && e1 >= e2;
-}
-
-static struct drm_buddy_block *
-__get_buddy(struct drm_buddy_block *block)
-{
-	struct drm_buddy_block *parent;
-
-	parent = block->parent;
-	if (!parent)
-		return NULL;
-
-	if (parent->left == block)
-		return parent->right;
-
-	return parent->left;
-}
-
-static unsigned int __drm_buddy_free(struct drm_buddy *mm,
-				     struct drm_buddy_block *block,
-				     bool force_merge)
-{
-	struct drm_buddy_block *parent;
-	unsigned int order;
-
-	while ((parent = block->parent)) {
-		struct drm_buddy_block *buddy;
-
-		buddy = __get_buddy(block);
-
-		if (!drm_buddy_block_is_free(buddy))
-			break;
-
-		if (!force_merge) {
-			/*
-			 * Check the block and its buddy clear state and exit
-			 * the loop if they both have the dissimilar state.
-			 */
-			if (drm_buddy_block_is_clear(block) !=
-			    drm_buddy_block_is_clear(buddy))
-				break;
-
-			if (drm_buddy_block_is_clear(block))
-				mark_cleared(parent);
-		}
-
-		rbtree_remove(mm, buddy);
-		if (force_merge && drm_buddy_block_is_clear(buddy))
-			mm->clear_avail -= drm_buddy_block_size(mm, buddy);
-
-		drm_block_free(mm, block);
-		drm_block_free(mm, buddy);
-
-		block = parent;
-	}
-
-	order = drm_buddy_block_order(block);
-	mark_free(mm, block);
-
-	return order;
-}
-
-static int __force_merge(struct drm_buddy *mm,
-			 u64 start,
-			 u64 end,
-			 unsigned int min_order)
-{
-	unsigned int tree, order;
-	int i;
-
-	if (!min_order)
-		return -ENOMEM;
-
-	if (min_order > mm->max_order)
-		return -EINVAL;
-
-	for_each_free_tree(tree) {
-		for (i = min_order - 1; i >= 0; i--) {
-			struct rb_node *iter = rb_last(&mm->free_trees[tree][i]);
-
-			while (iter) {
-				struct drm_buddy_block *block, *buddy;
-				u64 block_start, block_end;
-
-				block = rbtree_get_free_block(iter);
-				iter = rb_prev(iter);
-
-				if (!block || !block->parent)
-					continue;
-
-				block_start = drm_buddy_block_offset(block);
-				block_end = block_start + drm_buddy_block_size(mm, block) - 1;
-
-				if (!contains(start, end, block_start, block_end))
-					continue;
-
-				buddy = __get_buddy(block);
-				if (!drm_buddy_block_is_free(buddy))
-					continue;
-
-				WARN_ON(drm_buddy_block_is_clear(block) ==
-					drm_buddy_block_is_clear(buddy));
-
-				/*
-				 * Advance to the next node when the current node is the buddy,
-				 * as freeing the block will also remove its buddy from the tree.
-				 */
-				if (iter == &buddy->rb)
-					iter = rb_prev(iter);
-
-				rbtree_remove(mm, block);
-				if (drm_buddy_block_is_clear(block))
-					mm->clear_avail -= drm_buddy_block_size(mm, block);
-
-				order = __drm_buddy_free(mm, block, true);
-				if (order >= min_order)
-					return 0;
-			}
-		}
-	}
-
-	return -ENOMEM;
-}
-
-/**
- * drm_buddy_init - init memory manager
- *
- * @mm: DRM buddy manager to initialize
- * @size: size in bytes to manage
- * @chunk_size: minimum page size in bytes for our allocations
- *
- * Initializes the memory manager and its resources.
- *
- * Returns:
- * 0 on success, error code on failure.
- */
-int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)
-{
-	unsigned int i, j, root_count = 0;
-	u64 offset = 0;
-
-	if (size < chunk_size)
-		return -EINVAL;
-
-	if (chunk_size < SZ_4K)
-		return -EINVAL;
-
-	if (!is_power_of_2(chunk_size))
-		return -EINVAL;
-
-	size = round_down(size, chunk_size);
-
-	mm->size = size;
-	mm->avail = size;
-	mm->clear_avail = 0;
-	mm->chunk_size = chunk_size;
-	mm->max_order = ilog2(size) - ilog2(chunk_size);
-
-	BUG_ON(mm->max_order > DRM_BUDDY_MAX_ORDER);
-
-	mm->free_trees = kmalloc_array(DRM_BUDDY_MAX_FREE_TREES,
-				       sizeof(*mm->free_trees),
-				       GFP_KERNEL);
-	if (!mm->free_trees)
-		return -ENOMEM;
-
-	for_each_free_tree(i) {
-		mm->free_trees[i] = kmalloc_array(mm->max_order + 1,
-						  sizeof(struct rb_root),
-						  GFP_KERNEL);
-		if (!mm->free_trees[i])
-			goto out_free_tree;
-
-		for (j = 0; j <= mm->max_order; ++j)
-			mm->free_trees[i][j] = RB_ROOT;
-	}
-
-	mm->n_roots = hweight64(size);
-
-	mm->roots = kmalloc_array(mm->n_roots,
-				  sizeof(struct drm_buddy_block *),
-				  GFP_KERNEL);
-	if (!mm->roots)
-		goto out_free_tree;
-
-	/*
-	 * Split into power-of-two blocks, in case we are given a size that is
-	 * not itself a power-of-two.
-	 */
-	do {
-		struct drm_buddy_block *root;
-		unsigned int order;
-		u64 root_size;
-
-		order = ilog2(size) - ilog2(chunk_size);
-		root_size = chunk_size << order;
-
-		root = drm_block_alloc(mm, NULL, order, offset);
-		if (!root)
-			goto out_free_roots;
-
-		mark_free(mm, root);
-
-		BUG_ON(root_count > mm->max_order);
-		BUG_ON(drm_buddy_block_size(mm, root) < chunk_size);
-
-		mm->roots[root_count] = root;
-
-		offset += root_size;
-		size -= root_size;
-		root_count++;
-	} while (size);
-
-	return 0;
-
-out_free_roots:
-	while (root_count--)
-		drm_block_free(mm, mm->roots[root_count]);
-	kfree(mm->roots);
-out_free_tree:
-	while (i--)
-		kfree(mm->free_trees[i]);
-	kfree(mm->free_trees);
-	return -ENOMEM;
-}
-EXPORT_SYMBOL(drm_buddy_init);
-
-/**
- * drm_buddy_fini - tear down the memory manager
- *
- * @mm: DRM buddy manager to free
- *
- * Cleanup memory manager resources and the freetree
- */
-void drm_buddy_fini(struct drm_buddy *mm)
-{
-	u64 root_size, size, start;
-	unsigned int order;
-	int i;
-
-	size = mm->size;
-
-	for (i = 0; i < mm->n_roots; ++i) {
-		order = ilog2(size) - ilog2(mm->chunk_size);
-		start = drm_buddy_block_offset(mm->roots[i]);
-		__force_merge(mm, start, start + size, order);
-
-		WARN_ON(!drm_buddy_block_is_free(mm->roots[i]));
-		drm_block_free(mm, mm->roots[i]);
-
-		root_size = mm->chunk_size << order;
-		size -= root_size;
-	}
-
-	WARN_ON(mm->avail != mm->size);
-
-	for_each_free_tree(i)
-		kfree(mm->free_trees[i]);
-	kfree(mm->free_trees);
-	kfree(mm->roots);
-}
-EXPORT_SYMBOL(drm_buddy_fini);
-
-static int split_block(struct drm_buddy *mm,
-		       struct drm_buddy_block *block)
-{
-	unsigned int block_order = drm_buddy_block_order(block) - 1;
-	u64 offset = drm_buddy_block_offset(block);
-
-	BUG_ON(!drm_buddy_block_is_free(block));
-	BUG_ON(!drm_buddy_block_order(block));
-
-	block->left = drm_block_alloc(mm, block, block_order, offset);
-	if (!block->left)
-		return -ENOMEM;
-
-	block->right = drm_block_alloc(mm, block, block_order,
-				       offset + (mm->chunk_size << block_order));
-	if (!block->right) {
-		drm_block_free(mm, block->left);
-		return -ENOMEM;
-	}
-
-	mark_split(mm, block);
-
-	if (drm_buddy_block_is_clear(block)) {
-		mark_cleared(block->left);
-		mark_cleared(block->right);
-		clear_reset(block);
-	}
-
-	mark_free(mm, block->left);
-	mark_free(mm, block->right);
-
-	return 0;
-}
-
-/**
- * drm_get_buddy - get buddy address
- *
- * @block: DRM buddy block
- *
- * Returns the corresponding buddy block for @block, or NULL
- * if this is a root block and can't be merged further.
- * Requires some kind of locking to protect against
- * any concurrent allocate and free operations.
- */
-struct drm_buddy_block *
-drm_get_buddy(struct drm_buddy_block *block)
-{
-	return __get_buddy(block);
-}
-EXPORT_SYMBOL(drm_get_buddy);
-
-/**
- * drm_buddy_reset_clear - reset blocks clear state
- *
- * @mm: DRM buddy manager
- * @is_clear: blocks clear state
- *
- * Reset the clear state based on @is_clear value for each block
- * in the freetree.
- */
-void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear)
-{
-	enum drm_buddy_free_tree src_tree, dst_tree;
-	u64 root_size, size, start;
-	unsigned int order;
-	int i;
-
-	size = mm->size;
-	for (i = 0; i < mm->n_roots; ++i) {
-		order = ilog2(size) - ilog2(mm->chunk_size);
-		start = drm_buddy_block_offset(mm->roots[i]);
-		__force_merge(mm, start, start + size, order);
-
-		root_size = mm->chunk_size << order;
-		size -= root_size;
-	}
-
-	src_tree = is_clear ? DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE;
-	dst_tree = is_clear ? DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
-
-	for (i = 0; i <= mm->max_order; ++i) {
-		struct rb_root *root = &mm->free_trees[src_tree][i];
-		struct drm_buddy_block *block, *tmp;
-
-		rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
-			rbtree_remove(mm, block);
-			if (is_clear) {
-				mark_cleared(block);
-				mm->clear_avail += drm_buddy_block_size(mm, block);
-			} else {
-				clear_reset(block);
-				mm->clear_avail -= drm_buddy_block_size(mm, block);
-			}
-
-			rbtree_insert(mm, block, dst_tree);
-		}
-	}
-}
-EXPORT_SYMBOL(drm_buddy_reset_clear);
-
-/**
- * drm_buddy_free_block - free a block
- *
- * @mm: DRM buddy manager
- * @block: block to be freed
- */
-void drm_buddy_free_block(struct drm_buddy *mm,
-			  struct drm_buddy_block *block)
-{
-	BUG_ON(!drm_buddy_block_is_allocated(block));
-	mm->avail += drm_buddy_block_size(mm, block);
-	if (drm_buddy_block_is_clear(block))
-		mm->clear_avail += drm_buddy_block_size(mm, block);
-
-	__drm_buddy_free(mm, block, false);
-}
-EXPORT_SYMBOL(drm_buddy_free_block);
-
-static void __drm_buddy_free_list(struct drm_buddy *mm,
-				  struct list_head *objects,
-				  bool mark_clear,
-				  bool mark_dirty)
-{
-	struct drm_buddy_block *block, *on;
-
-	WARN_ON(mark_dirty && mark_clear);
-
-	list_for_each_entry_safe(block, on, objects, link) {
-		if (mark_clear)
-			mark_cleared(block);
-		else if (mark_dirty)
-			clear_reset(block);
-		drm_buddy_free_block(mm, block);
-		cond_resched();
-	}
-	INIT_LIST_HEAD(objects);
-}
-
-static void drm_buddy_free_list_internal(struct drm_buddy *mm,
-					 struct list_head *objects)
-{
-	/*
-	 * Don't touch the clear/dirty bit, since allocation is still internal
-	 * at this point. For example we might have just failed part of the
-	 * allocation.
-	 */
-	__drm_buddy_free_list(mm, objects, false, false);
-}
-
-/**
- * drm_buddy_free_list - free blocks
- *
- * @mm: DRM buddy manager
- * @objects: input list head to free blocks
- * @flags: optional flags like DRM_BUDDY_CLEARED
- */
-void drm_buddy_free_list(struct drm_buddy *mm,
-			 struct list_head *objects,
-			 unsigned int flags)
-{
-	bool mark_clear = flags & DRM_BUDDY_CLEARED;
-
-	__drm_buddy_free_list(mm, objects, mark_clear, !mark_clear);
-}
-EXPORT_SYMBOL(drm_buddy_free_list);
-
-static bool block_incompatible(struct drm_buddy_block *block, unsigned int flags)
-{
-	bool needs_clear = flags & DRM_BUDDY_CLEAR_ALLOCATION;
-
-	return needs_clear != drm_buddy_block_is_clear(block);
-}
-
-static struct drm_buddy_block *
-__alloc_range_bias(struct drm_buddy *mm,
-		   u64 start, u64 end,
-		   unsigned int order,
-		   unsigned long flags,
-		   bool fallback)
-{
-	u64 req_size = mm->chunk_size << order;
-	struct drm_buddy_block *block;
-	struct drm_buddy_block *buddy;
-	LIST_HEAD(dfs);
-	int err;
-	int i;
-
-	end = end - 1;
-
-	for (i = 0; i < mm->n_roots; ++i)
-		list_add_tail(&mm->roots[i]->tmp_link, &dfs);
-
-	do {
-		u64 block_start;
-		u64 block_end;
-
-		block = list_first_entry_or_null(&dfs,
-						 struct drm_buddy_block,
-						 tmp_link);
-		if (!block)
-			break;
-
-		list_del(&block->tmp_link);
-
-		if (drm_buddy_block_order(block) < order)
-			continue;
-
-		block_start = drm_buddy_block_offset(block);
-		block_end = block_start + drm_buddy_block_size(mm, block) - 1;
-
-		if (!overlaps(start, end, block_start, block_end))
-			continue;
-
-		if (drm_buddy_block_is_allocated(block))
-			continue;
-
-		if (block_start < start || block_end > end) {
-			u64 adjusted_start = max(block_start, start);
-			u64 adjusted_end = min(block_end, end);
-
-			if (round_down(adjusted_end + 1, req_size) <=
-			    round_up(adjusted_start, req_size))
-				continue;
-		}
-
-		if (!fallback && block_incompatible(block, flags))
-			continue;
-
-		if (contains(start, end, block_start, block_end) &&
-		    order == drm_buddy_block_order(block)) {
-			/*
-			 * Find the free block within the range.
-			 */
-			if (drm_buddy_block_is_free(block))
-				return block;
-
-			continue;
-		}
-
-		if (!drm_buddy_block_is_split(block)) {
-			err = split_block(mm, block);
-			if (unlikely(err))
-				goto err_undo;
-		}
-
-		list_add(&block->right->tmp_link, &dfs);
-		list_add(&block->left->tmp_link, &dfs);
-	} while (1);
-
-	return ERR_PTR(-ENOSPC);
-
-err_undo:
-	/*
-	 * We really don't want to leave around a bunch of split blocks, since
-	 * bigger is better, so make sure we merge everything back before we
-	 * free the allocated blocks.
-	 */
-	buddy = __get_buddy(block);
-	if (buddy &&
-	    (drm_buddy_block_is_free(block) &&
-	     drm_buddy_block_is_free(buddy)))
-		__drm_buddy_free(mm, block, false);
-	return ERR_PTR(err);
-}
-
-static struct drm_buddy_block *
-__drm_buddy_alloc_range_bias(struct drm_buddy *mm,
-			     u64 start, u64 end,
-			     unsigned int order,
-			     unsigned long flags)
-{
-	struct drm_buddy_block *block;
-	bool fallback = false;
-
-	block = __alloc_range_bias(mm, start, end, order,
-				   flags, fallback);
-	if (IS_ERR(block))
-		return __alloc_range_bias(mm, start, end, order,
-					  flags, !fallback);
-
-	return block;
-}
-
-static struct drm_buddy_block *
-get_maxblock(struct drm_buddy *mm,
-	     unsigned int order,
-	     enum drm_buddy_free_tree tree)
-{
-	struct drm_buddy_block *max_block = NULL, *block = NULL;
-	struct rb_root *root;
-	unsigned int i;
-
-	for (i = order; i <= mm->max_order; ++i) {
-		root = &mm->free_trees[tree][i];
-		block = rbtree_last_free_block(root);
-		if (!block)
-			continue;
-
-		if (!max_block) {
-			max_block = block;
-			continue;
-		}
-
-		if (drm_buddy_block_offset(block) >
-		    drm_buddy_block_offset(max_block)) {
-			max_block = block;
-		}
-	}
-
-	return max_block;
-}
-
-static struct drm_buddy_block *
-alloc_from_freetree(struct drm_buddy *mm,
-		    unsigned int order,
-		    unsigned long flags)
-{
-	struct drm_buddy_block *block = NULL;
-	struct rb_root *root;
-	enum drm_buddy_free_tree tree;
-	unsigned int tmp;
-	int err;
-
-	tree = (flags & DRM_BUDDY_CLEAR_ALLOCATION) ?
-		DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
-
-	if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
-		block = get_maxblock(mm, order, tree);
-		if (block)
-			/* Store the obtained block order */
-			tmp = drm_buddy_block_order(block);
-	} else {
-		for (tmp = order; tmp <= mm->max_order; ++tmp) {
-			/* Get RB tree root for this order and tree */
-			root = &mm->free_trees[tree][tmp];
-			block = rbtree_last_free_block(root);
-			if (block)
-				break;
-		}
-	}
-
-	if (!block) {
-		/* Try allocating from the other tree */
-		tree = (tree == DRM_BUDDY_CLEAR_TREE) ?
-			DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE;
-
-		for (tmp = order; tmp <= mm->max_order; ++tmp) {
-			root = &mm->free_trees[tree][tmp];
-			block = rbtree_last_free_block(root);
-			if (block)
-				break;
-		}
-
-		if (!block)
-			return ERR_PTR(-ENOSPC);
-	}
-
-	BUG_ON(!drm_buddy_block_is_free(block));
-
-	while (tmp != order) {
-		err = split_block(mm, block);
-		if (unlikely(err))
-			goto err_undo;
-
-		block = block->right;
-		tmp--;
-	}
-	return block;
-
-err_undo:
-	if (tmp != order)
-		__drm_buddy_free(mm, block, false);
-	return ERR_PTR(err);
-}
-
-static int __alloc_range(struct drm_buddy *mm,
-			 struct list_head *dfs,
-			 u64 start, u64 size,
-			 struct list_head *blocks,
-			 u64 *total_allocated_on_err)
-{
-	struct drm_buddy_block *block;
-	struct drm_buddy_block *buddy;
-	u64 total_allocated = 0;
-	LIST_HEAD(allocated);
-	u64 end;
-	int err;
-
-	end = start + size - 1;
-
-	do {
-		u64 block_start;
-		u64 block_end;
-
-		block = list_first_entry_or_null(dfs,
-						 struct drm_buddy_block,
-						 tmp_link);
-		if (!block)
-			break;
-
-		list_del(&block->tmp_link);
-
-		block_start = drm_buddy_block_offset(block);
-		block_end = block_start + drm_buddy_block_size(mm, block) - 1;
-
-		if (!overlaps(start, end, block_start, block_end))
-			continue;
-
-		if (drm_buddy_block_is_allocated(block)) {
-			err = -ENOSPC;
-			goto err_free;
-		}
-
-		if (contains(start, end, block_start, block_end)) {
-			if (drm_buddy_block_is_free(block)) {
-				mark_allocated(mm, block);
-				total_allocated += drm_buddy_block_size(mm, block);
-				mm->avail -= drm_buddy_block_size(mm, block);
-				if (drm_buddy_block_is_clear(block))
-					mm->clear_avail -= drm_buddy_block_size(mm, block);
-				list_add_tail(&block->link, &allocated);
-				continue;
-			} else if (!mm->clear_avail) {
-				err = -ENOSPC;
-				goto err_free;
-			}
-		}
-
-		if (!drm_buddy_block_is_split(block)) {
-			err = split_block(mm, block);
-			if (unlikely(err))
-				goto err_undo;
-		}
-
-		list_add(&block->right->tmp_link, dfs);
-		list_add(&block->left->tmp_link, dfs);
-	} while (1);
-
-	if (total_allocated < size) {
-		err = -ENOSPC;
-		goto err_free;
-	}
-
-	list_splice_tail(&allocated, blocks);
-
-	return 0;
-
-err_undo:
-	/*
-	 * We really don't want to leave around a bunch of split blocks, since
-	 * bigger is better, so make sure we merge everything back before we
-	 * free the allocated blocks.
-	 */
-	buddy = __get_buddy(block);
-	if (buddy &&
-	    (drm_buddy_block_is_free(block) &&
-	     drm_buddy_block_is_free(buddy)))
-		__drm_buddy_free(mm, block, false);
-
-err_free:
-	if (err == -ENOSPC && total_allocated_on_err) {
-		list_splice_tail(&allocated, blocks);
-		*total_allocated_on_err = total_allocated;
-	} else {
-		drm_buddy_free_list_internal(mm, &allocated);
-	}
-
-	return err;
-}
-
-static int __drm_buddy_alloc_range(struct drm_buddy *mm,
-				   u64 start,
-				   u64 size,
-				   u64 *total_allocated_on_err,
-				   struct list_head *blocks)
-{
-	LIST_HEAD(dfs);
-	int i;
-
-	for (i = 0; i < mm->n_roots; ++i)
-		list_add_tail(&mm->roots[i]->tmp_link, &dfs);
-
-	return __alloc_range(mm, &dfs, start, size,
-			     blocks, total_allocated_on_err);
-}
-
-static int __alloc_contig_try_harder(struct drm_buddy *mm,
-				     u64 size,
-				     u64 min_block_size,
-				     struct list_head *blocks)
-{
-	u64 rhs_offset, lhs_offset, lhs_size, filled;
-	struct drm_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;
-	if (order == 0)
-		return -ENOSPC;
-
-	for_each_free_tree(tree) {
-		struct rb_root *root;
-		struct rb_node *iter;
-
-		root = &mm->free_trees[tree][order];
-		if (rbtree_is_empty(root))
-			continue;
-
-		iter = rb_last(root);
-		while (iter) {
-			block = rbtree_get_free_block(iter);
-
-			/* Allocate blocks traversing RHS */
-			rhs_offset = drm_buddy_block_offset(block);
-			err =  __drm_buddy_alloc_range(mm, rhs_offset, size,
-						       &filled, blocks);
-			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 = drm_buddy_block_offset(block) - lhs_size;
-			err =  __drm_buddy_alloc_range(mm, lhs_offset, lhs_size,
-						       NULL, &blocks_lhs);
-			if (!err) {
-				list_splice(&blocks_lhs, blocks);
-				return 0;
-			} else if (err != -ENOSPC) {
-				drm_buddy_free_list_internal(mm, blocks);
-				return err;
-			}
-			/* Free blocks for the next iteration */
-			drm_buddy_free_list_internal(mm, blocks);
-
-			iter = rb_prev(iter);
-		}
-	}
-
-	return -ENOSPC;
-}
-
-/**
- * drm_buddy_block_trim - free unused pages
- *
- * @mm: DRM buddy manager
- * @start: start address to begin the trimming.
- * @new_size: original size requested
- * @blocks: Input and output list of allocated blocks.
- * MUST contain single block as input to be trimmed.
- * On success will contain the newly allocated blocks
- * making up the @new_size. Blocks always appear in
- * ascending order
- *
- * For contiguous allocation, we round up the size to the nearest
- * power of two value, drivers consume *actual* size, so remaining
- * portions are unused and can be optionally freed with this function
- *
- * Returns:
- * 0 on success, error code on failure.
- */
-int drm_buddy_block_trim(struct drm_buddy *mm,
-			 u64 *start,
-			 u64 new_size,
-			 struct list_head *blocks)
-{
-	struct drm_buddy_block *parent;
-	struct drm_buddy_block *block;
-	u64 block_start, block_end;
-	LIST_HEAD(dfs);
-	u64 new_start;
-	int err;
-
-	if (!list_is_singular(blocks))
-		return -EINVAL;
-
-	block = list_first_entry(blocks,
-				 struct drm_buddy_block,
-				 link);
-
-	block_start = drm_buddy_block_offset(block);
-	block_end = block_start + drm_buddy_block_size(mm, block);
-
-	if (WARN_ON(!drm_buddy_block_is_allocated(block)))
-		return -EINVAL;
-
-	if (new_size > drm_buddy_block_size(mm, block))
-		return -EINVAL;
-
-	if (!new_size || !IS_ALIGNED(new_size, mm->chunk_size))
-		return -EINVAL;
-
-	if (new_size == drm_buddy_block_size(mm, block))
-		return 0;
-
-	new_start = block_start;
-	if (start) {
-		new_start = *start;
-
-		if (new_start < block_start)
-			return -EINVAL;
-
-		if (!IS_ALIGNED(new_start, mm->chunk_size))
-			return -EINVAL;
-
-		if (range_overflows(new_start, new_size, block_end))
-			return -EINVAL;
-	}
-
-	list_del(&block->link);
-	mark_free(mm, block);
-	mm->avail += drm_buddy_block_size(mm, block);
-	if (drm_buddy_block_is_clear(block))
-		mm->clear_avail += drm_buddy_block_size(mm, block);
-
-	/* Prevent recursively freeing this node */
-	parent = block->parent;
-	block->parent = NULL;
-
-	list_add(&block->tmp_link, &dfs);
-	err =  __alloc_range(mm, &dfs, new_start, new_size, blocks, NULL);
-	if (err) {
-		mark_allocated(mm, block);
-		mm->avail -= drm_buddy_block_size(mm, block);
-		if (drm_buddy_block_is_clear(block))
-			mm->clear_avail -= drm_buddy_block_size(mm, block);
-		list_add(&block->link, blocks);
-	}
-
-	block->parent = parent;
-	return err;
-}
-EXPORT_SYMBOL(drm_buddy_block_trim);
-
-static struct drm_buddy_block *
-__drm_buddy_alloc_blocks(struct drm_buddy *mm,
-			 u64 start, u64 end,
-			 unsigned int order,
-			 unsigned long flags)
-{
-	if (flags & DRM_BUDDY_RANGE_ALLOCATION)
-		/* Allocate traversing within the range */
-		return  __drm_buddy_alloc_range_bias(mm, start, end,
-						     order, flags);
-	else
-		/* Allocate from freetree */
-		return alloc_from_freetree(mm, order, flags);
-}
-
-/**
- * drm_buddy_alloc_blocks - allocate power-of-two blocks
- *
- * @mm: DRM buddy manager to allocate from
- * @start: start of the allowed range for this block
- * @end: end of the allowed range for this block
- * @size: size of the allocation in bytes
- * @min_block_size: alignment of the allocation
- * @blocks: output list head to add allocated blocks
- * @flags: DRM_BUDDY_*_ALLOCATION flags
- *
- * alloc_range_bias() called on range limitations, which traverses
- * the tree and returns the desired block.
- *
- * alloc_from_freetree() called when *no* range restrictions
- * are enforced, which picks the block from the freetree.
- *
- * Returns:
- * 0 on success, error code on failure.
- */
-int drm_buddy_alloc_blocks(struct drm_buddy *mm,
-			   u64 start, u64 end, u64 size,
-			   u64 min_block_size,
-			   struct list_head *blocks,
-			   unsigned long flags)
-{
-	struct drm_buddy_block *block = NULL;
-	u64 original_size, original_min_size;
-	unsigned int min_order, order;
-	LIST_HEAD(allocated);
-	unsigned long pages;
-	int err;
-
-	if (size < mm->chunk_size)
-		return -EINVAL;
-
-	if (min_block_size < mm->chunk_size)
-		return -EINVAL;
-
-	if (!is_power_of_2(min_block_size))
-		return -EINVAL;
-
-	if (!IS_ALIGNED(start | end | size, mm->chunk_size))
-		return -EINVAL;
-
-	if (end > mm->size)
-		return -EINVAL;
-
-	if (range_overflows(start, size, mm->size))
-		return -EINVAL;
-
-	/* Actual range allocation */
-	if (start + size == end) {
-		if (!IS_ALIGNED(start | end, min_block_size))
-			return -EINVAL;
-
-		return __drm_buddy_alloc_range(mm, start, size, NULL, blocks);
-	}
-
-	original_size = size;
-	original_min_size = min_block_size;
-
-	/* Roundup the size to power of 2 */
-	if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) {
-		size = roundup_pow_of_two(size);
-		min_block_size = size;
-	/* Align size value to min_block_size */
-	} else if (!IS_ALIGNED(size, min_block_size)) {
-		size = round_up(size, min_block_size);
-	}
-
-	pages = size >> ilog2(mm->chunk_size);
-	order = fls(pages) - 1;
-	min_order = ilog2(min_block_size) - ilog2(mm->chunk_size);
-
-	if (order > mm->max_order || size > mm->size) {
-		if ((flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) &&
-		    !(flags & DRM_BUDDY_RANGE_ALLOCATION))
-			return __alloc_contig_try_harder(mm, original_size,
-							 original_min_size, blocks);
-
-		return -EINVAL;
-	}
-
-	do {
-		order = min(order, (unsigned int)fls(pages) - 1);
-		BUG_ON(order > mm->max_order);
-		BUG_ON(order < min_order);
-
-		do {
-			block = __drm_buddy_alloc_blocks(mm, start,
-							 end,
-							 order,
-							 flags);
-			if (!IS_ERR(block))
-				break;
-
-			if (order-- == min_order) {
-				/* Try allocation through force merge method */
-				if (mm->clear_avail &&
-				    !__force_merge(mm, start, end, min_order)) {
-					block = __drm_buddy_alloc_blocks(mm, start,
-									 end,
-									 min_order,
-									 flags);
-					if (!IS_ERR(block)) {
-						order = min_order;
-						break;
-					}
-				}
-
-				/*
-				 * Try contiguous block allocation through
-				 * try harder method.
-				 */
-				if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION &&
-				    !(flags & DRM_BUDDY_RANGE_ALLOCATION))
-					return __alloc_contig_try_harder(mm,
-									 original_size,
-									 original_min_size,
-									 blocks);
-				err = -ENOSPC;
-				goto err_free;
-			}
-		} while (1);
-
-		mark_allocated(mm, block);
-		mm->avail -= drm_buddy_block_size(mm, block);
-		if (drm_buddy_block_is_clear(block))
-			mm->clear_avail -= drm_buddy_block_size(mm, block);
-		kmemleak_update_trace(block);
-		list_add_tail(&block->link, &allocated);
-
-		pages -= BIT(order);
-
-		if (!pages)
-			break;
-	} while (1);
-
-	/* Trim the allocated block to the required size */
-	if (!(flags & DRM_BUDDY_TRIM_DISABLE) &&
-	    original_size != size) {
-		struct list_head *trim_list;
-		LIST_HEAD(temp);
-		u64 trim_size;
-
-		trim_list = &allocated;
-		trim_size = original_size;
-
-		if (!list_is_singular(&allocated)) {
-			block = list_last_entry(&allocated, typeof(*block), link);
-			list_move(&block->link, &temp);
-			trim_list = &temp;
-			trim_size = drm_buddy_block_size(mm, block) -
-				(size - original_size);
-		}
-
-		drm_buddy_block_trim(mm,
-				     NULL,
-				     trim_size,
-				     trim_list);
-
-		if (!list_empty(&temp))
-			list_splice_tail(trim_list, &allocated);
-	}
-
-	list_splice_tail(&allocated, blocks);
-	return 0;
-
-err_free:
-	drm_buddy_free_list_internal(mm, &allocated);
-	return err;
-}
-EXPORT_SYMBOL(drm_buddy_alloc_blocks);
+#include <drm/drm_print.h>
 
 /**
  * drm_buddy_block_print - print block information
@@ -1257,12 +21,12 @@ EXPORT_SYMBOL(drm_buddy_alloc_blocks);
  * @block: DRM buddy block
  * @p: DRM printer to use
  */
-void drm_buddy_block_print(struct drm_buddy *mm,
-			   struct drm_buddy_block *block,
+void drm_buddy_block_print(struct gpu_buddy *mm,
+			   struct gpu_buddy_block *block,
 			   struct drm_printer *p)
 {
-	u64 start = drm_buddy_block_offset(block);
-	u64 size = drm_buddy_block_size(mm, block);
+	u64 start = gpu_buddy_block_offset(block);
+	u64 size = gpu_buddy_block_size(mm, block);
 
 	drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size);
 }
@@ -1274,7 +38,7 @@ EXPORT_SYMBOL(drm_buddy_block_print);
  * @mm: DRM buddy manager
  * @p: DRM printer to use
  */
-void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p)
+void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p)
 {
 	int order;
 
@@ -1282,7 +46,7 @@ void drm_buddy_print(struct drm_buddy *m
 		   mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
 
 	for (order = mm->max_order; order >= 0; order--) {
-		struct drm_buddy_block *block, *tmp;
+		struct gpu_buddy_block *block, *tmp;
 		struct rb_root *root;
 		u64 count = 0, free;
 		unsigned int tree;
@@ -1291,7 +55,7 @@ void drm_buddy_print(struct drm_buddy *m
 			root = &mm->free_trees[tree][order];
 
 			rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
-				BUG_ON(!drm_buddy_block_is_free(block));
+				BUG_ON(!gpu_buddy_block_is_free(block));
 				count++;
 			}
 		}
@@ -1309,22 +73,5 @@ void drm_buddy_print(struct drm_buddy *m
 }
 EXPORT_SYMBOL(drm_buddy_print);
 
-static void drm_buddy_module_exit(void)
-{
-	kmem_cache_destroy(slab_blocks);
-}
-
-static int __init drm_buddy_module_init(void)
-{
-	slab_blocks = KMEM_CACHE(drm_buddy_block, 0);
-	if (!slab_blocks)
-		return -ENOMEM;
-
-	return 0;
-}
-
-module_init(drm_buddy_module_init);
-module_exit(drm_buddy_module_exit);
-
-MODULE_DESCRIPTION("DRM Buddy Allocator");
+MODULE_DESCRIPTION("DRM-specific GPU Buddy Allocator Print Helpers");
 MODULE_LICENSE("Dual MIT/GPL");
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -7,7 +7,7 @@
 
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_tt.h>
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
 
 #include "i915_drv.h"
 #include "i915_ttm_buddy_manager.h"
--- a/drivers/gpu/drm/i915/i915_scatterlist.c
+++ b/drivers/gpu/drm/i915/i915_scatterlist.c
@@ -7,7 +7,7 @@
 #include "i915_scatterlist.h"
 #include "i915_ttm_buddy_manager.h"
 
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
 #include <drm/drm_mm.h>
 
 #include <linux/slab.h>
@@ -167,9 +167,9 @@ struct i915_refct_sgt *i915_rsgt_from_bu
 	struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
 	const u64 size = res->size;
 	const u32 max_segment = round_down(UINT_MAX, page_alignment);
-	struct drm_buddy *mm = bman_res->mm;
+	struct gpu_buddy *mm = bman_res->mm;
 	struct list_head *blocks = &bman_res->blocks;
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	struct i915_refct_sgt *rsgt;
 	struct scatterlist *sg;
 	struct sg_table *st;
@@ -202,8 +202,8 @@ struct i915_refct_sgt *i915_rsgt_from_bu
 	list_for_each_entry(block, blocks, link) {
 		u64 block_size, offset;
 
-		block_size = min_t(u64, size, drm_buddy_block_size(mm, block));
-		offset = drm_buddy_block_offset(block);
+		block_size = min_t(u64, size, gpu_buddy_block_size(mm, block));
+		offset = gpu_buddy_block_offset(block);
 
 		while (block_size) {
 			u64 len;
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -8,6 +8,7 @@
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_bo.h>
 
+#include <linux/gpu_buddy.h>
 #include <drm/drm_buddy.h>
 
 #include "i915_ttm_buddy_manager.h"
@@ -16,7 +17,7 @@
 
 struct i915_ttm_buddy_manager {
 	struct ttm_resource_manager manager;
-	struct drm_buddy mm;
+	struct gpu_buddy mm;
 	struct list_head reserved;
 	struct mutex lock;
 	unsigned long visible_size;
@@ -38,7 +39,7 @@ static int i915_ttm_buddy_man_alloc(stru
 {
 	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
 	struct i915_ttm_buddy_resource *bman_res;
-	struct drm_buddy *mm = &bman->mm;
+	struct gpu_buddy *mm = &bman->mm;
 	unsigned long n_pages, lpfn;
 	u64 min_page_size;
 	u64 size;
@@ -57,13 +58,13 @@ static int i915_ttm_buddy_man_alloc(stru
 	bman_res->mm = mm;
 
 	if (place->flags & TTM_PL_FLAG_TOPDOWN)
-		bman_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+		bman_res->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
 
 	if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
-		bman_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+		bman_res->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;
 
 	if (place->fpfn || lpfn != man->size)
-		bman_res->flags |= DRM_BUDDY_RANGE_ALLOCATION;
+		bman_res->flags |= GPU_BUDDY_RANGE_ALLOCATION;
 
 	GEM_BUG_ON(!bman_res->base.size);
 	size = bman_res->base.size;
@@ -89,7 +90,7 @@ static int i915_ttm_buddy_man_alloc(stru
 		goto err_free_res;
 	}
 
-	err = drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
+	err = gpu_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
 				     (u64)lpfn << PAGE_SHIFT,
 				     (u64)n_pages << PAGE_SHIFT,
 				     min_page_size,
@@ -101,15 +102,15 @@ static int i915_ttm_buddy_man_alloc(stru
 	if (lpfn <= bman->visible_size) {
 		bman_res->used_visible_size = PFN_UP(bman_res->base.size);
 	} else {
-		struct drm_buddy_block *block;
+		struct gpu_buddy_block *block;
 
 		list_for_each_entry(block, &bman_res->blocks, link) {
 			unsigned long start =
-				drm_buddy_block_offset(block) >> PAGE_SHIFT;
+				gpu_buddy_block_offset(block) >> PAGE_SHIFT;
 
 			if (start < bman->visible_size) {
 				unsigned long end = start +
-					(drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+					(gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
 
 				bman_res->used_visible_size +=
 					min(end, bman->visible_size) - start;
@@ -126,7 +127,7 @@ static int i915_ttm_buddy_man_alloc(stru
 	return 0;
 
 err_free_blocks:
-	drm_buddy_free_list(mm, &bman_res->blocks, 0);
+	gpu_buddy_free_list(mm, &bman_res->blocks, 0);
 	mutex_unlock(&bman->lock);
 err_free_res:
 	ttm_resource_fini(man, &bman_res->base);
@@ -141,7 +142,7 @@ static void i915_ttm_buddy_man_free(stru
 	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
 
 	mutex_lock(&bman->lock);
-	drm_buddy_free_list(&bman->mm, &bman_res->blocks, 0);
+	gpu_buddy_free_list(&bman->mm, &bman_res->blocks, 0);
 	bman->visible_avail += bman_res->used_visible_size;
 	mutex_unlock(&bman->lock);
 
@@ -156,8 +157,8 @@ static bool i915_ttm_buddy_man_intersect
 {
 	struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
 	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
-	struct drm_buddy *mm = &bman->mm;
-	struct drm_buddy_block *block;
+	struct gpu_buddy *mm = &bman->mm;
+	struct gpu_buddy_block *block;
 
 	if (!place->fpfn && !place->lpfn)
 		return true;
@@ -176,9 +177,9 @@ static bool i915_ttm_buddy_man_intersect
 	/* Check each drm buddy block individually */
 	list_for_each_entry(block, &bman_res->blocks, link) {
 		unsigned long fpfn =
-			drm_buddy_block_offset(block) >> PAGE_SHIFT;
+			gpu_buddy_block_offset(block) >> PAGE_SHIFT;
 		unsigned long lpfn = fpfn +
-			(drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+			(gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
 
 		if (place->fpfn < lpfn && place->lpfn > fpfn)
 			return true;
@@ -194,8 +195,8 @@ static bool i915_ttm_buddy_man_compatibl
 {
 	struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
 	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
-	struct drm_buddy *mm = &bman->mm;
-	struct drm_buddy_block *block;
+	struct gpu_buddy *mm = &bman->mm;
+	struct gpu_buddy_block *block;
 
 	if (!place->fpfn && !place->lpfn)
 		return true;
@@ -209,9 +210,9 @@ static bool i915_ttm_buddy_man_compatibl
 	/* Check each drm buddy block individually */
 	list_for_each_entry(block, &bman_res->blocks, link) {
 		unsigned long fpfn =
-			drm_buddy_block_offset(block) >> PAGE_SHIFT;
+			gpu_buddy_block_offset(block) >> PAGE_SHIFT;
 		unsigned long lpfn = fpfn +
-			(drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+			(gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
 
 		if (fpfn < place->fpfn || lpfn > place->lpfn)
 			return false;
@@ -224,7 +225,7 @@ static void i915_ttm_buddy_man_debug(str
 				     struct drm_printer *printer)
 {
 	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 
 	mutex_lock(&bman->lock);
 	drm_printf(printer, "default_page_size: %lluKiB\n",
@@ -293,7 +294,7 @@ int i915_ttm_buddy_man_init(struct ttm_d
 	if (!bman)
 		return -ENOMEM;
 
-	err = drm_buddy_init(&bman->mm, size, chunk_size);
+	err = gpu_buddy_init(&bman->mm, size, chunk_size);
 	if (err)
 		goto err_free_bman;
 
@@ -333,7 +334,7 @@ int i915_ttm_buddy_man_fini(struct ttm_d
 {
 	struct ttm_resource_manager *man = ttm_manager_type(bdev, type);
 	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
-	struct drm_buddy *mm = &bman->mm;
+	struct gpu_buddy *mm = &bman->mm;
 	int ret;
 
 	ttm_resource_manager_set_used(man, false);
@@ -345,8 +346,8 @@ int i915_ttm_buddy_man_fini(struct ttm_d
 	ttm_set_driver_manager(bdev, type, NULL);
 
 	mutex_lock(&bman->lock);
-	drm_buddy_free_list(mm, &bman->reserved, 0);
-	drm_buddy_fini(mm);
+	gpu_buddy_free_list(mm, &bman->reserved, 0);
+	gpu_buddy_fini(mm);
 	bman->visible_avail += bman->visible_reserved;
 	WARN_ON_ONCE(bman->visible_avail != bman->visible_size);
 	mutex_unlock(&bman->lock);
@@ -371,15 +372,15 @@ int i915_ttm_buddy_man_reserve(struct tt
 			       u64 start, u64 size)
 {
 	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
-	struct drm_buddy *mm = &bman->mm;
+	struct gpu_buddy *mm = &bman->mm;
 	unsigned long fpfn = start >> PAGE_SHIFT;
 	unsigned long flags = 0;
 	int ret;
 
-	flags |= DRM_BUDDY_RANGE_ALLOCATION;
+	flags |= GPU_BUDDY_RANGE_ALLOCATION;
 
 	mutex_lock(&bman->lock);
-	ret = drm_buddy_alloc_blocks(mm, start,
+	ret = gpu_buddy_alloc_blocks(mm, start,
 				     start + size,
 				     size, mm->chunk_size,
 				     &bman->reserved,
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
@@ -13,7 +13,7 @@
 
 struct ttm_device;
 struct ttm_resource_manager;
-struct drm_buddy;
+struct gpu_buddy;
 
 /**
  * struct i915_ttm_buddy_resource
@@ -33,7 +33,7 @@ struct i915_ttm_buddy_resource {
 	struct list_head blocks;
 	unsigned long flags;
 	unsigned long used_visible_size;
-	struct drm_buddy *mm;
+	struct gpu_buddy *mm;
 };
 
 /**
--- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
@@ -6,7 +6,7 @@
 #include <linux/prime_numbers.h>
 #include <linux/sort.h>
 
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
 
 #include "../i915_selftest.h"
 
@@ -371,7 +371,7 @@ static int igt_mock_splintered_region(vo
 	struct drm_i915_private *i915 = mem->i915;
 	struct i915_ttm_buddy_resource *res;
 	struct drm_i915_gem_object *obj;
-	struct drm_buddy *mm;
+	struct gpu_buddy *mm;
 	unsigned int expected_order;
 	LIST_HEAD(objects);
 	u64 size;
@@ -455,8 +455,8 @@ static int igt_mock_max_segment(void *ar
 	struct drm_i915_private *i915 = mem->i915;
 	struct i915_ttm_buddy_resource *res;
 	struct drm_i915_gem_object *obj;
-	struct drm_buddy_block *block;
-	struct drm_buddy *mm;
+	struct gpu_buddy_block *block;
+	struct gpu_buddy *mm;
 	struct list_head *blocks;
 	struct scatterlist *sg;
 	I915_RND_STATE(prng);
@@ -495,8 +495,8 @@ static int igt_mock_max_segment(void *ar
 	mm = res->mm;
 	size = 0;
 	list_for_each_entry(block, blocks, link) {
-		if (drm_buddy_block_size(mm, block) > size)
-			size = drm_buddy_block_size(mm, block);
+		if (gpu_buddy_block_size(mm, block) > size)
+			size = gpu_buddy_block_size(mm, block);
 	}
 	if (size < max_segment) {
 		pr_err("%s: Failed to create a huge contiguous block [> %u], largest block %lld\n",
@@ -535,14 +535,14 @@ static u64 igt_object_mappable_total(str
 	struct intel_memory_region *mr = obj->mm.region;
 	struct i915_ttm_buddy_resource *bman_res =
 		to_ttm_buddy_resource(obj->mm.res);
-	struct drm_buddy *mm = bman_res->mm;
-	struct drm_buddy_block *block;
+	struct gpu_buddy *mm = bman_res->mm;
+	struct gpu_buddy_block *block;
 	u64 total;
 
 	total = 0;
 	list_for_each_entry(block, &bman_res->blocks, link) {
-		u64 start = drm_buddy_block_offset(block);
-		u64 end = start + drm_buddy_block_size(mm, block);
+		u64 start = gpu_buddy_block_offset(block);
+		u64 end = start + gpu_buddy_block_size(mm, block);
 
 		if (start < resource_size(&mr->io))
 			total += min_t(u64, end, resource_size(&mr->io)) - start;
--- a/drivers/gpu/drm/lib/drm_random.c
+++ /dev/null
@@ -1,43 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#include "drm_random.h"
-
-u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
-{
-	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
-}
-EXPORT_SYMBOL(drm_prandom_u32_max_state);
-
-void drm_random_reorder(unsigned int *order, unsigned int count,
-			struct rnd_state *state)
-{
-	unsigned int i, j;
-
-	for (i = 0; i < count; ++i) {
-		BUILD_BUG_ON(sizeof(unsigned int) > sizeof(u32));
-		j = drm_prandom_u32_max_state(count, state);
-		swap(order[i], order[j]);
-	}
-}
-EXPORT_SYMBOL(drm_random_reorder);
-
-unsigned int *drm_random_order(unsigned int count, struct rnd_state *state)
-{
-	unsigned int *order, i;
-
-	order = kmalloc_array(count, sizeof(*order), GFP_KERNEL);
-	if (!order)
-		return order;
-
-	for (i = 0; i < count; i++)
-		order[i] = i;
-
-	drm_random_reorder(order, count, state);
-	return order;
-}
-EXPORT_SYMBOL(drm_random_order);
--- a/drivers/gpu/drm/lib/drm_random.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __DRM_RANDOM_H__
-#define __DRM_RANDOM_H__
-
-/* This is a temporary home for a couple of utility functions that should
- * be transposed to lib/ at the earliest convenience.
- */
-
-#include <linux/random.h>
-
-#define DRM_RND_STATE_INITIALIZER(seed__) ({				\
-	struct rnd_state state__;					\
-	prandom_seed_state(&state__, (seed__));				\
-	state__;							\
-})
-
-#define DRM_RND_STATE(name__, seed__) \
-	struct rnd_state name__ = DRM_RND_STATE_INITIALIZER(seed__)
-
-unsigned int *drm_random_order(unsigned int count,
-			       struct rnd_state *state);
-void drm_random_reorder(unsigned int *order,
-			unsigned int count,
-			struct rnd_state *state);
-u32 drm_prandom_u32_max_state(u32 ep_ro,
-			      struct rnd_state *state);
-
-#endif /* !__DRM_RANDOM_H__ */
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -4,7 +4,6 @@ obj-$(CONFIG_DRM_KUNIT_TEST_HELPERS) +=
 	drm_kunit_helpers.o
 
 obj-$(CONFIG_DRM_KUNIT_TEST) += \
-	drm_buddy_test.o \
 	drm_cmdline_parser_test.o \
 	drm_connector_test.o \
 	drm_damage_helper_test.o \
--- a/drivers/gpu/drm/tests/drm_buddy_test.c
+++ /dev/null
@@ -1,778 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2019 Intel Corporation
- * Copyright © 2022 Maíra Canal <mairacanal@riseup.net>
- */
-
-#include <kunit/test.h>
-
-#include <linux/prime_numbers.h>
-#include <linux/sched/signal.h>
-#include <linux/sizes.h>
-
-#include <drm/drm_buddy.h>
-
-#include "../lib/drm_random.h"
-
-static unsigned int random_seed;
-
-static inline u64 get_size(int order, u64 chunk_size)
-{
-	return (1 << order) * chunk_size;
-}
-
-static void drm_test_buddy_alloc_range_bias(struct kunit *test)
-{
-	u32 mm_size, size, ps, bias_size, bias_start, bias_end, bias_rem;
-	DRM_RND_STATE(prng, random_seed);
-	unsigned int i, count, *order;
-	struct drm_buddy_block *block;
-	unsigned long flags;
-	struct drm_buddy mm;
-	LIST_HEAD(allocated);
-
-	bias_size = SZ_1M;
-	ps = roundup_pow_of_two(prandom_u32_state(&prng) % bias_size);
-	ps = max(SZ_4K, ps);
-	mm_size = (SZ_8M-1) & ~(ps-1); /* Multiple roots */
-
-	kunit_info(test, "mm_size=%u, ps=%u\n", mm_size, ps);
-
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps),
-			       "buddy_init failed\n");
-
-	count = mm_size / bias_size;
-	order = drm_random_order(count, &prng);
-	KUNIT_EXPECT_TRUE(test, order);
-
-	/*
-	 * Idea is to split the address space into uniform bias ranges, and then
-	 * in some random order allocate within each bias, using various
-	 * patterns within. This should detect if allocations leak out from a
-	 * given bias, for example.
-	 */
-
-	for (i = 0; i < count; i++) {
-		LIST_HEAD(tmp);
-		u32 size;
-
-		bias_start = order[i] * bias_size;
-		bias_end = bias_start + bias_size;
-		bias_rem = bias_size;
-
-		/* internal round_up too big */
-		KUNIT_ASSERT_TRUE_MSG(test,
-				      drm_buddy_alloc_blocks(&mm, bias_start,
-							     bias_end, bias_size + ps, bias_size,
-							     &allocated,
-							     DRM_BUDDY_RANGE_ALLOCATION),
-				      "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
-				      bias_start, bias_end, bias_size, bias_size);
-
-		/* size too big */
-		KUNIT_ASSERT_TRUE_MSG(test,
-				      drm_buddy_alloc_blocks(&mm, bias_start,
-							     bias_end, bias_size + ps, ps,
-							     &allocated,
-							     DRM_BUDDY_RANGE_ALLOCATION),
-				      "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
-				      bias_start, bias_end, bias_size + ps, ps);
-
-		/* bias range too small for size */
-		KUNIT_ASSERT_TRUE_MSG(test,
-				      drm_buddy_alloc_blocks(&mm, bias_start + ps,
-							     bias_end, bias_size, ps,
-							     &allocated,
-							     DRM_BUDDY_RANGE_ALLOCATION),
-				      "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
-				      bias_start + ps, bias_end, bias_size, ps);
-
-		/* bias misaligned */
-		KUNIT_ASSERT_TRUE_MSG(test,
-				      drm_buddy_alloc_blocks(&mm, bias_start + ps,
-							     bias_end - ps,
-							     bias_size >> 1, bias_size >> 1,
-							     &allocated,
-							     DRM_BUDDY_RANGE_ALLOCATION),
-				      "buddy_alloc h didn't fail with bias(%x-%x), size=%u, ps=%u\n",
-				      bias_start + ps, bias_end - ps, bias_size >> 1, bias_size >> 1);
-
-		/* single big page */
-		KUNIT_ASSERT_FALSE_MSG(test,
-				       drm_buddy_alloc_blocks(&mm, bias_start,
-							      bias_end, bias_size, bias_size,
-							      &tmp,
-							      DRM_BUDDY_RANGE_ALLOCATION),
-				       "buddy_alloc i failed with bias(%x-%x), size=%u, ps=%u\n",
-				       bias_start, bias_end, bias_size, bias_size);
-		drm_buddy_free_list(&mm, &tmp, 0);
-
-		/* single page with internal round_up */
-		KUNIT_ASSERT_FALSE_MSG(test,
-				       drm_buddy_alloc_blocks(&mm, bias_start,
-							      bias_end, ps, bias_size,
-							      &tmp,
-							      DRM_BUDDY_RANGE_ALLOCATION),
-				       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
-				       bias_start, bias_end, ps, bias_size);
-		drm_buddy_free_list(&mm, &tmp, 0);
-
-		/* random size within */
-		size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
-		if (size)
-			KUNIT_ASSERT_FALSE_MSG(test,
-					       drm_buddy_alloc_blocks(&mm, bias_start,
-								      bias_end, size, ps,
-								      &tmp,
-								      DRM_BUDDY_RANGE_ALLOCATION),
-					       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
-					       bias_start, bias_end, size, ps);
-
-		bias_rem -= size;
-		/* too big for current avail */
-		KUNIT_ASSERT_TRUE_MSG(test,
-				      drm_buddy_alloc_blocks(&mm, bias_start,
-							     bias_end, bias_rem + ps, ps,
-							     &allocated,
-							     DRM_BUDDY_RANGE_ALLOCATION),
-				      "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
-				      bias_start, bias_end, bias_rem + ps, ps);
-
-		if (bias_rem) {
-			/* random fill of the remainder */
-			size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
-			size = max(size, ps);
-
-			KUNIT_ASSERT_FALSE_MSG(test,
-					       drm_buddy_alloc_blocks(&mm, bias_start,
-								      bias_end, size, ps,
-								      &allocated,
-								      DRM_BUDDY_RANGE_ALLOCATION),
-					       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
-					       bias_start, bias_end, size, ps);
-			/*
-			 * Intentionally allow some space to be left
-			 * unallocated, and ideally not always on the bias
-			 * boundaries.
-			 */
-			drm_buddy_free_list(&mm, &tmp, 0);
-		} else {
-			list_splice_tail(&tmp, &allocated);
-		}
-	}
-
-	kfree(order);
-	drm_buddy_free_list(&mm, &allocated, 0);
-	drm_buddy_fini(&mm);
-
-	/*
-	 * Something more free-form. Idea is to pick a random starting bias
-	 * range within the address space and then start filling it up. Also
-	 * randomly grow the bias range in both directions as we go along. This
-	 * should give us bias start/end which is not always uniform like above,
-	 * and in some cases will require the allocator to jump over already
-	 * allocated nodes in the middle of the address space.
-	 */
-
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps),
-			       "buddy_init failed\n");
-
-	bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
-	bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
-	bias_end = max(bias_end, bias_start + ps);
-	bias_rem = bias_end - bias_start;
-
-	do {
-		u32 size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
-
-		KUNIT_ASSERT_FALSE_MSG(test,
-				       drm_buddy_alloc_blocks(&mm, bias_start,
-							      bias_end, size, ps,
-							      &allocated,
-							      DRM_BUDDY_RANGE_ALLOCATION),
-				       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
-				       bias_start, bias_end, size, ps);
-		bias_rem -= size;
-
-		/*
-		 * Try to randomly grow the bias range in both directions, or
-		 * only one, or perhaps don't grow at all.
-		 */
-		do {
-			u32 old_bias_start = bias_start;
-			u32 old_bias_end = bias_end;
-
-			if (bias_start)
-				bias_start -= round_up(prandom_u32_state(&prng) % bias_start, ps);
-			if (bias_end != mm_size)
-				bias_end += round_up(prandom_u32_state(&prng) % (mm_size - bias_end), ps);
-
-			bias_rem += old_bias_start - bias_start;
-			bias_rem += bias_end - old_bias_end;
-		} while (!bias_rem && (bias_start || bias_end != mm_size));
-	} while (bias_rem);
-
-	KUNIT_ASSERT_EQ(test, bias_start, 0);
-	KUNIT_ASSERT_EQ(test, bias_end, mm_size);
-	KUNIT_ASSERT_TRUE_MSG(test,
-			      drm_buddy_alloc_blocks(&mm, bias_start, bias_end,
-						     ps, ps,
-						     &allocated,
-						     DRM_BUDDY_RANGE_ALLOCATION),
-			      "buddy_alloc passed with bias(%x-%x), size=%u\n",
-			      bias_start, bias_end, ps);
-
-	drm_buddy_free_list(&mm, &allocated, 0);
-	drm_buddy_fini(&mm);
-
-	/*
-	 * Allocate cleared blocks in the bias range when the DRM buddy's clear avail is
-	 * zero. This will validate the bias range allocation in scenarios like system boot
-	 * when no cleared blocks are available and exercise the fallback path too. The resulting
-	 * blocks should always be dirty.
-	 */
-
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps),
-			       "buddy_init failed\n");
-
-	bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
-	bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
-	bias_end = max(bias_end, bias_start + ps);
-	bias_rem = bias_end - bias_start;
-
-	flags = DRM_BUDDY_CLEAR_ALLOCATION | DRM_BUDDY_RANGE_ALLOCATION;
-	size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
-
-	KUNIT_ASSERT_FALSE_MSG(test,
-			       drm_buddy_alloc_blocks(&mm, bias_start,
-						      bias_end, size, ps,
-						      &allocated,
-						      flags),
-			       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
-			       bias_start, bias_end, size, ps);
-
-	list_for_each_entry(block, &allocated, link)
-		KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false);
-
-	drm_buddy_free_list(&mm, &allocated, 0);
-	drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_clear(struct kunit *test)
-{
-	unsigned long n_pages, total, i = 0;
-	DRM_RND_STATE(prng, random_seed);
-	const unsigned long ps = SZ_4K;
-	struct drm_buddy_block *block;
-	const int max_order = 12;
-	LIST_HEAD(allocated);
-	struct drm_buddy mm;
-	unsigned int order;
-	u32 mm_size, size;
-	LIST_HEAD(dirty);
-	LIST_HEAD(clean);
-
-	mm_size = SZ_4K << max_order;
-	KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
-
-	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
-	/*
-	 * Idea is to allocate and free some random portion of the address space,
-	 * returning those pages as non-dirty and randomly alternate between
-	 * requesting dirty and non-dirty pages (not going over the limit
-	 * we freed as non-dirty), putting that into two separate lists.
-	 * Loop over both lists at the end checking that the dirty list
-	 * is indeed all dirty pages and vice versa. Free it all again,
-	 * keeping the dirty/clear status.
-	 */
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							    5 * ps, ps, &allocated,
-							    DRM_BUDDY_TOPDOWN_ALLOCATION),
-				"buddy_alloc hit an error size=%lu\n", 5 * ps);
-	drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED);
-
-	n_pages = 10;
-	do {
-		unsigned long flags;
-		struct list_head *list;
-		int slot = i % 2;
-
-		if (slot == 0) {
-			list = &dirty;
-			flags = 0;
-		} else {
-			list = &clean;
-			flags = DRM_BUDDY_CLEAR_ALLOCATION;
-		}
-
-		KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-								    ps, ps, list,
-								    flags),
-					"buddy_alloc hit an error size=%lu\n", ps);
-	} while (++i < n_pages);
-
-	list_for_each_entry(block, &clean, link)
-		KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), true);
-
-	list_for_each_entry(block, &dirty, link)
-		KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false);
-
-	drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED);
-
-	/*
-	 * Trying to go over the clear limit for some allocation.
-	 * The allocation should never fail with reasonable page-size.
-	 */
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							    10 * ps, ps, &clean,
-							    DRM_BUDDY_CLEAR_ALLOCATION),
-				"buddy_alloc hit an error size=%lu\n", 10 * ps);
-
-	drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED);
-	drm_buddy_free_list(&mm, &dirty, 0);
-	drm_buddy_fini(&mm);
-
-	KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
-
-	/*
-	 * Create a new mm. Intentionally fragment the address space by creating
-	 * two alternating lists. Free both lists, one as dirty the other as clean.
-	 * Try to allocate double the previous size with matching min_page_size. The
-	 * allocation should never fail as it calls the force_merge. Also check that
-	 * the page is always dirty after force_merge. Free the page as dirty, then
-	 * repeat the whole thing, increment the order until we hit the max_order.
-	 */
-
-	i = 0;
-	n_pages = mm_size / ps;
-	do {
-		struct list_head *list;
-		int slot = i % 2;
-
-		if (slot == 0)
-			list = &dirty;
-		else
-			list = &clean;
-
-		KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-								    ps, ps, list, 0),
-					"buddy_alloc hit an error size=%lu\n", ps);
-	} while (++i < n_pages);
-
-	drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED);
-	drm_buddy_free_list(&mm, &dirty, 0);
-
-	order = 1;
-	do {
-		size = SZ_4K << order;
-
-		KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-								    size, size, &allocated,
-								    DRM_BUDDY_CLEAR_ALLOCATION),
-					"buddy_alloc hit an error size=%u\n", size);
-		total = 0;
-		list_for_each_entry(block, &allocated, link) {
-			if (size != mm_size)
-				KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false);
-			total += drm_buddy_block_size(&mm, block);
-		}
-		KUNIT_EXPECT_EQ(test, total, size);
-
-		drm_buddy_free_list(&mm, &allocated, 0);
-	} while (++order <= max_order);
-
-	drm_buddy_fini(&mm);
-
-	/*
-	 * Create a new mm with a non power-of-two size. Allocate a random size, free as
-	 * cleared and then call fini. This will ensure the multi-root force merge during
-	 * fini.
-	 */
-	mm_size = 12 * SZ_4K;
-	size = max(round_up(prandom_u32_state(&prng) % mm_size, ps), ps);
-	KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							    size, ps, &allocated,
-							    DRM_BUDDY_TOPDOWN_ALLOCATION),
-				"buddy_alloc hit an error size=%u\n", size);
-	drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED);
-	drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_contiguous(struct kunit *test)
-{
-	const unsigned long ps = SZ_4K, mm_size = 16 * 3 * SZ_4K;
-	unsigned long i, n_pages, total;
-	struct drm_buddy_block *block;
-	struct drm_buddy mm;
-	LIST_HEAD(left);
-	LIST_HEAD(middle);
-	LIST_HEAD(right);
-	LIST_HEAD(allocated);
-
-	KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
-
-	/*
-	 * Idea is to fragment the address space by alternating block
-	 * allocations between three different lists; one for left, middle and
-	 * right. We can then free a list to simulate fragmentation. In
-	 * particular we want to exercise the DRM_BUDDY_CONTIGUOUS_ALLOCATION,
-	 * including the try_harder path.
-	 */
-
-	i = 0;
-	n_pages = mm_size / ps;
-	do {
-		struct list_head *list;
-		int slot = i % 3;
-
-		if (slot == 0)
-			list = &left;
-		else if (slot == 1)
-			list = &middle;
-		else
-			list = &right;
-		KUNIT_ASSERT_FALSE_MSG(test,
-				       drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							      ps, ps, list, 0),
-				       "buddy_alloc hit an error size=%lu\n",
-				       ps);
-	} while (++i < n_pages);
-
-	KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							   3 * ps, ps, &allocated,
-							   DRM_BUDDY_CONTIGUOUS_ALLOCATION),
-			       "buddy_alloc didn't error size=%lu\n", 3 * ps);
-
-	drm_buddy_free_list(&mm, &middle, 0);
-	KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							   3 * ps, ps, &allocated,
-							   DRM_BUDDY_CONTIGUOUS_ALLOCATION),
-			       "buddy_alloc didn't error size=%lu\n", 3 * ps);
-	KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							   2 * ps, ps, &allocated,
-							   DRM_BUDDY_CONTIGUOUS_ALLOCATION),
-			       "buddy_alloc didn't error size=%lu\n", 2 * ps);
-
-	drm_buddy_free_list(&mm, &right, 0);
-	KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							   3 * ps, ps, &allocated,
-							   DRM_BUDDY_CONTIGUOUS_ALLOCATION),
-			       "buddy_alloc didn't error size=%lu\n", 3 * ps);
-	/*
-	 * At this point we should have enough contiguous space for 2 blocks,
-	 * however they are never buddies (since we freed middle and right) so
-	 * will require the try_harder logic to find them.
-	 */
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							    2 * ps, ps, &allocated,
-							    DRM_BUDDY_CONTIGUOUS_ALLOCATION),
-			       "buddy_alloc hit an error size=%lu\n", 2 * ps);
-
-	drm_buddy_free_list(&mm, &left, 0);
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
-							    3 * ps, ps, &allocated,
-							    DRM_BUDDY_CONTIGUOUS_ALLOCATION),
-			       "buddy_alloc hit an error size=%lu\n", 3 * ps);
-
-	total = 0;
-	list_for_each_entry(block, &allocated, link)
-		total += drm_buddy_block_size(&mm, block);
-
-	KUNIT_ASSERT_EQ(test, total, ps * 2 + ps * 3);
-
-	drm_buddy_free_list(&mm, &allocated, 0);
-	drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_pathological(struct kunit *test)
-{
-	u64 mm_size, size, start = 0;
-	struct drm_buddy_block *block;
-	const int max_order = 3;
-	unsigned long flags = 0;
-	int order, top;
-	struct drm_buddy mm;
-	LIST_HEAD(blocks);
-	LIST_HEAD(holes);
-	LIST_HEAD(tmp);
-
-	/*
-	 * Create a pot-sized mm, then allocate one of each possible
-	 * order within. This should leave the mm with exactly one
-	 * page left. Free the largest block, then whittle down again.
-	 * Eventually we will have a fully 50% fragmented mm.
-	 */
-
-	mm_size = SZ_4K << max_order;
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K),
-			       "buddy_init failed\n");
-
-	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
-	for (top = max_order; top; top--) {
-		/* Make room by freeing the largest allocated block */
-		block = list_first_entry_or_null(&blocks, typeof(*block), link);
-		if (block) {
-			list_del(&block->link);
-			drm_buddy_free_block(&mm, block);
-		}
-
-		for (order = top; order--;) {
-			size = get_size(order, mm.chunk_size);
-			KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start,
-									    mm_size, size, size,
-										&tmp, flags),
-					"buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
-					order, top);
-
-			block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
-			KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
-			list_move_tail(&block->link, &blocks);
-		}
-
-		/* There should be one final page for this sub-allocation */
-		size = get_size(0, mm.chunk_size);
-		KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-								    size, size, &tmp, flags),
-							   "buddy_alloc hit -ENOMEM for hole\n");
-
-		block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
-		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
-		list_move_tail(&block->link, &holes);
-
-		size = get_size(top, mm.chunk_size);
-		KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-								   size, size, &tmp, flags),
-							  "buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
-							  top, max_order);
-	}
-
-	drm_buddy_free_list(&mm, &holes, 0);
-
-	/* Nothing larger than blocks of chunk_size now available */
-	for (order = 1; order <= max_order; order++) {
-		size = get_size(order, mm.chunk_size);
-		KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-								   size, size, &tmp, flags),
-							  "buddy_alloc unexpectedly succeeded at order %d, it should be full!",
-							  order);
-	}
-
-	list_splice_tail(&holes, &blocks);
-	drm_buddy_free_list(&mm, &blocks, 0);
-	drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_pessimistic(struct kunit *test)
-{
-	u64 mm_size, size, start = 0;
-	struct drm_buddy_block *block, *bn;
-	const unsigned int max_order = 16;
-	unsigned long flags = 0;
-	struct drm_buddy mm;
-	unsigned int order;
-	LIST_HEAD(blocks);
-	LIST_HEAD(tmp);
-
-	/*
-	 * Create a pot-sized mm, then allocate one of each possible
-	 * order within. This should leave the mm with exactly one
-	 * page left.
-	 */
-
-	mm_size = SZ_4K << max_order;
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K),
-			       "buddy_init failed\n");
-
-	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
-	for (order = 0; order < max_order; order++) {
-		size = get_size(order, mm.chunk_size);
-		KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-								    size, size, &tmp, flags),
-							   "buddy_alloc hit -ENOMEM with order=%d\n",
-							   order);
-
-		block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
-		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
-		list_move_tail(&block->link, &blocks);
-	}
-
-	/* And now the last remaining block available */
-	size = get_size(0, mm.chunk_size);
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-							    size, size, &tmp, flags),
-						   "buddy_alloc hit -ENOMEM on final alloc\n");
-
-	block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
-	KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
-	list_move_tail(&block->link, &blocks);
-
-	/* Should be completely full! */
-	for (order = max_order; order--;) {
-		size = get_size(order, mm.chunk_size);
-		KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-								   size, size, &tmp, flags),
-							  "buddy_alloc unexpectedly succeeded, it should be full!");
-	}
-
-	block = list_last_entry(&blocks, typeof(*block), link);
-	list_del(&block->link);
-	drm_buddy_free_block(&mm, block);
-
-	/* As we free in increasing size, we make available larger blocks */
-	order = 1;
-	list_for_each_entry_safe(block, bn, &blocks, link) {
-		list_del(&block->link);
-		drm_buddy_free_block(&mm, block);
-
-		size = get_size(order, mm.chunk_size);
-		KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-								    size, size, &tmp, flags),
-							   "buddy_alloc hit -ENOMEM with order=%d\n",
-							   order);
-
-		block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
-		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
-		list_del(&block->link);
-		drm_buddy_free_block(&mm, block);
-		order++;
-	}
-
-	/* To confirm, now the whole mm should be available */
-	size = get_size(max_order, mm.chunk_size);
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-							    size, size, &tmp, flags),
-						   "buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
-						   max_order);
-
-	block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
-	KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
-	list_del(&block->link);
-	drm_buddy_free_block(&mm, block);
-	drm_buddy_free_list(&mm, &blocks, 0);
-	drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_optimistic(struct kunit *test)
-{
-	u64 mm_size, size, start = 0;
-	struct drm_buddy_block *block;
-	unsigned long flags = 0;
-	const int max_order = 16;
-	struct drm_buddy mm;
-	LIST_HEAD(blocks);
-	LIST_HEAD(tmp);
-	int order;
-
-	/*
-	 * Create a mm with one block of each order available, and
-	 * try to allocate them all.
-	 */
-
-	mm_size = SZ_4K * ((1 << (max_order + 1)) - 1);
-
-	KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K),
-			       "buddy_init failed\n");
-
-	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
-	for (order = 0; order <= max_order; order++) {
-		size = get_size(order, mm.chunk_size);
-		KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-								    size, size, &tmp, flags),
-							   "buddy_alloc hit -ENOMEM with order=%d\n",
-							   order);
-
-		block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
-		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
-		list_move_tail(&block->link, &blocks);
-	}
-
-	/* Should be completely full! */
-	size = get_size(0, mm.chunk_size);
-	KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
-							   size, size, &tmp, flags),
-						  "buddy_alloc unexpectedly succeeded, it should be full!");
-
-	drm_buddy_free_list(&mm, &blocks, 0);
-	drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_limit(struct kunit *test)
-{
-	u64 size = U64_MAX, start = 0;
-	struct drm_buddy_block *block;
-	unsigned long flags = 0;
-	LIST_HEAD(allocated);
-	struct drm_buddy mm;
-
-	KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, size, SZ_4K));
-
-	KUNIT_EXPECT_EQ_MSG(test, mm.max_order, DRM_BUDDY_MAX_ORDER,
-			    "mm.max_order(%d) != %d\n", mm.max_order,
-						DRM_BUDDY_MAX_ORDER);
-
-	size = mm.chunk_size << mm.max_order;
-	KUNIT_EXPECT_FALSE(test, drm_buddy_alloc_blocks(&mm, start, size, size,
-							mm.chunk_size, &allocated, flags));
-
-	block = list_first_entry_or_null(&allocated, struct drm_buddy_block, link);
-	KUNIT_EXPECT_TRUE(test, block);
-
-	KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_order(block), mm.max_order,
-			    "block order(%d) != %d\n",
-						drm_buddy_block_order(block), mm.max_order);
-
-	KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_size(&mm, block),
-			    BIT_ULL(mm.max_order) * mm.chunk_size,
-						"block size(%llu) != %llu\n",
-						drm_buddy_block_size(&mm, block),
-						BIT_ULL(mm.max_order) * mm.chunk_size);
-
-	drm_buddy_free_list(&mm, &allocated, 0);
-	drm_buddy_fini(&mm);
-}
-
-static int drm_buddy_suite_init(struct kunit_suite *suite)
-{
-	while (!random_seed)
-		random_seed = get_random_u32();
-
-	kunit_info(suite, "Testing DRM buddy manager, with random_seed=0x%x\n",
-		   random_seed);
-
-	return 0;
-}
-
-static struct kunit_case drm_buddy_tests[] = {
-	KUNIT_CASE(drm_test_buddy_alloc_limit),
-	KUNIT_CASE(drm_test_buddy_alloc_optimistic),
-	KUNIT_CASE(drm_test_buddy_alloc_pessimistic),
-	KUNIT_CASE(drm_test_buddy_alloc_pathological),
-	KUNIT_CASE(drm_test_buddy_alloc_contiguous),
-	KUNIT_CASE(drm_test_buddy_alloc_clear),
-	KUNIT_CASE(drm_test_buddy_alloc_range_bias),
-	{}
-};
-
-static struct kunit_suite drm_buddy_test_suite = {
-	.name = "drm_buddy",
-	.suite_init = drm_buddy_suite_init,
-	.test_cases = drm_buddy_tests,
-};
-
-kunit_test_suite(drm_buddy_test_suite);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Kunit test for drm_buddy functions");
-MODULE_LICENSE("GPL");
--- a/drivers/gpu/drm/tests/drm_exec_test.c
+++ b/drivers/gpu/drm/tests/drm_exec_test.c
@@ -16,8 +16,6 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_kunit_helpers.h>
 
-#include "../lib/drm_random.h"
-
 struct drm_exec_priv {
 	struct device *dev;
 	struct drm_device *drm;
--- a/drivers/gpu/drm/tests/drm_mm_test.c
+++ b/drivers/gpu/drm/tests/drm_mm_test.c
@@ -15,8 +15,6 @@
 
 #include <drm/drm_mm.h>
 
-#include "../lib/drm_random.h"
-
 enum {
 	BEST,
 	BOTTOMUP,
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -251,7 +251,7 @@ static void ttm_bo_validate_basic(struct
 				   NULL, &dummy_ttm_bo_destroy);
 	KUNIT_EXPECT_EQ(test, err, 0);
 
-	snd_place = ttm_place_kunit_init(test, snd_mem, DRM_BUDDY_TOPDOWN_ALLOCATION);
+	snd_place = ttm_place_kunit_init(test, snd_mem, GPU_BUDDY_TOPDOWN_ALLOCATION);
 	snd_placement = ttm_placement_kunit_init(test, snd_place, 1);
 
 	err = ttm_bo_validate(bo, snd_placement, &ctx_val);
@@ -263,7 +263,7 @@ static void ttm_bo_validate_basic(struct
 	KUNIT_EXPECT_TRUE(test, ttm_tt_is_populated(bo->ttm));
 	KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
 	KUNIT_EXPECT_EQ(test, bo->resource->placement,
-			DRM_BUDDY_TOPDOWN_ALLOCATION);
+			GPU_BUDDY_TOPDOWN_ALLOCATION);
 
 	ttm_bo_put(bo);
 	ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
--- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
@@ -27,7 +27,7 @@ static int ttm_mock_manager_alloc(struct
 {
 	struct ttm_mock_manager *manager = to_mock_mgr(man);
 	struct ttm_mock_resource *mock_res;
-	struct drm_buddy *mm = &manager->mm;
+	struct gpu_buddy *mm = &manager->mm;
 	u64 lpfn, fpfn, alloc_size;
 	int err;
 
@@ -43,14 +43,14 @@ static int ttm_mock_manager_alloc(struct
 	INIT_LIST_HEAD(&mock_res->blocks);
 
 	if (place->flags & TTM_PL_FLAG_TOPDOWN)
-		mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+		mock_res->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
 
 	if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
-		mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+		mock_res->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;
 
 	alloc_size = (uint64_t)mock_res->base.size;
 	mutex_lock(&manager->lock);
-	err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
+	err = gpu_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
 				     manager->default_page_size,
 				     &mock_res->blocks,
 				     mock_res->flags);
@@ -63,7 +63,7 @@ static int ttm_mock_manager_alloc(struct
 	return 0;
 
 error_free_blocks:
-	drm_buddy_free_list(mm, &mock_res->blocks, 0);
+	gpu_buddy_free_list(mm, &mock_res->blocks, 0);
 	ttm_resource_fini(man, &mock_res->base);
 	mutex_unlock(&manager->lock);
 
@@ -75,10 +75,10 @@ static void ttm_mock_manager_free(struct
 {
 	struct ttm_mock_manager *manager = to_mock_mgr(man);
 	struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res);
-	struct drm_buddy *mm = &manager->mm;
+	struct gpu_buddy *mm = &manager->mm;
 
 	mutex_lock(&manager->lock);
-	drm_buddy_free_list(mm, &mock_res->blocks, 0);
+	gpu_buddy_free_list(mm, &mock_res->blocks, 0);
 	mutex_unlock(&manager->lock);
 
 	ttm_resource_fini(man, res);
@@ -102,7 +102,7 @@ int ttm_mock_manager_init(struct ttm_dev
 
 	mutex_init(&manager->lock);
 
-	err = drm_buddy_init(&manager->mm, size, PAGE_SIZE);
+	err = gpu_buddy_init(&manager->mm, size, PAGE_SIZE);
 
 	if (err) {
 		kfree(manager);
@@ -138,7 +138,7 @@ void ttm_mock_manager_fini(struct ttm_de
 	ttm_resource_manager_set_used(man, false);
 
 	mutex_lock(&mock_man->lock);
-	drm_buddy_fini(&mock_man->mm);
+	gpu_buddy_fini(&mock_man->mm);
 	mutex_unlock(&mock_man->lock);
 
 	ttm_set_driver_manager(bdev, mem_type, NULL);
--- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
@@ -5,11 +5,11 @@
 #ifndef TTM_MOCK_MANAGER_H
 #define TTM_MOCK_MANAGER_H
 
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
 
 struct ttm_mock_manager {
 	struct ttm_resource_manager man;
-	struct drm_buddy mm;
+	struct gpu_buddy mm;
 	u64 default_page_size;
 	/* protects allocations of mock buffer objects */
 	struct mutex lock;
--- a/drivers/gpu/drm/xe/xe_res_cursor.h
+++ b/drivers/gpu/drm/xe/xe_res_cursor.h
@@ -44,10 +44,10 @@ struct xe_res_cursor {
 	void *node;
 	u32 mem_type;
 	struct scatterlist *sgl;
-	struct drm_buddy *mm;
+	struct gpu_buddy *mm;
 };
 
-static struct drm_buddy *xe_res_get_buddy(struct ttm_resource *res)
+static struct gpu_buddy *xe_res_get_buddy(struct ttm_resource *res)
 {
 	struct ttm_resource_manager *mgr;
 
@@ -81,30 +81,30 @@ static inline void xe_res_first(struct t
 	case XE_PL_STOLEN:
 	case XE_PL_VRAM0:
 	case XE_PL_VRAM1: {
-		struct drm_buddy_block *block;
+		struct gpu_buddy_block *block;
 		struct list_head *head, *next;
-		struct drm_buddy *mm = xe_res_get_buddy(res);
+		struct gpu_buddy *mm = xe_res_get_buddy(res);
 
 		head = &to_xe_ttm_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;
 
-		while (start >= drm_buddy_block_size(mm, block)) {
-			start -= drm_buddy_block_size(mm, block);
+		while (start >= gpu_buddy_block_size(mm, block)) {
+			start -= gpu_buddy_block_size(mm, block);
 
 			next = block->link.next;
 			if (next != head)
-				block = list_entry(next, struct drm_buddy_block,
+				block = list_entry(next, struct gpu_buddy_block,
 						   link);
 		}
 
 		cur->mm = mm;
-		cur->start = drm_buddy_block_offset(block) + start;
-		cur->size = min(drm_buddy_block_size(mm, block) - start,
+		cur->start = gpu_buddy_block_offset(block) + start;
+		cur->size = min(gpu_buddy_block_size(mm, block) - start,
 				size);
 		cur->remaining = size;
 		cur->node = block;
@@ -175,7 +175,7 @@ static inline void xe_res_first_sg(const
  */
 static inline void xe_res_next(struct xe_res_cursor *cur, u64 size)
 {
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	struct list_head *next;
 	u64 start;
 
@@ -205,18 +205,18 @@ static inline void xe_res_next(struct xe
 		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);
 
 
-		while (start >= drm_buddy_block_size(cur->mm, block)) {
-			start -= drm_buddy_block_size(cur->mm, block);
+		while (start >= gpu_buddy_block_size(cur->mm, block)) {
+			start -= gpu_buddy_block_size(cur->mm, block);
 
 			next = block->link.next;
-			block = list_entry(next, struct drm_buddy_block, link);
+			block = list_entry(next, struct gpu_buddy_block, link);
 		}
 
-		cur->start = drm_buddy_block_offset(block) + start;
-		cur->size = min(drm_buddy_block_size(cur->mm, block) - start,
+		cur->start = gpu_buddy_block_offset(block) + start;
+		cur->size = min(gpu_buddy_block_size(cur->mm, block) - start,
 				cur->remaining);
 		cur->node = block;
 		break;
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
@@ -5,6 +5,7 @@
  */
 
 #include <drm/drm_managed.h>
+#include <drm/drm_buddy.h>
 
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_range_manager.h>
@@ -15,16 +16,16 @@
 #include "xe_res_cursor.h"
 #include "xe_ttm_vram_mgr.h"
 
-static inline struct drm_buddy_block *
+static inline struct gpu_buddy_block *
 xe_ttm_vram_mgr_first_block(struct list_head *list)
 {
-	return list_first_entry_or_null(list, struct drm_buddy_block, link);
+	return list_first_entry_or_null(list, struct gpu_buddy_block, link);
 }
 
-static inline bool xe_is_vram_mgr_blocks_contiguous(struct drm_buddy *mm,
+static inline bool xe_is_vram_mgr_blocks_contiguous(struct gpu_buddy *mm,
 						    struct list_head *head)
 {
-	struct drm_buddy_block *block;
+	struct gpu_buddy_block *block;
 	u64 start, size;
 
 	block = xe_ttm_vram_mgr_first_block(head);
@@ -32,12 +33,12 @@ static inline bool xe_is_vram_mgr_blocks
 		return false;
 
 	while (head != block->link.next) {
-		start = drm_buddy_block_offset(block);
-		size = drm_buddy_block_size(mm, block);
+		start = gpu_buddy_block_offset(block);
+		size = gpu_buddy_block_size(mm, block);
 
-		block = list_entry(block->link.next, struct drm_buddy_block,
+		block = list_entry(block->link.next, struct gpu_buddy_block,
 				   link);
-		if (start + size != drm_buddy_block_offset(block))
+		if (start + size != gpu_buddy_block_offset(block))
 			return false;
 	}
 
@@ -51,7 +52,7 @@ static int xe_ttm_vram_mgr_new(struct tt
 {
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
 	struct xe_ttm_vram_mgr_resource *vres;
-	struct drm_buddy *mm = &mgr->mm;
+	struct gpu_buddy *mm = &mgr->mm;
 	u64 size, remaining_size, min_page_size;
 	unsigned long lpfn;
 	int err;
@@ -78,10 +79,10 @@ static int xe_ttm_vram_mgr_new(struct tt
 	INIT_LIST_HEAD(&vres->blocks);
 
 	if (place->flags & TTM_PL_FLAG_TOPDOWN)
-		vres->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+		vres->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
 
 	if (place->fpfn || lpfn != man->size >> PAGE_SHIFT)
-		vres->flags |= DRM_BUDDY_RANGE_ALLOCATION;
+		vres->flags |= GPU_BUDDY_RANGE_ALLOCATION;
 
 	if (WARN_ON(!vres->base.size)) {
 		err = -EINVAL;
@@ -137,7 +138,7 @@ static int xe_ttm_vram_mgr_new(struct tt
 		 */
 		u64 alloc_size = min_t(u64, remaining_size, SZ_2G);
 
-		err = drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
+		err = gpu_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
 					     (u64)lpfn << PAGE_SHIFT,
 					     alloc_size,
 					     min_page_size,
@@ -150,20 +151,20 @@ static int xe_ttm_vram_mgr_new(struct tt
 	} while (remaining_size);
 
 	if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
-		if (!drm_buddy_block_trim(mm, NULL, vres->base.size, &vres->blocks))
+		if (!gpu_buddy_block_trim(mm, NULL, vres->base.size, &vres->blocks))
 			size = vres->base.size;
 	}
 
 	if (lpfn <= mgr->visible_size >> PAGE_SHIFT) {
 		vres->used_visible_size = size;
 	} else {
-		struct drm_buddy_block *block;
+		struct gpu_buddy_block *block;
 
 		list_for_each_entry(block, &vres->blocks, link) {
-			u64 start = drm_buddy_block_offset(block);
+			u64 start = gpu_buddy_block_offset(block);
 
 			if (start < mgr->visible_size) {
-				u64 end = start + drm_buddy_block_size(mm, block);
+				u64 end = start + gpu_buddy_block_size(mm, block);
 
 				vres->used_visible_size +=
 					min(end, mgr->visible_size) - start;
@@ -183,11 +184,11 @@ static int xe_ttm_vram_mgr_new(struct tt
 	 * the object.
 	 */
 	if (vres->base.placement & TTM_PL_FLAG_CONTIGUOUS) {
-		struct drm_buddy_block *block = list_first_entry(&vres->blocks,
+		struct gpu_buddy_block *block = list_first_entry(&vres->blocks,
 								 typeof(*block),
 								 link);
 
-		vres->base.start = drm_buddy_block_offset(block) >> PAGE_SHIFT;
+		vres->base.start = gpu_buddy_block_offset(block) >> PAGE_SHIFT;
 	} else {
 		vres->base.start = XE_BO_INVALID_OFFSET;
 	}
@@ -196,7 +197,7 @@ static int xe_ttm_vram_mgr_new(struct tt
 	return 0;
 
 error_free_blocks:
-	drm_buddy_free_list(mm, &vres->blocks, 0);
+	gpu_buddy_free_list(mm, &vres->blocks, 0);
 	mutex_unlock(&mgr->lock);
 error_fini:
 	ttm_resource_fini(man, &vres->base);
@@ -211,10 +212,10 @@ static void xe_ttm_vram_mgr_del(struct t
 	struct xe_ttm_vram_mgr_resource *vres =
 		to_xe_ttm_vram_mgr_resource(res);
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
-	struct drm_buddy *mm = &mgr->mm;
+	struct gpu_buddy *mm = &mgr->mm;
 
 	mutex_lock(&mgr->lock);
-	drm_buddy_free_list(mm, &vres->blocks, 0);
+	gpu_buddy_free_list(mm, &vres->blocks, 0);
 	mgr->visible_avail += vres->used_visible_size;
 	mutex_unlock(&mgr->lock);
 
@@ -227,7 +228,7 @@ static void xe_ttm_vram_mgr_debug(struct
 				  struct drm_printer *printer)
 {
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
-	struct drm_buddy *mm = &mgr->mm;
+	struct gpu_buddy *mm = &mgr->mm;
 
 	mutex_lock(&mgr->lock);
 	drm_printf(printer, "default_page_size: %lluKiB\n",
@@ -250,8 +251,8 @@ static bool xe_ttm_vram_mgr_intersects(s
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
 	struct xe_ttm_vram_mgr_resource *vres =
 		to_xe_ttm_vram_mgr_resource(res);
-	struct drm_buddy *mm = &mgr->mm;
-	struct drm_buddy_block *block;
+	struct gpu_buddy *mm = &mgr->mm;
+	struct gpu_buddy_block *block;
 
 	if (!place->fpfn && !place->lpfn)
 		return true;
@@ -261,9 +262,9 @@ static bool xe_ttm_vram_mgr_intersects(s
 
 	list_for_each_entry(block, &vres->blocks, link) {
 		unsigned long fpfn =
-			drm_buddy_block_offset(block) >> PAGE_SHIFT;
+			gpu_buddy_block_offset(block) >> PAGE_SHIFT;
 		unsigned long lpfn = fpfn +
-			(drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+			(gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
 
 		if (place->fpfn < lpfn && place->lpfn > fpfn)
 			return true;
@@ -280,8 +281,8 @@ static bool xe_ttm_vram_mgr_compatible(s
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
 	struct xe_ttm_vram_mgr_resource *vres =
 		to_xe_ttm_vram_mgr_resource(res);
-	struct drm_buddy *mm = &mgr->mm;
-	struct drm_buddy_block *block;
+	struct gpu_buddy *mm = &mgr->mm;
+	struct gpu_buddy_block *block;
 
 	if (!place->fpfn && !place->lpfn)
 		return true;
@@ -291,9 +292,9 @@ static bool xe_ttm_vram_mgr_compatible(s
 
 	list_for_each_entry(block, &vres->blocks, link) {
 		unsigned long fpfn =
-			drm_buddy_block_offset(block) >> PAGE_SHIFT;
+			gpu_buddy_block_offset(block) >> PAGE_SHIFT;
 		unsigned long lpfn = fpfn +
-			(drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+			(gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
 
 		if (fpfn < place->fpfn || lpfn > place->lpfn)
 			return false;
@@ -323,7 +324,7 @@ static void ttm_vram_mgr_fini(struct drm
 
 	WARN_ON_ONCE(mgr->visible_avail != mgr->visible_size);
 
-	drm_buddy_fini(&mgr->mm);
+	gpu_buddy_fini(&mgr->mm);
 
 	ttm_resource_manager_cleanup(&mgr->manager);
 
@@ -347,7 +348,7 @@ int __xe_ttm_vram_mgr_init(struct xe_dev
 	mgr->visible_avail = io_size;
 
 	ttm_resource_manager_init(man, &xe->ttm, size);
-	err = drm_buddy_init(&mgr->mm, man->size, default_page_size);
+	err = gpu_buddy_init(&mgr->mm, man->size, default_page_size);
 	if (err)
 		return err;
 
@@ -389,7 +390,7 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_
 	if (!*sgt)
 		return -ENOMEM;
 
-	/* Determine the number of DRM_BUDDY blocks to export */
+	/* Determine the number of GPU_BUDDY blocks to export */
 	xe_res_first(res, offset, length, &cursor);
 	while (cursor.remaining) {
 		num_entries++;
@@ -405,10 +406,10 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_
 		sg->length = 0;
 
 	/*
-	 * Walk down DRM_BUDDY blocks to populate scatterlist nodes
-	 * @note: Use iterator api to get first the DRM_BUDDY block
+	 * Walk down GPU_BUDDY blocks to populate scatterlist nodes
+	 * @note: Use iterator api to get first the GPU_BUDDY block
 	 * and the number of bytes from it. Access the following
-	 * DRM_BUDDY block(s) if more buffer needs to exported
+	 * GPU_BUDDY block(s) if more buffer needs to exported
 	 */
 	xe_res_first(res, offset, length, &cursor);
 	for_each_sgtable_sg((*sgt), sg, i) {
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
@@ -6,7 +6,7 @@
 #ifndef _XE_TTM_VRAM_MGR_TYPES_H_
 #define _XE_TTM_VRAM_MGR_TYPES_H_
 
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
 #include <drm/ttm/ttm_device.h>
 
 struct xe_mem_region;
@@ -20,7 +20,7 @@ struct xe_ttm_vram_mgr {
 	/** @manager: Base TTM resource manager */
 	struct ttm_resource_manager manager;
 	/** @mm: DRM buddy allocator which manages the VRAM */
-	struct drm_buddy mm;
+	struct gpu_buddy mm;
 	/** @vram: ptr to details of associated VRAM region */
 	struct xe_mem_region *vram;
 	/** @visible_size: Proped size of the CPU visible portion */
--- /dev/null
+++ b/drivers/gpu/tests/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+gpu_buddy_tests-y = gpu_buddy_test.o gpu_random.o
+obj-$(CONFIG_GPU_BUDDY_KUNIT_TEST) += gpu_buddy_tests.o
--- /dev/null
+++ b/drivers/gpu/tests/gpu_buddy_test.c
@@ -0,0 +1,778 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ * Copyright © 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <linux/prime_numbers.h>
+#include <linux/sched/signal.h>
+#include <linux/sizes.h>
+
+#include <linux/gpu_buddy.h>
+
+#include "gpu_random.h"
+
+static unsigned int random_seed;
+
+static inline u64 get_size(int order, u64 chunk_size)
+{
+	return (1 << order) * chunk_size;
+}
+
+static void drm_test_buddy_alloc_range_bias(struct kunit *test)
+{
+	u32 mm_size, size, ps, bias_size, bias_start, bias_end, bias_rem;
+	GPU_RND_STATE(prng, random_seed);
+	unsigned int i, count, *order;
+	struct gpu_buddy_block *block;
+	unsigned long flags;
+	struct gpu_buddy mm;
+	LIST_HEAD(allocated);
+
+	bias_size = SZ_1M;
+	ps = roundup_pow_of_two(prandom_u32_state(&prng) % bias_size);
+	ps = max(SZ_4K, ps);
+	mm_size = (SZ_8M-1) & ~(ps-1); /* Multiple roots */
+
+	kunit_info(test, "mm_size=%u, ps=%u\n", mm_size, ps);
+
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
+			       "buddy_init failed\n");
+
+	count = mm_size / bias_size;
+	order = gpu_random_order(count, &prng);
+	KUNIT_EXPECT_TRUE(test, order);
+
+	/*
+	 * Idea is to split the address space into uniform bias ranges, and then
+	 * in some random order allocate within each bias, using various
+	 * patterns within. This should detect if allocations leak out from a
+	 * given bias, for example.
+	 */
+
+	for (i = 0; i < count; i++) {
+		LIST_HEAD(tmp);
+		u32 size;
+
+		bias_start = order[i] * bias_size;
+		bias_end = bias_start + bias_size;
+		bias_rem = bias_size;
+
+		/* internal round_up too big */
+		KUNIT_ASSERT_TRUE_MSG(test,
+				      gpu_buddy_alloc_blocks(&mm, bias_start,
+							     bias_end, bias_size + ps, bias_size,
+							     &allocated,
+							     GPU_BUDDY_RANGE_ALLOCATION),
+				      "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+				      bias_start, bias_end, bias_size, bias_size);
+
+		/* size too big */
+		KUNIT_ASSERT_TRUE_MSG(test,
+				      gpu_buddy_alloc_blocks(&mm, bias_start,
+							     bias_end, bias_size + ps, ps,
+							     &allocated,
+							     GPU_BUDDY_RANGE_ALLOCATION),
+				      "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+				      bias_start, bias_end, bias_size + ps, ps);
+
+		/* bias range too small for size */
+		KUNIT_ASSERT_TRUE_MSG(test,
+				      gpu_buddy_alloc_blocks(&mm, bias_start + ps,
+							     bias_end, bias_size, ps,
+							     &allocated,
+							     GPU_BUDDY_RANGE_ALLOCATION),
+				      "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+				      bias_start + ps, bias_end, bias_size, ps);
+
+		/* bias misaligned */
+		KUNIT_ASSERT_TRUE_MSG(test,
+				      gpu_buddy_alloc_blocks(&mm, bias_start + ps,
+							     bias_end - ps,
+							     bias_size >> 1, bias_size >> 1,
+							     &allocated,
+							     GPU_BUDDY_RANGE_ALLOCATION),
+				      "buddy_alloc h didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+				      bias_start + ps, bias_end - ps, bias_size >> 1, bias_size >> 1);
+
+		/* single big page */
+		KUNIT_ASSERT_FALSE_MSG(test,
+				       gpu_buddy_alloc_blocks(&mm, bias_start,
+							      bias_end, bias_size, bias_size,
+							      &tmp,
+							      GPU_BUDDY_RANGE_ALLOCATION),
+				       "buddy_alloc i failed with bias(%x-%x), size=%u, ps=%u\n",
+				       bias_start, bias_end, bias_size, bias_size);
+		gpu_buddy_free_list(&mm, &tmp, 0);
+
+		/* single page with internal round_up */
+		KUNIT_ASSERT_FALSE_MSG(test,
+				       gpu_buddy_alloc_blocks(&mm, bias_start,
+							      bias_end, ps, bias_size,
+							      &tmp,
+							      GPU_BUDDY_RANGE_ALLOCATION),
+				       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+				       bias_start, bias_end, ps, bias_size);
+		gpu_buddy_free_list(&mm, &tmp, 0);
+
+		/* random size within */
+		size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+		if (size)
+			KUNIT_ASSERT_FALSE_MSG(test,
+					       gpu_buddy_alloc_blocks(&mm, bias_start,
+								      bias_end, size, ps,
+								      &tmp,
+								      GPU_BUDDY_RANGE_ALLOCATION),
+					       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+					       bias_start, bias_end, size, ps);
+
+		bias_rem -= size;
+		/* too big for current avail */
+		KUNIT_ASSERT_TRUE_MSG(test,
+				      gpu_buddy_alloc_blocks(&mm, bias_start,
+							     bias_end, bias_rem + ps, ps,
+							     &allocated,
+							     GPU_BUDDY_RANGE_ALLOCATION),
+				      "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+				      bias_start, bias_end, bias_rem + ps, ps);
+
+		if (bias_rem) {
+			/* random fill of the remainder */
+			size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+			size = max(size, ps);
+
+			KUNIT_ASSERT_FALSE_MSG(test,
+					       gpu_buddy_alloc_blocks(&mm, bias_start,
+								      bias_end, size, ps,
+								      &allocated,
+								      GPU_BUDDY_RANGE_ALLOCATION),
+					       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+					       bias_start, bias_end, size, ps);
+			/*
+			 * Intentionally allow some space to be left
+			 * unallocated, and ideally not always on the bias
+			 * boundaries.
+			 */
+			gpu_buddy_free_list(&mm, &tmp, 0);
+		} else {
+			list_splice_tail(&tmp, &allocated);
+		}
+	}
+
+	kfree(order);
+	gpu_buddy_free_list(&mm, &allocated, 0);
+	gpu_buddy_fini(&mm);
+
+	/*
+	 * Something more free-form. Idea is to pick a random starting bias
+	 * range within the address space and then start filling it up. Also
+	 * randomly grow the bias range in both directions as we go along. This
+	 * should give us bias start/end which is not always uniform like above,
+	 * and in some cases will require the allocator to jump over already
+	 * allocated nodes in the middle of the address space.
+	 */
+
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
+			       "buddy_init failed\n");
+
+	bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
+	bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
+	bias_end = max(bias_end, bias_start + ps);
+	bias_rem = bias_end - bias_start;
+
+	do {
+		u32 size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+
+		KUNIT_ASSERT_FALSE_MSG(test,
+				       gpu_buddy_alloc_blocks(&mm, bias_start,
+							      bias_end, size, ps,
+							      &allocated,
+							      GPU_BUDDY_RANGE_ALLOCATION),
+				       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+				       bias_start, bias_end, size, ps);
+		bias_rem -= size;
+
+		/*
+		 * Try to randomly grow the bias range in both directions, or
+		 * only one, or perhaps don't grow at all.
+		 */
+		do {
+			u32 old_bias_start = bias_start;
+			u32 old_bias_end = bias_end;
+
+			if (bias_start)
+				bias_start -= round_up(prandom_u32_state(&prng) % bias_start, ps);
+			if (bias_end != mm_size)
+				bias_end += round_up(prandom_u32_state(&prng) % (mm_size - bias_end), ps);
+
+			bias_rem += old_bias_start - bias_start;
+			bias_rem += bias_end - old_bias_end;
+		} while (!bias_rem && (bias_start || bias_end != mm_size));
+	} while (bias_rem);
+
+	KUNIT_ASSERT_EQ(test, bias_start, 0);
+	KUNIT_ASSERT_EQ(test, bias_end, mm_size);
+	KUNIT_ASSERT_TRUE_MSG(test,
+			      gpu_buddy_alloc_blocks(&mm, bias_start, bias_end,
+						     ps, ps,
+						     &allocated,
+						     GPU_BUDDY_RANGE_ALLOCATION),
+			      "buddy_alloc passed with bias(%x-%x), size=%u\n",
+			      bias_start, bias_end, ps);
+
+	gpu_buddy_free_list(&mm, &allocated, 0);
+	gpu_buddy_fini(&mm);
+
+	/*
+	 * Allocate cleared blocks in the bias range when the DRM buddy's clear avail is
+	 * zero. This will validate the bias range allocation in scenarios like system boot
+	 * when no cleared blocks are available and exercise the fallback path too. The resulting
+	 * blocks should always be dirty.
+	 */
+
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
+			       "buddy_init failed\n");
+
+	bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
+	bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
+	bias_end = max(bias_end, bias_start + ps);
+	bias_rem = bias_end - bias_start;
+
+	flags = GPU_BUDDY_CLEAR_ALLOCATION | GPU_BUDDY_RANGE_ALLOCATION;
+	size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+
+	KUNIT_ASSERT_FALSE_MSG(test,
+			       gpu_buddy_alloc_blocks(&mm, bias_start,
+						      bias_end, size, ps,
+						      &allocated,
+						      flags),
+			       "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+			       bias_start, bias_end, size, ps);
+
+	list_for_each_entry(block, &allocated, link)
+		KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false);
+
+	gpu_buddy_free_list(&mm, &allocated, 0);
+	gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_clear(struct kunit *test)
+{
+	unsigned long n_pages, total, i = 0;
+	GPU_RND_STATE(prng, random_seed);
+	const unsigned long ps = SZ_4K;
+	struct gpu_buddy_block *block;
+	const int max_order = 12;
+	LIST_HEAD(allocated);
+	struct gpu_buddy mm;
+	unsigned int order;
+	u32 mm_size, size;
+	LIST_HEAD(dirty);
+	LIST_HEAD(clean);
+
+	mm_size = SZ_4K << max_order;
+	KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+	/*
+	 * Idea is to allocate and free some random portion of the address space,
+	 * returning those pages as non-dirty and randomly alternate between
+	 * requesting dirty and non-dirty pages (not going over the limit
+	 * we freed as non-dirty), putting that into two separate lists.
+	 * Loop over both lists at the end checking that the dirty list
+	 * is indeed all dirty pages and vice versa. Free it all again,
+	 * keeping the dirty/clear status.
+	 */
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							    5 * ps, ps, &allocated,
+							    GPU_BUDDY_TOPDOWN_ALLOCATION),
+				"buddy_alloc hit an error size=%lu\n", 5 * ps);
+	gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED);
+
+	n_pages = 10;
+	do {
+		unsigned long flags;
+		struct list_head *list;
+		int slot = i % 2;
+
+		if (slot == 0) {
+			list = &dirty;
+			flags = 0;
+		} else {
+			list = &clean;
+			flags = GPU_BUDDY_CLEAR_ALLOCATION;
+		}
+
+		KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+								    ps, ps, list,
+								    flags),
+					"buddy_alloc hit an error size=%lu\n", ps);
+	} while (++i < n_pages);
+
+	list_for_each_entry(block, &clean, link)
+		KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), true);
+
+	list_for_each_entry(block, &dirty, link)
+		KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false);
+
+	gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
+
+	/*
+	 * Trying to go over the clear limit for some allocation.
+	 * The allocation should never fail with reasonable page-size.
+	 */
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							    10 * ps, ps, &clean,
+							    GPU_BUDDY_CLEAR_ALLOCATION),
+				"buddy_alloc hit an error size=%lu\n", 10 * ps);
+
+	gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
+	gpu_buddy_free_list(&mm, &dirty, 0);
+	gpu_buddy_fini(&mm);
+
+	KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+	/*
+	 * Create a new mm. Intentionally fragment the address space by creating
+	 * two alternating lists. Free both lists, one as dirty the other as clean.
+	 * Try to allocate double the previous size with matching min_page_size. The
+	 * allocation should never fail as it calls the force_merge. Also check that
+	 * the page is always dirty after force_merge. Free the page as dirty, then
+	 * repeat the whole thing, increment the order until we hit the max_order.
+	 */
+
+	i = 0;
+	n_pages = mm_size / ps;
+	do {
+		struct list_head *list;
+		int slot = i % 2;
+
+		if (slot == 0)
+			list = &dirty;
+		else
+			list = &clean;
+
+		KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+								    ps, ps, list, 0),
+					"buddy_alloc hit an error size=%lu\n", ps);
+	} while (++i < n_pages);
+
+	gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
+	gpu_buddy_free_list(&mm, &dirty, 0);
+
+	order = 1;
+	do {
+		size = SZ_4K << order;
+
+		KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+								    size, size, &allocated,
+								    GPU_BUDDY_CLEAR_ALLOCATION),
+					"buddy_alloc hit an error size=%u\n", size);
+		total = 0;
+		list_for_each_entry(block, &allocated, link) {
+			if (size != mm_size)
+				KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false);
+			total += gpu_buddy_block_size(&mm, block);
+		}
+		KUNIT_EXPECT_EQ(test, total, size);
+
+		gpu_buddy_free_list(&mm, &allocated, 0);
+	} while (++order <= max_order);
+
+	gpu_buddy_fini(&mm);
+
+	/*
+	 * Create a new mm with a non power-of-two size. Allocate a random size, free as
+	 * cleared and then call fini. This will ensure the multi-root force merge during
+	 * fini.
+	 */
+	mm_size = 12 * SZ_4K;
+	size = max(round_up(prandom_u32_state(&prng) % mm_size, ps), ps);
+	KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							    size, ps, &allocated,
+							    GPU_BUDDY_TOPDOWN_ALLOCATION),
+				"buddy_alloc hit an error size=%u\n", size);
+	gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED);
+	gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_contiguous(struct kunit *test)
+{
+	const unsigned long ps = SZ_4K, mm_size = 16 * 3 * SZ_4K;
+	unsigned long i, n_pages, total;
+	struct gpu_buddy_block *block;
+	struct gpu_buddy mm;
+	LIST_HEAD(left);
+	LIST_HEAD(middle);
+	LIST_HEAD(right);
+	LIST_HEAD(allocated);
+
+	KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+	/*
+	 * Idea is to fragment the address space by alternating block
+	 * allocations between three different lists; one for left, middle and
+	 * right. We can then free a list to simulate fragmentation. In
+	 * particular we want to exercise the GPU_BUDDY_CONTIGUOUS_ALLOCATION,
+	 * including the try_harder path.
+	 */
+
+	i = 0;
+	n_pages = mm_size / ps;
+	do {
+		struct list_head *list;
+		int slot = i % 3;
+
+		if (slot == 0)
+			list = &left;
+		else if (slot == 1)
+			list = &middle;
+		else
+			list = &right;
+		KUNIT_ASSERT_FALSE_MSG(test,
+				       gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							      ps, ps, list, 0),
+				       "buddy_alloc hit an error size=%lu\n",
+				       ps);
+	} while (++i < n_pages);
+
+	KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							   3 * ps, ps, &allocated,
+							   GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+			       "buddy_alloc didn't error size=%lu\n", 3 * ps);
+
+	gpu_buddy_free_list(&mm, &middle, 0);
+	KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							   3 * ps, ps, &allocated,
+							   GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+			       "buddy_alloc didn't error size=%lu\n", 3 * ps);
+	KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							   2 * ps, ps, &allocated,
+							   GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+			       "buddy_alloc didn't error size=%lu\n", 2 * ps);
+
+	gpu_buddy_free_list(&mm, &right, 0);
+	KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							   3 * ps, ps, &allocated,
+							   GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+			       "buddy_alloc didn't error size=%lu\n", 3 * ps);
+	/*
+	 * At this point we should have enough contiguous space for 2 blocks,
+	 * however they are never buddies (since we freed middle and right) so
+	 * will require the try_harder logic to find them.
+	 */
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							    2 * ps, ps, &allocated,
+							    GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+			       "buddy_alloc hit an error size=%lu\n", 2 * ps);
+
+	gpu_buddy_free_list(&mm, &left, 0);
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+							    3 * ps, ps, &allocated,
+							    GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+			       "buddy_alloc hit an error size=%lu\n", 3 * ps);
+
+	total = 0;
+	list_for_each_entry(block, &allocated, link)
+		total += gpu_buddy_block_size(&mm, block);
+
+	KUNIT_ASSERT_EQ(test, total, ps * 2 + ps * 3);
+
+	gpu_buddy_free_list(&mm, &allocated, 0);
+	gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_pathological(struct kunit *test)
+{
+	u64 mm_size, size, start = 0;
+	struct gpu_buddy_block *block;
+	const int max_order = 3;
+	unsigned long flags = 0;
+	int order, top;
+	struct gpu_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(holes);
+	LIST_HEAD(tmp);
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left. Free the largest block, then whittle down again.
+	 * Eventually we will have a fully 50% fragmented mm.
+	 */
+
+	mm_size = SZ_4K << max_order;
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+			       "buddy_init failed\n");
+
+	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+	for (top = max_order; top; top--) {
+		/* Make room by freeing the largest allocated block */
+		block = list_first_entry_or_null(&blocks, typeof(*block), link);
+		if (block) {
+			list_del(&block->link);
+			gpu_buddy_free_block(&mm, block);
+		}
+
+		for (order = top; order--;) {
+			size = get_size(order, mm.chunk_size);
+			KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start,
+									    mm_size, size, size,
+										&tmp, flags),
+					"buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
+					order, top);
+
+			block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+			KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+			list_move_tail(&block->link, &blocks);
+		}
+
+		/* There should be one final page for this sub-allocation */
+		size = get_size(0, mm.chunk_size);
+		KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+								    size, size, &tmp, flags),
+							   "buddy_alloc hit -ENOMEM for hole\n");
+
+		block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+		list_move_tail(&block->link, &holes);
+
+		size = get_size(top, mm.chunk_size);
+		KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+								   size, size, &tmp, flags),
+							  "buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
+							  top, max_order);
+	}
+
+	gpu_buddy_free_list(&mm, &holes, 0);
+
+	/* Nothing larger than blocks of chunk_size now available */
+	for (order = 1; order <= max_order; order++) {
+		size = get_size(order, mm.chunk_size);
+		KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+								   size, size, &tmp, flags),
+							  "buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+							  order);
+	}
+
+	list_splice_tail(&holes, &blocks);
+	gpu_buddy_free_list(&mm, &blocks, 0);
+	gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_pessimistic(struct kunit *test)
+{
+	u64 mm_size, size, start = 0;
+	struct gpu_buddy_block *block, *bn;
+	const unsigned int max_order = 16;
+	unsigned long flags = 0;
+	struct gpu_buddy mm;
+	unsigned int order;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left.
+	 */
+
+	mm_size = SZ_4K << max_order;
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+			       "buddy_init failed\n");
+
+	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+	for (order = 0; order < max_order; order++) {
+		size = get_size(order, mm.chunk_size);
+		KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+								    size, size, &tmp, flags),
+							   "buddy_alloc hit -ENOMEM with order=%d\n",
+							   order);
+
+		block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+		list_move_tail(&block->link, &blocks);
+	}
+
+	/* And now the last remaining block available */
+	size = get_size(0, mm.chunk_size);
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+							    size, size, &tmp, flags),
+						   "buddy_alloc hit -ENOMEM on final alloc\n");
+
+	block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+	KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+	list_move_tail(&block->link, &blocks);
+
+	/* Should be completely full! */
+	for (order = max_order; order--;) {
+		size = get_size(order, mm.chunk_size);
+		KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+								   size, size, &tmp, flags),
+							  "buddy_alloc unexpectedly succeeded, it should be full!");
+	}
+
+	block = list_last_entry(&blocks, typeof(*block), link);
+	list_del(&block->link);
+	gpu_buddy_free_block(&mm, block);
+
+	/* As we free in increasing size, we make available larger blocks */
+	order = 1;
+	list_for_each_entry_safe(block, bn, &blocks, link) {
+		list_del(&block->link);
+		gpu_buddy_free_block(&mm, block);
+
+		size = get_size(order, mm.chunk_size);
+		KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+								    size, size, &tmp, flags),
+							   "buddy_alloc hit -ENOMEM with order=%d\n",
+							   order);
+
+		block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+		list_del(&block->link);
+		gpu_buddy_free_block(&mm, block);
+		order++;
+	}
+
+	/* To confirm, now the whole mm should be available */
+	size = get_size(max_order, mm.chunk_size);
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+							    size, size, &tmp, flags),
+						   "buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+						   max_order);
+
+	block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+	KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+	list_del(&block->link);
+	gpu_buddy_free_block(&mm, block);
+	gpu_buddy_free_list(&mm, &blocks, 0);
+	gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_optimistic(struct kunit *test)
+{
+	u64 mm_size, size, start = 0;
+	struct gpu_buddy_block *block;
+	unsigned long flags = 0;
+	const int max_order = 16;
+	struct gpu_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+	int order;
+
+	/*
+	 * Create a mm with one block of each order available, and
+	 * try to allocate them all.
+	 */
+
+	mm_size = SZ_4K * ((1 << (max_order + 1)) - 1);
+
+	KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+			       "buddy_init failed\n");
+
+	KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+	for (order = 0; order <= max_order; order++) {
+		size = get_size(order, mm.chunk_size);
+		KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+								    size, size, &tmp, flags),
+							   "buddy_alloc hit -ENOMEM with order=%d\n",
+							   order);
+
+		block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+		KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+		list_move_tail(&block->link, &blocks);
+	}
+
+	/* Should be completely full! */
+	size = get_size(0, mm.chunk_size);
+	KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+							   size, size, &tmp, flags),
+						  "buddy_alloc unexpectedly succeeded, it should be full!");
+
+	gpu_buddy_free_list(&mm, &blocks, 0);
+	gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_limit(struct kunit *test)
+{
+	u64 size = U64_MAX, start = 0;
+	struct gpu_buddy_block *block;
+	unsigned long flags = 0;
+	LIST_HEAD(allocated);
+	struct gpu_buddy mm;
+
+	KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, size, SZ_4K));
+
+	KUNIT_EXPECT_EQ_MSG(test, mm.max_order, GPU_BUDDY_MAX_ORDER,
+			    "mm.max_order(%d) != %d\n", mm.max_order,
+						GPU_BUDDY_MAX_ORDER);
+
+	size = mm.chunk_size << mm.max_order;
+	KUNIT_EXPECT_FALSE(test, gpu_buddy_alloc_blocks(&mm, start, size, size,
+							mm.chunk_size, &allocated, flags));
+
+	block = list_first_entry_or_null(&allocated, struct gpu_buddy_block, link);
+	KUNIT_EXPECT_TRUE(test, block);
+
+	KUNIT_EXPECT_EQ_MSG(test, gpu_buddy_block_order(block), mm.max_order,
+			    "block order(%d) != %d\n",
+						gpu_buddy_block_order(block), mm.max_order);
+
+	KUNIT_EXPECT_EQ_MSG(test, gpu_buddy_block_size(&mm, block),
+			    BIT_ULL(mm.max_order) * mm.chunk_size,
+						"block size(%llu) != %llu\n",
+						gpu_buddy_block_size(&mm, block),
+						BIT_ULL(mm.max_order) * mm.chunk_size);
+
+	gpu_buddy_free_list(&mm, &allocated, 0);
+	gpu_buddy_fini(&mm);
+}
+
+static int gpu_buddy_suite_init(struct kunit_suite *suite)
+{
+	while (!random_seed)
+		random_seed = get_random_u32();
+
+	kunit_info(suite, "Testing DRM buddy manager, with random_seed=0x%x\n",
+		   random_seed);
+
+	return 0;
+}
+
+static struct kunit_case gpu_buddy_tests[] = {
+	KUNIT_CASE(drm_test_buddy_alloc_limit),
+	KUNIT_CASE(drm_test_buddy_alloc_optimistic),
+	KUNIT_CASE(drm_test_buddy_alloc_pessimistic),
+	KUNIT_CASE(drm_test_buddy_alloc_pathological),
+	KUNIT_CASE(drm_test_buddy_alloc_contiguous),
+	KUNIT_CASE(drm_test_buddy_alloc_clear),
+	KUNIT_CASE(drm_test_buddy_alloc_range_bias),
+	{}
+};
+
+static struct kunit_suite gpu_buddy_test_suite = {
+	.name = "gpu_buddy",
+	.suite_init = gpu_buddy_suite_init,
+	.test_cases = gpu_buddy_tests,
+};
+
+kunit_test_suite(gpu_buddy_test_suite);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Kunit test for gpu_buddy functions");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/drivers/gpu/tests/gpu_random.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "gpu_random.h"
+
+u32 gpu_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
+{
+	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
+}
+EXPORT_SYMBOL(gpu_prandom_u32_max_state);
+
+void gpu_random_reorder(unsigned int *order, unsigned int count,
+			struct rnd_state *state)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < count; ++i) {
+		BUILD_BUG_ON(sizeof(unsigned int) > sizeof(u32));
+		j = gpu_prandom_u32_max_state(count, state);
+		swap(order[i], order[j]);
+	}
+}
+EXPORT_SYMBOL(gpu_random_reorder);
+
+unsigned int *gpu_random_order(unsigned int count, struct rnd_state *state)
+{
+	unsigned int *order, i;
+
+	order = kmalloc_array(count, sizeof(*order), GFP_KERNEL);
+	if (!order)
+		return order;
+
+	for (i = 0; i < count; i++)
+		order[i] = i;
+
+	gpu_random_reorder(order, count, state);
+	return order;
+}
+EXPORT_SYMBOL(gpu_random_order);
--- /dev/null
+++ b/drivers/gpu/tests/gpu_random.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __GPU_RANDOM_H__
+#define __GPU_RANDOM_H__
+
+/* This is a temporary home for a couple of utility functions that should
+ * be transposed to lib/ at the earliest convenience.
+ */
+
+#include <linux/random.h>
+
+#define GPU_RND_STATE_INITIALIZER(seed__) ({				\
+	struct rnd_state state__;					\
+	prandom_seed_state(&state__, (seed__));				\
+	state__;							\
+})
+
+#define GPU_RND_STATE(name__, seed__) \
+	struct rnd_state name__ = GPU_RND_STATE_INITIALIZER(seed__)
+
+unsigned int *gpu_random_order(unsigned int count,
+			       struct rnd_state *state);
+void gpu_random_reorder(unsigned int *order,
+			unsigned int count,
+			struct rnd_state *state);
+u32 gpu_prandom_u32_max_state(u32 ep_ro,
+			      struct rnd_state *state);
+
+#endif /* !__GPU_RANDOM_H__ */
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -37,6 +37,7 @@ source "drivers/char/agp/Kconfig"
 
 source "drivers/gpu/vga/Kconfig"
 
+source "drivers/gpu/Kconfig"
 source "drivers/gpu/host1x/Kconfig"
 source "drivers/gpu/ipu-v3/Kconfig"
 
--- a/include/drm/drm_buddy.h
+++ b/include/drm/drm_buddy.h
@@ -6,175 +6,13 @@
 #ifndef __DRM_BUDDY_H__
 #define __DRM_BUDDY_H__
 
-#include <linux/bitops.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/rbtree.h>
+#include <linux/gpu_buddy.h>
 
-#include <drm/drm_print.h>
+struct drm_printer;
 
-#define range_overflows(start, size, max) ({ \
-	typeof(start) start__ = (start); \
-	typeof(size) size__ = (size); \
-	typeof(max) max__ = (max); \
-	(void)(&start__ == &size__); \
-	(void)(&start__ == &max__); \
-	start__ >= max__ || size__ > max__ - start__; \
-})
-
-#define DRM_BUDDY_RANGE_ALLOCATION		BIT(0)
-#define DRM_BUDDY_TOPDOWN_ALLOCATION		BIT(1)
-#define DRM_BUDDY_CONTIGUOUS_ALLOCATION		BIT(2)
-#define DRM_BUDDY_CLEAR_ALLOCATION		BIT(3)
-#define DRM_BUDDY_CLEARED			BIT(4)
-#define DRM_BUDDY_TRIM_DISABLE			BIT(5)
-
-struct drm_buddy_block {
-#define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
-#define DRM_BUDDY_HEADER_STATE  GENMASK_ULL(11, 10)
-#define   DRM_BUDDY_ALLOCATED	   (1 << 10)
-#define   DRM_BUDDY_FREE	   (2 << 10)
-#define   DRM_BUDDY_SPLIT	   (3 << 10)
-#define DRM_BUDDY_HEADER_CLEAR  GENMASK_ULL(9, 9)
-/* Free to be used, if needed in the future */
-#define DRM_BUDDY_HEADER_UNUSED GENMASK_ULL(8, 6)
-#define DRM_BUDDY_HEADER_ORDER  GENMASK_ULL(5, 0)
-	u64 header;
-
-	struct drm_buddy_block *left;
-	struct drm_buddy_block *right;
-	struct drm_buddy_block *parent;
-
-	void *private; /* owned by creator */
-
-	/*
-	 * While the block is allocated by the user through drm_buddy_alloc*,
-	 * the user has ownership of the link, for example to maintain within
-	 * a list, if so desired. As soon as the block is freed with
-	 * drm_buddy_free* ownership is given back to the mm.
-	 */
-	union {
-		struct rb_node rb;
-		struct list_head link;
-	};
-
-	struct list_head tmp_link;
-};
-
-/* Order-zero must be at least SZ_4K */
-#define DRM_BUDDY_MAX_ORDER (63 - 12)
-
-/*
- * Binary Buddy System.
- *
- * Locking should be handled by the user, a simple mutex around
- * drm_buddy_alloc* and drm_buddy_free* should suffice.
- */
-struct drm_buddy {
-	/* Maintain a free list for each order. */
-	struct rb_root **free_trees;
-
-	/*
-	 * Maintain explicit binary tree(s) to track the allocation of the
-	 * address space. This gives us a simple way of finding a buddy block
-	 * and performing the potentially recursive merge step when freeing a
-	 * block.  Nodes are either allocated or free, in which case they will
-	 * also exist on the respective free list.
-	 */
-	struct drm_buddy_block **roots;
-
-	/*
-	 * Anything from here is public, and remains static for the lifetime of
-	 * the mm. Everything above is considered do-not-touch.
-	 */
-	unsigned int n_roots;
-	unsigned int max_order;
-
-	/* Must be at least SZ_4K */
-	u64 chunk_size;
-	u64 size;
-	u64 avail;
-	u64 clear_avail;
-};
-
-static inline u64
-drm_buddy_block_offset(const struct drm_buddy_block *block)
-{
-	return block->header & DRM_BUDDY_HEADER_OFFSET;
-}
-
-static inline unsigned int
-drm_buddy_block_order(struct drm_buddy_block *block)
-{
-	return block->header & DRM_BUDDY_HEADER_ORDER;
-}
-
-static inline unsigned int
-drm_buddy_block_state(struct drm_buddy_block *block)
-{
-	return block->header & DRM_BUDDY_HEADER_STATE;
-}
-
-static inline bool
-drm_buddy_block_is_allocated(struct drm_buddy_block *block)
-{
-	return drm_buddy_block_state(block) == DRM_BUDDY_ALLOCATED;
-}
-
-static inline bool
-drm_buddy_block_is_clear(struct drm_buddy_block *block)
-{
-	return block->header & DRM_BUDDY_HEADER_CLEAR;
-}
-
-static inline bool
-drm_buddy_block_is_free(struct drm_buddy_block *block)
-{
-	return drm_buddy_block_state(block) == DRM_BUDDY_FREE;
-}
-
-static inline bool
-drm_buddy_block_is_split(struct drm_buddy_block *block)
-{
-	return drm_buddy_block_state(block) == DRM_BUDDY_SPLIT;
-}
-
-static inline u64
-drm_buddy_block_size(struct drm_buddy *mm,
-		     struct drm_buddy_block *block)
-{
-	return mm->chunk_size << drm_buddy_block_order(block);
-}
-
-int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
-
-void drm_buddy_fini(struct drm_buddy *mm);
-
-struct drm_buddy_block *
-drm_get_buddy(struct drm_buddy_block *block);
-
-int drm_buddy_alloc_blocks(struct drm_buddy *mm,
-			   u64 start, u64 end, u64 size,
-			   u64 min_page_size,
-			   struct list_head *blocks,
-			   unsigned long flags);
-
-int drm_buddy_block_trim(struct drm_buddy *mm,
-			 u64 *start,
-			 u64 new_size,
-			 struct list_head *blocks);
-
-void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear);
-
-void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block);
-
-void drm_buddy_free_list(struct drm_buddy *mm,
-			 struct list_head *objects,
-			 unsigned int flags);
-
-void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p);
-void drm_buddy_block_print(struct drm_buddy *mm,
-			   struct drm_buddy_block *block,
+/* DRM-specific GPU Buddy Allocator print helpers */
+void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p);
+void drm_buddy_block_print(struct gpu_buddy *mm,
+			   struct gpu_buddy_block *block,
 			   struct drm_printer *p);
 #endif
--- /dev/null
+++ b/include/linux/gpu_buddy.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef __GPU_BUDDY_H__
+#define __GPU_BUDDY_H__
+
+#include <linux/bitops.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/rbtree.h>
+
+#include <drm/drm_print.h>
+
+#define range_overflows(start, size, max) ({ \
+	typeof(start) start__ = (start); \
+	typeof(size) size__ = (size); \
+	typeof(max) max__ = (max); \
+	(void)(&start__ == &size__); \
+	(void)(&start__ == &max__); \
+	start__ >= max__ || size__ > max__ - start__; \
+})
+
+#define GPU_BUDDY_RANGE_ALLOCATION		BIT(0)
+#define GPU_BUDDY_TOPDOWN_ALLOCATION		BIT(1)
+#define GPU_BUDDY_CONTIGUOUS_ALLOCATION		BIT(2)
+#define GPU_BUDDY_CLEAR_ALLOCATION		BIT(3)
+#define GPU_BUDDY_CLEARED			BIT(4)
+#define GPU_BUDDY_TRIM_DISABLE			BIT(5)
+
+enum gpu_buddy_free_tree {
+	GPU_BUDDY_CLEAR_TREE = 0,
+	GPU_BUDDY_DIRTY_TREE,
+	GPU_BUDDY_MAX_FREE_TREES,
+};
+
+#define for_each_free_tree(tree) \
+	for ((tree) = 0; (tree) < GPU_BUDDY_MAX_FREE_TREES; (tree)++)
+
+struct gpu_buddy_block {
+#define GPU_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
+#define GPU_BUDDY_HEADER_STATE  GENMASK_ULL(11, 10)
+#define   GPU_BUDDY_ALLOCATED	   (1 << 10)
+#define   GPU_BUDDY_FREE	   (2 << 10)
+#define   GPU_BUDDY_SPLIT	   (3 << 10)
+#define GPU_BUDDY_HEADER_CLEAR  GENMASK_ULL(9, 9)
+/* Free to be used, if needed in the future */
+#define GPU_BUDDY_HEADER_UNUSED GENMASK_ULL(8, 6)
+#define GPU_BUDDY_HEADER_ORDER  GENMASK_ULL(5, 0)
+	u64 header;
+
+	struct gpu_buddy_block *left;
+	struct gpu_buddy_block *right;
+	struct gpu_buddy_block *parent;
+
+	void *private; /* owned by creator */
+
+	/*
+	 * While the block is allocated by the user through gpu_buddy_alloc*,
+	 * the user has ownership of the link, for example to maintain within
+	 * a list, if so desired. As soon as the block is freed with
+	 * gpu_buddy_free* ownership is given back to the mm.
+	 */
+	union {
+		struct rb_node rb;
+		struct list_head link;
+	};
+
+	struct list_head tmp_link;
+};
+
+/* Order-zero must be at least SZ_4K */
+#define GPU_BUDDY_MAX_ORDER (63 - 12)
+
+/*
+ * Binary Buddy System.
+ *
+ * Locking should be handled by the user, a simple mutex around
+ * gpu_buddy_alloc* and gpu_buddy_free* should suffice.
+ */
+struct gpu_buddy {
+	/* Maintain a free list for each order. */
+	struct rb_root **free_trees;
+
+	/*
+	 * Maintain explicit binary tree(s) to track the allocation of the
+	 * address space. This gives us a simple way of finding a buddy block
+	 * and performing the potentially recursive merge step when freeing a
+	 * block.  Nodes are either allocated or free, in which case they will
+	 * also exist on the respective free list.
+	 */
+	struct gpu_buddy_block **roots;
+
+	/*
+	 * Anything from here is public, and remains static for the lifetime of
+	 * the mm. Everything above is considered do-not-touch.
+	 */
+	unsigned int n_roots;
+	unsigned int max_order;
+
+	/* Must be at least SZ_4K */
+	u64 chunk_size;
+	u64 size;
+	u64 avail;
+	u64 clear_avail;
+};
+
+static inline u64
+gpu_buddy_block_offset(const struct gpu_buddy_block *block)
+{
+	return block->header & GPU_BUDDY_HEADER_OFFSET;
+}
+
+static inline unsigned int
+gpu_buddy_block_order(struct gpu_buddy_block *block)
+{
+	return block->header & GPU_BUDDY_HEADER_ORDER;
+}
+
+static inline unsigned int
+gpu_buddy_block_state(struct gpu_buddy_block *block)
+{
+	return block->header & GPU_BUDDY_HEADER_STATE;
+}
+
+static inline bool
+gpu_buddy_block_is_allocated(struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_state(block) == GPU_BUDDY_ALLOCATED;
+}
+
+static inline bool
+gpu_buddy_block_is_clear(struct gpu_buddy_block *block)
+{
+	return block->header & GPU_BUDDY_HEADER_CLEAR;
+}
+
+static inline bool
+gpu_buddy_block_is_free(struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_state(block) == GPU_BUDDY_FREE;
+}
+
+static inline bool
+gpu_buddy_block_is_split(struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_state(block) == GPU_BUDDY_SPLIT;
+}
+
+static inline u64
+gpu_buddy_block_size(struct gpu_buddy *mm,
+		     struct gpu_buddy_block *block)
+{
+	return mm->chunk_size << gpu_buddy_block_order(block);
+}
+
+int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size);
+
+void gpu_buddy_fini(struct gpu_buddy *mm);
+
+struct gpu_buddy_block *
+gpu_get_buddy(struct gpu_buddy_block *block);
+
+int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
+			   u64 start, u64 end, u64 size,
+			   u64 min_page_size,
+			   struct list_head *blocks,
+			   unsigned long flags);
+
+int gpu_buddy_block_trim(struct gpu_buddy *mm,
+			 u64 *start,
+			 u64 new_size,
+			 struct list_head *blocks);
+
+void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear);
+
+void gpu_buddy_free_block(struct gpu_buddy *mm, struct gpu_buddy_block *block);
+
+void gpu_buddy_free_list(struct gpu_buddy *mm,
+			 struct list_head *objects,
+			 unsigned int flags);
+
+void gpu_buddy_print(struct gpu_buddy *mm);
+void gpu_buddy_block_print(struct gpu_buddy *mm,
+			   struct gpu_buddy_block *block);
+#endif



  parent reply	other threads:[~2026-07-30 15:51 UTC|newest]

Thread overview: 607+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 001/602] platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU hotplug Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 002/602] net: airoha: Move airoha_eth driver in a dedicated folder Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 003/602] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue() Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 004/602] bpf: Fix ld_{abs,ind} failure path analysis in subprogs Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 005/602] selftests/bpf: Add tests for ld_{abs,ind} failure path " Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 006/602] netfilter: nft_counter: serialize reset with spinlock Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 007/602] netfilter: nft_quota: use atomic64_xchg for reset Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 008/602] netfilter: nf_tables: revert commit_mutex usage in reset path Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 009/602] drm/virtio: fix deadlock in display_info_cb by removing hotplug from dequeue worker Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 010/602] fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 011/602] seqlock: Cure some more scoped_seqlock() optimization fails Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 012/602] seqlock: Allow KASAN to fail optimizing Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 013/602] seqlock: Allow UBSAN_ALIGNMENT " Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 014/602] KVM: x86: Check for invalid/obsolete root *after* making MMU pages available Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 015/602] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 016/602] KVM: nVMX: Hide shadow VMCS right after VMCLEAR Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 017/602] KVM: x86/mmu: Fix use-after-free on vendor module reload Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 018/602] can: bcm: add locking when updating filter and timer values Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 019/602] can: bcm: fix CAN frame rx/tx statistics Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 020/602] can: bcm: extend bcm_tx_lock usage for data and timer updates Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 021/602] can: bcm: validate frame length in bcm_rx_setup() for RTR replies Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 022/602] can: bcm: add missing device refcount for CAN filter removal Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 023/602] can: bcm: fix stale rx/tx ops after device removal Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 024/602] can: bcm: fix data race on rx_stamp/rx_ifindex in bcm_rx_handler() Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 025/602] can: bcm: track a single source interface for ANYDEV timeout/throttle ops Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 026/602] can: isotp: fix use-after-free race with concurrent NETDEV_UNREGISTER Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 027/602] can: isotp: serialize TX state transitions under so->rx_lock Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 028/602] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 029/602] Revert "arm64: dts: ti: k3-am62a7-sk: Add bootph-all tag to vqmmc" Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 030/602] gpu: host1x: Fix use-after-free in host1x_bo_clear_cached_mappings Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 031/602] crypto: tegra - Dont touch bo refcount in host1x bo pin/unpin Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 032/602] xprtrdma: Clear receive-side ownership pointers on release Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 033/602] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 034/602] Input: ims-pcu - fix logic error in packet reset Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 035/602] soc: qcom: ice: Allow explicit votes on iface clock for ICE Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 036/602] arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 037/602] firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 038/602] IB/mad: Drop unmatched RMPP responses before reassembly Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 039/602] mtd: mtdswap: remove debugfs stats file on teardown Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 040/602] mtd: nand: mtk-ecc: stop on ECC idle timeouts Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 041/602] btrfs: reject free space cache with more entries than pages Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 042/602] btrfs: fix root leak if its reloc root is unexpected in merge_reloc_roots() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 043/602] firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 044/602] RDMA/cma: Fix hardware address comparison length in netevent callback Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 045/602] RDMA/umem: Add pinned revocable dmabuf import interface Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 046/602] RDMA/irdma: Prevent rereg_mr for non-mem regions Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 047/602] RDMA/erdma: initialize ret for empty receive WR lists Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 048/602] RDMA/hns: Fix potential integer overflow in mhop hem cleanup Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 049/602] RDMA/siw: publish QP after initialization Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 050/602] mtd: fix double free and WARN_ON in add_mtd_device() error paths Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 051/602] selftests/alsa: Fix memory leak in find_controls error path Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 052/602] RDMA/irdma: Prevent overflows in memory contiguity checks Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 053/602] xfrm6: clear dst.dev on error to avoid double netdev_put in xfrm6_fill_dst() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 054/602] xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild reinsert Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 055/602] wifi: cfg80211: cancel sched scan results work on unregister Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 056/602] wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 057/602] wifi: mac80211_hwsim: clamp virtio RX length before skb_put Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 058/602] wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc failure Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 059/602] wifi: mac80211: fix fils_discovery " Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 060/602] wifi: libertas: fix memory leak in helper_firmware_cb() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 061/602] wifi: p54: validate RX frame length in p54_rx_eeprom_readback() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 062/602] wifi: cfg80211: pass net_device to .set_monitor_channel Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 063/602] wifi: cfg80211: define and use wiphy guard Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 064/602] wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 065/602] wifi: nl80211: free RNR data on MBSSID mismatch Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 066/602] wifi: cfg80211: derive S1G beacon TSF from S1G fields Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 067/602] wifi: nl80211: validate nested MBSSID IE blobs Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 068/602] wifi: cfg80211: validate PMSR measurement type data Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 069/602] wifi: cfg80211: validate PMSR FTM preamble range Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 070/602] wifi: cfg80211: reject unsupported PMSR FTM location requests Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 071/602] wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 072/602] wifi: brcmfmac: initialize SDIO data work before cleanup Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 073/602] wifi: cfg80211: bound element ID read when checking non-inheritance Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 074/602] ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on start/stop Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 075/602] ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 076/602] ASoC: cs42l43: Correct report for forced microphone jack Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 077/602] ASoC: tas2562: fix deprecated shut-down GPIO always cleared after lookup Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 078/602] firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 079/602] cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 080/602] ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 081/602] ipv4: fib: free fib_alias with kfree_rcu() on insert error path Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 082/602] net/iucv: take a reference on the socket found in afiucv_hs_rcv() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 083/602] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 084/602] scsi: core: wake eh reliably when using scsi_schedule_eh Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 085/602] ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is registered Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 086/602] ata: sata_dwc_460ex: use platform_get_irq() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 087/602] ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending interrupts Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 088/602] ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 089/602] accel/ivpu: Fix wrong register read in LNL failure diagnostics Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 090/602] ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 091/602] Bluetooth: qca: fix NVM tag length underflow in TLV parser Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 092/602] Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 093/602] Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 094/602] Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 095/602] Bluetooth: hci_qca: Clear memdump state on invalid dump size Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 096/602] smb/client: handle overlapping allocated ranges in fallocate Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 097/602] drm/i915/gt: use correct selftest config symbol Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 098/602] powerpc/85xx: Add fsl,ifc to common device ids Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 099/602] powerpc/time: Prepare to stop elapsing in dynticks-idle Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 100/602] powerpc/vtime: Initialize starttime at boot for native accounting Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 101/602] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 102/602] s390/checksum: Fix csum_partial() without vector facility Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 103/602] riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 104/602] can: j1939: fix lockless local-destination check Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 105/602] drm/xe/wopcm: fix WOPCM size for LNL+ Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 106/602] smb: move some duplicate definitions to common/cifsglob.h Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 107/602] ksmbd: pin conn during async oplock break notification Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 108/602] ksmbd: validate compound request size before reading StructureSize2 Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 109/602] drm/i915/selftests: Fix GT PM sort comparators Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 110/602] net/sched: act_tunnel_key: Defer dst_release to RCU callback Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 111/602] sctp: fix auth_hmacs array size in struct sctp_cookie Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 112/602] mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 113/602] usb: core: sysfs: add lock to bos_descriptors_read() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 114/602] wifi: at76c50x-usb: avoid length underflow in at76_guess_freq() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 115/602] usb: core: port: Deattach Type-C connector on component unbind Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 116/602] USB: storage: add NO_ATA_1X quirk for Longmai USB Key Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 117/602] usb: chipidea: fix usage_count leak when autosuspend_delay is negative Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 118/602] usb: gadget: dummy_hcd: prevent fifo_req reuse during giveback Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 119/602] usb: gadget: f_midi: cancel pending IN work before freeing the midi object Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 120/602] usb: gadget: printer: fix infinite loop in printer_read() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 121/602] USB: gadget: snps-udc: fix device name leak on probe failure Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 122/602] USB: gadget: fsl-udc: " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 123/602] usb: gadget: f_ncm: validate datagram bounds in ncm_unwrap_ntb() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 124/602] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 125/602] usb: gadget: uvc: clamp SEND_RESPONSE length to the response buffer Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 126/602] USB: serial: ftdi_sio: add support for E+H FXA291 Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 127/602] USB: serial: io_edgeport: cap received transmit credits Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 128/602] USB: serial: keyspan_pda: fix data loss on receive throttling Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 129/602] USB: serial: option: add TDTECH MT5710-CN Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 130/602] crypto: rsa-pkcs1pad: Dont WARN on an empty digest Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 131/602] Revert "drm/amd/display: Add missing kdoc for ALLM parameters" Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 132/602] RISC-V: KVM: Serialize virtual interrupt pending state updates Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 133/602] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 134/602] wifi: ath9k: hif_usb: dont dereference hif_dev after re-arming firmware request Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 135/602] wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 136/602] hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 137/602] hwmon: (corsair-cpro) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 138/602] hwmon: (gigabyte_waterforce) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 139/602] hwmon: (nzxt-smart2) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 140/602] hwmon: (nzxt-kraken3) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 141/602] watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 142/602] wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 143/602] wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 144/602] wifi: ath12k: " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 145/602] firewire: net: Fix fragmented datagram reassembly Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 146/602] wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 147/602] wifi: ath6kl: fix OOB read from firmware IE lengths in connect event Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 148/602] wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 149/602] wifi: carl9170: fix OOB read from off-by-two in TX status handler Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 150/602] wifi: carl9170: fix buffer overflow in rx_stream failover path Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 151/602] btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 152/602] btrfs: dont propagate EXTENT_FLAG_LOGGING to split extent maps Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 153/602] btrfs: free mapping node on duplicate reloc root insert Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 154/602] ASoC: tas2781: bound firmware description string parsing Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 155/602] ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_get_acpi_mute_state() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 156/602] ALSA: hda: cs35l41: validate and free ACPI mute object Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 157/602] ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 158/602] ASoC: cs35l56: Dont use devres to unregister component Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 159/602] ASoC: cs35l56: Fix potential probe() deadlock Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 160/602] ASoC: cs35l56: Use complete_all() to signal init_completion Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 161/602] wifi: iwlwifi: mvm: validate SAR GEO response payload size Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 162/602] wifi: iwlwifi: mvm: fix read in wake packet notification handler Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 163/602] usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 164/602] drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 165/602] hwmon: (asus-ec-sensors) fix looping over banks while reading from EC Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 166/602] hwmon: (asus-ec-sensors) fix EC read intervals Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 167/602] hwmon: (asus-ec-sensors) add missed handle for ENOMEM Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 168/602] smb: client: validate DFS referral PathConsumed Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 169/602] hwmon: occ: validate poll response sensor blocks Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 170/602] regulator: mt6358: use regmap helper to read fixed LDO calibration Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 171/602] Bluetooth: btusb: validate Realtek vendor event length Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 172/602] netlink: specs: rt-link: convert bridge port flag attributes to u8 Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 173/602] net/packet: avoid fanout hook re-registration after unregister Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 174/602] bonding: fix devconf_all NULL dereference when IPv6 is disabled Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 175/602] rds: drop incoming messages that cross network namespace boundaries Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 176/602] gtp: parse extension headers before reading inner protocol Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 177/602] dpaa2-switch: put MAC endpoint device on disconnect Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 178/602] dpaa2-eth: " Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 179/602] iommu/amd: Wait for completion instead of returning early in iommu_completion_wait() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 180/602] wifi: mac80211: tear down new links on vif update error path Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 181/602] nfp: Check resource mutex allocation Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 182/602] wan: wanxl: Only reset hardware after BAR mapping Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 183/602] wifi: mwifiex: bound uAP association event IEs to the event buffer Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 184/602] iommu/amd: Bound the early ACPI HID map Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 185/602] iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 186/602] wifi: mac80211: recalculate TIM when a station enters power save Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 187/602] pds_core: reject component parameter in legacy firmware update Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 188/602] amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 189/602] net: txgbe: fix FDIR filter leak on remove Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 190/602] sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 191/602] pds_core: fix deadlock between reset thread and remove Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 192/602] pds_core: fix use-after-free on workqueue during remove Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 193/602] pds_core: yield the CPU while waiting for the adminq to drain Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 194/602] pds_core: order completion reads after the ownership check Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 195/602] pds_core: fix auxiliary device add/del races Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 196/602] pds_core: check for workqueue allocation failure Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 197/602] sctp: validate stream count in sctp_process_strreset_inreq() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 198/602] net: mctp i3c: clean up notifier and buses if driver register fails Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 199/602] tls: device: push pending open record on splice EOF Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 200/602] selftests: af_unix: add USER_NS config Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 201/602] selftests: openvswitch: add config file Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 202/602] gtp: check skb_pull_data() return in gtp1u_send_echo_resp() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 203/602] nexthop: initialize extack in nh_res_bucket_migrate() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 204/602] tipc: fix infinite loop in __tipc_nl_compat_dumpit Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 205/602] wifi: mt76: mt7925: guard link STA in decap offload Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 206/602] wifi: mt76: mt7915: guard HE capability lookups Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 207/602] wifi: mt76: connac: fix possible NULL-pointer deref in mt76_connac_mcu_uni_bss_he_tlv() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 208/602] wifi: mt76: mt7925: fix possible NULL-pointer deref in mt7925_mcu_bss_he_tlv() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 209/602] wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 210/602] wifi: mt76: mt7925: fix crash in reset link replay Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 211/602] wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 212/602] wifi: brcmfmac: fix 802.1X-SHA256 call trace warning Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 213/602] ovl: fix trusted xattr escape prefix matching Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 214/602] amt: re-read skb header pointers after every pull Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 215/602] amt: make the head writable before rewriting the L2 header Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 216/602] net: bridge: vlan: fix vlan range dumps starting with pvid Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 217/602] net: hsr: fix memory leak on slave unregistration by removing synced VLANs Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 218/602] net: dpaa: fix mode setting Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 219/602] sctp: auth: verify auth requirement when auth_chunk is NULL Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 220/602] vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 221/602] iomap: correct the range of a partial dirty clear Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 222/602] tipc: fix u16 MTU truncation in media and bearer MTU validation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 223/602] drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 224/602] net: stmmac: fix l3l4 filter rejecting unsupported offload requests Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 225/602] net: stmmac: reset residual action in L3L4 filters on delete Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 226/602] net: stmmac: enable the MAC on link up for all supported speeds Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 227/602] net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 228/602] octeontx2-vf: set TC flower flag on MCAM entry allocation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 229/602] ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 230/602] ppp: use IFF_NO_QUEUE in virtual interfaces Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 231/602] ppp: convert to percpu netstats Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 232/602] ppp: enable TX scatter-gather Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 233/602] ppp: annotate data races in ppp_generic Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 234/602] hinic: remove unused ethtool RSS user configuration buffers Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 235/602] net: qrtr: restrict socket creation to the initial network namespace Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 236/602] dpll: add clock quality level attribute and op Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 237/602] net/mlx5: DPLL, Add clock quality level op implementation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 238/602] net/mlx5: Remove newline at the end of a netlink error message Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 239/602] net/mlx5: Refactor EEPROM query error handling to return status separately Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 240/602] net/mlx5: Fix MCIA register buffer overflow on 32 dword reads Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 241/602] net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 242/602] net/mlx5e: Report zero bandwidth for non-ETS traffic classes Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 243/602] net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 244/602] octeontx2-pf: tc: fix egress ratelimiting Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 245/602] net: ipv6: fix dif and sdif mismatch in raw6_icmp_error Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 246/602] ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 247/602] ice: fix LAG recipe to profile association Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 248/602] rds: tcp: unregister sysctl before tearing down listen socket Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 249/602] net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 250/602] bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 251/602] drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 252/602] drm/rockchip: cdn-dp: add missing check in cdn_dp_config_video() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 253/602] drm/imagination: Count paired job fence as dependency in prepare_job() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 254/602] drm/bridge: cdns-dsi: Replace deprecated UNIVERSAL_DEV_PM_OPS() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 255/602] drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 256/602] drm/dp/mst: fix buffer overflows in sideband chunk accumulation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 257/602] drm/imagination: Fit paired fragment job in the correct CCCB Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 258/602] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 259/602] drm/amdgpu/uvd: Fix forcing MSG, FB BOs into VCPU segment when it isnt at 0 (v2) Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 260/602] drm/amdgpu/uvd: Place VCPU BO only in VRAM for UVD 4.x and older Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 261/602] drm/amdgpu: Fix amdgpu_bo_move() when old_mem and new_mem are both GTT Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 262/602] drm/amdgpu: validate CP_GFX_SHADOW chunk size in CS pass1 Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 263/602] drm/nouveau: fix reversed error cleanup order in ucopy functions Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 264/602] drm/displayid: fix Tiled Display Topology ID size Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 265/602] drm/i915/gem: Add missing nospec on parallel submit slot Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 266/602] drm/nouveau/acr: fix missing nvkm_done() in error path of nvkm_acr_oneinit() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 267/602] drm/radeon: fix r100_copy_blit for large BOs Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 268/602] drm/xe: Fix PTE index in xe_vm_populate_pgtable() for chunked binds Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 269/602] drm/imagination: Fix double call to drm_sched_entity_fini() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 270/602] drm/imagination: Fix user array stride in pvr_set_uobj_array() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 271/602] drm/imagination: fix error checking of pvr_vm_context_lookup() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 272/602] drm/imagination: acquire vm_ctx->lock before mapping memory to GPU VM Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 273/602] drm/amdkfd: Use kvcalloc to allocate arrays Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 274/602] drm/amdkfd: Check bounds in allocate_event_notification_slot Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 275/602] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 276/602] drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 277/602] drm/amd/display: detect_link_and_local_sink: DP alt mode timeout path leaks prev_sink reference Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 278/602] drm/virtio: bound EDID block reads to the response buffer Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 279/602] drm/amdgpu/sdma7.0: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 280/602] drm/amdgpu/sdma6.0: " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 281/602] drm/amdgpu/sdma5.2: " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 282/602] drm/amdgpu/sdma5.0: " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 283/602] drm/i915: Return NULL on error in active_instance Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 284/602] drm/i915/bios: range check LFP Data Block panel_type2 Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 285/602] drm/amdgpu: fix lifetime issue of amdgpu_vm_get_task_info_pasid() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 286/602] drm/i915/gem: Do not leak siblings[] on proto context error Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 287/602] drm/i915/gem: Fix NULL deref in I915_CONTEXT_PARAM_SSEU Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 288/602] drm/amd/pm: fix smu14 power limit range calculation Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 289/602] drm/gfx10: Program DB_RING_CONTROL Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 290/602] drm/panthor: return error on truncated firmware Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 291/602] drm/amdgpu: Fix VFCT bus number matching with soft filter Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 292/602] drm/amd/pm/ci: Dont disable MCLK DPM on Bonaire 0x6658 (R7 260X) Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 293/602] drm/amd/display: set new_stream to NULL after release Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 294/602] drm/amd/display: dce100: skip non-DP stream encoders for DP MST Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 295/602] drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 296/602] drm/amdgpu: fix bo->pin leaking in amdgpu_bo_create_reserved Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 297/602] drm/vmwgfx: Validate vmw_surface_metadata::array_size Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 298/602] drm/vc4: Prevent shader BO mappings from becoming writable Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 299/602] media: airspy: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 300/602] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 301/602] media: cec: seco: unregister adapter on IR " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 302/602] media: cedrus: clean up media device on " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 303/602] media: cedrus: Fix missing cleanup in error path Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 304/602] media: cedrus: skip invalid H.264 reference list entries Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 305/602] media: chips-media: wave5: Move src_buf Removal to finish_encode Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 306/602] media: cx231xx: fix devres lifetime Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 307/602] media: cx23885: add ioremap return check and cleanup Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 308/602] media: i2c: alvium: fix critical pointer access in alvium_ctrl_init Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 309/602] media: intel/ipu6: Improve DWC PHY HSFREQRANGE band selection for overlapping ranges Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 310/602] media: marvell-cam: fix missing pci_disable_device() on remove Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 311/602] media: meson: vdec: Fix memory leak in error path of vdec_open Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 312/602] media: msi2500: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 313/602] media: nuvoton: npcm-video: fix error handling in npcm_video_init() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 314/602] media: nuvoton: npcm-video: fix memory leaks in probe and remove Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 315/602] media: nxp: imx8-isi: Add missing v4l2_subdev_cleanup() in crossbar and pipe Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 316/602] media: nxp: imx8-isi: Clean up already-initialized pipes on probe failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 317/602] media: nxp: imx8-isi: Fix missing v4l2_subdev_cleanup() in pipe init error path Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 318/602] media: nxp: imx8-isi: Fix potential out-of-bounds issues Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 319/602] media: nxp: imx8-isi: Fix scale factor calculation for hardware rounding Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 320/602] media: pci: dm1105: Free allocated workqueue Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 321/602] media: pwc: Drain fill_buf on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 322/602] media: pwc: Return queued buffers " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 323/602] media: qcom: camss: Fix RDI streaming for CSID GEN2 Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 324/602] media: radio-si476x: Unregister v4l2_device on probe failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 325/602] media: rtl2832: fix use-after-free in rtl2832_remove() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 326/602] media: rtl2832_sdr: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 327/602] media: saa7134: Fix a possible memory leak in saa7134_video_init1 Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 328/602] media: stm32: dcmi: unregister notifier on probe failure Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 329/602] media: sun4i-csi: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 330/602] media: tegra-video: vi: fix invalid u32 return value in format lookup Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 331/602] media: ti: vpe: unwind v4l2 device registration on probe error Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 332/602] media: v4l2-ctrls-request: add NULL check in v4l2_ctrl_request_complete() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 333/602] media: v4l2-ctrls: validate HEVC active reference counts Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 334/602] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 335/602] media: v4l2-subdev: Fail {enable,disable}_streams and s_streaming nicely Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 336/602] media: vb2: use ssize_t for vb2_read/vb2_write Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 337/602] media: vidtv: fix reference leak on failed device registration Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 338/602] media: vimc: " Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 339/602] media: vivid: add vivid_update_reduced_fps() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 340/602] media: vivid: check for vb2_is_busy() when toggling caps Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 341/602] media: vivid: fix cleanup bugs in vivid_init() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 342/602] media: vpif_capture: fix OF node reference imbalance Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 343/602] ALSA: seq: close a re-opened queue timer in the destructor Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 344/602] ALSA: timer: drain a slaves callback before its master detaches it Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 345/602] ALSA: timer: dont re-enter an instance callback that is still running Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 346/602] wifi: ath6kl: fix OOB access from firmware ADDBA window size Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 347/602] wifi: mwifiex: fix NULL dereference when the AP has HT-cap but no HT-oper Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 348/602] wifi: wilc1000: validate assoc response length before subtracting header Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 349/602] wifi: mt76: mt7615: drop TXRX_NOTIFY on non-mmio buses Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 350/602] wifi: mt76: mt7921: " Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 351/602] wifi: mt76: mt7925: " Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 352/602] wifi: brcmfmac: make release_scratchbuffers idempotent Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 353/602] staging: rtl8723bs: fix OOB reads in rtw_get_wps_ie() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 354/602] staging: rtl8723bs: fix inverted HT40 secondary channel offset Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 355/602] Bluetooth: hci_sync: Protect UUID list traversal Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 356/602] Bluetooth: RFCOMM: Fix session UAF in set_termios Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 357/602] exec: fix unsigned loop counter wrap in transfer_args_to_stack() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 358/602] binfmt_misc: set have_execfd only once the interpreter is opened Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 359/602] platform/loongarch: laptop: Explicitly reset bl_powered state when suspend Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 360/602] rust: allow `clippy::unwrap_or_default` globally Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 361/602] objtool/rust: add one more `noreturn` Rust function for Rust 1.99.0 Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 362/602] LoongArch: Fix oops during single-step debugging Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 363/602] LoongArch: Move jump_label_init() before parse_early_param() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 364/602] LoongArch: Retrieve CPU package ID from PPTT when available Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 365/602] cdrom: fix stack out-of-bounds read in CDROMVOLCTRL Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 366/602] firmware: stratix10-svc: fix memory leaks and list corruption bugs Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 367/602] x86/boot/compressed: Disable jump tables Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 368/602] comedi: comedi_parport: deal with premature interrupt Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 369/602] uio_hv_generic: Bind to FCopy device by default Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 370/602] serial: sc16is7xx: implement gpio get_direction() callback Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 371/602] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 372/602] mei: bus: access mei_device under device_lock on cleanup Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 373/602] intel_th: fix MSC output device reference leak Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 374/602] misc: nsm: only unlock nsm_dev on post-lock error paths Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 375/602] misc: nsm: pin the module while the device is open Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 376/602] tracing: Fix mmiotrace possible NULL dereferencing of hiter->dev Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 377/602] tracing: Fix resource leak on mmiotrace trace_pipe close Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 378/602] tracing/eprobe: Fix exact system name matching in eprobe_dyn_event_match() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 379/602] tracing/probes: Avoid temporary buffer truncation in trace_probe_match_command_args() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 380/602] tracing/probes: Fix potential underflow in LEN_OR_ZERO macro Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 381/602] tracing/probes: Prevent out-of-bounds write in __trace_probe_log_err() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 382/602] arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 383/602] Revert "arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates" Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 384/602] mptcp: decrement subflows counter on failed passive join Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 385/602] mptcp: only set DATA_FIN when a mapping is present Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 386/602] sctp: dont free the ASCONFs own transport in DEL-IP processing Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 387/602] sctp: avoid auth_enable sysctl UAF during netns teardown Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 388/602] sctp: close UDP tunnel sockets " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 389/602] ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT* Greg Kroah-Hartman
2026-07-30 17:40   ` Ilya Dryomov
2026-07-30 14:13 ` [PATCH 6.12 390/602] ceph: fix pre-auth out-of-bounds read on snaptrace in ceph_handle_caps() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 391/602] ceph: fix refcount leak in ceph_readdir() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 392/602] libceph: bound get_version reply decode to front len Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 393/602] libceph: Fix multiplication overflow in decode_new_up_state_weight() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 394/602] libceph: guard missing CRUSH type name lookup Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 395/602] libceph: refresh auth->authorizer_buf{,_len} after authorizer update Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 396/602] libceph: Reject monmaps advertising zero monitors Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 397/602] libceph: reject zero bucket types in crush_decode Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 398/602] libceph: remove debugfs files before client teardown Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 399/602] amt: fix use-after-free in AMT delayed works Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 400/602] ASoC: fsl_sai: Fix spurious BCLK on resume by clearing BYP Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 401/602] binfmt_elf_fdpic: only honour the first PT_INTERP Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 402/602] fs: preserve ACL_DONT_CACHE state in forget_cached_acl() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 403/602] fscrypt: Add missing superblock check in find_or_insert_direct_key() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 404/602] ftrace: Add global mutex to serialize trace_parser access Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 405/602] iomap: fix out-of-bounds bitmap_set() with zero-length range Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 406/602] iommu/vt-d: Disallow SVA if page walk is not coherent Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 407/602] phonet: pep: fix use-after-free in pep_get_sb() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 408/602] vxlan: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 409/602] net: slip: serialize receive against buffer reallocation Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 410/602] geneve: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 411/602] net/af_iucv: fix NULL deref in afiucv_hs_callback_syn() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 412/602] net/iucv: fix use-after-free of a severed iucv_path Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 413/602] net/mlx5e: Use sender devcom for MPV master-up Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 414/602] net/x25: fix use-after-free in x25_kill_by_neigh() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 415/602] net: gro: fix double aggregation of flush-marked skbs Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 416/602] net: hip04: fix RX buffer leak on build_skb failure Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 417/602] proc: Fix broken error paths for namespace links Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 418/602] ice: fix PTP Call Trace during PTP release Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 419/602] selftests/ftrace: Reset triggers at top level before instance loop Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 420/602] rbd: Reset positive result codes to zero in object map update path Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 421/602] ksmbd: defer destroy_previous_session() until after NTLM authentication Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 422/602] ice: reject out-of-range ptype in ice_parser_profile_init Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 423/602] ice: use READ_ONCE() to access cached PHC time Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 424/602] ila: reload IPv6 header after pskb_may_pull in checksum adjust Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 425/602] mac802154: hold an interface reference across the scan worker Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 426/602] mac802154: llsec: reject frames shorter than the authentication tag Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 427/602] mctp: serial: handle zero-length frames to prevent rx buffer overflow Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 428/602] openvswitch: fix GSO userspace truncation underflow Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 429/602] pppoe: reload header pointer after dev_hard_header() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 430/602] rtase: Workaround for TX hang caused by hardware packet parsing Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 431/602] tcp: initialize standalone TCP-AO response padding Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 432/602] tipc: clear sock->sk on the failed-insert path in tipc_sk_create() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 433/602] vsock/virtio: collapse receive queue under memory pressure Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 434/602] vxlan: mdb: Fix source list corruption on a failed replace Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 435/602] drm/amd/pm: fix amdgpu_pm_info power display units Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 436/602] drm/amd/pm: make pp_features read-only when scpm is enabled Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 437/602] drm/amdgpu/gfx10: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 438/602] drm/amdgpu/gfx11: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 439/602] drm/amdgpu/gfx12: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 440/602] drm/amdgpu/gfx8: drop unecessary BUG_ON() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 441/602] drm/amdgpu/gfx9.4.3: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 442/602] drm/amdgpu/gfx9: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 443/602] drm/amdgpu/sdma4.4.2: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 444/602] drm/amdgpu/vce: fix integer overflow in image size Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 445/602] drm/amdgpu/vcn4: avoid rereading IB param length Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 446/602] drm/dp_mst: Handle torn-down topology gracefully in drm_dp_mst_topology_queue_probe() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 447/602] drm/amdgpu: fix division by zero with invalid uvd dimensions Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 448/602] drm/amdgpu: invoke pm_genpd_remove() before freeing genpd Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 449/602] drm/amdgpu: fix aperture mapping leak Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 450/602] drm/amd/pm: fix smu13 power limit range calculation Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 451/602] bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 452/602] net: qrtr: ns: Raise node count limit to 512 Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 453/602] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 454/602] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 455/602] ksmbd: bound DACL dedup walk to copied ACEs Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 456/602] ksmbd: validate ACE size against SID sub-authorities Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 457/602] fscrypt: Avoid dynamic allocation in fscrypt_get_devices() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 458/602] drm/amd/display: Fix DTB DTO updates breaking live pixel rate sources Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 459/602] io_uring/rw: fix missing ERESTARTSYS conversion in read paths Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 460/602] net: pcs: xpcs: fix SGMII state reading Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 461/602] gve: fix Rx queue stall on alloc failure Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 462/602] rust: allow `suspicious_runtime_symbol_definitions` lint for Rust >= 1.98 Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 463/602] mm/damon/core: validate ranges in damon_set_regions() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 464/602] mm/damon/core: disallow overlapping input ranges for damon_set_regions() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 465/602] iommufd: Reject invalid read count in iommufd_fault_fops_read() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 466/602] iommufd: Break the loop on failure " Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 467/602] iommufd: Avoid partial fault group delivery " Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 468/602] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 469/602] i2c: davinci: Unregister cpufreq notifier on probe failure Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 470/602] VFS/audit: introduce kern_path_parent() for audit Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 471/602] audit: widen ino fields to u64 Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 472/602] audit: use unsigned int instead of unsigned Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 473/602] audit: fix recursive locking deadlock in audit_dupe_exe() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 474/602] i2c: i801: fix hardware state machine corruption in error path Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 475/602] ALSA: hda: conexant: Remove mic bias threshold override Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 476/602] ALSA: hda: Fix cached processing coefficient verbs Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 477/602] rxrpc: Pull out certain app callback funcs into an ops table Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 478/602] rxrpc: serialize kernel accept preallocation with socket teardown Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 479/602] xfs: factor out xfs_attr3_leaf_init Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 480/602] xfs: dont replace the wrong part of the cow fork Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 481/602] fbcon: Rename struct fbcon_ops to struct fbcon_par Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 482/602] fbcon: Use correct type for vc_resize() return value Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 483/602] rxrpc: Fix CPU time starvation in I/O thread Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 484/602] rxrpc: Dont need barrier for ->tx_bottom and ->acks_hard_ack Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 485/602] rxrpc: Use irq-disabling spinlocks between app and I/O thread Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 486/602] rxrpc: Fix notification vs call-release vs recvmsg Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 487/602] rxrpc: Fix socket notification race Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 488/602] tipc: restrict socket queue dumps in enqueue tracepoints Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 489/602] vduse: Use fixed 4KB bounce pages for non-4KB page size Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 490/602] vduse: remove unused vaddr parameter of vduse_domain_free_coherent Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 491/602] vduse: take out allocations from vduse_dev_alloc_coherent Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 492/602] VDUSE: avoid leaking information to userspace Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 493/602] octeontx2: Annotate mmio regions as __iomem Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 494/602] octeontx2-vf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 495/602] octeontx2-pf: " Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 496/602] arm64: dts: qcom: correct RBR opp entry Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 497/602] arm64: dts: qcom: hamoa: Fix OPP tables for all DisplayPort controllers Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 498/602] ASoC: mediatek: mt8192-afe-pcm: Simplify probe() with local dev variable Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 499/602] ASoC: mediatek: mt8192: Check runtime resume during probe Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 500/602] ASoC: mediatek: mt8183-afe-pcm: Shorten memif_data table using macros Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 501/602] ASoC: mediatek: mt8183-afe-pcm: Support >32 bit DMA addresses Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 502/602] ASoC: mediatek: mt8183-afe-pcm: use local `dev` pointer in driver callbacks Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 503/602] ASoC: mediatek: mt8183: Check runtime resume during probe Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 504/602] netfilter: nf_conntrack_sip: remove net variable shadowing Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 505/602] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 506/602] netfilter: bitwise: rename some boolean operation functions Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 507/602] netfilter: nf_tables: Remove unused nft_reduce_is_readonly() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 508/602] netfilter: nf_tables: remove register tracking infrastructure Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 509/602] netfilter: nft_fib: reject fib expression on the netdev egress hook Greg Kroah-Hartman
2026-07-30 14:15 ` Greg Kroah-Hartman [this message]
2026-07-30 14:15 ` [PATCH 6.12 511/602] gpu/buddy: bail out of try_harder when alignment cannot be honoured Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 512/602] NFSD: pass nfsd_file to nfsd_iter_read() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 513/602] sunrpc: allocate a separate bvec array for socket sends Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 514/602] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 515/602] SUNRPC: Return an error from xdr_buf_to_bvec() on overflow Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 516/602] remoteproc: xlnx: Check remote core state Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 517/602] mm/hugetlb: fix hugetlb cgroup rsvd charge/uncharge mismatch Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 518/602] mm/sparse-vmemmap: fix vmemmap accounting underflow Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 519/602] landlock: Prepare to use credential instead of domain for fowner Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 520/602] landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 521/602] mm/mm_init: fix pageblock migratetype for ZONE_DEVICE compound pages Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 522/602] mtd: maps: vmu-flash: fix fault in unaligned fixup Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 523/602] mm: prepare to move subsection_map_init() to mm/sparse-vmemmap.c Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 524/602] mm/sparse-vmemmap: fix DAX vmemmap accounting with optimization Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 525/602] thunderbolt: Keep XDomain reference during the lifetime of a service Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 526/602] thunderbolt: Remove service debugfs entries during unregister Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 527/602] thunderbolt: Remove XDomain from the bus without holding tb->lock Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 528/602] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 529/602] dma: dw-edma: Fix build warning in dw_edma_pcie_probe() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 530/602] dmaengine: dw-edma: Fix confusing cleanup.h syntax Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 531/602] dmaengine: dw-edma-pcie: Reject devices without driver data Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 532/602] i2c: imx: separate atomic, dma and non-dma use case Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 533/602] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 534/602] xfrm: Use nested-BH locking for nat_keepalive_sk_ipv[46] Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 535/602] xfrm: nat_keepalive: avoid double free on send error Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 536/602] tcp: defer md5sig_info kfree past RCU grace period in tcp_connect Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 537/602] tcp: Decrement tcp_md5_needed static branch Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 538/602] nvmet: Introduce nvmet_req_transfer_len() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 539/602] nvmet-auth: reject short AUTH_RECEIVE buffers Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 540/602] ovl: use linked upper dentry in copy-up tmpfile Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 541/602] bpf: Refactor {acquire,release}_reference_state Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 542/602] bpf: Refactor check_ctx_access() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 543/602] bpf: Reset register bounds before narrowing retval range in check_mem_access() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 544/602] block: add helper add_disk_final() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 545/602] block: remove redundant GD_NEED_PART_SCAN in add_disk_final() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 546/602] dm-integrity: fix leaking uninitialized kernel memory Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 547/602] cleanup: add a scoped version of CLASS() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 548/602] cleanup: fix scoped_class() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 549/602] cred: add kernel_cred() helper Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 550/602] cred: add scoped_with_kernel_creds() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 551/602] dm: avoid leaking the callers thread keyring via the table device file Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 552/602] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 553/602] mmc: vub300: fix use-after-free on disconnect Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 554/602] mmc: vub300: rename probe error labels Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 555/602] mmc: vub300: fix use-after-free on probe failure Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 556/602] locking/rt: Fix the incorrect RCU protection in rt_spin_unlock() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 557/602] net: mana: Validate the packet length reported by the NIC Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 558/602] net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 559/602] gve: fix header buffer corruption with header-split and HW-GRO Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 560/602] gpio: mt7621: avoid corruption of shared interrupt trigger state Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 561/602] octeontx2-af: cn10k: restrict VF LMTLINE sharing to its own PF Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 562/602] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 563/602] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 564/602] ipmi: fix refcount leak in i_ipmi_request() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 565/602] net/mlx5: HWS, Rearrange to prevent forward declaration Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 566/602] net/mlx5: HWS, fix matcher leak on resize target setup failure Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 567/602] octeontx2-pf: fix SQB pointer leak on init failure Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 568/602] ata: libata-core: Reject an invalid concurrent positioning ranges count Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 569/602] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 570/602] net: macb: drop in-flight Tx SKBs on close Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 571/602] net: ipa: fix SMEM state handle leaks in SMP2P init Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 572/602] Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 573/602] Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 574/602] afs: Improve server refcount/active count tracing Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 575/602] afs: Make afs_lookup_cell() take a trace note Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 576/602] afs: Drop the net parameter from afs_unuse_cell() Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 577/602] rxrpc: Allow the app to store private data on peer structs Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 578/602] afs: Use the per-peer app data provided by rxrpc Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 579/602] afs: Fix afs_server ref accounting Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 580/602] afs: Simplify cell record handling Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 581/602] afs: Fix dynamic lookup to fail on cell lookup failure Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 582/602] afs: Fix lack of locking around modifications of net->cells_dyn_ino Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 583/602] USB: gadget: Use str_enable_disable-like helpers Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 584/602] USB: gadget: fsl-udc: fix dev_printk() device Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 585/602] usb: musb: omap2430: clean up probe error handling Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 586/602] usb: musb: omap2430: Do not put borrowed of_node in probe Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 587/602] net/mlx5e: Fix NULL pointer dereference in ioctl module EEPROM query Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 588/602] gpu: Fix uninitialized buddy for built-in drivers Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 589/602] rxrpc: Disable IRQ, not BH, to take the lock for ->attend_link Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 590/602] rxrpc: Fix locking issues with the peer record hash Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 591/602] wifi: nl80211: fix nl80211_start_radar_detection return value Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 592/602] net: ethernet: Remove accidental duplication in Kconfig file Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 593/602] afs: Set vllist to NULL if addr parsing fails Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 594/602] dpll: fix clock quality level reporting Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 595/602] afs: Fix delayed allocation of a cells anonymous key Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 596/602] afs: handle CB.InitCallBackState3 requests without a server record Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 597/602] Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 598/602] Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 599/602] Bluetooth: hci_conn: Fix not cleaning up PA_LINK connections Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 600/602] Bluetooth: hci_conn: Fix memory leak in hci_le_big_terminate() Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 601/602] afs: Fix uninit var in afs_alloc_anon_key() Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 602/602] KVM: SVM: Bump asid_generation on CPU online to avoid ASID collision after hotplug Greg Kroah-Hartman
2026-07-30 17:37 ` [PATCH 6.12 000/602] 6.12.101-rc1 review Florian Fainelli
2026-07-30 18:47 ` Miguel Ojeda
2026-07-30 19:15 ` Peter Schneider

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260730141446.712461318@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=airlied@redhat.com \
    --cc=joelagnelf@nvidia.com \
    --cc=patches@lists.linux.dev \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox