From: Venkata Sandeep Dhanalakota venkata.s.dhanalakota@intel.com
when allocating pages to lmem object of size 4G or greater we allocate memory blocks from buddy system. In this scenario buddy sytem can allocate blocks that can have size >= 4G and these blocks require >32b to represent block size with these blocks we run into an issue with sg list construction because sg->length field is only 32b wide.
Hence limit the max allowed block size to less than 4G.
Cc: Niranjana Vishwanathapura niranjana.vishwanathapura@intel.com Cc: Matthew Auld matthew.auld@intel.com Cc: CQ Tang cq.tang@intel.com Signed-off-by: Venkata Sandeep Dhanalakota venkata.s.dhanalakota@intel.com --- drivers/gpu/drm/i915/intel_memory_region.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index 554fdd7735a8..371cd88ff6d8 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -101,6 +101,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)); @@ -121,6 +122,16 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
n_pages = size >> ilog2(mem->mm.chunk_size);
+ /* + * When allocating pages for an lmem object of size > 4G + * the memory blocks allocated from buddy system could be + * from sizes greater than 4G requiring > 32b to represent + * block size. But those blocks cannot be used in sg list + * construction(in caller) as sg->length is only 32b wide. + * Hence limiting the block size to 4G. + */ + max_order = (ilog2(SZ_4G) - 1) - ilog2(mem->mm.chunk_size); + mutex_lock(&mem->mm_lock);
do { @@ -128,7 +139,7 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem, unsigned int order; bool retry = true; retry: - order = fls(n_pages) - 1; + order = min_t(u32, (fls(n_pages) - 1), max_order); GEM_BUG_ON(order > mem->mm.max_order); GEM_BUG_ON(order < min_order);