Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: b908be543e44 ("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 83ebef47f8ebe320d5c5673db82f9903a4f40a69)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

authored by

Matthew Auld and committed by
Rodrigo Vivi
09a729b1 3650b228

+79 -2
+1 -1
drivers/gpu/drm/i915/intel_memory_region.c
··· 87 87 min_order = ilog2(size) - ilog2(mem->mm.chunk_size); 88 88 } 89 89 90 - if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size) 90 + if (size > mem->mm.size) 91 91 return -E2BIG; 92 92 93 93 n_pages = size >> ilog2(mem->mm.chunk_size);
+77
drivers/gpu/drm/i915/selftests/intel_memory_region.c
··· 261 261 return err; 262 262 } 263 263 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 + 264 340 static int igt_gpu_write_dw(struct intel_context *ce, 265 341 struct i915_vma *vma, 266 342 u32 dword, ··· 847 771 static const struct i915_subtest tests[] = { 848 772 SUBTEST(igt_mock_fill), 849 773 SUBTEST(igt_mock_contiguous), 774 + SUBTEST(igt_mock_splintered_region), 850 775 }; 851 776 struct intel_memory_region *mem; 852 777 struct drm_i915_private *i915;
+1 -1
drivers/gpu/drm/i915/selftests/mock_region.c
··· 24 24 struct drm_i915_private *i915 = mem->i915; 25 25 struct drm_i915_gem_object *obj; 26 26 27 - if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size) 27 + if (size > mem->mm.size) 28 28 return ERR_PTR(-E2BIG); 29 29 30 30 obj = i915_gem_object_alloc();