[Intel-gfx] [PATCH] drm/i915/lmem: Limit block size to 4G
Chris Wilson
chris at chris-wilson.co.uk
Mon Nov 30 13:18:49 UTC 2020
Quoting Matthew Auld (2020-11-30 13:08:43)
> From: Venkata Sandeep Dhanalakota <venkata.s.dhanalakota at intel.com>
>
> Block sizes are only limited by the largest power-of-two that will fit
> in the region size, but to construct an object we also require feeding
> it into an sg list, where the upper limit of the sg entry is at most
> UINT_MAX. Therefore to prevent issues with allocating blocks that are
> too large, add the flag I915_ALLOC_MAX_SEGMENT_SIZE which should limit
> block sizes to the i915_sg_segment_size().
>
> v2: (matt)
> - query the max segment.
> - prefer flag to limit block size to 4G, since it's best not to assume
> the user will feed the blocks into an sg list.
> - simple selftest so we don't have to guess.
>
> Cc: Niranjana Vishwanathapura <niranjana.vishwanathapura at intel.com>
> Cc: Matthew Auld <matthew.auld at intel.com>
> Cc: CQ Tang <cq.tang at intel.com>
> Signed-off-by: Venkata Sandeep Dhanalakota <venkata.s.dhanalakota at intel.com>
> Signed-off-by: Matthew Auld <matthew.auld at intel.com>
> ---
> drivers/gpu/drm/i915/gem/i915_gem_region.c | 2 +-
> drivers/gpu/drm/i915/intel_memory_region.c | 16 +++++-
> drivers/gpu/drm/i915/intel_memory_region.h | 5 +-
> .../drm/i915/selftests/intel_memory_region.c | 50 +++++++++++++++++++
> 4 files changed, 69 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c
> index 1515384d7e0e..e72d78074c9e 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c
> @@ -42,7 +42,7 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj)
> return -ENOMEM;
> }
>
> - flags = I915_ALLOC_MIN_PAGE_SIZE;
> + flags = I915_ALLOC_MIN_PAGE_SIZE | I915_ALLOC_MAX_SEGMENT_SIZE;
> if (obj->flags & I915_BO_ALLOC_CONTIGUOUS)
> flags |= I915_ALLOC_CONTIGUOUS;
>
> diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c
> index b326993a1026..8a376f1b5b3b 100644
> --- a/drivers/gpu/drm/i915/intel_memory_region.c
> +++ b/drivers/gpu/drm/i915/intel_memory_region.c
> @@ -72,6 +72,7 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
> struct list_head *blocks)
> {
> unsigned int min_order = 0;
> + unsigned int max_order;
> unsigned long n_pages;
>
> GEM_BUG_ON(!IS_ALIGNED(size, mem->mm.chunk_size));
> @@ -92,13 +93,26 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
>
> n_pages = size >> ilog2(mem->mm.chunk_size);
>
> + /*
> + * If we going to feed this into an sg list we should limit the block
> + * sizes such that we don't exceed the i915_sg_segment_size().
> + */
> + if (flags & I915_ALLOC_MAX_SEGMENT_SIZE) {
> + unsigned int max_segment = i915_sg_segment_size();
> +
> + GEM_BUG_ON(max_segment < mem->mm.chunk_size);
iirc, the swiotlb segment size can be adjusted by user parameter.
[Don't ask if swiotlb is compatible with lmem, I suspect not ;]
I think err on the side of safety, just in case the user does find a way
to adjust the parameter,
if (GEM_WARN_ON(max_segment < mem->mm.chunk_size))
max_order = 0;
else
max_order = ilog2(max_segment) - ilog2(mem->mm.chunk_size);
> + max_order = ilog2(max_segment) - ilog2(mem->mm.chunk_size);
> + } else {
> + max_order = mem->mm.max_order;
> + }
> +
> mutex_lock(&mem->mm_lock);
>
> do {
> struct i915_buddy_block *block;
> unsigned int order;
>
> - order = fls(n_pages) - 1;
> + order = min_t(u32, (fls(n_pages) - 1), max_order);
Spare () around fls.
> GEM_BUG_ON(order > mem->mm.max_order);
> GEM_BUG_ON(order < min_order);
>
> diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h
> index 232490d89a83..5fb9bcf86b97 100644
> --- a/drivers/gpu/drm/i915/intel_memory_region.h
> +++ b/drivers/gpu/drm/i915/intel_memory_region.h
> @@ -44,8 +44,9 @@ enum intel_region_id {
> #define MEMORY_TYPE_FROM_REGION(r) (ilog2((r) >> INTEL_MEMORY_TYPE_SHIFT))
> #define MEMORY_INSTANCE_FROM_REGION(r) (ilog2((r) & 0xffff))
>
> -#define I915_ALLOC_MIN_PAGE_SIZE BIT(0)
> -#define I915_ALLOC_CONTIGUOUS BIT(1)
> +#define I915_ALLOC_MIN_PAGE_SIZE BIT(0)
> +#define I915_ALLOC_CONTIGUOUS BIT(1)
> +#define I915_ALLOC_MAX_SEGMENT_SIZE BIT(2)
>
> #define for_each_memory_region(mr, i915, id) \
> for (id = 0; id < ARRAY_SIZE((i915)->mm.regions); id++) \
> diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
> index 0aeba8e3af28..cd706c0d9213 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
> @@ -337,6 +337,55 @@ static int igt_mock_splintered_region(void *arg)
> return err;
> }
>
> +#define SZ_8G BIT(33)
BIT_ULL
Otherwise makes sense.
Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
-Chris
More information about the Intel-gfx
mailing list