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
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
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
> > 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
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
> 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
> > 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
> 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
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
> 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
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
© 2016 - 2025 Red Hat, Inc.