[PATCH v2 07/10] x86: support dma_map_pfn()

2015-05-06 Thread Dan Williams
Fix up x86 dma_map_ops to allow pfn-only mappings.

As long as a dma_map_sg() implementation uses the generic sg_phys()
helpers it can support scatterlists that use __pfn_t instead of struct
page.

Signed-off-by: Dan Williams 
---
 arch/x86/Kconfig |5 +
 arch/x86/kernel/amd_gart_64.c|   22 +-
 arch/x86/kernel/pci-nommu.c  |   22 +-
 arch/x86/kernel/pci-swiotlb.c|4 
 arch/x86/pci/sta2x11-fixup.c |4 
 arch/x86/xen/pci-swiotlb-xen.c   |4 
 drivers/iommu/amd_iommu.c|   21 -
 drivers/iommu/intel-iommu.c  |   22 +-
 drivers/xen/swiotlb-xen.c|   29 +++--
 include/asm-generic/dma-mapping-common.h |4 ++--
 include/asm-generic/scatterlist.h|1 +
 include/linux/swiotlb.h  |4 
 lib/swiotlb.c|   20 +++-
 13 files changed, 125 insertions(+), 37 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d5696e1d1..1fae5e842423 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -796,6 +796,7 @@ config CALGARY_IOMMU
bool "IBM Calgary IOMMU support"
select SWIOTLB
depends on X86_64 && PCI
+   depends on !HAVE_DMA_PFN
---help---
  Support for hardware IOMMUs in IBM's xSeries x366 and x460
  systems. Needed to run systems with more than 3GB of memory
@@ -1432,6 +1433,10 @@ config X86_PMEM_LEGACY
 
  Say Y if unsure.
 
+config X86_PMEM_DMA
+   def_bool PMEM_IO
+   select HAVE_DMA_PFN
+
 config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
depends on HIGHMEM
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 8e3842fc8bea..8fad83c8dfd2 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -239,13 +239,13 @@ static dma_addr_t dma_map_area(struct device *dev, 
dma_addr_t phys_mem,
 }
 
 /* Map a single area into the IOMMU */
