Blob Blame History Raw
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,