On 9/8/20 3:51 AM, Alexey Kardashevskiy wrote: > There are 2 problems with it: > 1. "<" vs expected "<<" > 2. the shift number is an IOMMU page number mask, not an address mask > as the IOMMU page shift is missing. > > This did not hit us before f1565c24b596 ("powerpc: use the generic > dma_ops_bypass mode") because we had there additional code to handle > bypass mask so this chunk (almost?) never executed. However there > were reports that aacraid does not work with "iommu=nobypass". > After f1565c24b596, aacraid (and probably others which call > dma_get_required_mask() before setting the mask) was unable to > enable 64bit DMA and fall back to using IOMMU which was known not to work, > one of the problems is double free of an IOMMU page. > > This fixes DMA for aacraid, both with and without "iommu=nobypass" > in the kernel command line. Verified with "stress-ng -d 4". > > Fixes: f1565c24b596 ("powerpc: use the generic dma_ops_bypass mode") > Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru>
The boston system looks solid with this patch. Tested-by: Cédric Le Goater <c...@kaod.org> Thanks a lot ! C. > --- > > The original code came Jun 24 2011: > 6a5c7be5e484 ("powerpc: Override dma_get_required_mask by platform hook and > ops") > > > What is dma_get_required_mask() for anyway? What "requires" what here? > > Even though it works for now (due to huge - >4GB - default DMA window), > I am still not convinced we do not want this chunk here > (this is what f1565c24b596 removed): > > if (dev_is_pci(dev)) { > u64 bypass_mask = dma_direct_get_required_mask(dev); > > if (dma_iommu_bypass_supported(dev, bypass_mask)) > return bypass_mask; > } > --- > arch/powerpc/kernel/dma-iommu.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c > index 569fecd7b5b2..9053fc9d20c7 100644 > --- a/arch/powerpc/kernel/dma-iommu.c > +++ b/arch/powerpc/kernel/dma-iommu.c > @@ -120,7 +120,8 @@ u64 dma_iommu_get_required_mask(struct device *dev) > if (!tbl) > return 0; > > - mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1); > + mask = 1ULL << (fls_long(tbl->it_offset + tbl->it_size) + > + tbl->it_page_shift - 1); > mask += mask - 1; > > return mask; >