From: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
Date: Sat, 27 Feb 2021 07:52:36 -0600
Subject: [PATCH] iommu/amd: Add support for map/unmap_resource
Patch-mainline: Never, upstream code was rewritten to get same support
References: jsc#ECO-3482
In Linux kernel prior to version 5.5, the AMD IOMMU driver does not
support these APIs, which are required for P2P support where device
perform DMA write/read directly into MMIO register to/from target
devices.
Re-factor the current map_page to map_helper, and also re-use for
map_resource. Note that the IOMMU_MMIO flag is not needed for AMD
IOMMU since the IO page table does not need separation between
RAM and MMIO region.
Also, reuse unmap_page for unmap_resource.
Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Acked-By: Joerg Roedel <jroedel@suse.de>
---
drivers/iommu/amd_iommu.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2606,15 +2606,10 @@ static void __unmap_single(struct dma_op
}
}
-/*
- * The exported map_single function for dma_ops.
- */
-static dma_addr_t map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- unsigned long attrs)
+static dma_addr_t map_helper(struct device *dev, phys_addr_t paddr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
{
- phys_addr_t paddr = page_to_phys(page) + offset;
struct protection_domain *domain;
struct dma_ops_domain *dma_dom;
u64 dma_mask;
@@ -2632,8 +2627,25 @@ static dma_addr_t map_page(struct device
}
/*
- * The exported unmap_single function for dma_ops.
+ * The exported map_single function for dma_ops.
*/
+static dma_addr_t map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ phys_addr_t paddr = page_to_phys(page) + offset;
+
+ return map_helper(dev, paddr, size, dir, attrs);
+}
+
+static dma_addr_t map_resource(struct device *dev, phys_addr_t paddr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ return map_helper(dev, paddr, size, dir, attrs);
+}
+
static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir, unsigned long attrs)
{
@@ -2891,6 +2903,8 @@ static const struct dma_map_ops amd_iomm
.unmap_page = unmap_page,
.map_sg = map_sg,
.unmap_sg = unmap_sg,
+ .map_resource = map_resource,
+ .unmap_resource = unmap_page,
.dma_supported = amd_iommu_dma_supported,
.mmap = dma_common_mmap,
.get_sgtable = dma_common_get_sgtable,