From 730ee3602f300b5133717048859358a02251322f Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Jul 2014 00:23:14 +0100 Subject: net: fec: make rx skb handling more robust Allocate, and then map the receive skb before writing any data to the ring descriptor or storing the skb. When freeing the receive ring entries, unmap and free the skb, and then clear the stored skb pointer. This means we have ring data and skb pointer in one of two states: either both fully setup, or nothing setup. This simplifies the cleanup, as we can use just the skb pointer to indicate whether the descriptor is setup, and thus avoids potentially calling dma_unmap_single() on a DMA error value. Acked-by: Fugang Duan Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/net/ethernet/freescale/fec_main.c') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 309aa2ff8cc9..70853a59627a 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2066,12 +2066,12 @@ static void fec_enet_free_buffers(struct net_device *ndev) bdp = fep->rx_bd_base; for (i = 0; i < fep->rx_ring_size; i++) { skb = fep->rx_skbuff[i]; - - if (bdp->cbd_bufaddr) + fep->rx_skbuff[i] = NULL; + if (skb) { dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - if (skb) dev_kfree_skb(skb); + } bdp = fec_enet_get_nextdesc(bdp, fep); } @@ -2089,21 +2089,26 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp = fep->rx_bd_base; for (i = 0; i < fep->rx_ring_size; i++) { + dma_addr_t addr; + skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); if (!skb) { fec_enet_free_buffers(ndev); return -ENOMEM; } - fep->rx_skbuff[i] = skb; - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, + addr = dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { + if (dma_mapping_error(&fep->pdev->dev, addr)) { + dev_kfree_skb(skb); fec_enet_free_buffers(ndev); if (net_ratelimit()) netdev_err(ndev, "Rx DMA memory map failed\n"); return -ENOMEM; } + + fep->rx_skbuff[i] = skb; + bdp->cbd_bufaddr = addr; bdp->cbd_sc = BD_ENET_RX_EMPTY; if (fep->bufdesc_ex) { -- cgit v1.2.3-59-g8ed1b