Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ibmveth: Fix issue with DMA mapping failure

descs[].fields.address is 32bit which truncates any dma mapping
errors so dma_mapping_error() fails to catch it.

Use a dma_addr_t to do the comparison. With this patch I was able
to transfer many gigabytes of data with IOMMU fault injection set
at 10% probability.

Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: <stable@kernel.org> # v2.6.37+
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Anton Blanchard and committed by
David S. Miller
b93da27f 33a48ab1

+5 -5
+5 -5
drivers/net/ibmveth.c
··· 930 930 union ibmveth_buf_desc descs[6]; 931 931 int last, i; 932 932 int force_bounce = 0; 933 + dma_addr_t dma_addr; 933 934 934 935 /* 935 936 * veth handles a maximum of 6 segments including the header, so ··· 995 994 } 996 995 997 996 /* Map the header */ 998 - descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data, 999 - skb_headlen(skb), 1000 - DMA_TO_DEVICE); 1001 - if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address)) 997 + dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, 998 + skb_headlen(skb), DMA_TO_DEVICE); 999 + if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) 1002 1000 goto map_failed; 1003 1001 1004 1002 descs[0].fields.flags_len = desc_flags | skb_headlen(skb); 1003 + descs[0].fields.address = dma_addr; 1005 1004 1006 1005 /* Map the frags */ 1007 1006 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1008 - unsigned long dma_addr; 1009 1007 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 1010 1008 1011 1009 dma_addr = dma_map_page(&adapter->vdev->dev, frag->page,