aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSebastian Siewior <bigeasy@linutronix.de>2013-12-02 04:52:55 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:57:32 -0400
commit95a75cc28db936385c06961e032cf75a289e366e (patch)
treecd3155a340620778e7bf13a18e26c562fabbb213 /drivers/net
parent7588a68dea2971e9b8539927e9262f5ab4d6ecbc (diff)
net: fec_main: dma_map() only the length of the skb
On tx submit the driver always dma_map_single() FEC_ENET_TX_FRSIZE (=2048) bytes. This works because we don't overwrite any memory after the data buffer, we remove it from cache if it was there. So we hurt performace in case the mapping of a smaller area makes a difference. There is also a bug: If the data area starts shortly before the end of RAM say 0xc7fffa10 and the RAM ends at 0xc8000000 then we have enough space to fit the data area (according to skb->len) but we would map beyond end of ram if we are using 2048. In v2.6.31 (against which kernel this patch made) there is the following check in dma_cache_maint(): |BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1)); Since the area starting at 0xc8000000 is no longer virt_addr_valid() we BUG() during dma_map_single(). The BUG() statement was removed in v3.5-rc1 as per 2dc6a016 ("ARM: dma-mapping: use asm-generic/dma-mapping-common.h"). This patch was tested on v2.6.31 and then forward-ported and compile tested only against the net tree. I think it is still worth fixing mainline even after the BUG() statement is gone. Tested-by: Fugang Duan <B38611@freescale.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Fugang Duan <B38611@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net> Conflicts: drivers/net/ethernet/freescale/fec_main.c
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index e643f354b1a5..0d6c56a334d5 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -385,7 +385,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
385 * data. 385 * data.
386 */ 386 */
387 bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr, 387 bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
388 FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); 388 skb->len, DMA_TO_DEVICE);
389 if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { 389 if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
390 bdp->cbd_bufaddr = 0; 390 bdp->cbd_bufaddr = 0;
391 netdev_err(ndev, "Tx DMA memory map failed\n"); 391 netdev_err(ndev, "Tx DMA memory map failed\n");
@@ -876,12 +876,11 @@ fec_enet_tx(struct net_device *ndev)
876 else 876 else
877 index = bdp - txq->tx_bd_base; 877 index = bdp - txq->tx_bd_base;
878 878
879 skb = txq->tx_skbuff[index];
879 dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, 880 dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
880 FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); 881 skb->len, DMA_TO_DEVICE);
881 bdp->cbd_bufaddr = 0; 882 bdp->cbd_bufaddr = 0;
882 883
883 skb = txq->tx_skbuff[index];
884
885 /* Check for errors. */ 884 /* Check for errors. */
886 if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | 885 if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
887 BD_ENET_TX_RL | BD_ENET_TX_UN | 886 BD_ENET_TX_RL | BD_ENET_TX_UN |