Gaurav Batra <gba...@linux.vnet.ibm.com> writes:
> When DMA window is backed by 2MB TCEs, the DMA address for the mapped
> page should be the offset of the page relative to the 2MB TCE. The code
> was incorrectly setting the DMA address to the beginning of the TCE
> range.
>
> Mellanox driver is reporting timeout trying to ENABLE_HCA for an SR-IOV
> ethernet port, when DMA window is backed by 2MB TCEs.

I assume this is similar or related to the bug Srikar reported?

  
https://lore.kernel.org/linuxppc-dev/20230323095333.gi1005...@linux.vnet.ibm.com/

In that thread Alexey suggested a patch, have you tried his patch? He
suggested rounding up the allocation size, rather than adjusting the
dma_handle.

> Fixes: 3872731187141d5d0a5c4fb30007b8b9ec36a44d

That's not the right syntax, it's described in the documentation how to
generate it.

It should be:

  Fixes: 387273118714 ("powerps/pseries/dma: Add support for 2M IOMMU page 
size")

cheers

> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
> index ee95937bdaf1..ca57526ce47a 100644
> --- a/arch/powerpc/kernel/iommu.c
> +++ b/arch/powerpc/kernel/iommu.c
> @@ -517,7 +517,7 @@ int ppc_iommu_map_sg(struct device *dev, struct 
> iommu_table *tbl,
>               /* Convert entry to a dma_addr_t */
>               entry += tbl->it_offset;
>               dma_addr = entry << tbl->it_page_shift;
> -             dma_addr |= (s->offset & ~IOMMU_PAGE_MASK(tbl));
> +             dma_addr |= (vaddr & ~IOMMU_PAGE_MASK(tbl));
>  
>               DBG("  - %lu pages, entry: %lx, dma_addr: %lx\n",
>                           npages, entry, dma_addr);
> @@ -904,6 +904,7 @@ void *iommu_alloc_coherent(struct device *dev, struct 
> iommu_table *tbl,
>       unsigned int order;
>       unsigned int nio_pages, io_order;
>       struct page *page;
> +     int tcesize = (1 << tbl->it_page_shift);
>  
>       size = PAGE_ALIGN(size);
>       order = get_order(size);
> @@ -930,7 +931,8 @@ void *iommu_alloc_coherent(struct device *dev, struct 
> iommu_table *tbl,
>       memset(ret, 0, size);
>  
>       /* Set up tces to cover the allocated range */
> -     nio_pages = size >> tbl->it_page_shift;
> +     nio_pages = IOMMU_PAGE_ALIGN(size, tbl) >> tbl->it_page_shift;
> +
>       io_order = get_iommu_order(size, tbl);
>       mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
>                             mask >> tbl->it_page_shift, io_order, 0);
> @@ -938,7 +940,8 @@ void *iommu_alloc_coherent(struct device *dev, struct 
> iommu_table *tbl,
>               free_pages((unsigned long)ret, order);
>               return NULL;
>       }
> -     *dma_handle = mapping;
> +
> +     *dma_handle = mapping | ((u64)ret & (tcesize - 1));
>       return ret;
>  }
>  
> -- 

Reply via email to