Skip to content

Commit 09a729b

Browse files
matt-auldrodrigovivi
authored andcommitted
drm/i915/region: fix max size calculation
We are incorrectly limiting the max allocation size as per the mm max_order, which is effectively the largest power-of-two that we can fit in the region size. However, it's normal to setup the region or allocator with a non-power-of-two size(for example 3G), which we should already handle correctly, except it seems for the early too-big-check. v2: make sure we also exercise the I915_BO_ALLOC_CONTIGUOUS path, which is quite different, since for that we are actually limited by the largest power-of-two that we can fit within the region size. (Chris) Fixes: b908be5 ("drm/i915: support creating LMEM objects") Signed-off-by: Matthew Auld <matthew.auld@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: CQ Tang <cq.tang@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20201021103606.241395-1-matthew.auld@intel.com (cherry picked from commit 83ebef4) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
1 parent 3650b22 commit 09a729b

3 files changed

Lines changed: 79 additions & 2 deletions

File tree

drivers/gpu/drm/i915/intel_memory_region.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
8787
min_order = ilog2(size) - ilog2(mem->mm.chunk_size);
8888
}
8989

90-
if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size)
90+
if (size > mem->mm.size)
9191
return -E2BIG;
9292

9393
n_pages = size >> ilog2(mem->mm.chunk_size);

drivers/gpu/drm/i915/selftests/intel_memory_region.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,82 @@ static int igt_mock_contiguous(void *arg)
261261
return err;
262262
}
263263

264+
static int igt_mock_splintered_region(void *arg)
265+
{
266+
struct intel_memory_region *mem = arg;
267+
struct drm_i915_private *i915 = mem->i915;
268+
struct drm_i915_gem_object *obj;
269+
unsigned int expected_order;
270+
LIST_HEAD(objects);
271+
u64 size;
272+
int err = 0;
273+
274+
/*
275+
* Sanity check we can still allocate everything even if the
276+
* mm.max_order != mm.size. i.e our starting address space size is not a
277+
* power-of-two.
278+
*/
279+
280+
size = (SZ_4G - 1) & PAGE_MASK;
281+
mem = mock_region_create(i915, 0, size, PAGE_SIZE, 0);
282+
if (IS_ERR(mem))
283+
return PTR_ERR(mem);
284+
285+
if (mem->mm.size != size) {
286+
pr_err("%s size mismatch(%llu != %llu)\n",
287+
__func__, mem->mm.size, size);
288+
err = -EINVAL;
289+
goto out_put;
290+
}
291+
292+
expected_order = get_order(rounddown_pow_of_two(size));
293+
if (mem->mm.max_order != expected_order) {
294+
pr_err("%s order mismatch(%u != %u)\n",
295+
__func__, mem->mm.max_order, expected_order);
296+
err = -EINVAL;
297+
goto out_put;
298+
}
299+
300+
obj = igt_object_create(mem, &objects, size, 0);
301+
if (IS_ERR(obj)) {
302+
err = PTR_ERR(obj);
303+
goto out_close;
304+
}
305+
306+
close_objects(mem, &objects);
307+
308+
/*
309+
* While we should be able allocate everything without any flag
310+
* restrictions, if we consider I915_BO_ALLOC_CONTIGUOUS then we are
311+
* actually limited to the largest power-of-two for the region size i.e
312+
* max_order, due to the inner workings of the buddy allocator. So make
313+
* sure that does indeed hold true.
314+
*/
315+
316+
obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS);
317+
if (!IS_ERR(obj)) {
318+
pr_err("%s too large contiguous allocation was not rejected\n",
319+
__func__);
320+
err = -EINVAL;
321+
goto out_close;
322+
}
323+
324+
obj = igt_object_create(mem, &objects, rounddown_pow_of_two(size),
325+
I915_BO_ALLOC_CONTIGUOUS);
326+
if (IS_ERR(obj)) {
327+
pr_err("%s largest possible contiguous allocation failed\n",
328+
__func__);
329+
err = PTR_ERR(obj);
330+
goto out_close;
331+
}
332+
333+
out_close:
334+
close_objects(mem, &objects);
335+
out_put:
336+
intel_memory_region_put(mem);
337+
return err;
338+
}
339+
264340
static int igt_gpu_write_dw(struct intel_context *ce,
265341
struct i915_vma *vma,
266342
u32 dword,
@@ -771,6 +847,7 @@ int intel_memory_region_mock_selftests(void)
771847
static const struct i915_subtest tests[] = {
772848
SUBTEST(igt_mock_fill),
773849
SUBTEST(igt_mock_contiguous),
850+
SUBTEST(igt_mock_splintered_region),
774851
};
775852
struct intel_memory_region *mem;
776853
struct drm_i915_private *i915;

drivers/gpu/drm/i915/selftests/mock_region.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mock_object_create(struct intel_memory_region *mem,
2424
struct drm_i915_private *i915 = mem->i915;
2525
struct drm_i915_gem_object *obj;
2626

27-
if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size)
27+
if (size > mem->mm.size)
2828
return ERR_PTR(-E2BIG);
2929

3030
obj = i915_gem_object_alloc();

0 commit comments

Comments
 (0)