Skip to content

Commit b743922

Browse files
davejianggregkh
authored andcommitted
ntb: Force physically contiguous allocation of rx ring buffers
[ Upstream commit 061a785 ] Physical addresses under IOVA on x86 platform are mapped contiguously as a side effect before the patch that removed CONFIG_DMA_REMAP. The NTB rx buffer ring is a single chunk DMA buffer that is allocated against the NTB PCI device. If the receive side is using a DMA device, then the buffers are remapped against the DMA device before being submitted via the dmaengine API. This scheme becomes a problem when the physical memory is discontiguous. When dma_map_page() is called on the kernel virtual address from the dma_alloc_coherent() call, the new IOVA mapping no longer points to all the physical memory allocated due to being discontiguous. Change dma_alloc_coherent() to dma_alloc_attrs() in order to force DMA_ATTR_FORCE_CONTIGUOUS attribute. This is the best fix for the circumstance. A potential future solution may be having the DMA mapping API providing a way to alias an existing IOVA mapping to a new device perhaps. This fix is not to fix the patch pointed to by the fixes tag, but to fix the issue arised in the ntb_transport driver on x86 platforms after the said patch is applied. Reported-by: Jerry Dai <[email protected]> Fixes: f5ff79f ("dma-mapping: remove CONFIG_DMA_REMAP") Tested-by: Jerry Dai <[email protected]> Signed-off-by: Dave Jiang <[email protected]> Signed-off-by: Jon Mason <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent fd8932c commit b743922

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

drivers/ntb/ntb_transport.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -807,16 +807,29 @@ static void ntb_free_mw(struct ntb_transport_ctx *nt, int num_mw)
807807
}
808808

809809
static int ntb_alloc_mw_buffer(struct ntb_transport_mw *mw,
810-
struct device *dma_dev, size_t align)
810+
struct device *ntb_dev, size_t align)
811811
{
812812
dma_addr_t dma_addr;
813813
void *alloc_addr, *virt_addr;
814814
int rc;
815815

816-
alloc_addr = dma_alloc_coherent(dma_dev, mw->alloc_size,
817-
&dma_addr, GFP_KERNEL);
816+
/*
817+
* The buffer here is allocated against the NTB device. The reason to
818+
* use dma_alloc_*() call is to allocate a large IOVA contiguous buffer
819+
* backing the NTB BAR for the remote host to write to. During receive
820+
* processing, the data is being copied out of the receive buffer to
821+
* the kernel skbuff. When a DMA device is being used, dma_map_page()
822+
* is called on the kvaddr of the receive buffer (from dma_alloc_*())
823+
* and remapped against the DMA device. It appears to be a double
824+
* DMA mapping of buffers, but first is mapped to the NTB device and
825+
* second is to the DMA device. DMA_ATTR_FORCE_CONTIGUOUS is necessary
826+
* in order for the later dma_map_page() to not fail.
827+
*/
828+
alloc_addr = dma_alloc_attrs(ntb_dev, mw->alloc_size,
829+
&dma_addr, GFP_KERNEL,
830+
DMA_ATTR_FORCE_CONTIGUOUS);
818831
if (!alloc_addr) {
819-
dev_err(dma_dev, "Unable to alloc MW buff of size %zu\n",
832+
dev_err(ntb_dev, "Unable to alloc MW buff of size %zu\n",
820833
mw->alloc_size);
821834
return -ENOMEM;
822835
}
@@ -845,7 +858,7 @@ static int ntb_alloc_mw_buffer(struct ntb_transport_mw *mw,
845858
return 0;
846859

847860
err:
848-
dma_free_coherent(dma_dev, mw->alloc_size, alloc_addr, dma_addr);
861+
dma_free_coherent(ntb_dev, mw->alloc_size, alloc_addr, dma_addr);
849862

850863
return rc;
851864
}

0 commit comments

Comments
 (0)