[PATCH v2 07/10] x86: support dma_map_pfn()
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()
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