Message ID | 20230504175913.83844-1-gbatra@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 096339ab84f36beae0b1db25e0ce63fb3873e8b2 |
Headers | show |
Series | [v3] powerpc/iommu: DMA address offset is incorrectly calculated with 2MB TCEs | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/github-powerpc_ppctests | success | Successfully ran 8 jobs. |
snowpatch_ozlabs/github-powerpc_selftests | success | Successfully ran 8 jobs. |
snowpatch_ozlabs/github-powerpc_sparse | success | Successfully ran 4 jobs. |
snowpatch_ozlabs/github-powerpc_kernel_qemu | success | Successfully ran 24 jobs. |
snowpatch_ozlabs/github-powerpc_clang | success | Successfully ran 6 jobs. |
* Gaurav Batra <gbatra@linux.vnet.ibm.com> [2023-05-04 12:59:13]: > 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. > > Fixes: 387273118714 ("powerps/pseries/dma: Add support for 2M IOMMU page size") > > Signed-off-by: Gaurav Batra <gbatra@linux.vnet.ibm.com> > Works with this patch. Tested-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> > Reviewed-by: Greg Joyce <gjoyce@linux.vnet.ibm.com> > Reviewed-by: Brian King <brking@linux.vnet.ibm.com> > ---
On Thu, 04 May 2023 12:59:13 -0500, Gaurav Batra wrote: > 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. > > [...] Applied to powerpc/fixes. [1/1] powerpc/iommu: DMA address offset is incorrectly calculated with 2MB TCEs https://git.kernel.org/powerpc/c/096339ab84f36beae0b1db25e0ce63fb3873e8b2 cheers
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index ee95937bdaf1..b8b7a189cd3c 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; } @@ -949,7 +952,7 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size, unsigned int nio_pages; size = PAGE_ALIGN(size); - nio_pages = size >> tbl->it_page_shift; + nio_pages = IOMMU_PAGE_ALIGN(size, tbl) >> tbl->it_page_shift; iommu_free(tbl, dma_handle, nio_pages); size = PAGE_ALIGN(size); free_pages((unsigned long)vaddr, get_order(size));