MMIO_REMAP (HDP flush page) exposes a hardware MMIO register window via a PCI BAR.
Handle it as fixed I/O: - map(): if MMIO_REMAP, require P2P, compute the BAR address (bus_addr + page offset), and build a 1-entry sg_table with dma_map_resource(). - unmap(): if MMIO_REMAP, call dma_unmap_resource() and return. Cc: Christian König <[email protected]> Cc: Alex Deucher <[email protected]> Signed-off-by: Srinivasan Shanmugam <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 39 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 33fa17a927ce..f85e16be438f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -151,7 +151,7 @@ static void amdgpu_dma_buf_unpin(struct dma_buf_attachment *attach) } /* Map a BAR-backed I/O span as a 1-entry sg_table via dma_map_resource(). */ -static __maybe_unused struct sg_table * +static struct sg_table * amdgpu_dmabuf_map_iomem(struct device *dev, resource_size_t phys, size_t size, enum dma_data_direction dir) { @@ -183,7 +183,7 @@ amdgpu_dmabuf_map_iomem(struct device *dev, resource_size_t phys, return sgt; } -static __maybe_unused void +static void amdgpu_dmabuf_unmap_iomem(struct device *dev, struct sg_table *sgt, enum dma_data_direction dir) { @@ -218,6 +218,9 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach, struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct sg_table *sgt; + resource_size_t phys; + u64 off; + size_t len; long r; if (!bo->tbo.pin_count) { @@ -261,6 +264,29 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach, if (r) return ERR_PTR(r); break; + + case AMDGPU_PL_MMIO_REMAP: + /* Only allow when importer can reach exporter via P2P. */ + if (!attach->peer2peer || + pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0) + return ERR_PTR(-EOPNOTSUPP); + + if (!adev->rmmio_remap.bus_addr) + return ERR_PTR(-ENODEV); + + if (bo->tbo.base.size != AMDGPU_GPU_PAGE_SIZE) + return ERR_PTR(-EINVAL); + + /* TTM start is in pages → convert to byte offset. */ + off = (u64)bo->tbo.resource->start << PAGE_SHIFT; + len = AMDGPU_GPU_PAGE_SIZE; + phys = adev->rmmio_remap.bus_addr + off; + + sgt = amdgpu_dmabuf_map_iomem(attach->dev, phys, len, dir); + if (IS_ERR(sgt)) + return sgt; + break; + default: return ERR_PTR(-EINVAL); } @@ -286,6 +312,15 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach, struct sg_table *sgt, enum dma_data_direction dir) { + struct drm_gem_object *obj = attach->dmabuf->priv; + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + + if (bo->tbo.resource && + bo->tbo.resource->mem_type == AMDGPU_PL_MMIO_REMAP) { + amdgpu_dmabuf_unmap_iomem(attach->dev, sgt, dir); + return; + } + if (sg_page(sgt->sgl)) { dma_unmap_sgtable(attach->dev, sgt, dir, 0); sg_free_table(sgt); -- 2.34.1
