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; >> ... Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland
