This is to work around a bug in function drm_prime_pages_to_sg if length of nr_pages >= 4GB, by doing the same check for max_segment and then calling sg_alloc_table_from_pages_segment directly instead.
This issue shows up on APU because VRAM is allocated as GTT memory. It also fixes >=4GB GTT memory mapping for mGPUs with IOMMU isolation mode. Signed-off-by: Philip Yang <philip.y...@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 50 ++++++++++++++------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 055ba2ea4c12..a203633fd629 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -171,18 +171,41 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach, } switch (bo->tbo.resource->mem_type) { - case TTM_PL_TT: - sgt = drm_prime_pages_to_sg(obj->dev, - bo->tbo.ttm->pages, - bo->tbo.ttm->num_pages); - if (IS_ERR(sgt)) - return sgt; - - if (dma_map_sgtable(attach->dev, sgt, dir, - DMA_ATTR_SKIP_CPU_SYNC)) - goto error_free; - break; + case TTM_PL_TT: { + size_t max_segment = 0; + u64 num_pages; + int err; + + sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + return ERR_PTR(-ENOMEM); + + if (obj->dev) + max_segment = dma_max_mapping_size(obj->dev->dev); + if (max_segment == 0) + max_segment = UINT_MAX; + + /* + * Use u64, otherwise if length of num_pages >= 4GB then size + * (num_pages << PAGE_SHIFT) becomes 0 + */ + num_pages = bo->tbo.ttm->num_pages; + err = sg_alloc_table_from_pages_segment(sgt, bo->tbo.ttm->pages, + num_pages, 0, + num_pages << PAGE_SHIFT, + max_segment, GFP_KERNEL); + if (err) { + kfree(sgt); + return ERR_PTR(err); + } + if (dma_map_sgtable(attach->dev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC)) { + sg_free_table(sgt); + kfree(sgt); + return ERR_PTR(-EBUSY); + } + break; + } case TTM_PL_VRAM: r = amdgpu_vram_mgr_alloc_sgt(adev, bo->tbo.resource, 0, bo->tbo.base.size, attach->dev, @@ -195,11 +218,6 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach, } return sgt; - -error_free: - sg_free_table(sgt); - kfree(sgt); - return ERR_PTR(-EBUSY); } /** -- 2.35.1