ll_temac: fix DMA resources leak
authorDenis Kirjanov <dkirjanov@hera.kernel.org>
Thu, 8 Jul 2010 10:24:51 +0000 (10:24 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 9 Jul 2010 06:39:49 +0000 (23:39 -0700)
V2: Check pointers before releasing resources.

Fix DMA resources leak.
Signed-off-by: Denis Kirjanov <dkirjanov@kernel.org>
Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
drivers/net/ll_temac_main.c

index fa303c881a48afbbf65a74fbb068c598ebfdc0a0..b57d0ff5251935a6b6e353fdba298002f3ad0033 100644 (file)
@@ -192,6 +192,35 @@ static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
 
 #endif
 
+/**
+ *  * temac_dma_bd_release - Release buffer descriptor rings
+ */
+static void temac_dma_bd_release(struct net_device *ndev)
+{
+       struct temac_local *lp = netdev_priv(ndev);
+       int i;
+
+       for (i = 0; i < RX_BD_NUM; i++) {
+               if (!lp->rx_skb[i])
+                       break;
+               else {
+                       dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
+                                       XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE);
+                       dev_kfree_skb(lp->rx_skb[i]);
+               }
+       }
+       if (lp->rx_bd_v)
+               dma_free_coherent(ndev->dev.parent,
+                               sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+                               lp->rx_bd_v, lp->rx_bd_p);
+       if (lp->tx_bd_v)
+               dma_free_coherent(ndev->dev.parent,
+                               sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+                               lp->tx_bd_v, lp->tx_bd_p);
+       if (lp->rx_skb)
+               kfree(lp->rx_skb);
+}
+
 /**
  * temac_dma_bd_init - Setup buffer descriptor rings
  */
@@ -275,6 +304,7 @@ static int temac_dma_bd_init(struct net_device *ndev)
        return 0;
 
 out:
+       temac_dma_bd_release(ndev);
        return -ENOMEM;
 }
 
@@ -858,6 +888,8 @@ static int temac_stop(struct net_device *ndev)
                phy_disconnect(lp->phy_dev);
        lp->phy_dev = NULL;
 
+       temac_dma_bd_release(ndev);
+
        return 0;
 }