-static dma_addr_t gart_map_page(struct device *dev, struct page *page,
-   unsigned long offset, size_t size,
-   enum dma_data_direction dir,
-   struct dma_attrs *attrs)
+static dma_addr_t gart_map_pfn(struct device *dev, __pfn_t pfn,
+  unsigned long offset, size_t size,
+  enum dma_data_direction dir,
+  struct dma_attrs *attrs)
 {
unsigned long bus;
-   phys_addr_t paddr = page_to_phys(page) + offset;
+   phys_addr_t paddr = __pfn_t_to_phys(pfn) + offset;
 
if (!dev)
dev = _dma_fallback_dev;
@@ -259,6 +259,14 @@ static dma_addr_t gart_map_page(struct device *dev, struct 
page *page,
return bus;
 }
 
+static __maybe_unused dma_addr_t gart_map_page(struct device *dev,
+   struct page *page, unsigned long offset, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   return gart_map_pfn(dev, page_to_pfn_t(page), offset, size, dir,
+   attrs);
+}
+
 /*
  * Free a DMA mapping.
  */
@@ -699,7 +707,11 @@ static __init int init_amd_gatt(struct agp_kern_info *info)
 static struct dma_map_ops gart_dma_ops = {
.map_sg = gart_map_sg,
.unmap_sg   = gart_unmap_sg,
+#ifdef CONFIG_HAVE_DMA_PFN
+   .map_pfn= gart_map_pfn,
+#else
.map_page   = gart_map_page,
+#endif
.unmap_page = gart_unmap_page,
.alloc  = gart_alloc_coherent,
.free   = gart_free_coherent,
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index da15918d1c81..876dacfbabf6 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -25,12 +25,12 @@ check_addr(char *name, struct device *hwdev, dma_addr_t 
bus, size_t size)
return 1;
 }
 
-static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
-unsigned long offset, size_t size,
-enum dma_data_direction dir,
-struct dma_attrs *attrs)
+static dma_addr_t nommu_map_pfn(struct device *dev, __pfn_t pfn,
+   unsigned long offset, size_t size,
+   enum dma_data_direction dir,
+   struct dma_attrs *attrs)
 {
-   dma_addr_t bus = page_to_phys(page) + offset;
+   dma_addr_t bus = __pfn_t_to_phys(pfn) + offset;
WARN_ON(size == 0);
if (!check_addr("map_single", dev, bus, size))
return DMA_ERROR_CODE;
@@ -38,6 +38,14 @@ static dma_addr_t 

[PATCH v2 07/10] x86: support dma_map_pfn()

2015-05-06 Thread Dan Williams
Fix up x86 dma_map_ops to allow pfn-only mappings.

As long as a dma_map_sg() implementation uses the generic sg_phys()
helpers it can support scatterlists that use __pfn_t instead of struct
page.

Signed-off-by: Dan Williams dan.j.willi...@intel.com
---
 arch/x86/Kconfig |5 +
 arch/x86/kernel/amd_gart_64.c|   22 +-
 arch/x86/kernel/pci-nommu.c  |   22 +-
 arch/x86/kernel/pci-swiotlb.c|4 
 arch/x86/pci/sta2x11-fixup.c |4 
 arch/x86/xen/pci-swiotlb-xen.c   |4 
 drivers/iommu/amd_iommu.c|   21 -
 drivers/iommu/intel-iommu.c  |   22 +-
 drivers/xen/swiotlb-xen.c|   29 +++--
 include/asm-generic/dma-mapping-common.h |4 ++--
 include/asm-generic/scatterlist.h|1 +
 include/linux/swiotlb.h  |4 
 lib/swiotlb.c|   20 +++-
 13 files changed, 125 insertions(+), 37 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d5696e1d1..1fae5e842423 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -796,6 +796,7 @@ config CALGARY_IOMMU
bool IBM Calgary IOMMU support
select SWIOTLB
depends on X86_64  PCI
+   depends on !HAVE_DMA_PFN
---help---
  Support for hardware IOMMUs in IBM's xSeries x366 and x460
  systems. Needed to run systems with more than 3GB of memory
@@ -1432,6 +1433,10 @@ config X86_PMEM_LEGACY
 
  Say Y if unsure.
 
+config X86_PMEM_DMA
+   def_bool PMEM_IO
+   select HAVE_DMA_PFN
+
 config HIGHPTE
bool Allocate 3rd-level pagetables from highmem
depends on HIGHMEM
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 8e3842fc8bea..8fad83c8dfd2 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -239,13 +239,13 @@ static dma_addr_t dma_map_area(struct device *dev, 
dma_addr_t phys_mem,
 }
 
 /* Map a single area into the IOMMU */
-static dma_addr_t gart_map_page(struct device *dev, struct page *page,
-   unsigned long offset, size_t size,
-   enum dma_data_direction dir,
-   struct dma_attrs *attrs)
+static dma_addr_t gart_map_pfn(struct device *dev, __pfn_t pfn,
+  unsigned long offset, size_t size,
+  enum dma_data_direction dir,
+  struct dma_attrs *attrs)
 {
unsigned long bus;
-   phys_addr_t paddr = page_to_phys(page) + offset;
+   phys_addr_t paddr = __pfn_t_to_phys(pfn) + offset;
 
if (!dev)
dev = x86_dma_fallback_dev;
@@ -259,6 +259,14 @@ static dma_addr_t gart_map_page(struct device *dev, struct 
page *page,
return bus;
 }
 
+static __maybe_unused dma_addr_t gart_map_page(struct device *dev,
+   struct page *page, unsigned long offset, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   return gart_map_pfn(dev, page_to_pfn_t(page), offset, size, dir,
+   attrs);
+}
+
 /*
  * Free a DMA mapping.
  */
@@ -699,7 +707,11 @@ static __init int init_amd_gatt(struct agp_kern_info *info)
 static struct dma_map_ops gart_dma_ops = {
.map_sg = gart_map_sg,
.unmap_sg   = gart_unmap_sg,
+#ifdef CONFIG_HAVE_DMA_PFN
+   .map_pfn= gart_map_pfn,
+#else
.map_page   = gart_map_page,
+#endif
.unmap_page = gart_unmap_page,
.alloc  = gart_alloc_coherent,
.free   = gart_free_coherent,
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index da15918d1c81..876dacfbabf6 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -25,12 +25,12 @@ check_addr(char *name, struct device *hwdev, dma_addr_t 
bus, size_t size)
return 1;
 }
 
-static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
-unsigned long offset, size_t size,
-enum dma_data_direction dir,
-struct dma_attrs *attrs)
+static dma_addr_t nommu_map_pfn(struct device *dev, __pfn_t pfn,
+   unsigned long offset, size_t size,
+   enum dma_data_direction dir,
+   struct dma_attrs *attrs)
 {
-   dma_addr_t bus = page_to_phys(page) + offset;
+   dma_addr_t bus = __pfn_t_to_phys(pfn) + offset;
WARN_ON(size == 0);
if (!check_addr(map_single, dev, bus, size))
return DMA_ERROR_CODE;
@@ -38,6 +38,14 @@ static