* [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-22 21:04 ` Magnus Lindholm
2025-09-18 18:45 ` [PATCH 2/9] MIPS/jazzdma: Provide physical address directly Leon Romanovsky
` (7 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
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.
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
arch/alpha/kernel/pci_iommu.c | 47 +++++++++++++++--------------------
1 file changed, 20 insertions(+), 27 deletions(-)
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index dc91de50f906d..b62d9937d1d3a 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -224,28 +224,25 @@ 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;
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 +252,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 +287,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_in_page(paddr);
- 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 +319,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 (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 +339,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 +349,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 +423,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 +637,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 +910,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] 20+ messages in thread* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-18 18:45 ` [PATCH 1/9] alpha: Convert mapping routine to rely on physical address Leon Romanovsky
@ 2025-09-22 21:04 ` Magnus Lindholm
2025-09-23 17:18 ` Leon Romanovsky
0 siblings, 1 reply; 20+ messages in thread
From: Magnus Lindholm @ 2025-09-22 21:04 UTC (permalink / raw)
To: Leon Romanovsky
Cc: Marek Szyprowski, Leon Romanovsky, Jason Gunthorpe,
Andreas Larsson, Borislav Petkov, Dave Hansen, David S. Miller,
Geoff Levand, Helge Deller, Ingo Molnar, iommu,
James E.J. Bottomley, Jason Wang, Juergen Gross, linux-alpha,
linux-kernel, linux-mips, linux-parisc, linuxppc-dev,
Madhavan Srinivasan, Matt Turner, Michael Ellerman,
Michael S. Tsirkin, Richard Henderson, sparclinux,
Stefano Stabellini, Thomas Bogendoerfer, Thomas Gleixner,
virtualization, x86, xen-devel
On Thu, Sep 18, 2025 at 8:45 PM Leon Romanovsky <leon@kernel.org> wrote:
>
> 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.
Hi,
SInce this patch affects the Alpha platform I got curious and decided to
try it out. The patch series requires some preparatory patches. Leon
provided me with links to his dmabuf-vfio branch, which had the
patches (and some prerequisite stuff) applied already.
Based on the dmabuf-vfio branch, I've built a kernel and tested it on
my ES40 Alphaserver, the kernel booted fine but after a while of
moderate filesystem load I started seeing some ext3/4 related error
messages in the system logs. Rebooting with my old kernel into
single user mode, I was able to recover the filesystem using fsck.
Clearly this set of patches breaks things (at least on Alpha).
I haven't yet dug any deeper into the root causes of the file system
corruptions and I've only tested this on Alpha, maybe there has been
more testing done on other platforms targeted by this set
of patches?
Regards
Magnus Lindholm
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-22 21:04 ` Magnus Lindholm
@ 2025-09-23 17:18 ` Leon Romanovsky
2025-09-23 19:34 ` Magnus Lindholm
0 siblings, 1 reply; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-23 17:18 UTC (permalink / raw)
To: Magnus Lindholm
Cc: Marek Szyprowski, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
On Mon, Sep 22, 2025 at 11:04:06PM +0200, Magnus Lindholm wrote:
> On Thu, Sep 18, 2025 at 8:45 PM Leon Romanovsky <leon@kernel.org> wrote:
> >
> > 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.
>
>
> Hi,
>
> SInce this patch affects the Alpha platform I got curious and decided to
> try it out. The patch series requires some preparatory patches. Leon
> provided me with links to his dmabuf-vfio branch, which had the
> patches (and some prerequisite stuff) applied already.
>
> Based on the dmabuf-vfio branch, I've built a kernel and tested it on
> my ES40 Alphaserver, the kernel booted fine but after a while of
> moderate filesystem load I started seeing some ext3/4 related error
> messages in the system logs. Rebooting with my old kernel into
> single user mode, I was able to recover the filesystem using fsck.
> Clearly this set of patches breaks things (at least on Alpha).
I will try to setup Alpha architecture in QEMU in following days, but
would like to ask first. Did you test alpha on clean v6.17-rc5 (without
my patches) as a reference?
Thanks
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-23 17:18 ` Leon Romanovsky
@ 2025-09-23 19:34 ` Magnus Lindholm
2025-09-23 23:53 ` Jason Gunthorpe
0 siblings, 1 reply; 20+ messages in thread
From: Magnus Lindholm @ 2025-09-23 19:34 UTC (permalink / raw)
To: Leon Romanovsky
Cc: Marek Szyprowski, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
>
> I will try to setup Alpha architecture in QEMU in following days, but
> would like to ask first. Did you test alpha on clean v6.17-rc5 (without
> my patches) as a reference?
>
I'm running now on a fresh git pull from today so it's more like a
6.17-rc7. So no problems running the latest git at least. I can
dig deeper into this to see if we can figure this one out. First
of all, is this alpha specific?
Regards
Magnus
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-23 19:34 ` Magnus Lindholm
@ 2025-09-23 23:53 ` Jason Gunthorpe
2025-09-24 7:32 ` Magnus Lindholm
0 siblings, 1 reply; 20+ messages in thread
From: Jason Gunthorpe @ 2025-09-23 23:53 UTC (permalink / raw)
To: Magnus Lindholm
Cc: Leon Romanovsky, Marek Szyprowski, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
On Tue, Sep 23, 2025 at 09:34:31PM +0200, Magnus Lindholm wrote:
> >
> > I will try to setup Alpha architecture in QEMU in following days, but
> > would like to ask first. Did you test alpha on clean v6.17-rc5 (without
> > my patches) as a reference?
> >
> I'm running now on a fresh git pull from today so it's more like a
> 6.17-rc7. So no problems running the latest git at least. I can
> dig deeper into this to see if we can figure this one out. First
> of all, is this alpha specific?
I spent a bit of time looking at the alpha patch and could not spot a
typo, it looked OK to me. I was worried for a bit that virt_to_phys()
vs __pa() were different, but I could not find a difference.
Suggest testing the same branch with the alpha patch reverted just to
rule out any issue in the core code. If it reproduces suggest to
bisect Leon's branch.
Thanks,
Jason
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-23 23:53 ` Jason Gunthorpe
@ 2025-09-24 7:32 ` Magnus Lindholm
2025-09-27 19:20 ` Magnus Lindholm
0 siblings, 1 reply; 20+ messages in thread
From: Magnus Lindholm @ 2025-09-24 7:32 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Leon Romanovsky, Marek Szyprowski, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
> Suggest testing the same branch with the alpha patch reverted just to
> rule out any issue in the core code. If it reproduces suggest to
> bisect Leon's branch.
>
I can try to revert just the patch containing the alpha-specific stuff and
see what happens and then, as you say, maybe do a bisect from there.
First I'll just try the same kernel again a few times more just to make sure
that this is really reproducible.
/Magnus
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-24 7:32 ` Magnus Lindholm
@ 2025-09-27 19:20 ` Magnus Lindholm
2025-09-28 10:23 ` Magnus Lindholm
0 siblings, 1 reply; 20+ messages in thread
From: Magnus Lindholm @ 2025-09-27 19:20 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Leon Romanovsky, Marek Szyprowski, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
> > Suggest testing the same branch with the alpha patch reverted just to
> > rule out any issue in the core code. If it reproduces suggest to
> > bisect Leon's branch.
Hi again, I've booted up the ES40 again with the kernel build from Leons
branch, it boots up but message log is full off messages like
"EXT4-fs error (device sda4): ext4_find_extent:939: inode
#16257327: comm init: pblk 65114257 bad header/extent:
invalid magic"
The filesystem is broken after just booting with the kernel.
This time fsck did not fix it, I needed to re-install gentoo stage3.
So it's for sure reproducible as well as destructive. It's not possible to
revert all the commits individually, since this will leave the source tree
in a state where the kernel doesn't build. I've started off by reverting
the following commits:
e78a9d72517a88faa6f16dab4d1c6f966ed378ae
(dma-mapping: remove unused map_page callback)
d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
(alpha: Convert mapping routine to rely on physical address)
3cd47242d513050d7a81ac6e7020fd3ef5462ad4
(block-dma: properly take MMIO path)
7950995bef32aa7e5f74699c7d0fdac41d2dad14
(block-dma: migrate to dma_map_phys instead of map_page)
After reverting the above commits, I'm able to build a working kernel,
that is, no filesystem corruption occurs. I'll take a closer look at this
after the weekend.
Regards
Magnus
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-27 19:20 ` Magnus Lindholm
@ 2025-09-28 10:23 ` Magnus Lindholm
2025-09-28 10:54 ` Leon Romanovsky
0 siblings, 1 reply; 20+ messages in thread
From: Magnus Lindholm @ 2025-09-28 10:23 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Leon Romanovsky, Marek Szyprowski, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
> After reverting the above commits, I'm able to build a working kernel,
> that is, no filesystem corruption occurs. I'll take a closer look at this
> after the weekend.
>
Short update, It is enough to revert the following commits, in order to
have a working kernel on alpha:
e78a9d72517a88faa6f16dab4d1c6f966ed378ae
(dma-mapping: remove unused map_page callback)
d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
(alpha: Convert mapping routine to rely on physical address)
/Magnus
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-28 10:23 ` Magnus Lindholm
@ 2025-09-28 10:54 ` Leon Romanovsky
2025-09-28 11:27 ` Magnus Lindholm
0 siblings, 1 reply; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-28 10:54 UTC (permalink / raw)
To: Magnus Lindholm
Cc: Jason Gunthorpe, Marek Szyprowski, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
On Sun, Sep 28, 2025 at 12:23:48PM +0200, Magnus Lindholm wrote:
> > After reverting the above commits, I'm able to build a working kernel,
> > that is, no filesystem corruption occurs. I'll take a closer look at this
> > after the weekend.
> >
>
> Short update, It is enough to revert the following commits, in order to
> have a working kernel on alpha:
>
> e78a9d72517a88faa6f16dab4d1c6f966ed378ae
> (dma-mapping: remove unused map_page callback)
>
> d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
> (alpha: Convert mapping routine to rely on physical address)
Thanks for the effort.
Can you please check the following change instead of reverting the patches?
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index b62d9937d1d3a..3e4f631a1f27d 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -229,6 +229,7 @@ pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size,
{
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;
dma_addr_t ret;
@@ -287,7 +288,7 @@ pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size,
arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);
ret = arena->dma_base + dma_ofs * PAGE_SIZE;
- ret += offset_in_page(paddr);
+ ret += offset;
DBGA2("pci_map_single: [%pa,%zx] np %ld -> sg %llx from %ps\n",
&paddr, size, npages, ret, __builtin_return_address(0));
~
>
>
> /Magnus
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-28 10:54 ` Leon Romanovsky
@ 2025-09-28 11:27 ` Magnus Lindholm
2025-09-28 11:58 ` Leon Romanovsky
0 siblings, 1 reply; 20+ messages in thread
From: Magnus Lindholm @ 2025-09-28 11:27 UTC (permalink / raw)
To: Leon Romanovsky
Cc: Jason Gunthorpe, Marek Szyprowski, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
> Thanks for the effort.
>
> Can you please check the following change instead of reverting the patches?
>
No problem, happy to assist. I think this did the trick! preliminary
testing shows
that this now works on alpha! I guess the offset information in paddr was lost
by doing "paddr &= PAGE_MASK" before retrieving the offset, well spotted!
I'll keep running the system with some load to make sure there is nothing else
we haven't spotted yet, but so far so good. I'll keep you posted.
Will you be putting out a v2 of this patchset with these updates?
Regards
Magnus Lindholm
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
2025-09-28 11:27 ` Magnus Lindholm
@ 2025-09-28 11:58 ` Leon Romanovsky
0 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-28 11:58 UTC (permalink / raw)
To: Magnus Lindholm
Cc: Jason Gunthorpe, Marek Szyprowski, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
On Sun, Sep 28, 2025 at 01:27:12PM +0200, Magnus Lindholm wrote:
> > Thanks for the effort.
> >
> > Can you please check the following change instead of reverting the patches?
> >
>
> No problem, happy to assist. I think this did the trick! preliminary
> testing shows
> that this now works on alpha! I guess the offset information in paddr was lost
> by doing "paddr &= PAGE_MASK" before retrieving the offset, well spotted!
>
> I'll keep running the system with some load to make sure there is nothing else
> we haven't spotted yet, but so far so good. I'll keep you posted.
>
> Will you be putting out a v2 of this patchset with these updates?
Yes, will try to send today.
Thanks again for your help.
>
> Regards
>
> Magnus Lindholm
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 2/9] MIPS/jazzdma: Provide physical address directly
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
2025-09-18 18:45 ` [PATCH 1/9] alpha: Convert mapping routine to rely on physical address Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-18 18:45 ` [PATCH 3/9] parisc: Convert DMA map_page to map_phys interface Leon Romanovsky
` (6 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
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.
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 c97b089b99029..45fe71aa454b7 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 (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] 20+ messages in thread* [PATCH 3/9] parisc: Convert DMA map_page to map_phys interface
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
2025-09-18 18:45 ` [PATCH 1/9] alpha: Convert mapping routine to rely on physical address Leon Romanovsky
2025-09-18 18:45 ` [PATCH 2/9] MIPS/jazzdma: Provide physical address directly Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-18 18:45 ` [PATCH 4/9] powerpc: Convert to physical address DMA mapping Leon Romanovsky
` (5 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
From: Leon Romanovsky <leonro@nvidia.com>
Perform mechanical conversion from .map_page to .map_phys callback.
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
drivers/parisc/ccio-dma.c | 25 +++++++++++++------------
drivers/parisc/sba_iommu.c | 23 ++++++++++++-----------
2 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index feef537257d05..d45f3634f8270 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -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 (attrs & DMA_ATTR_MMIO)
+ return DMA_MAPPING_ERROR;
+
+ return ccio_map_single(dev, phys_to_virt(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;
@@ -873,7 +874,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));
}
@@ -1004,7 +1005,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 +1018,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 +1073,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/sba_iommu.c b/drivers/parisc/sba_iommu.c
index fc3863c09f83d..8040aa4e6ff42 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -778,17 +778,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 (attrs & DMA_ATTR_MMIO)
+ return DMA_MAPPING_ERROR;
+
+ return sba_map_single(dev, phys_to_virt(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 +799,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;
@@ -914,7 +915,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));
}
@@ -1061,7 +1062,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 +1086,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] 20+ messages in thread* [PATCH 4/9] powerpc: Convert to physical address DMA mapping
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
` (2 preceding siblings ...)
2025-09-18 18:45 ` [PATCH 3/9] parisc: Convert DMA map_page to map_phys interface Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-18 18:45 ` [PATCH 5/9] sparc64: Use " Leon Romanovsky
` (4 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
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 b410021ad4c69..eafdd63cd6c4f 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 0359ab72cd3ba..aa3689d619179 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 244eb4857e7f4..6b5f4b72ce97f 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 afbaabf182d01..6adcf76c70219 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 (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 (attrs & DMA_ATTR_MMIO)
+ return;
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 3436b0af795e2..cad2deb7e70d9 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 ac1d2d2c9a88a..838e29d473785 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 (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] 20+ messages in thread* [PATCH 5/9] sparc64: Use physical address DMA mapping
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
` (3 preceding siblings ...)
2025-09-18 18:45 ` [PATCH 4/9] powerpc: Convert to physical address DMA mapping Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-18 18:45 ` [PATCH 6/9] x86: Use physical address for " Leon Romanovsky
` (3 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
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 | 16 ++++++------
arch/sparc/kernel/pci_sun4v.c | 16 ++++++------
arch/sparc/mm/io-unit.c | 13 +++++-----
arch/sparc/mm/iommu.c | 46 ++++++++++++++++++-----------------
4 files changed, 48 insertions(+), 43 deletions(-)
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index da03636925283..72bd7519ac2ab 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -260,9 +260,8 @@ 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;
@@ -273,13 +272,16 @@ static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,
u32 bus_addr, ret;
unsigned long iopte_protection;
+ if (attrs & DMA_ATTR_MMIO)
+ goto bad;
+
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;
@@ -383,7 +385,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 +755,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 b720b21ccfbd8..d9d2464a948c9 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;
@@ -367,13 +366,16 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
dma_addr_t bus_addr, ret;
long entry;
+ if (attrs & DMA_ATTR_MMIO)
+ 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;
@@ -426,7 +428,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 +688,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 d8376f61b4d08..fab303cc33700 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -142,11 +142,10 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
return vaddr;
}
-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;
+ void *vaddr = phys_to_virt(phys);
struct iounit_struct *iounit = dev->archdata.iommu;
unsigned long ret, flags;
@@ -178,7 +177,7 @@ static int iounit_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
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 +278,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 5a5080db800f5..dfcd981fa7efc 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 (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] 20+ messages in thread* [PATCH 6/9] x86: Use physical address for DMA mapping
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
` (4 preceding siblings ...)
2025-09-18 18:45 ` [PATCH 5/9] sparc64: Use " Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-18 18:45 ` [PATCH 7/9] vdpa: Convert to physical address " Leon Romanovsky
` (2 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
From: Leon Romanovsky <leonro@nvidia.com>
Perform mechanical conversion from DMA .map_page to .map_phys.
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 3485d419c2f5e..f1ffdc0e4a3ab 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 (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] 20+ messages in thread* [PATCH 7/9] vdpa: Convert to physical address DMA mapping
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
` (5 preceding siblings ...)
2025-09-18 18:45 ` [PATCH 6/9] x86: Use physical address for " Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-18 18:45 ` [PATCH 8/9] xen: swiotlb: Convert mapping routine to rely on physical address Leon Romanovsky
2025-09-18 18:45 ` [PATCH 9/9] dma-mapping: remove unused map_page callback Leon Romanovsky
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
From: Leon Romanovsky <leonro@nvidia.com>
Use physical address directly in DMA mapping flow.
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
drivers/vdpa/vdpa_user/iova_domain.c | 11 +++++------
drivers/vdpa/vdpa_user/iova_domain.h | 8 ++++----
drivers/vdpa/vdpa_user/vduse_dev.c | 18 ++++++++++--------
3 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/vdpa/vdpa_user/iova_domain.c b/drivers/vdpa/vdpa_user/iova_domain.c
index 58116f89d8dae..c0ecf01003cd3 100644
--- a/drivers/vdpa/vdpa_user/iova_domain.c
+++ b/drivers/vdpa/vdpa_user/iova_domain.c
@@ -396,17 +396,16 @@ void vduse_domain_sync_single_for_cpu(struct vduse_iova_domain *domain,
read_unlock(&domain->bounce_lock);
}
-dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,
- struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction dir,
+dma_addr_t vduse_domain_map_phys(struct vduse_iova_domain *domain,
+ phys_addr_t pa, size_t size,
+ enum dma_data_direction dir,
unsigned long attrs)
{
struct iova_domain *iovad = &domain->stream_iovad;
unsigned long limit = domain->bounce_size - 1;
- phys_addr_t pa = page_to_phys(page) + offset;
dma_addr_t iova = vduse_domain_alloc_iova(iovad, size, limit);
- if (!iova)
+ if (!iova || (attrs & DMA_ATTR_MMIO))
return DMA_MAPPING_ERROR;
if (vduse_domain_init_bounce_map(domain))
@@ -430,7 +429,7 @@ dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,
return DMA_MAPPING_ERROR;
}
-void vduse_domain_unmap_page(struct vduse_iova_domain *domain,
+void vduse_domain_unmap_phys(struct vduse_iova_domain *domain,
dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir, unsigned long attrs)
{
diff --git a/drivers/vdpa/vdpa_user/iova_domain.h b/drivers/vdpa/vdpa_user/iova_domain.h
index 7f3f0928ec781..7c4546fd856ab 100644
--- a/drivers/vdpa/vdpa_user/iova_domain.h
+++ b/drivers/vdpa/vdpa_user/iova_domain.h
@@ -53,12 +53,12 @@ void vduse_domain_sync_single_for_cpu(struct vduse_iova_domain *domain,
dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir);
-dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,
- struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction dir,
+dma_addr_t vduse_domain_map_phys(struct vduse_iova_domain *domain,
+ phys_addr_t phys, size_t size,
+ enum dma_data_direction dir,
unsigned long attrs);
-void vduse_domain_unmap_page(struct vduse_iova_domain *domain,
+void vduse_domain_unmap_phys(struct vduse_iova_domain *domain,
dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir, unsigned long attrs);
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 04620bb77203d..75aa3c9f83fb5 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -834,25 +834,27 @@ static void vduse_dev_sync_single_for_cpu(struct device *dev,
vduse_domain_sync_single_for_cpu(domain, dma_addr, size, dir);
}
-static dma_addr_t vduse_dev_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
+static dma_addr_t vduse_dev_map_phys(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
struct vduse_dev *vdev = dev_to_vduse(dev);
struct vduse_iova_domain *domain = vdev->domain;
- return vduse_domain_map_page(domain, page, offset, size, dir, attrs);
+ if (attrs & DMA_ATTR_MMIO)
+ return DMA_MAPPING_ERROR;
+
+ return vduse_domain_map_phys(domain, phys, size, dir, attrs);
}
-static void vduse_dev_unmap_page(struct device *dev, dma_addr_t dma_addr,
+static void vduse_dev_unmap_phys(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
unsigned long attrs)
{
struct vduse_dev *vdev = dev_to_vduse(dev);
struct vduse_iova_domain *domain = vdev->domain;
- return vduse_domain_unmap_page(domain, dma_addr, size, dir, attrs);
+ return vduse_domain_unmap_phys(domain, dma_addr, size, dir, attrs);
}
static void *vduse_dev_alloc_coherent(struct device *dev, size_t size,
@@ -896,8 +898,8 @@ static size_t vduse_dev_max_mapping_size(struct device *dev)
static const struct dma_map_ops vduse_dev_dma_ops = {
.sync_single_for_device = vduse_dev_sync_single_for_device,
.sync_single_for_cpu = vduse_dev_sync_single_for_cpu,
- .map_page = vduse_dev_map_page,
- .unmap_page = vduse_dev_unmap_page,
+ .map_phys = vduse_dev_map_phys,
+ .unmap_phys = vduse_dev_unmap_phys,
.alloc = vduse_dev_alloc_coherent,
.free = vduse_dev_free_coherent,
.max_mapping_size = vduse_dev_max_mapping_size,
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 8/9] xen: swiotlb: Convert mapping routine to rely on physical address
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
` (6 preceding siblings ...)
2025-09-18 18:45 ` [PATCH 7/9] vdpa: Convert to physical address " Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
2025-09-18 18:45 ` [PATCH 9/9] dma-mapping: remove unused map_page callback Leon Romanovsky
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
From: Leon Romanovsky <leonro@nvidia.com>
Switch to .map_phys callback instead of .map_page.
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 29257d2639dbf..7f76e516fe24c 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 (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] 20+ messages in thread* [PATCH 9/9] dma-mapping: remove unused map_page callback
2025-09-18 18:45 [PATCH 0/9] Remove DMA .map_page and .unmap_page callbacks Leon Romanovsky
` (7 preceding siblings ...)
2025-09-18 18:45 ` [PATCH 8/9] xen: swiotlb: Convert mapping routine to rely on physical address Leon Romanovsky
@ 2025-09-18 18:45 ` Leon Romanovsky
8 siblings, 0 replies; 20+ messages in thread
From: Leon Romanovsky @ 2025-09-18 18:45 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Leon Romanovsky, Jason Gunthorpe, Andreas Larsson,
Borislav Petkov, Dave Hansen, David S. Miller, Geoff Levand,
Helge Deller, Ingo Molnar, iommu, James E.J. Bottomley,
Jason Wang, Juergen Gross, linux-alpha, linux-kernel, linux-mips,
linux-parisc, linuxppc-dev, Madhavan Srinivasan, Matt Turner,
Michael Ellerman, Michael S. Tsirkin, Richard Henderson,
sparclinux, Stefano Stabellini, Thomas Bogendoerfer,
Thomas Gleixner, virtualization, x86, xen-devel
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.
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 a2ec1566aa270..e0a78991fa8a3 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 32a85bfdf873a..37163eb49f9fa 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 1eccbdbc99c1e..20caf9cabf699 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] 20+ messages in thread