Add helpers to map/unmap a hardware MMIO register window (PCI BAR) as a
1-entry sg_table using dma_map_resource()/dma_unmap_resource(). This
will be used by MMIO_REMAP.

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 | 51 +++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index ff98c87b2e0b..33fa17a927ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -37,11 +37,15 @@
 #include "amdgpu_dma_buf.h"
 #include "amdgpu_xgmi.h"
 #include "amdgpu_vm.h"
+#include "amdgpu_object.h"
 #include <drm/amdgpu_drm.h>
 #include <drm/ttm/ttm_tt.h>
 #include <linux/dma-buf.h>
 #include <linux/dma-fence-array.h>
 #include <linux/pci-p2pdma.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
 
 static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops;
 
@@ -146,6 +150,53 @@ static void amdgpu_dma_buf_unpin(struct dma_buf_attachment 
*attach)
        amdgpu_bo_unpin(bo);
 }
 
+/* Map a BAR-backed I/O span as a 1-entry sg_table via dma_map_resource(). */
+static __maybe_unused struct sg_table *
+amdgpu_dmabuf_map_iomem(struct device *dev, resource_size_t phys,
+                       size_t size, enum dma_data_direction dir)
+{
+       struct sg_table *sgt;
+       unsigned long attrs = DMA_ATTR_SKIP_CPU_SYNC; /* no P2PDMA attr */
+       dma_addr_t dma;
+
+       sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+       if (!sgt)
+               return ERR_PTR(-ENOMEM);
+
+       if (sg_alloc_table(sgt, 1, GFP_KERNEL)) {
+               kfree(sgt);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* No struct page backing for I/O regions. */
+       sg_set_page(sgt->sgl, NULL, size, 0);
+
+       dma = dma_map_resource(dev, phys, size, dir, attrs);
+       if (dma_mapping_error(dev, dma)) {
+               sg_free_table(sgt);
+               kfree(sgt);
+               return ERR_PTR(-EIO);
+       }
+
+       sg_dma_address(sgt->sgl) = dma;
+       sg_dma_len(sgt->sgl) = size;
+       return sgt;
+}
+
+static __maybe_unused void
+amdgpu_dmabuf_unmap_iomem(struct device *dev, struct sg_table *sgt,
+                         enum dma_data_direction dir)
+{
+       /* attrs must match map side; we only used SKIP_CPU_SYNC above */
+       dma_unmap_resource(dev,
+                          sg_dma_address(sgt->sgl),
+                          sg_dma_len(sgt->sgl),
+                          dir,
+                          0);
+       sg_free_table(sgt);
+       kfree(sgt);
+}
+
 /**
  * amdgpu_dma_buf_map - &dma_buf_ops.map_dma_buf implementation
  * @attach: DMA-buf attachment
-- 
2.34.1

Reply via email to