Skip to content

Commit 4289531

Browse files
arunpravin24gregkh
authored andcommitted
gpu/buddy: bail out of try_harder when alignment cannot be honoured
[ Upstream commit 56bc638 ] The try_harder contiguous fallback could return a range whose start offset did not match the caller's min_block_size. When a candidate's start is misaligned, realign it: free the misaligned run and reallocate exactly @SiZe at the next lower min_block_size boundary. This keeps the returned size unchanged with no surplus to trim, and rejects the request only when no aligned candidate fits. v2: align misaligned candidates down to min_block_size instead of bailing out, for both the RHS and LHS paths (Matthew). Fixes: 0a1844b ("drm/buddy: Improve contiguous memory allocation") Suggested-by: Christian König <christian.koenig@amd.com> Cc: Matthew Auld <matthew.auld@intel.com> Cc: Christian König <christian.koenig@amd.com> Cc: Timur Kristóf <timur.kristof@gmail.com> Cc: stable@vger.kernel.org Reviewed-by: Matthew Auld <matthew.auld@intel.com> Tested-by: John Olender <john.olender@gmail.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com> Link: https://patch.msgid.link/20260709131050.1022759-1-Arunpravin.PaneerSelvam@amd.com Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 1c44c26 commit 4289531

1 file changed

Lines changed: 44 additions & 19 deletions

File tree

drivers/gpu/buddy.c

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -901,22 +901,30 @@ static int __gpu_buddy_alloc_range(struct gpu_buddy *mm,
901901
blocks, total_allocated_on_err);
902902
}
903903

904+
static int __alloc_contig_aligned_retry(struct gpu_buddy *mm,
905+
u64 unaligned_offset,
906+
u64 size,
907+
u64 min_block_size,
908+
struct list_head *blocks)
909+
{
910+
u64 aligned_offset = round_down(unaligned_offset, min_block_size);
911+
912+
return __gpu_buddy_alloc_range(mm, aligned_offset, size, NULL, blocks);
913+
}
914+
904915
static int __alloc_contig_try_harder(struct gpu_buddy *mm,
905916
u64 size,
906917
u64 min_block_size,
907918
struct list_head *blocks)
908919
{
909-
u64 rhs_offset, lhs_offset, lhs_size, filled;
920+
u64 rhs_offset, lhs_offset, filled;
910921
struct gpu_buddy_block *block;
911922
unsigned int tree, order;
912-
LIST_HEAD(blocks_lhs);
913-
unsigned long pages;
914923
u64 modify_size;
915924
int err;
916925

917926
modify_size = rounddown_pow_of_two(size);
918-
pages = modify_size >> ilog2(mm->chunk_size);
919-
order = fls(pages) - 1;
927+
order = ilog2(modify_size) - ilog2(mm->chunk_size);
920928
if (order == 0)
921929
return -ENOSPC;
922930

@@ -932,31 +940,48 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
932940
while (iter) {
933941
block = rbtree_get_free_block(iter);
934942

935-
/* Allocate blocks traversing RHS */
936943
rhs_offset = gpu_buddy_block_offset(block);
944+
945+
/* Allocate blocks traversing RHS */
937946
err = __gpu_buddy_alloc_range(mm, rhs_offset, size,
938947
&filled, blocks);
939-
if (!err || err != -ENOSPC)
948+
if (err && err != -ENOSPC)
940949
return err;
950+
if (!err && IS_ALIGNED(rhs_offset, min_block_size))
951+
return 0;
952+
if (!err) {
953+
/* Allocate the unaligned RHS offset using round_down */
954+
gpu_buddy_free_list_internal(mm, blocks);
955+
err = __alloc_contig_aligned_retry(mm, rhs_offset,
956+
size,
957+
min_block_size,
958+
blocks);
959+
if (!err)
960+
return 0;
961+
if (err != -ENOSPC) {
962+
gpu_buddy_free_list_internal(mm, blocks);
963+
return err;
964+
}
965+
goto next;
966+
}
941967

942-
lhs_size = max((size - filled), min_block_size);
943-
if (!IS_ALIGNED(lhs_size, min_block_size))
944-
lhs_size = round_up(lhs_size, min_block_size);
968+
if (size - filled > rhs_offset)
969+
goto next;
945970

946-
/* Allocate blocks traversing LHS */
947-
lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
948-
err = __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
949-
NULL, &blocks_lhs);
950-
if (!err) {
951-
list_splice(&blocks_lhs, blocks);
971+
lhs_offset = rhs_offset - (size - filled);
972+
973+
/* Allocate the unaligned LHS offset using round_down */
974+
gpu_buddy_free_list_internal(mm, blocks);
975+
err = __alloc_contig_aligned_retry(mm, lhs_offset, size,
976+
min_block_size, blocks);
977+
if (!err)
952978
return 0;
953-
} else if (err != -ENOSPC) {
979+
if (err != -ENOSPC) {
954980
gpu_buddy_free_list_internal(mm, blocks);
955981
return err;
956982
}
957-
/* Free blocks for the next iteration */
983+
next:
958984
gpu_buddy_free_list_internal(mm, blocks);
959-
960985
iter = rb_prev(iter);
961986
}
962987
}

0 commit comments

Comments
 (0)