Re: [PATCH v5 11/14] sparc: Use physical address DMA mapping

John Paul Adrian Glaubitz <[email protected]>
Newsgroups org.kernel.vger.sparclinux,dev.linux.lists.iommu,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-alpha,org.kernel.vger.linux-kernel,org.kernel.vger.linux-mips,org.kernel.vger.linux-parisc,org.ozlabs.lists.linuxppc-dev,org.xenproject.lists.xen-devel
Message-ID <8317613a286ab637ac29740433ff51286ebbbaca.camel@physik.fu-berlin.de>
Hi Marek,

On Tue, 2026-02-17 at 13:55 +0100, Marek Szyprowski wrote:
> On 17.02.2026 13:27, John Paul Adrian Glaubitz wrote:
> > On Wed, 2025-10-15 at 12:12 +0300, Leon Romanovsky wrote:
> > > From: Leon Romanovsky <[email protected]>
> > > 
> > > Convert sparc architecture DMA code to use .map_phys callback.
> > > 
> > > Signed-off-by: Leon Romanovsky <[email protected]>
> > > ---
> > >   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;
> 
> 'base_paddr' was aligned to start of a page before this patch, while 
> 'phys' includes the offset within a page.
> 
> 
> Could You check if the following change fixes the issue?
> 
> diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
> index 46ef88bc9c26..edb0ffb21e2f 100644
> --- a/arch/sparc/kernel/iommu.c
> +++ b/arch/sparc/kernel/iommu.c
> @@ -312,6 +312,7 @@ static dma_addr_t dma_4u_map_phys(struct device 
> *dev, phys_addr_t phys,
>          if (direction != DMA_TO_DEVICE)
>                  iopte_protection |= IOPTE_WRITE;
> 
> +       phys -= offset_in_page(phys);
>          for (i = 0; i < npages; i++, base++, phys += IO_PAGE_SIZE)
>                  iopte_val(*base) = iopte_protection | phys;

Thanks, I have forwarded your patch and asked the user to answer here if possible [1].

Adrian

> [1] https://github.com/sparclinux/issues/issues/75#issuecomment-3914791862

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.