aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorSebastian Siewior <bigeasy@linutronix.de>2013-12-02 04:52:55 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-02 16:59:20 -0500
commit2488a54e485bc108ab136e8e3cb95b99e97f68b5 (patch)
tree25ac72e8d61713dbb4b23787084a57d899e98ef7 /drivers/net/ethernet/freescale
parent3a27bfac17fe375539c4e0a53478679645eb5ae2 (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>
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 4cbebf3d80eb..73b000df8a08 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 fep->tx_skbuff[index] = NULL; 391 fep->tx_skbuff[index] = NULL;
@@ -779,11 +779,10 @@ fec_enet_tx(struct net_device *ndev)
779 else 779 else
780 index = bdp - fep->tx_bd_base; 780 index = bdp - fep->tx_bd_base;
781 781
782 dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
783 FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
784 bdp->cbd_bufaddr = 0;
785
786 skb = fep->tx_skbuff[index]; 782 skb = fep->tx_skbuff[index];
783 dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,
784 DMA_TO_DEVICE);
785 bdp->cbd_bufaddr = 0;
787 786
788 /* Check for errors. */ 787 /* Check for errors. */
789 if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | 788 if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |