* [PATCH v5 01/14] dma-mapping: prepare dma_map_ops to conversion to physical address
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 02/14] dma-mapping: convert dummy ops to physical address mapping Leon Romanovsky
` (14 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Add new .map_phys() and .unmap_phys() callbacks to dma_map_ops as a
preparation to replace .map_page() and .unmap_page() respectively.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
include/linux/dma-map-ops.h | 7 +++++++
kernel/dma/mapping.c | 4 ++++
kernel/dma/ops_helpers.c | 12 ++++++++++--
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 10882d00cb17..79d2a74d4b49 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -37,6 +37,13 @@ struct dma_map_ops {
void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
unsigned long attrs);
+
+ dma_addr_t (*map_phys)(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs);
+ void (*unmap_phys)(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs);
/*
* map_sg should return a negative error code on error. See
* dma_map_sgtable() for a list of appropriate error codes
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index fe7472f13b10..4080aebe5deb 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -169,6 +169,8 @@ dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
addr = dma_direct_map_phys(dev, phys, size, dir, attrs);
else if (use_dma_iommu(dev))
addr = iommu_dma_map_phys(dev, phys, size, dir, attrs);
+ else if (ops->map_phys)
+ addr = ops->map_phys(dev, phys, size, dir, attrs);
else if (is_mmio) {
if (!ops->map_resource)
return DMA_MAPPING_ERROR;
@@ -223,6 +225,8 @@ void dma_unmap_phys(struct device *dev, dma_addr_t addr, size_t size,
dma_direct_unmap_phys(dev, addr, size, dir, attrs);
else if (use_dma_iommu(dev))
iommu_dma_unmap_phys(dev, addr, size, dir, attrs);
+ else if (ops->unmap_phys)
+ ops->unmap_phys(dev, addr, size, dir, attrs);
else if (is_mmio) {
if (ops->unmap_resource)
ops->unmap_resource(dev, addr, size, dir, attrs);
diff --git a/kernel/dma/ops_helpers.c b/kernel/dma/ops_helpers.c
index 6f9d604d9d40..1eccbdbc99c1 100644
--- a/kernel/dma/ops_helpers.c
+++ b/kernel/dma/ops_helpers.c
@@ -64,6 +64,7 @@ struct page *dma_common_alloc_pages(struct device *dev, size_t size,
{
const struct dma_map_ops *ops = get_dma_ops(dev);
struct page *page;
+ phys_addr_t phys;
page = dma_alloc_contiguous(dev, size, gfp);
if (!page)
@@ -71,9 +72,13 @@ struct page *dma_common_alloc_pages(struct device *dev, size_t size,
if (!page)
return NULL;
+ phys = page_to_phys(page);
if (use_dma_iommu(dev))
- *dma_handle = iommu_dma_map_phys(dev, page_to_phys(page), size,
- dir, DMA_ATTR_SKIP_CPU_SYNC);
+ *dma_handle = iommu_dma_map_phys(dev, phys, size, dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ else if (ops->map_phys)
+ *dma_handle = ops->map_phys(dev, phys, size, dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
else
*dma_handle = ops->map_page(dev, page, 0, size, dir,
DMA_ATTR_SKIP_CPU_SYNC);
@@ -94,6 +99,9 @@ void dma_common_free_pages(struct device *dev, size_t size, struct page *page,
if (use_dma_iommu(dev))
iommu_dma_unmap_phys(dev, dma_handle, size, dir,
DMA_ATTR_SKIP_CPU_SYNC);
+ else if (ops->unmap_phys)
+ ops->unmap_phys(dev, dma_handle, size, dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
else if (ops->unmap_page)
ops->unmap_page(dev, dma_handle, size, dir,
DMA_ATTR_SKIP_CPU_SYNC);
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 02/14] dma-mapping: convert dummy ops to physical address mapping
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 01/14] dma-mapping: prepare dma_map_ops to conversion to physical address Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 03/14] ARM: dma-mapping: Reduce struct page exposure in arch_sync_dma*() Leon Romanovsky
` (13 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Change dma_dummy_map_page and dma_dummy_unmap_page routines
to accept physical address and rename them.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
kernel/dma/dummy.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/kernel/dma/dummy.c b/kernel/dma/dummy.c
index 92de80e5b057..16a51736a2a3 100644
--- a/kernel/dma/dummy.c
+++ b/kernel/dma/dummy.c
@@ -11,17 +11,16 @@ static int dma_dummy_mmap(struct device *dev, struct vm_area_struct *vma,
return -ENXIO;
}
-static dma_addr_t dma_dummy_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 dma_dummy_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
return DMA_MAPPING_ERROR;
}
-static void dma_dummy_unmap_page(struct device *dev, dma_addr_t dma_handle,
+static void dma_dummy_unmap_phys(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
/*
- * Dummy ops doesn't support map_page, so unmap_page should never be
+ * Dummy ops doesn't support map_phys, so unmap_page should never be
* called.
*/
WARN_ON_ONCE(true);
@@ -51,8 +50,8 @@ static int dma_dummy_supported(struct device *hwdev, u64 mask)
const struct dma_map_ops dma_dummy_ops = {
.mmap = dma_dummy_mmap,
- .map_page = dma_dummy_map_page,
- .unmap_page = dma_dummy_unmap_page,
+ .map_phys = dma_dummy_map_phys,
+ .unmap_phys = dma_dummy_unmap_phys,
.map_sg = dma_dummy_map_sg,
.unmap_sg = dma_dummy_unmap_sg,
.dma_supported = dma_dummy_supported,
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 03/14] ARM: dma-mapping: Reduce struct page exposure in arch_sync_dma*()
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 01/14] dma-mapping: prepare dma_map_ops to conversion to physical address Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 02/14] dma-mapping: convert dummy ops to physical address mapping Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 04/14] ARM: dma-mapping: Switch to physical address mapping callbacks Leon Romanovsky
` (12 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
As a preparation to changing from .map_page to use .map_phys DMA
callbacks, convert arch_sync_dma*() functions to use physical addresses
instead of struct page.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/arm/mm/dma-mapping.c | 82 ++++++++++++++++++-----------------------------
1 file changed, 31 insertions(+), 51 deletions(-)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 08641a936394..b0310d6762d5 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -624,16 +624,14 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
kfree(buf);
}
-static void dma_cache_maint_page(struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction dir,
+static void dma_cache_maint_page(phys_addr_t phys, size_t size,
+ enum dma_data_direction dir,
void (*op)(const void *, size_t, int))
{
- unsigned long pfn;
+ unsigned long offset = offset_in_page(phys);
+ unsigned long pfn = __phys_to_pfn(phys);
size_t left = size;
- pfn = page_to_pfn(page) + offset / PAGE_SIZE;
- offset %= PAGE_SIZE;
-
/*
* A single sg entry may refer to multiple physically contiguous
* pages. But we still need to process highmem pages individually.
@@ -644,17 +642,18 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
size_t len = left;
void *vaddr;
- page = pfn_to_page(pfn);
-
- if (PageHighMem(page)) {
+ phys = __pfn_to_phys(pfn);
+ if (PhysHighMem(phys)) {
if (len + offset > PAGE_SIZE)
len = PAGE_SIZE - offset;
if (cache_is_vipt_nonaliasing()) {
- vaddr = kmap_atomic(page);
+ vaddr = kmap_atomic_pfn(pfn);
op(vaddr + offset, len, dir);
kunmap_atomic(vaddr);
} else {
+ struct page *page = phys_to_page(phys);
+
vaddr = kmap_high_get(page);
if (vaddr) {
op(vaddr + offset, len, dir);
@@ -662,7 +661,8 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
}
}
} else {
- vaddr = page_address(page) + offset;
+ phys += offset;
+ vaddr = phys_to_virt(phys);
op(vaddr, len, dir);
}
offset = 0;
@@ -676,14 +676,11 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
* Note: Drivers should NOT use this function directly.
* Use the driver DMA support - see dma-mapping.h (dma_sync_*)
*/
-static void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
- size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
{
- phys_addr_t paddr;
-
- dma_cache_maint_page(page, off, size, dir, dmac_map_area);
+ dma_cache_maint_page(paddr, size, dir, dmac_map_area);
- paddr = page_to_phys(page) + off;
if (dir == DMA_FROM_DEVICE) {
outer_inv_range(paddr, paddr + size);
} else {
@@ -692,17 +689,15 @@ static void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
/* FIXME: non-speculating: flush on bidirectional mappings? */
}
-static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
- size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
{
- phys_addr_t paddr = page_to_phys(page) + off;
-
/* FIXME: non-speculating: not required */
/* in any case, don't bother invalidating if DMA to device */
if (dir != DMA_TO_DEVICE) {
outer_inv_range(paddr, paddr + size);
- dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
+ dma_cache_maint_page(paddr, size, dir, dmac_unmap_area);
}
/*
@@ -1205,7 +1200,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
unsigned int len = PAGE_ALIGN(s->offset + s->length);
if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
- __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
+ arch_sync_dma_for_device(sg_phys(s), s->length, dir);
prot = __dma_info_to_prot(dir, attrs);
@@ -1307,8 +1302,7 @@ static void arm_iommu_unmap_sg(struct device *dev,
__iommu_remove_mapping(dev, sg_dma_address(s),
sg_dma_len(s));
if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
- __dma_page_dev_to_cpu(sg_page(s), s->offset,
- s->length, dir);
+ arch_sync_dma_for_cpu(sg_phys(s), s->length, dir);
}
}
@@ -1330,7 +1324,7 @@ static void arm_iommu_sync_sg_for_cpu(struct device *dev,
return;
for_each_sg(sg, s, nents, i)
- __dma_page_dev_to_cpu(sg_page(s), s->offset, s->length, dir);
+ arch_sync_dma_for_cpu(sg_phys(s), s->length, dir);
}
@@ -1352,7 +1346,7 @@ static void arm_iommu_sync_sg_for_device(struct device *dev,
return;
for_each_sg(sg, s, nents, i)
- __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
+ arch_sync_dma_for_device(sg_phys(s), s->length, dir);
}
/**
@@ -1374,7 +1368,7 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
int ret, prot, len = PAGE_ALIGN(size + offset);
if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
- __dma_page_cpu_to_dev(page, offset, size, dir);
+ arch_sync_dma_for_device(page_to_phys(page), offset, size, dir);
dma_addr = __alloc_iova(mapping, len);
if (dma_addr == DMA_MAPPING_ERROR)
@@ -1407,7 +1401,6 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
dma_addr_t iova = handle & PAGE_MASK;
- struct page *page;
int offset = handle & ~PAGE_MASK;
int len = PAGE_ALIGN(size + offset);
@@ -1415,8 +1408,9 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
return;
if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
- page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
- __dma_page_dev_to_cpu(page, offset, size, dir);
+ phys_addr_t phys = iommu_iova_to_phys(mapping->domain, iova);
+
+ arch_sync_dma_for_cpu(phys + offset, size, dir);
}
iommu_unmap(mapping->domain, iova, len);
@@ -1485,14 +1479,14 @@ static void arm_iommu_sync_single_for_cpu(struct device *dev,
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
dma_addr_t iova = handle & PAGE_MASK;
- struct page *page;
unsigned int offset = handle & ~PAGE_MASK;
+ phys_addr_t phys;
if (dev->dma_coherent || !iova)
return;
- page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
- __dma_page_dev_to_cpu(page, offset, size, dir);
+ phys = iommu_iova_to_phys(mapping->domain, iova);
+ arch_sync_dma_for_cpu(phys + offset, size, dir);
}
static void arm_iommu_sync_single_for_device(struct device *dev,
@@ -1500,14 +1494,14 @@ static void arm_iommu_sync_single_for_device(struct device *dev,
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
dma_addr_t iova = handle & PAGE_MASK;
- struct page *page;
unsigned int offset = handle & ~PAGE_MASK;
+ phys_addr_t phys;
if (dev->dma_coherent || !iova)
return;
- page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
- __dma_page_cpu_to_dev(page, offset, size, dir);
+ phys = iommu_iova_to_phys(mapping->domain, iova);
+ arch_sync_dma_for_device(phys + offset, size, dir);
}
static const struct dma_map_ops iommu_ops = {
@@ -1794,20 +1788,6 @@ void arch_teardown_dma_ops(struct device *dev)
set_dma_ops(dev, NULL);
}
-void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
- enum dma_data_direction dir)
-{
- __dma_page_cpu_to_dev(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
- size, dir);
-}
-
-void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
- enum dma_data_direction dir)
-{
- __dma_page_dev_to_cpu(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
- size, dir);
-}
-
void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t gfp, unsigned long attrs)
{
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 04/14] ARM: dma-mapping: Switch to physical address mapping callbacks
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (2 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 03/14] ARM: dma-mapping: Reduce struct page exposure in arch_sync_dma*() Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 05/14] xen: swiotlb: " Leon Romanovsky
` (11 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Combine resource and page mappings routines to one function, which
handles both these flows at the same manner. This conversion allows
us to remove .map_resource/.unmap_resource callbacks completely.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/arm/mm/dma-mapping.c | 100 +++++++++++-----------------------------------
1 file changed, 23 insertions(+), 77 deletions(-)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index b0310d6762d5..a4c765d24692 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -732,6 +732,9 @@ static int __dma_info_to_prot(enum dma_data_direction dir, unsigned long attrs)
if (attrs & DMA_ATTR_PRIVILEGED)
prot |= IOMMU_PRIV;
+ if (attrs & DMA_ATTR_MMIO)
+ prot |= IOMMU_MMIO;
+
switch (dir) {
case DMA_BIDIRECTIONAL:
return prot | IOMMU_READ | IOMMU_WRITE;
@@ -1350,25 +1353,27 @@ static void arm_iommu_sync_sg_for_device(struct device *dev,
}
/**
- * arm_iommu_map_page
+ * arm_iommu_map_phys
* @dev: valid struct device pointer
- * @page: page that buffer resides in
- * @offset: offset into page for start of buffer
+ * @phys: physical address that buffer resides in
* @size: size of buffer to map
* @dir: DMA transfer direction
+ * @attrs: DMA mapping attributes
*
* IOMMU aware version of arm_dma_map_page()
*/
-static dma_addr_t arm_iommu_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 arm_iommu_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+ int len = PAGE_ALIGN(size + offset_in_page(phys));
+ phys_addr_t addr = phys & PAGE_MASK;
dma_addr_t dma_addr;
- int ret, prot, len = PAGE_ALIGN(size + offset);
+ int ret, prot;
- if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
- arch_sync_dma_for_device(page_to_phys(page), offset, size, dir);
+ if (!dev->dma_coherent &&
+ !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO)))
+ arch_sync_dma_for_device(phys, size, dir);
dma_addr = __alloc_iova(mapping, len);
if (dma_addr == DMA_MAPPING_ERROR)
@@ -1376,12 +1381,11 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
prot = __dma_info_to_prot(dir, attrs);
- ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len,
- prot, GFP_KERNEL);
+ ret = iommu_map(mapping->domain, dma_addr, addr, len, prot, GFP_KERNEL);
if (ret < 0)
goto fail;
- return dma_addr + offset;
+ return dma_addr + offset_in_page(phys);
fail:
__free_iova(mapping, dma_addr, len);
return DMA_MAPPING_ERROR;
@@ -1393,10 +1397,11 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
* @handle: DMA address of buffer
* @size: size of buffer (same as passed to dma_map_page)
* @dir: DMA transfer direction (same as passed to dma_map_page)
+ * @attrs: DMA mapping attributes
*
- * IOMMU aware version of arm_dma_unmap_page()
+ * IOMMU aware version of arm_dma_unmap_phys()
*/
-static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
+static void arm_iommu_unmap_phys(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
@@ -1407,7 +1412,8 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
if (!iova)
return;
- if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
+ if (!dev->dma_coherent &&
+ !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) {
phys_addr_t phys = iommu_iova_to_phys(mapping->domain, iova);
arch_sync_dma_for_cpu(phys + offset, size, dir);
@@ -1417,63 +1423,6 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
__free_iova(mapping, iova, len);
}
-/**
- * arm_iommu_map_resource - map a device resource for DMA
- * @dev: valid struct device pointer
- * @phys_addr: physical address of resource
- * @size: size of resource to map
- * @dir: DMA transfer direction
- */
-static dma_addr_t arm_iommu_map_resource(struct device *dev,
- phys_addr_t phys_addr, size_t size,
- enum dma_data_direction dir, unsigned long attrs)
-{
- struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
- dma_addr_t dma_addr;
- int ret, prot;
- phys_addr_t addr = phys_addr & PAGE_MASK;
- unsigned int offset = phys_addr & ~PAGE_MASK;
- size_t len = PAGE_ALIGN(size + offset);
-
- dma_addr = __alloc_iova(mapping, len);
- if (dma_addr == DMA_MAPPING_ERROR)
- return dma_addr;
-
- prot = __dma_info_to_prot(dir, attrs) | IOMMU_MMIO;
-
- ret = iommu_map(mapping->domain, dma_addr, addr, len, prot, GFP_KERNEL);
- if (ret < 0)
- goto fail;
-
- return dma_addr + offset;
-fail:
- __free_iova(mapping, dma_addr, len);
- return DMA_MAPPING_ERROR;
-}
-
-/**
- * arm_iommu_unmap_resource - unmap a device DMA resource
- * @dev: valid struct device pointer
- * @dma_handle: DMA address to resource
- * @size: size of resource to map
- * @dir: DMA transfer direction
- */
-static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction dir,
- unsigned long attrs)
-{
- struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
- dma_addr_t iova = dma_handle & PAGE_MASK;
- unsigned int offset = dma_handle & ~PAGE_MASK;
- size_t len = PAGE_ALIGN(size + offset);
-
- if (!iova)
- return;
-
- iommu_unmap(mapping->domain, iova, len);
- __free_iova(mapping, iova, len);
-}
-
static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
{
@@ -1510,8 +1459,8 @@ static const struct dma_map_ops iommu_ops = {
.mmap = arm_iommu_mmap_attrs,
.get_sgtable = arm_iommu_get_sgtable,
- .map_page = arm_iommu_map_page,
- .unmap_page = arm_iommu_unmap_page,
+ .map_phys = arm_iommu_map_phys,
+ .unmap_phys = arm_iommu_unmap_phys,
.sync_single_for_cpu = arm_iommu_sync_single_for_cpu,
.sync_single_for_device = arm_iommu_sync_single_for_device,
@@ -1519,9 +1468,6 @@ static const struct dma_map_ops iommu_ops = {
.unmap_sg = arm_iommu_unmap_sg,
.sync_sg_for_cpu = arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
-
- .map_resource = arm_iommu_map_resource,
- .unmap_resource = arm_iommu_unmap_resource,
};
/**
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 05/14] xen: swiotlb: Switch to physical address mapping callbacks
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (3 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 04/14] ARM: dma-mapping: Switch to physical address mapping callbacks Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 06/14] dma-mapping: remove unused mapping resource callbacks Leon Romanovsky
` (10 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Combine resource and page mappings routines to one function
and remove .map_resource/.unmap_resource callbacks completely.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
drivers/xen/swiotlb-xen.c | 63 ++++++++++++++++++++++-------------------------
1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index dd7747a2de87..ccf25027bec1 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -200,17 +200,32 @@ xen_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr,
* physical address to use is returned.
*
* Once the device is given the dma address, the device owns this memory until
- * either xen_swiotlb_unmap_page or xen_swiotlb_dma_sync_single is performed.
+ * either xen_swiotlb_unmap_phys or xen_swiotlb_dma_sync_single is performed.
*/
-static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
+static dma_addr_t xen_swiotlb_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
- phys_addr_t map, phys = page_to_phys(page) + offset;
- dma_addr_t dev_addr = xen_phys_to_dma(dev, phys);
+ dma_addr_t dev_addr;
+ phys_addr_t map;
BUG_ON(dir == DMA_NONE);
+
+ if (attrs & DMA_ATTR_MMIO) {
+ if (unlikely(!dma_capable(dev, phys, size, false))) {
+ dev_err_once(
+ dev,
+ "DMA addr %pa+%zu overflow (mask %llx, bus limit %llx).\n",
+ &phys, size, *dev->dma_mask,
+ dev->bus_dma_limit);
+ WARN_ON_ONCE(1);
+ return DMA_MAPPING_ERROR;
+ }
+ return phys;
+ }
+
+ dev_addr = xen_phys_to_dma(dev, phys);
+
/*
* If the address happens to be in the device's DMA window,
* we can safely return the device addr and not worry about bounce
@@ -257,13 +272,13 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
/*
* Unmap a single streaming mode DMA translation. The dma_addr and size must
- * match what was provided for in a previous xen_swiotlb_map_page call. All
+ * match what was provided for in a previous xen_swiotlb_map_phys call. All
* other usages are undefined.
*
* After this call, reads by the cpu to the buffer are guaranteed to see
* whatever the device wrote there.
*/
-static void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
+static void xen_swiotlb_unmap_phys(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
phys_addr_t paddr = xen_dma_to_phys(hwdev, dev_addr);
@@ -325,7 +340,7 @@ xen_swiotlb_sync_single_for_device(struct device *dev, dma_addr_t dma_addr,
/*
* Unmap a set of streaming mode DMA translations. Again, cpu read rules
- * concerning calls here are the same as for swiotlb_unmap_page() above.
+ * concerning calls here are the same as for swiotlb_unmap_phys() above.
*/
static void
xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
@@ -337,7 +352,7 @@ xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
BUG_ON(dir == DMA_NONE);
for_each_sg(sgl, sg, nelems, i)
- xen_swiotlb_unmap_page(hwdev, sg->dma_address, sg_dma_len(sg),
+ xen_swiotlb_unmap_phys(hwdev, sg->dma_address, sg_dma_len(sg),
dir, attrs);
}
@@ -352,8 +367,8 @@ xen_swiotlb_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
BUG_ON(dir == DMA_NONE);
for_each_sg(sgl, sg, nelems, i) {
- sg->dma_address = xen_swiotlb_map_page(dev, sg_page(sg),
- sg->offset, sg->length, dir, attrs);
+ sg->dma_address = xen_swiotlb_map_phys(dev, sg_phys(sg),
+ sg->length, dir, attrs);
if (sg->dma_address == DMA_MAPPING_ERROR)
goto out_unmap;
sg_dma_len(sg) = sg->length;
@@ -392,25 +407,6 @@ xen_swiotlb_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
}
}
-static dma_addr_t xen_swiotlb_direct_map_resource(struct device *dev,
- phys_addr_t paddr,
- size_t size,
- enum dma_data_direction dir,
- unsigned long attrs)
-{
- dma_addr_t dma_addr = paddr;
-
- if (unlikely(!dma_capable(dev, dma_addr, size, false))) {
- dev_err_once(dev,
- "DMA addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
- &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
- WARN_ON_ONCE(1);
- return DMA_MAPPING_ERROR;
- }
-
- return dma_addr;
-}
-
/*
* Return whether the given device DMA address mask can be supported
* properly. For example, if your device can only drive the low 24-bits
@@ -437,13 +433,12 @@ const struct dma_map_ops xen_swiotlb_dma_ops = {
.sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
.map_sg = xen_swiotlb_map_sg,
.unmap_sg = xen_swiotlb_unmap_sg,
- .map_page = xen_swiotlb_map_page,
- .unmap_page = xen_swiotlb_unmap_page,
+ .map_phys = xen_swiotlb_map_phys,
+ .unmap_phys = xen_swiotlb_unmap_phys,
.dma_supported = xen_swiotlb_dma_supported,
.mmap = dma_common_mmap,
.get_sgtable = dma_common_get_sgtable,
.alloc_pages_op = dma_common_alloc_pages,
.free_pages = dma_common_free_pages,
.max_mapping_size = swiotlb_max_mapping_size,
- .map_resource = xen_swiotlb_direct_map_resource,
};
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 06/14] dma-mapping: remove unused mapping resource callbacks
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (4 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 05/14] xen: swiotlb: " Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 07/14] alpha: Convert mapping routine to rely on physical address Leon Romanovsky
` (9 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
After ARM and XEN conversions to use physical addresses for the mapping,
there are no in-kernel users for map_resource/unmap_resource callbacks,
so remove them.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
include/linux/dma-map-ops.h | 6 ------
kernel/dma/mapping.c | 16 ++++------------
2 files changed, 4 insertions(+), 18 deletions(-)
diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 79d2a74d4b49..2e98ecc313a3 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -53,12 +53,6 @@ struct dma_map_ops {
enum dma_data_direction dir, unsigned long attrs);
void (*unmap_sg)(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir, unsigned long attrs);
- dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
- size_t size, enum dma_data_direction dir,
- unsigned long attrs);
- void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction dir,
- unsigned long attrs);
void (*sync_single_for_cpu)(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir);
void (*sync_single_for_device)(struct device *dev,
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 4080aebe5deb..32a85bfdf873 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -157,7 +157,7 @@ dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
{
const struct dma_map_ops *ops = get_dma_ops(dev);
bool is_mmio = attrs & DMA_ATTR_MMIO;
- dma_addr_t addr;
+ dma_addr_t addr = DMA_MAPPING_ERROR;
BUG_ON(!valid_dma_direction(dir));
@@ -171,18 +171,13 @@ dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
addr = iommu_dma_map_phys(dev, phys, size, dir, attrs);
else if (ops->map_phys)
addr = ops->map_phys(dev, phys, size, dir, attrs);
- else if (is_mmio) {
- if (!ops->map_resource)
- return DMA_MAPPING_ERROR;
-
- addr = ops->map_resource(dev, phys, size, dir, attrs);
- } else {
+ else if (!is_mmio && ops->map_page) {
struct page *page = phys_to_page(phys);
size_t offset = offset_in_page(phys);
/*
* The dma_ops API contract for ops->map_page() requires
- * kmappable memory, while ops->map_resource() does not.
+ * kmappable memory.
*/
addr = ops->map_page(dev, page, offset, size, dir, attrs);
}
@@ -227,10 +222,7 @@ void dma_unmap_phys(struct device *dev, dma_addr_t addr, size_t size,
iommu_dma_unmap_phys(dev, addr, size, dir, attrs);
else if (ops->unmap_phys)
ops->unmap_phys(dev, addr, size, dir, attrs);
- else if (is_mmio) {
- if (ops->unmap_resource)
- ops->unmap_resource(dev, addr, size, dir, attrs);
- } else
+ else
ops->unmap_page(dev, addr, size, dir, attrs);
trace_dma_unmap_phys(dev, addr, size, dir, attrs);
debug_dma_unmap_phys(dev, addr, size, dir);
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 07/14] alpha: Convert mapping routine to rely on physical address
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (5 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 06/14] dma-mapping: remove unused mapping resource callbacks Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 08/14] MIPS/jazzdma: Provide physical address directly Leon Romanovsky
` (8 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Magnus Lindholm, Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Alpha doesn't need struct *page and can perform mapping based on
physical addresses. So convert it to implement new .map_phys callback.
As part of this change, remove useless BUG_ON() as DMA mapping layer
ensures that right direction is provided.
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/alpha/kernel/pci_iommu.c | 48 +++++++++++++++++++------------------------
1 file changed, 21 insertions(+), 27 deletions(-)
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index dc91de50f906..955b6ca61627 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -224,28 +224,26 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
until either pci_unmap_single or pci_dma_sync_single is performed. */
static dma_addr_t
-pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
+pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size,
int dac_allowed)
{
struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+ unsigned long offset = offset_in_page(paddr);
struct pci_iommu_arena *arena;
long npages, dma_ofs, i;
- unsigned long paddr;
dma_addr_t ret;
unsigned int align = 0;
struct device *dev = pdev ? &pdev->dev : NULL;
- paddr = __pa(cpu_addr);
-
#if !DEBUG_NODIRECT
/* First check to see if we can use the direct map window. */
if (paddr + size + __direct_map_base - 1 <= max_dma
&& paddr + size <= __direct_map_size) {
ret = paddr + __direct_map_base;
- DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %ps\n",
- cpu_addr, size, ret, __builtin_return_address(0));
+ DBGA2("pci_map_single: [%pa,%zx] -> direct %llx from %ps\n",
+ &paddr, size, ret, __builtin_return_address(0));
return ret;
}
@@ -255,8 +253,8 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
if (dac_allowed) {
ret = paddr + alpha_mv.pci_dac_offset;
- DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %ps\n",
- cpu_addr, size, ret, __builtin_return_address(0));
+ DBGA2("pci_map_single: [%pa,%zx] -> DAC %llx from %ps\n",
+ &paddr, size, ret, __builtin_return_address(0));
return ret;
}
@@ -290,10 +288,10 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);
ret = arena->dma_base + dma_ofs * PAGE_SIZE;
- ret += (unsigned long)cpu_addr & ~PAGE_MASK;
+ ret += offset;
- DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %ps\n",
- cpu_addr, size, npages, ret, __builtin_return_address(0));
+ DBGA2("pci_map_single: [%pa,%zx] np %ld -> sg %llx from %ps\n",
+ &paddr, size, npages, ret, __builtin_return_address(0));
return ret;
}
@@ -322,19 +320,18 @@ static struct pci_dev *alpha_gendev_to_pci(struct device *dev)
return NULL;
}
-static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
+static dma_addr_t alpha_pci_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
int dac_allowed;
- BUG_ON(dir == DMA_NONE);
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
- dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
- return pci_map_single_1(pdev, (char *)page_address(page) + offset,
- size, dac_allowed);
+ dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ return pci_map_single_1(pdev, phys, size, dac_allowed);
}
/* Unmap a single streaming mode DMA translation. The DMA_ADDR and
@@ -343,7 +340,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
the cpu to the buffer are guaranteed to see whatever the device
wrote there. */
-static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
+static void alpha_pci_unmap_phys(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
@@ -353,8 +350,6 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
struct pci_iommu_arena *arena;
long dma_ofs, npages;
- BUG_ON(dir == DMA_NONE);
-
if (dma_addr >= __direct_map_base
&& dma_addr < __direct_map_base + __direct_map_size) {
/* Nothing to do. */
@@ -429,7 +424,7 @@ static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
}
memset(cpu_addr, 0, size);
- *dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
+ *dma_addrp = pci_map_single_1(pdev, virt_to_phys(cpu_addr), size, 0);
if (*dma_addrp == DMA_MAPPING_ERROR) {
free_pages((unsigned long)cpu_addr, order);
if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
@@ -643,9 +638,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
/* Fast path single entry scatterlists. */
if (nents == 1) {
sg->dma_length = sg->length;
- sg->dma_address
- = pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
- sg->length, dac_allowed);
+ sg->dma_address = pci_map_single_1(pdev, sg_phys(sg),
+ sg->length, dac_allowed);
if (sg->dma_address == DMA_MAPPING_ERROR)
return -EIO;
return 1;
@@ -917,8 +911,8 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
const struct dma_map_ops alpha_pci_ops = {
.alloc = alpha_pci_alloc_coherent,
.free = alpha_pci_free_coherent,
- .map_page = alpha_pci_map_page,
- .unmap_page = alpha_pci_unmap_page,
+ .map_phys = alpha_pci_map_phys,
+ .unmap_phys = alpha_pci_unmap_phys,
.map_sg = alpha_pci_map_sg,
.unmap_sg = alpha_pci_unmap_sg,
.dma_supported = alpha_pci_supported,
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 08/14] MIPS/jazzdma: Provide physical address directly
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (6 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 07/14] alpha: Convert mapping routine to rely on physical address Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 09/14] parisc: Convert DMA map_page to map_phys interface Leon Romanovsky
` (7 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
MIPS jazz uses physical addresses for mapping pages, so convert
it to get them directly from DMA mapping routine.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/mips/jazz/jazzdma.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
index c97b089b9902..eb9fb2f2a720 100644
--- a/arch/mips/jazz/jazzdma.c
+++ b/arch/mips/jazz/jazzdma.c
@@ -521,18 +521,24 @@ static void jazz_dma_free(struct device *dev, size_t size, void *vaddr,
__free_pages(virt_to_page(vaddr), get_order(size));
}
-static dma_addr_t jazz_dma_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 jazz_dma_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
- phys_addr_t phys = page_to_phys(page) + offset;
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ /*
+ * This check is included because older versions of the code lacked
+ * MMIO path support, and my ability to test this path is limited.
+ * However, from a software technical standpoint, there is no restriction,
+ * as the following code operates solely on physical addresses.
+ */
+ return DMA_MAPPING_ERROR;
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
arch_sync_dma_for_device(phys, size, dir);
return vdma_alloc(phys, size);
}
-static void jazz_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
+static void jazz_dma_unmap_phys(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
@@ -607,8 +613,8 @@ static void jazz_dma_sync_sg_for_cpu(struct device *dev,
const struct dma_map_ops jazz_dma_ops = {
.alloc = jazz_dma_alloc,
.free = jazz_dma_free,
- .map_page = jazz_dma_map_page,
- .unmap_page = jazz_dma_unmap_page,
+ .map_phys = jazz_dma_map_phys,
+ .unmap_phys = jazz_dma_unmap_phys,
.map_sg = jazz_dma_map_sg,
.unmap_sg = jazz_dma_unmap_sg,
.sync_single_for_cpu = jazz_dma_sync_single_for_cpu,
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 09/14] parisc: Convert DMA map_page to map_phys interface
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (7 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 08/14] MIPS/jazzdma: Provide physical address directly Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 10/14] powerpc: Convert to physical address DMA mapping Leon Romanovsky
` (6 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Perform mechanical conversion from .map_page to .map_phys callback.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
drivers/parisc/ccio-dma.c | 54 ++++++++++++++++++++++--------------------
drivers/parisc/iommu-helpers.h | 10 ++++----
drivers/parisc/sba_iommu.c | 54 ++++++++++++++++++++----------------------
3 files changed, 59 insertions(+), 59 deletions(-)
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index feef537257d0..4e7071714356 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -517,10 +517,10 @@ static u32 hint_lookup[] = {
* ccio_io_pdir_entry - Initialize an I/O Pdir.
* @pdir_ptr: A pointer into I/O Pdir.
* @sid: The Space Identifier.
- * @vba: The virtual address.
+ * @pba: The physical address.
* @hints: The DMA Hint.
*
- * Given a virtual address (vba, arg2) and space id, (sid, arg1),
+ * Given a physical address (pba, arg2) and space id, (sid, arg1),
* load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir
* entry consists of 8 bytes as shown below (MSB == bit 0):
*
@@ -543,7 +543,7 @@ static u32 hint_lookup[] = {
* index are bits 12:19 of the value returned by LCI.
*/
static void
-ccio_io_pdir_entry(__le64 *pdir_ptr, space_t sid, unsigned long vba,
+ccio_io_pdir_entry(__le64 *pdir_ptr, space_t sid, phys_addr_t pba,
unsigned long hints)
{
register unsigned long pa;
@@ -557,7 +557,7 @@ ccio_io_pdir_entry(__le64 *pdir_ptr, space_t sid, unsigned long vba,
** "hints" parm includes the VALID bit!
** "dep" clobbers the physical address offset bits as well.
*/
- pa = lpa(vba);
+ pa = pba;
asm volatile("depw %1,31,12,%0" : "+r" (pa) : "r" (hints));
((u32 *)pdir_ptr)[1] = (u32) pa;
@@ -582,7 +582,7 @@ ccio_io_pdir_entry(__le64 *pdir_ptr, space_t sid, unsigned long vba,
** Grab virtual index [0:11]
** Deposit virt_idx bits into I/O PDIR word
*/
- asm volatile ("lci %%r0(%1), %0" : "=r" (ci) : "r" (vba));
+ asm volatile ("lci %%r0(%1), %0" : "=r" (ci) : "r" (phys_to_virt(pba)));
asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci));
@@ -704,14 +704,14 @@ ccio_dma_supported(struct device *dev, u64 mask)
/**
* ccio_map_single - Map an address range into the IOMMU.
* @dev: The PCI device.
- * @addr: The start address of the DMA region.
+ * @addr: The physical address of the DMA region.
* @size: The length of the DMA region.
* @direction: The direction of the DMA transaction (to/from device).
*
* This function implements the pci_map_single function.
*/
static dma_addr_t
-ccio_map_single(struct device *dev, void *addr, size_t size,
+ccio_map_single(struct device *dev, phys_addr_t addr, size_t size,
enum dma_data_direction direction)
{
int idx;
@@ -730,7 +730,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
BUG_ON(size <= 0);
/* save offset bits */
- offset = ((unsigned long) addr) & ~IOVP_MASK;
+ offset = offset_in_page(addr);
/* round up to nearest IOVP_SIZE */
size = ALIGN(size + offset, IOVP_SIZE);
@@ -746,15 +746,15 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
pdir_start = &(ioc->pdir_base[idx]);
- DBG_RUN("%s() %px -> %#lx size: %zu\n",
- __func__, addr, (long)(iovp | offset), size);
+ DBG_RUN("%s() %pa -> %#lx size: %zu\n",
+ __func__, &addr, (long)(iovp | offset), size);
/* If not cacheline aligned, force SAFE_DMA on the whole mess */
- if((size % L1_CACHE_BYTES) || ((unsigned long)addr % L1_CACHE_BYTES))
+ if ((size % L1_CACHE_BYTES) || (addr % L1_CACHE_BYTES))
hint |= HINT_SAFE_DMA;
while(size > 0) {
- ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long)addr, hint);
+ ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, hint);
DBG_RUN(" pdir %p %08x%08x\n",
pdir_start,
@@ -773,17 +773,18 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
static dma_addr_t
-ccio_map_page(struct device *dev, struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction direction,
- unsigned long attrs)
+ccio_map_phys(struct device *dev, phys_addr_t phys, size_t size,
+ enum dma_data_direction direction, unsigned long attrs)
{
- return ccio_map_single(dev, page_address(page) + offset, size,
- direction);
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
+
+ return ccio_map_single(dev, phys, size, direction);
}
/**
- * ccio_unmap_page - Unmap an address range from the IOMMU.
+ * ccio_unmap_phys - Unmap an address range from the IOMMU.
* @dev: The PCI device.
* @iova: The start address of the DMA region.
* @size: The length of the DMA region.
@@ -791,7 +792,7 @@ ccio_map_page(struct device *dev, struct page *page, unsigned long offset,
* @attrs: attributes
*/
static void
-ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
+ccio_unmap_phys(struct device *dev, dma_addr_t iova, size_t size,
enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
@@ -853,7 +854,8 @@ ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag,
if (ret) {
memset(ret, 0, size);
- *dma_handle = ccio_map_single(dev, ret, size, DMA_BIDIRECTIONAL);
+ *dma_handle = ccio_map_single(dev, virt_to_phys(ret), size,
+ DMA_BIDIRECTIONAL);
}
return ret;
@@ -873,7 +875,7 @@ static void
ccio_free(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle, unsigned long attrs)
{
- ccio_unmap_page(dev, dma_handle, size, 0, 0);
+ ccio_unmap_phys(dev, dma_handle, size, 0, 0);
free_pages((unsigned long)cpu_addr, get_order(size));
}
@@ -920,7 +922,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
/* Fast path single entry scatterlists. */
if (nents == 1) {
sg_dma_address(sglist) = ccio_map_single(dev,
- sg_virt(sglist), sglist->length,
+ sg_phys(sglist), sglist->length,
direction);
sg_dma_len(sglist) = sglist->length;
return 1;
@@ -1004,7 +1006,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
#ifdef CCIO_COLLECT_STATS
ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
#endif
- ccio_unmap_page(dev, sg_dma_address(sglist),
+ ccio_unmap_phys(dev, sg_dma_address(sglist),
sg_dma_len(sglist), direction, 0);
++sglist;
nents--;
@@ -1017,8 +1019,8 @@ static const struct dma_map_ops ccio_ops = {
.dma_supported = ccio_dma_supported,
.alloc = ccio_alloc,
.free = ccio_free,
- .map_page = ccio_map_page,
- .unmap_page = ccio_unmap_page,
+ .map_phys = ccio_map_phys,
+ .unmap_phys = ccio_unmap_phys,
.map_sg = ccio_map_sg,
.unmap_sg = ccio_unmap_sg,
.get_sgtable = dma_common_get_sgtable,
@@ -1072,7 +1074,7 @@ static int ccio_proc_info(struct seq_file *m, void *p)
ioc->msingle_calls, ioc->msingle_pages,
(int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
- /* KLUGE - unmap_sg calls unmap_page for each mapped page */
+ /* KLUGE - unmap_sg calls unmap_phys for each mapped page */
min = ioc->usingle_calls - ioc->usg_calls;
max = ioc->usingle_pages - ioc->usg_pages;
seq_printf(m, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
index c43f1a212a5c..0691884f5095 100644
--- a/drivers/parisc/iommu-helpers.h
+++ b/drivers/parisc/iommu-helpers.h
@@ -14,7 +14,7 @@
static inline unsigned int
iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
unsigned long hint,
- void (*iommu_io_pdir_entry)(__le64 *, space_t, unsigned long,
+ void (*iommu_io_pdir_entry)(__le64 *, space_t, phys_addr_t,
unsigned long))
{
struct scatterlist *dma_sg = startsg; /* pointer to current DMA */
@@ -28,7 +28,7 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
dma_sg--;
while (nents-- > 0) {
- unsigned long vaddr;
+ phys_addr_t paddr;
long size;
DBG_RUN_SG(" %d : %08lx %p/%05x\n", nents,
@@ -67,7 +67,7 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
BUG_ON(pdirp == NULL);
- vaddr = (unsigned long)sg_virt(startsg);
+ paddr = sg_phys(startsg);
sg_dma_len(dma_sg) += startsg->length;
size = startsg->length + dma_offset;
dma_offset = 0;
@@ -76,8 +76,8 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
#endif
do {
iommu_io_pdir_entry(pdirp, KERNEL_SPACE,
- vaddr, hint);
- vaddr += IOVP_SIZE;
+ paddr, hint);
+ paddr += IOVP_SIZE;
size -= IOVP_SIZE;
pdirp++;
} while(unlikely(size > 0));
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index fc3863c09f83..a6eb6bffa5ea 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -532,7 +532,7 @@ typedef unsigned long space_t;
* sba_io_pdir_entry - fill in one IO PDIR entry
* @pdir_ptr: pointer to IO PDIR entry
* @sid: process Space ID - currently only support KERNEL_SPACE
- * @vba: Virtual CPU address of buffer to map
+ * @pba: Physical address of buffer to map
* @hint: DMA hint set to use for this mapping
*
* SBA Mapping Routine
@@ -569,20 +569,17 @@ typedef unsigned long space_t;
*/
static void
-sba_io_pdir_entry(__le64 *pdir_ptr, space_t sid, unsigned long vba,
+sba_io_pdir_entry(__le64 *pdir_ptr, space_t sid, phys_addr_t pba,
unsigned long hint)
{
- u64 pa; /* physical address */
register unsigned ci; /* coherent index */
- pa = lpa(vba);
- pa &= IOVP_MASK;
+ asm("lci 0(%1), %0" : "=r" (ci) : "r" (phys_to_virt(pba)));
+ pba &= IOVP_MASK;
+ pba |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */
- asm("lci 0(%1), %0" : "=r" (ci) : "r" (vba));
- pa |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */
-
- pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
- *pdir_ptr = cpu_to_le64(pa); /* swap and store into I/O Pdir */
+ pba |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
+ *pdir_ptr = cpu_to_le64(pba); /* swap and store into I/O Pdir */
/*
* If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit set
@@ -707,7 +704,7 @@ static int sba_dma_supported( struct device *dev, u64 mask)
* See Documentation/core-api/dma-api-howto.rst
*/
static dma_addr_t
-sba_map_single(struct device *dev, void *addr, size_t size,
+sba_map_single(struct device *dev, phys_addr_t addr, size_t size,
enum dma_data_direction direction)
{
struct ioc *ioc;
@@ -722,7 +719,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
return DMA_MAPPING_ERROR;
/* save offset bits */
- offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
+ offset = offset_in_page(addr);
/* round up to nearest IOVP_SIZE */
size = (size + offset + ~IOVP_MASK) & IOVP_MASK;
@@ -739,13 +736,13 @@ sba_map_single(struct device *dev, void *addr, size_t size,
pide = sba_alloc_range(ioc, dev, size);
iovp = (dma_addr_t) pide << IOVP_SHIFT;
- DBG_RUN("%s() 0x%p -> 0x%lx\n",
- __func__, addr, (long) iovp | offset);
+ DBG_RUN("%s() 0x%pa -> 0x%lx\n",
+ __func__, &addr, (long) iovp | offset);
pdir_start = &(ioc->pdir_base[pide]);
while (size > 0) {
- sba_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long) addr, 0);
+ sba_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, 0);
DBG_RUN(" pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n",
pdir_start,
@@ -778,17 +775,18 @@ sba_map_single(struct device *dev, void *addr, size_t size,
static dma_addr_t
-sba_map_page(struct device *dev, struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction direction,
- unsigned long attrs)
+sba_map_phys(struct device *dev, phys_addr_t phys, size_t size,
+ enum dma_data_direction direction, unsigned long attrs)
{
- return sba_map_single(dev, page_address(page) + offset, size,
- direction);
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
+
+ return sba_map_single(dev, phys, size, direction);
}
/**
- * sba_unmap_page - unmap one IOVA and free resources
+ * sba_unmap_phys - unmap one IOVA and free resources
* @dev: instance of PCI owned by the driver that's asking.
* @iova: IOVA of driver buffer previously mapped.
* @size: number of bytes mapped in driver buffer.
@@ -798,7 +796,7 @@ sba_map_page(struct device *dev, struct page *page, unsigned long offset,
* See Documentation/core-api/dma-api-howto.rst
*/
static void
-sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
+sba_unmap_phys(struct device *dev, dma_addr_t iova, size_t size,
enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
@@ -893,7 +891,7 @@ static void *sba_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle
if (ret) {
memset(ret, 0, size);
- *dma_handle = sba_map_single(hwdev, ret, size, 0);
+ *dma_handle = sba_map_single(hwdev, virt_to_phys(ret), size, 0);
}
return ret;
@@ -914,7 +912,7 @@ static void
sba_free(struct device *hwdev, size_t size, void *vaddr,
dma_addr_t dma_handle, unsigned long attrs)
{
- sba_unmap_page(hwdev, dma_handle, size, 0, 0);
+ sba_unmap_phys(hwdev, dma_handle, size, 0, 0);
free_pages((unsigned long) vaddr, get_order(size));
}
@@ -962,7 +960,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
/* Fast path single entry scatterlists. */
if (nents == 1) {
- sg_dma_address(sglist) = sba_map_single(dev, sg_virt(sglist),
+ sg_dma_address(sglist) = sba_map_single(dev, sg_phys(sglist),
sglist->length, direction);
sg_dma_len(sglist) = sglist->length;
return 1;
@@ -1061,7 +1059,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
while (nents && sg_dma_len(sglist)) {
- sba_unmap_page(dev, sg_dma_address(sglist), sg_dma_len(sglist),
+ sba_unmap_phys(dev, sg_dma_address(sglist), sg_dma_len(sglist),
direction, 0);
#ifdef SBA_COLLECT_STATS
ioc->usg_pages += ((sg_dma_address(sglist) & ~IOVP_MASK) + sg_dma_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT;
@@ -1085,8 +1083,8 @@ static const struct dma_map_ops sba_ops = {
.dma_supported = sba_dma_supported,
.alloc = sba_alloc,
.free = sba_free,
- .map_page = sba_map_page,
- .unmap_page = sba_unmap_page,
+ .map_phys = sba_map_phys,
+ .unmap_phys = sba_unmap_phys,
.map_sg = sba_map_sg,
.unmap_sg = sba_unmap_sg,
.get_sgtable = dma_common_get_sgtable,
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 10/14] powerpc: Convert to physical address DMA mapping
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (8 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 09/14] parisc: Convert DMA map_page to map_phys interface Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 11/14] sparc: Use " Leon Romanovsky
` (5 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux
From: Leon Romanovsky <leonro@nvidia.com>
Adapt PowerPC DMA to use physical addresses in order to prepare code
to removal .map_page and .unmap_page.
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/powerpc/include/asm/iommu.h | 8 ++++----
arch/powerpc/kernel/dma-iommu.c | 22 ++++++++++-----------
arch/powerpc/kernel/iommu.c | 14 +++++++-------
arch/powerpc/platforms/ps3/system-bus.c | 33 ++++++++++++++++++--------------
arch/powerpc/platforms/pseries/ibmebus.c | 15 ++++++++-------
arch/powerpc/platforms/pseries/vio.c | 21 +++++++++++---------
6 files changed, 60 insertions(+), 53 deletions(-)
diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index b410021ad4c6..eafdd63cd6c4 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -274,12 +274,12 @@ extern void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
unsigned long mask, gfp_t flag, int node);
extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
void *vaddr, dma_addr_t dma_handle);
-extern dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
- struct page *page, unsigned long offset,
- size_t size, unsigned long mask,
+extern dma_addr_t iommu_map_phys(struct device *dev, struct iommu_table *tbl,
+ phys_addr_t phys, size_t size,
+ unsigned long mask,
enum dma_data_direction direction,
unsigned long attrs);
-extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
+extern void iommu_unmap_phys(struct iommu_table *tbl, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
unsigned long attrs);
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 0359ab72cd3b..aa3689d61917 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -93,28 +93,26 @@ static void dma_iommu_free_coherent(struct device *dev, size_t size,
/* Creates TCEs for a user provided buffer. The user buffer must be
* contiguous real kernel storage (not vmalloc). The address passed here
- * comprises a page address and offset into that page. The dma_addr_t
- * returned will point to the same byte within the page as was passed in.
+ * is a physical address to that page. The dma_addr_t returned will point
+ * to the same byte within the page as was passed in.
*/
-static dma_addr_t dma_iommu_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
+static dma_addr_t dma_iommu_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size,
enum dma_data_direction direction,
unsigned long attrs)
{
- return iommu_map_page(dev, get_iommu_table_base(dev), page, offset,
- size, dma_get_mask(dev), direction, attrs);
+ return iommu_map_phys(dev, get_iommu_table_base(dev), phys, size,
+ dma_get_mask(dev), direction, attrs);
}
-
-static void dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
+static void dma_iommu_unmap_phys(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
unsigned long attrs)
{
- iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size, direction,
+ iommu_unmap_phys(get_iommu_table_base(dev), dma_handle, size, direction,
attrs);
}
-
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
unsigned long attrs)
@@ -211,8 +209,8 @@ const struct dma_map_ops dma_iommu_ops = {
.map_sg = dma_iommu_map_sg,
.unmap_sg = dma_iommu_unmap_sg,
.dma_supported = dma_iommu_dma_supported,
- .map_page = dma_iommu_map_page,
- .unmap_page = dma_iommu_unmap_page,
+ .map_phys = dma_iommu_map_phys,
+ .unmap_phys = dma_iommu_unmap_phys,
.get_required_mask = dma_iommu_get_required_mask,
.mmap = dma_common_mmap,
.get_sgtable = dma_common_get_sgtable,
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 244eb4857e7f..6b5f4b72ce97 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -848,12 +848,12 @@ EXPORT_SYMBOL_GPL(iommu_tce_table_put);
/* Creates TCEs for a user provided buffer. The user buffer must be
* contiguous real kernel storage (not vmalloc). The address passed here
- * comprises a page address and offset into that page. The dma_addr_t
- * returned will point to the same byte within the page as was passed in.
+ * is physical address into that page. The dma_addr_t returned will point
+ * to the same byte within the page as was passed in.
*/
-dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
- struct page *page, unsigned long offset, size_t size,
- unsigned long mask, enum dma_data_direction direction,
+dma_addr_t iommu_map_phys(struct device *dev, struct iommu_table *tbl,
+ phys_addr_t phys, size_t size, unsigned long mask,
+ enum dma_data_direction direction,
unsigned long attrs)
{
dma_addr_t dma_handle = DMA_MAPPING_ERROR;
@@ -863,7 +863,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
BUG_ON(direction == DMA_NONE);
- vaddr = page_address(page) + offset;
+ vaddr = phys_to_virt(phys);
uaddr = (unsigned long)vaddr;
if (tbl) {
@@ -890,7 +890,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
return dma_handle;
}
-void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
+void iommu_unmap_phys(struct iommu_table *tbl, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
unsigned long attrs)
{
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index afbaabf182d0..f4f3477d3a23 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -551,18 +551,20 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
/* Creates TCEs for a user provided buffer. The user buffer must be
* contiguous real kernel storage (not vmalloc). The address passed here
- * comprises a page address and offset into that page. The dma_addr_t
- * returned will point to the same byte within the page as was passed in.
+ * is physical address to that hat page. The dma_addr_t returned will point
+ * to the same byte within the page as was passed in.
*/
-static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction direction,
- unsigned long attrs)
+static dma_addr_t ps3_sb_map_phys(struct device *_dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction direction, unsigned long attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
dma_addr_t bus_addr;
- void *ptr = page_address(page) + offset;
+ void *ptr = phys_to_virt(phys);
+
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
&bus_addr,
@@ -577,8 +579,8 @@ static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,
return bus_addr;
}
-static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
- unsigned long offset, size_t size,
+static dma_addr_t ps3_ioc0_map_phys(struct device *_dev, phys_addr_t phys,
+ size_t size,
enum dma_data_direction direction,
unsigned long attrs)
{
@@ -586,7 +588,10 @@ static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
int result;
dma_addr_t bus_addr;
u64 iopte_flag;
- void *ptr = page_address(page) + offset;
+ void *ptr = phys_to_virt(phys);
+
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
iopte_flag = CBE_IOPTE_M;
switch (direction) {
@@ -613,7 +618,7 @@ static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
return bus_addr;
}
-static void ps3_unmap_page(struct device *_dev, dma_addr_t dma_addr,
+static void ps3_unmap_phys(struct device *_dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction, unsigned long attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
@@ -690,8 +695,8 @@ static const struct dma_map_ops ps3_sb_dma_ops = {
.map_sg = ps3_sb_map_sg,
.unmap_sg = ps3_sb_unmap_sg,
.dma_supported = ps3_dma_supported,
- .map_page = ps3_sb_map_page,
- .unmap_page = ps3_unmap_page,
+ .map_phys = ps3_sb_map_phys,
+ .unmap_phys = ps3_unmap_phys,
.mmap = dma_common_mmap,
.get_sgtable = dma_common_get_sgtable,
.alloc_pages_op = dma_common_alloc_pages,
@@ -704,8 +709,8 @@ static const struct dma_map_ops ps3_ioc0_dma_ops = {
.map_sg = ps3_ioc0_map_sg,
.unmap_sg = ps3_ioc0_unmap_sg,
.dma_supported = ps3_dma_supported,
- .map_page = ps3_ioc0_map_page,
- .unmap_page = ps3_unmap_page,
+ .map_phys = ps3_ioc0_map_phys,
+ .unmap_phys = ps3_unmap_phys,
.mmap = dma_common_mmap,
.get_sgtable = dma_common_get_sgtable,
.alloc_pages_op = dma_common_alloc_pages,
diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c
index 3436b0af795e..cad2deb7e70d 100644
--- a/arch/powerpc/platforms/pseries/ibmebus.c
+++ b/arch/powerpc/platforms/pseries/ibmebus.c
@@ -86,17 +86,18 @@ static void ibmebus_free_coherent(struct device *dev,
kfree(vaddr);
}
-static dma_addr_t ibmebus_map_page(struct device *dev,
- struct page *page,
- unsigned long offset,
+static dma_addr_t ibmebus_map_phys(struct device *dev, phys_addr_t phys,
size_t size,
enum dma_data_direction direction,
unsigned long attrs)
{
- return (dma_addr_t)(page_address(page) + offset);
+ if (attrs & DMA_ATTR_MMIO)
+ return DMA_MAPPING_ERROR;
+
+ return (dma_addr_t)(phys_to_virt(phys));
}
-static void ibmebus_unmap_page(struct device *dev,
+static void ibmebus_unmap_phys(struct device *dev,
dma_addr_t dma_addr,
size_t size,
enum dma_data_direction direction,
@@ -146,8 +147,8 @@ static const struct dma_map_ops ibmebus_dma_ops = {
.unmap_sg = ibmebus_unmap_sg,
.dma_supported = ibmebus_dma_supported,
.get_required_mask = ibmebus_dma_get_required_mask,
- .map_page = ibmebus_map_page,
- .unmap_page = ibmebus_unmap_page,
+ .map_phys = ibmebus_map_phys,
+ .unmap_phys = ibmebus_unmap_phys,
};
static int ibmebus_match_path(struct device *dev, const void *data)
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index ac1d2d2c9a88..18cffac5468f 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -512,18 +512,21 @@ static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
}
-static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction,
- unsigned long attrs)
+static dma_addr_t vio_dma_iommu_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size,
+ enum dma_data_direction direction,
+ unsigned long attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
struct iommu_table *tbl = get_iommu_table_base(dev);
dma_addr_t ret = DMA_MAPPING_ERROR;
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return ret;
+
if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl))))
goto out_fail;
- ret = iommu_map_page(dev, tbl, page, offset, size, dma_get_mask(dev),
+ ret = iommu_map_phys(dev, tbl, phys, size, dma_get_mask(dev),
direction, attrs);
if (unlikely(ret == DMA_MAPPING_ERROR))
goto out_deallocate;
@@ -536,7 +539,7 @@ static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
return DMA_MAPPING_ERROR;
}
-static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
+static void vio_dma_iommu_unmap_phys(struct device *dev, dma_addr_t dma_handle,
size_t size,
enum dma_data_direction direction,
unsigned long attrs)
@@ -544,7 +547,7 @@ static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
struct vio_dev *viodev = to_vio_dev(dev);
struct iommu_table *tbl = get_iommu_table_base(dev);
- iommu_unmap_page(tbl, dma_handle, size, direction, attrs);
+ iommu_unmap_phys(tbl, dma_handle, size, direction, attrs);
vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
}
@@ -605,8 +608,8 @@ static const struct dma_map_ops vio_dma_mapping_ops = {
.free = vio_dma_iommu_free_coherent,
.map_sg = vio_dma_iommu_map_sg,
.unmap_sg = vio_dma_iommu_unmap_sg,
- .map_page = vio_dma_iommu_map_page,
- .unmap_page = vio_dma_iommu_unmap_page,
+ .map_phys = vio_dma_iommu_map_phys,
+ .unmap_phys = vio_dma_iommu_unmap_phys,
.dma_supported = dma_iommu_dma_supported,
.get_required_mask = dma_iommu_get_required_mask,
.mmap = dma_common_mmap,
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 11/14] sparc: Use physical address DMA mapping
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (9 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 10/14] powerpc: Convert to physical address DMA mapping Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 12/14] x86: Use physical address for " Leon Romanovsky
` (4 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux
From: Leon Romanovsky <leonro@nvidia.com>
Convert sparc architecture DMA code to use .map_phys callback.
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/sparc/kernel/iommu.c | 30 +++++++++++++++++-----------
arch/sparc/kernel/pci_sun4v.c | 31 ++++++++++++++++++-----------
arch/sparc/mm/io-unit.c | 38 ++++++++++++++++++-----------------
arch/sparc/mm/iommu.c | 46 ++++++++++++++++++++++---------------------
4 files changed, 82 insertions(+), 63 deletions(-)
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index da0363692528..46ef88bc9c26 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -260,26 +260,35 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,
free_pages((unsigned long)cpu, order);
}
-static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t sz,
- enum dma_data_direction direction,
+static dma_addr_t dma_4u_map_phys(struct device *dev, phys_addr_t phys,
+ size_t sz, enum dma_data_direction direction,
unsigned long attrs)
{
struct iommu *iommu;
struct strbuf *strbuf;
iopte_t *base;
unsigned long flags, npages, oaddr;
- unsigned long i, base_paddr, ctx;
+ unsigned long i, ctx;
u32 bus_addr, ret;
unsigned long iopte_protection;
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ /*
+ * This check is included because older versions of the code
+ * lacked MMIO path support, and my ability to test this path
+ * is limited. However, from a software technical standpoint,
+ * there is no restriction, as the following code operates
+ * solely on physical addresses.
+ */
+ goto bad_no_ctx;
+
iommu = dev->archdata.iommu;
strbuf = dev->archdata.stc;
if (unlikely(direction == DMA_NONE))
goto bad_no_ctx;
- oaddr = (unsigned long)(page_address(page) + offset);
+ oaddr = (unsigned long)(phys_to_virt(phys));
npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
@@ -296,7 +305,6 @@ static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,
bus_addr = (iommu->tbl.table_map_base +
((base - iommu->page_table) << IO_PAGE_SHIFT));
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
- base_paddr = __pa(oaddr & IO_PAGE_MASK);
if (strbuf->strbuf_enabled)
iopte_protection = IOPTE_STREAMING(ctx);
else
@@ -304,8 +312,8 @@ static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,
if (direction != DMA_TO_DEVICE)
iopte_protection |= IOPTE_WRITE;
- for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE)
- iopte_val(*base) = iopte_protection | base_paddr;
+ for (i = 0; i < npages; i++, base++, phys += IO_PAGE_SIZE)
+ iopte_val(*base) = iopte_protection | phys;
return ret;
@@ -383,7 +391,7 @@ static void strbuf_flush(struct strbuf *strbuf, struct iommu *iommu,
vaddr, ctx, npages);
}
-static void dma_4u_unmap_page(struct device *dev, dma_addr_t bus_addr,
+static void dma_4u_unmap_phys(struct device *dev, dma_addr_t bus_addr,
size_t sz, enum dma_data_direction direction,
unsigned long attrs)
{
@@ -753,8 +761,8 @@ static int dma_4u_supported(struct device *dev, u64 device_mask)
static const struct dma_map_ops sun4u_dma_ops = {
.alloc = dma_4u_alloc_coherent,
.free = dma_4u_free_coherent,
- .map_page = dma_4u_map_page,
- .unmap_page = dma_4u_unmap_page,
+ .map_phys = dma_4u_map_phys,
+ .unmap_phys = dma_4u_unmap_phys,
.map_sg = dma_4u_map_sg,
.unmap_sg = dma_4u_unmap_sg,
.sync_single_for_cpu = dma_4u_sync_single_for_cpu,
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index b720b21ccfbd..791f0a76665f 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -352,9 +352,8 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
free_pages((unsigned long)cpu, order);
}
-static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t sz,
- enum dma_data_direction direction,
+static dma_addr_t dma_4v_map_phys(struct device *dev, phys_addr_t phys,
+ size_t sz, enum dma_data_direction direction,
unsigned long attrs)
{
struct iommu *iommu;
@@ -362,18 +361,27 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
struct iommu_map_table *tbl;
u64 mask;
unsigned long flags, npages, oaddr;
- unsigned long i, base_paddr;
- unsigned long prot;
+ unsigned long i, prot;
dma_addr_t bus_addr, ret;
long entry;
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ /*
+ * This check is included because older versions of the code
+ * lacked MMIO path support, and my ability to test this path
+ * is limited. However, from a software technical standpoint,
+ * there is no restriction, as the following code operates
+ * solely on physical addresses.
+ */
+ goto bad;
+
iommu = dev->archdata.iommu;
atu = iommu->atu;
if (unlikely(direction == DMA_NONE))
goto bad;
- oaddr = (unsigned long)(page_address(page) + offset);
+ oaddr = (unsigned long)(phys_to_virt(phys));
npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
@@ -391,7 +399,6 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
bus_addr = (tbl->table_map_base + (entry << IO_PAGE_SHIFT));
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
- base_paddr = __pa(oaddr & IO_PAGE_MASK);
prot = HV_PCI_MAP_ATTR_READ;
if (direction != DMA_TO_DEVICE)
prot |= HV_PCI_MAP_ATTR_WRITE;
@@ -403,8 +410,8 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
iommu_batch_start(dev, prot, entry);
- for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE) {
- long err = iommu_batch_add(base_paddr, mask);
+ for (i = 0; i < npages; i++, phys += IO_PAGE_SIZE) {
+ long err = iommu_batch_add(phys, mask);
if (unlikely(err < 0L))
goto iommu_map_fail;
}
@@ -426,7 +433,7 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
return DMA_MAPPING_ERROR;
}
-static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
+static void dma_4v_unmap_phys(struct device *dev, dma_addr_t bus_addr,
size_t sz, enum dma_data_direction direction,
unsigned long attrs)
{
@@ -686,8 +693,8 @@ static int dma_4v_supported(struct device *dev, u64 device_mask)
static const struct dma_map_ops sun4v_dma_ops = {
.alloc = dma_4v_alloc_coherent,
.free = dma_4v_free_coherent,
- .map_page = dma_4v_map_page,
- .unmap_page = dma_4v_unmap_page,
+ .map_phys = dma_4v_map_phys,
+ .unmap_phys = dma_4v_unmap_phys,
.map_sg = dma_4v_map_sg,
.unmap_sg = dma_4v_unmap_sg,
.dma_supported = dma_4v_supported,
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index d8376f61b4d0..d409cb450de4 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -94,13 +94,14 @@ static int __init iounit_init(void)
subsys_initcall(iounit_init);
/* One has to hold iounit->lock to call this */
-static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned long vaddr, int size)
+static dma_addr_t iounit_get_area(struct iounit_struct *iounit,
+ phys_addr_t phys, int size)
{
int i, j, k, npages;
unsigned long rotor, scan, limit;
iopte_t iopte;
- npages = ((vaddr & ~PAGE_MASK) + size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
+ npages = (offset_in_page(phys) + size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
/* A tiny bit of magic ingredience :) */
switch (npages) {
@@ -109,7 +110,7 @@ static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned long
default: i = 0x0213; break;
}
- IOD(("iounit_get_area(%08lx,%d[%d])=", vaddr, size, npages));
+ IOD(("%s(%pa,%d[%d])=", __func__, &phys, size, npages));
next: j = (i & 15);
rotor = iounit->rotor[j - 1];
@@ -124,7 +125,8 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
}
i >>= 4;
if (!(i & 15))
- panic("iounit_get_area: Couldn't find free iopte slots for (%08lx,%d)\n", vaddr, size);
+ panic("iounit_get_area: Couldn't find free iopte slots for (%pa,%d)\n",
+ &phys, size);
goto next;
}
for (k = 1, scan++; k < npages; k++)
@@ -132,30 +134,29 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
goto nexti;
iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
scan -= npages;
- iopte = MKIOPTE(__pa(vaddr & PAGE_MASK));
- vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK);
+ iopte = MKIOPTE(phys & PAGE_MASK);
+ phys = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + offset_in_page(phys);
for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) {
set_bit(scan, iounit->bmap);
sbus_writel(iopte_val(iopte), &iounit->page_table[scan]);
}
- IOD(("%08lx\n", vaddr));
- return vaddr;
+ IOD(("%pa\n", &phys));
+ return phys;
}
-static dma_addr_t iounit_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t len, enum dma_data_direction dir,
- unsigned long attrs)
+static dma_addr_t iounit_map_phys(struct device *dev, phys_addr_t phys,
+ size_t len, enum dma_data_direction dir, unsigned long attrs)
{
- void *vaddr = page_address(page) + offset;
struct iounit_struct *iounit = dev->archdata.iommu;
- unsigned long ret, flags;
+ unsigned long flags;
+ dma_addr_t ret;
/* XXX So what is maxphys for us and how do drivers know it? */
if (!len || len > 256 * 1024)
return DMA_MAPPING_ERROR;
spin_lock_irqsave(&iounit->lock, flags);
- ret = iounit_get_area(iounit, (unsigned long)vaddr, len);
+ ret = iounit_get_area(iounit, phys, len);
spin_unlock_irqrestore(&iounit->lock, flags);
return ret;
}
@@ -171,14 +172,15 @@ static int iounit_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
/* FIXME: Cache some resolved pages - often several sg entries are to the same page */
spin_lock_irqsave(&iounit->lock, flags);
for_each_sg(sgl, sg, nents, i) {
- sg->dma_address = iounit_get_area(iounit, (unsigned long) sg_virt(sg), sg->length);
+ sg->dma_address =
+ iounit_get_area(iounit, sg_phys(sg), sg->length);
sg->dma_length = sg->length;
}
spin_unlock_irqrestore(&iounit->lock, flags);
return nents;
}
-static void iounit_unmap_page(struct device *dev, dma_addr_t vaddr, size_t len,
+static void iounit_unmap_phys(struct device *dev, dma_addr_t vaddr, size_t len,
enum dma_data_direction dir, unsigned long attrs)
{
struct iounit_struct *iounit = dev->archdata.iommu;
@@ -279,8 +281,8 @@ static const struct dma_map_ops iounit_dma_ops = {
.alloc = iounit_alloc,
.free = iounit_free,
#endif
- .map_page = iounit_map_page,
- .unmap_page = iounit_unmap_page,
+ .map_phys = iounit_map_phys,
+ .unmap_phys = iounit_unmap_phys,
.map_sg = iounit_map_sg,
.unmap_sg = iounit_unmap_sg,
};
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 5a5080db800f..f48adf62724a 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -181,18 +181,20 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
}
}
-static dma_addr_t __sbus_iommu_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t len, bool per_page_flush)
+static dma_addr_t __sbus_iommu_map_phys(struct device *dev, phys_addr_t paddr,
+ size_t len, bool per_page_flush, unsigned long attrs)
{
struct iommu_struct *iommu = dev->archdata.iommu;
- phys_addr_t paddr = page_to_phys(page) + offset;
- unsigned long off = paddr & ~PAGE_MASK;
+ unsigned long off = offset_in_page(paddr);
unsigned long npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long pfn = __phys_to_pfn(paddr);
unsigned int busa, busa0;
iopte_t *iopte, *iopte0;
int ioptex, i;
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
+
/* XXX So what is maxphys for us and how do drivers know it? */
if (!len || len > 256 * 1024)
return DMA_MAPPING_ERROR;
@@ -202,10 +204,10 @@ static dma_addr_t __sbus_iommu_map_page(struct device *dev, struct page *page,
* XXX Is this a good assumption?
* XXX What if someone else unmaps it here and races us?
*/
- if (per_page_flush && !PageHighMem(page)) {
+ if (per_page_flush && !PhysHighMem(paddr)) {
unsigned long vaddr, p;
- vaddr = (unsigned long)page_address(page) + offset;
+ vaddr = (unsigned long)phys_to_virt(paddr);
for (p = vaddr & PAGE_MASK; p < vaddr + len; p += PAGE_SIZE)
flush_page_for_dma(p);
}
@@ -231,19 +233,19 @@ static dma_addr_t __sbus_iommu_map_page(struct device *dev, struct page *page,
return busa0 + off;
}
-static dma_addr_t sbus_iommu_map_page_gflush(struct device *dev,
- struct page *page, unsigned long offset, size_t len,
- enum dma_data_direction dir, unsigned long attrs)
+static dma_addr_t sbus_iommu_map_phys_gflush(struct device *dev,
+ phys_addr_t phys, size_t len, enum dma_data_direction dir,
+ unsigned long attrs)
{
flush_page_for_dma(0);
- return __sbus_iommu_map_page(dev, page, offset, len, false);
+ return __sbus_iommu_map_phys(dev, phys, len, false, attrs);
}
-static dma_addr_t sbus_iommu_map_page_pflush(struct device *dev,
- struct page *page, unsigned long offset, size_t len,
- enum dma_data_direction dir, unsigned long attrs)
+static dma_addr_t sbus_iommu_map_phys_pflush(struct device *dev,
+ phys_addr_t phys, size_t len, enum dma_data_direction dir,
+ unsigned long attrs)
{
- return __sbus_iommu_map_page(dev, page, offset, len, true);
+ return __sbus_iommu_map_phys(dev, phys, len, true, attrs);
}
static int __sbus_iommu_map_sg(struct device *dev, struct scatterlist *sgl,
@@ -254,8 +256,8 @@ static int __sbus_iommu_map_sg(struct device *dev, struct scatterlist *sgl,
int j;
for_each_sg(sgl, sg, nents, j) {
- sg->dma_address =__sbus_iommu_map_page(dev, sg_page(sg),
- sg->offset, sg->length, per_page_flush);
+ sg->dma_address = __sbus_iommu_map_phys(dev, sg_phys(sg),
+ sg->length, per_page_flush, attrs);
if (sg->dma_address == DMA_MAPPING_ERROR)
return -EIO;
sg->dma_length = sg->length;
@@ -277,7 +279,7 @@ static int sbus_iommu_map_sg_pflush(struct device *dev, struct scatterlist *sgl,
return __sbus_iommu_map_sg(dev, sgl, nents, dir, attrs, true);
}
-static void sbus_iommu_unmap_page(struct device *dev, dma_addr_t dma_addr,
+static void sbus_iommu_unmap_phys(struct device *dev, dma_addr_t dma_addr,
size_t len, enum dma_data_direction dir, unsigned long attrs)
{
struct iommu_struct *iommu = dev->archdata.iommu;
@@ -303,7 +305,7 @@ static void sbus_iommu_unmap_sg(struct device *dev, struct scatterlist *sgl,
int i;
for_each_sg(sgl, sg, nents, i) {
- sbus_iommu_unmap_page(dev, sg->dma_address, sg->length, dir,
+ sbus_iommu_unmap_phys(dev, sg->dma_address, sg->length, dir,
attrs);
sg->dma_address = 0x21212121;
}
@@ -426,8 +428,8 @@ static const struct dma_map_ops sbus_iommu_dma_gflush_ops = {
.alloc = sbus_iommu_alloc,
.free = sbus_iommu_free,
#endif
- .map_page = sbus_iommu_map_page_gflush,
- .unmap_page = sbus_iommu_unmap_page,
+ .map_phys = sbus_iommu_map_phys_gflush,
+ .unmap_phys = sbus_iommu_unmap_phys,
.map_sg = sbus_iommu_map_sg_gflush,
.unmap_sg = sbus_iommu_unmap_sg,
};
@@ -437,8 +439,8 @@ static const struct dma_map_ops sbus_iommu_dma_pflush_ops = {
.alloc = sbus_iommu_alloc,
.free = sbus_iommu_free,
#endif
- .map_page = sbus_iommu_map_page_pflush,
- .unmap_page = sbus_iommu_unmap_page,
+ .map_phys = sbus_iommu_map_phys_pflush,
+ .unmap_phys = sbus_iommu_unmap_phys,
.map_sg = sbus_iommu_map_sg_pflush,
.unmap_sg = sbus_iommu_unmap_sg,
};
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 12/14] x86: Use physical address for DMA mapping
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (10 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 11/14] sparc: Use " Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:12 ` [PATCH v5 13/14] xen: swiotlb: Convert mapping routine to rely on physical address Leon Romanovsky
` (3 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Perform mechanical conversion from DMA .map_page to .map_phys.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/x86/kernel/amd_gart_64.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 3485d419c2f5..93a06307d953 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -222,13 +222,14 @@ 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,
+static dma_addr_t gart_map_phys(struct device *dev, phys_addr_t paddr,
+ size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
unsigned long bus;
- phys_addr_t paddr = page_to_phys(page) + offset;
+
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
if (!need_iommu(dev, paddr, size))
return paddr;
@@ -242,7 +243,7 @@ static dma_addr_t gart_map_page(struct device *dev, struct page *page,
/*
* Free a DMA mapping.
*/
-static void gart_unmap_page(struct device *dev, dma_addr_t dma_addr,
+static void gart_unmap_phys(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
@@ -282,7 +283,7 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
for_each_sg(sg, s, nents, i) {
if (!s->dma_length || !s->length)
break;
- gart_unmap_page(dev, s->dma_address, s->dma_length, dir, 0);
+ gart_unmap_phys(dev, s->dma_address, s->dma_length, dir, 0);
}
}
@@ -487,7 +488,7 @@ static void
gart_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_addr, unsigned long attrs)
{
- gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0);
+ gart_unmap_phys(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0);
dma_direct_free(dev, size, vaddr, dma_addr, attrs);
}
@@ -668,8 +669,8 @@ static __init int init_amd_gatt(struct agp_kern_info *info)
static const struct dma_map_ops gart_dma_ops = {
.map_sg = gart_map_sg,
.unmap_sg = gart_unmap_sg,
- .map_page = gart_map_page,
- .unmap_page = gart_unmap_page,
+ .map_phys = gart_map_phys,
+ .unmap_phys = gart_unmap_phys,
.alloc = gart_alloc_coherent,
.free = gart_free_coherent,
.mmap = dma_common_mmap,
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 13/14] xen: swiotlb: Convert mapping routine to rely on physical address
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (11 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 12/14] x86: Use physical address for " Leon Romanovsky
@ 2025-10-15 9:12 ` Leon Romanovsky
2025-10-15 9:13 ` [PATCH v5 14/14] dma-mapping: remove unused map_page callback Leon Romanovsky
` (2 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:12 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
Switch to .map_phys callback instead of .map_page.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
drivers/xen/grant-dma-ops.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c
index 29257d2639db..14077d23f2a1 100644
--- a/drivers/xen/grant-dma-ops.c
+++ b/drivers/xen/grant-dma-ops.c
@@ -163,18 +163,22 @@ static void xen_grant_dma_free_pages(struct device *dev, size_t size,
xen_grant_dma_free(dev, size, page_to_virt(vaddr), dma_handle, 0);
}
-static dma_addr_t xen_grant_dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
+static dma_addr_t xen_grant_dma_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
struct xen_grant_dma_data *data;
+ unsigned long offset = offset_in_page(phys);
unsigned long dma_offset = xen_offset_in_page(offset),
pfn_offset = XEN_PFN_DOWN(offset);
unsigned int i, n_pages = XEN_PFN_UP(dma_offset + size);
grant_ref_t grant;
dma_addr_t dma_handle;
+ if (unlikely(attrs & DMA_ATTR_MMIO))
+ return DMA_MAPPING_ERROR;
+
if (WARN_ON(dir == DMA_NONE))
return DMA_MAPPING_ERROR;
@@ -190,7 +194,7 @@ static dma_addr_t xen_grant_dma_map_page(struct device *dev, struct page *page,
for (i = 0; i < n_pages; i++) {
gnttab_grant_foreign_access_ref(grant + i, data->backend_domid,
- pfn_to_gfn(page_to_xen_pfn(page) + i + pfn_offset),
+ pfn_to_gfn(page_to_xen_pfn(phys_to_page(phys)) + i + pfn_offset),
dir == DMA_TO_DEVICE);
}
@@ -199,7 +203,7 @@ static dma_addr_t xen_grant_dma_map_page(struct device *dev, struct page *page,
return dma_handle;
}
-static void xen_grant_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
+static void xen_grant_dma_unmap_phys(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
@@ -242,7 +246,7 @@ static void xen_grant_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
return;
for_each_sg(sg, s, nents, i)
- xen_grant_dma_unmap_page(dev, s->dma_address, sg_dma_len(s), dir,
+ xen_grant_dma_unmap_phys(dev, s->dma_address, sg_dma_len(s), dir,
attrs);
}
@@ -257,7 +261,7 @@ static int xen_grant_dma_map_sg(struct device *dev, struct scatterlist *sg,
return -EINVAL;
for_each_sg(sg, s, nents, i) {
- s->dma_address = xen_grant_dma_map_page(dev, sg_page(s), s->offset,
+ s->dma_address = xen_grant_dma_map_phys(dev, sg_phys(s),
s->length, dir, attrs);
if (s->dma_address == DMA_MAPPING_ERROR)
goto out;
@@ -286,8 +290,8 @@ static const struct dma_map_ops xen_grant_dma_ops = {
.free_pages = xen_grant_dma_free_pages,
.mmap = dma_common_mmap,
.get_sgtable = dma_common_get_sgtable,
- .map_page = xen_grant_dma_map_page,
- .unmap_page = xen_grant_dma_unmap_page,
+ .map_phys = xen_grant_dma_map_phys,
+ .unmap_phys = xen_grant_dma_unmap_phys,
.map_sg = xen_grant_dma_map_sg,
.unmap_sg = xen_grant_dma_unmap_sg,
.dma_supported = xen_grant_dma_supported,
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v5 14/14] dma-mapping: remove unused map_page callback
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (12 preceding siblings ...)
2025-10-15 9:12 ` [PATCH v5 13/14] xen: swiotlb: Convert mapping routine to rely on physical address Leon Romanovsky
@ 2025-10-15 9:13 ` Leon Romanovsky
2025-10-20 16:27 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Marek Szyprowski
2025-10-29 10:00 ` Marek Szyprowski
15 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-15 9:13 UTC (permalink / raw)
To: Marek Szyprowski, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Jason Gunthorpe, Jason Gunthorpe
From: Leon Romanovsky <leonro@nvidia.com>
After conversion of arch code to use physical address mapping,
there are no users of .map_page() and .unmap_page() callbacks,
so let's remove them.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
include/linux/dma-map-ops.h | 7 -------
kernel/dma/mapping.c | 12 ------------
kernel/dma/ops_helpers.c | 8 +-------
3 files changed, 1 insertion(+), 26 deletions(-)
diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 2e98ecc313a3..4809204c674c 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -31,13 +31,6 @@ struct dma_map_ops {
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs);
- 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);
- void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction dir,
- unsigned long attrs);
-
dma_addr_t (*map_phys)(struct device *dev, phys_addr_t phys,
size_t size, enum dma_data_direction dir,
unsigned long attrs);
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 32a85bfdf873..37163eb49f9f 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -171,16 +171,6 @@ dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
addr = iommu_dma_map_phys(dev, phys, size, dir, attrs);
else if (ops->map_phys)
addr = ops->map_phys(dev, phys, size, dir, attrs);
- else if (!is_mmio && ops->map_page) {
- struct page *page = phys_to_page(phys);
- size_t offset = offset_in_page(phys);
-
- /*
- * The dma_ops API contract for ops->map_page() requires
- * kmappable memory.
- */
- addr = ops->map_page(dev, page, offset, size, dir, attrs);
- }
if (!is_mmio)
kmsan_handle_dma(phys, size, dir);
@@ -222,8 +212,6 @@ void dma_unmap_phys(struct device *dev, dma_addr_t addr, size_t size,
iommu_dma_unmap_phys(dev, addr, size, dir, attrs);
else if (ops->unmap_phys)
ops->unmap_phys(dev, addr, size, dir, attrs);
- else
- ops->unmap_page(dev, addr, size, dir, attrs);
trace_dma_unmap_phys(dev, addr, size, dir, attrs);
debug_dma_unmap_phys(dev, addr, size, dir);
}
diff --git a/kernel/dma/ops_helpers.c b/kernel/dma/ops_helpers.c
index 1eccbdbc99c1..20caf9cabf69 100644
--- a/kernel/dma/ops_helpers.c
+++ b/kernel/dma/ops_helpers.c
@@ -76,11 +76,8 @@ struct page *dma_common_alloc_pages(struct device *dev, size_t size,
if (use_dma_iommu(dev))
*dma_handle = iommu_dma_map_phys(dev, phys, size, dir,
DMA_ATTR_SKIP_CPU_SYNC);
- else if (ops->map_phys)
- *dma_handle = ops->map_phys(dev, phys, size, dir,
- DMA_ATTR_SKIP_CPU_SYNC);
else
- *dma_handle = ops->map_page(dev, page, 0, size, dir,
+ *dma_handle = ops->map_phys(dev, phys, size, dir,
DMA_ATTR_SKIP_CPU_SYNC);
if (*dma_handle == DMA_MAPPING_ERROR) {
dma_free_contiguous(dev, page, size);
@@ -102,8 +99,5 @@ void dma_common_free_pages(struct device *dev, size_t size, struct page *page,
else if (ops->unmap_phys)
ops->unmap_phys(dev, dma_handle, size, dir,
DMA_ATTR_SKIP_CPU_SYNC);
- else if (ops->unmap_page)
- ops->unmap_page(dev, dma_handle, size, dir,
- DMA_ATTR_SKIP_CPU_SYNC);
dma_free_contiguous(dev, page, size);
}
--
2.51.0
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (13 preceding siblings ...)
2025-10-15 9:13 ` [PATCH v5 14/14] dma-mapping: remove unused map_page callback Leon Romanovsky
@ 2025-10-20 16:27 ` Marek Szyprowski
2025-10-26 7:38 ` Leon Romanovsky
2025-10-29 10:00 ` Marek Szyprowski
15 siblings, 1 reply; 18+ messages in thread
From: Marek Szyprowski @ 2025-10-20 16:27 UTC (permalink / raw)
To: Leon Romanovsky, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Magnus Lindholm, Jason Gunthorpe
Dear All,
On 15.10.2025 11:12, Leon Romanovsky wrote:
> This series is a combination of previous two steps [1, 2] to reduce
> number of accesses to struct page in the code "below" DMA layer.
>
> In this series, the DMA .map_page/.map_resource/.unmap_page/.unmap_resource
> callbacks are converted to newly introduced .map_phys/.unmap_phys interfaces.
I would like to have some acks from respective arch maintainers before
applying this patchset.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks
2025-10-20 16:27 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Marek Szyprowski
@ 2025-10-26 7:38 ` Leon Romanovsky
0 siblings, 0 replies; 18+ messages in thread
From: Leon Romanovsky @ 2025-10-26 7:38 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Robin Murphy, Russell King, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, Richard Henderson, Matt Turner,
Thomas Bogendoerfer, James E.J. Bottomley, Helge Deller,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy, Geoff Levand, David S. Miller, Andreas Larsson,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, iommu, linux-kernel, linux-arm-kernel, xen-devel,
linux-alpha, linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Magnus Lindholm, Jason Gunthorpe
On Mon, Oct 20, 2025 at 06:27:32PM +0200, Marek Szyprowski wrote:
> Dear All,
>
> On 15.10.2025 11:12, Leon Romanovsky wrote:
> > This series is a combination of previous two steps [1, 2] to reduce
> > number of accesses to struct page in the code "below" DMA layer.
> >
> > In this series, the DMA .map_page/.map_resource/.unmap_page/.unmap_resource
> > callbacks are converted to newly introduced .map_phys/.unmap_phys interfaces.
>
> I would like to have some acks from respective arch maintainers before
> applying this patchset.
If to judge by git log and lore for some of these arch (didn't check all),
you won't get any response and will need to make a call by yourself.
Thanks
>
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks
2025-10-15 9:12 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Leon Romanovsky
` (14 preceding siblings ...)
2025-10-20 16:27 ` [PATCH v5 00/14] Remove DMA map_page/map_resource and their unmap callbacks Marek Szyprowski
@ 2025-10-29 10:00 ` Marek Szyprowski
15 siblings, 0 replies; 18+ messages in thread
From: Marek Szyprowski @ 2025-10-29 10:00 UTC (permalink / raw)
To: Leon Romanovsky, Robin Murphy, Russell King, Juergen Gross,
Stefano Stabellini, Oleksandr Tyshchenko, Richard Henderson,
Matt Turner, Thomas Bogendoerfer, James E.J. Bottomley,
Helge Deller, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy, Geoff Levand, David S. Miller,
Andreas Larsson, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin
Cc: iommu, linux-kernel, linux-arm-kernel, xen-devel, linux-alpha,
linux-mips, linux-parisc, linuxppc-dev, sparclinux,
Magnus Lindholm, Jason Gunthorpe
On 15.10.2025 11:12, Leon Romanovsky wrote:
> This series is a combination of previous two steps [1, 2] to reduce
> number of accesses to struct page in the code "below" DMA layer.
>
> In this series, the DMA .map_page/.map_resource/.unmap_page/.unmap_resource
> callbacks are converted to newly introduced .map_phys/.unmap_phys interfaces.
>
> Thanks
>
> [1] https://lore.kernel.org/all/cover.1758203802.git.leon@kernel.org
> [2] https://lore.kernel.org/all/cover.1759071169.git.leon@kernel.org
Applied to dma-mapping-for-next branch.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 18+ messages in thread