mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Francois Romieu <romieu@fr.zoreil.com>
To: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: David Vrabel <dvrabel@cantab.net>,
	linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
	david@pleyades.net
Subject: [PATCH 3/3] ipg: plug leaks in the error path of ipg_nic_open
Date: Tue, 2 May 2006 01:12:06 +0200	[thread overview]
Message-ID: <20060501231206.GD7419@electric-eye.fr.zoreil.com> (raw)
In-Reply-To: <1146506939.23931.2.camel@localhost>

Added ipg_{rx/tx}_clear() to factor out some code.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>

---

 drivers/net/ipg.c |  161 +++++++++++++++++++++++++++++++----------------------
 1 files changed, 93 insertions(+), 68 deletions(-)

96f29e9d57f503f1275757f4bbec76c0f7f421fc
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index da0fa22..393b617 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -16,6 +16,9 @@
  */
 #include <linux/crc32.h>
 
+#define IPG_RX_RING_BYTES	(sizeof(struct RFD) * IPG_RFDLIST_LENGTH)
+#define IPG_TX_RING_BYTES	(sizeof(struct TFD) * IPG_TFDLIST_LENGTH)
+
 #define JUMBO_FRAME_4k_ONLY
 enum {
 	netdev_io_size = 128
@@ -1485,15 +1488,46 @@ static void ipg_nic_txfree(struct net_de
 	} while (maxtfdcount != 0);
 }
 
-static int ipg_nic_open(struct net_device *dev)
+static void ipg_rx_clear(struct ipg_nic_private *sp)
 {
-	/* The IPG NIC Ethernet interface is opened when activated
-	 * by ifconfig.
-	 */
+	struct pci_dev *pdev = sp->pdev;
+	unsigned int i;
 
-	int error = 0;
-	void __iomem *ioaddr = ipg_ioaddr(dev);
+	for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
+		if (sp->RxBuff[i]) {
+			struct ipg_dmabuff *desc = sp->RxBuffDMAhandle + i;
+
+			IPG_DEV_KFREE_SKB(sp->RxBuff[i]);
+			sp->RxBuff[i] = NULL;
+			pci_unmap_single(pdev, desc->dmahandle, desc->len,
+					 PCI_DMA_FROMDEVICE);
+		}
+	}
+}
+
+static void ipg_tx_clear(struct ipg_nic_private *sp)
+{
+	struct pci_dev *pdev = sp->pdev;
+	unsigned int i;
+
+	for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
+		if (sp->TxBuff[i]) {
+			struct ipg_dmabuff *desc = sp->TxBuffDMAhandle + i;
+
+			IPG_DEV_KFREE_SKB(sp->TxBuff[i]);
+			sp->TxBuff[i] = NULL;
+			pci_unmap_single(pdev, desc->dmahandle, desc->len,
+					 PCI_DMA_TODEVICE);
+		}
+	}
+}
+
+static int ipg_nic_open(struct net_device *dev)
+{
 	struct ipg_nic_private *sp = netdev_priv(dev);
+	void __iomem *ioaddr = ipg_ioaddr(dev);
+	struct pci_dev *pdev = sp->pdev;
+	int rc;
 
 	IPG_DEBUG_MSG("_nic_open\n");
 
@@ -1508,59 +1542,53 @@ static int ipg_nic_open(struct net_devic
 	/* Register the interrupt line to be used by the IPG within
 	 * the Linux system.
 	 */
-	if ((error = request_irq(sp->pdev->irq,
-				 &ipg_interrupt_handler,
-				 SA_SHIRQ, dev->name, dev)) < 0) {
+	rc = request_irq(pdev->irq, &ipg_interrupt_handler, SA_SHIRQ,
+			 dev->name, dev);
+	if (rc < 0) {
 		printk(KERN_INFO "%s: Error when requesting interrupt.\n",
 		       dev->name);
-		return error;
+		goto out;
 	}
 
-	dev->irq = sp->pdev->irq;
+	dev->irq = pdev->irq;
 
-	sp->RFDList = pci_alloc_consistent(sp->pdev,
-					   (sizeof(struct RFD) *
-					    IPG_RFDLIST_LENGTH),
+	rc = -ENOMEM;
+
+	sp->RFDList = pci_alloc_consistent(pdev, IPG_RX_RING_BYTES,
 					   &sp->RFDListDMAhandle);
+	if (!sp->RFDList)
+		goto err_free_irq_0;
 
-	sp->TFDList = pci_alloc_consistent(sp->pdev,
-					   (sizeof(struct TFD) *
-					    IPG_TFDLIST_LENGTH),
+	sp->TFDList = pci_alloc_consistent(pdev, IPG_TX_RING_BYTES,
 					   &sp->TFDListDMAhandle);
+	if (!sp->TFDList)
+		goto err_free_rx_1;
 
-	if ((sp->RFDList == NULL) || (sp->TFDList == NULL)) {
-		printk(KERN_INFO
-		       "%s: No memory available for IP1000 RFD and/or TFD lists.\n",
-		       dev->name);
-		return -ENOMEM;
-	}
-
-	error = init_rfdlist(dev);
-	if (error < 0) {
+	rc = init_rfdlist(dev);
+	if (rc < 0) {
 		printk(KERN_INFO "%s: Error during configuration.\n",
 		       dev->name);
-		return error;
+		goto err_free_tx_2;
 	}
 
-	error = init_tfdlist(dev);
-	if (error < 0) {
+	rc = init_tfdlist(dev);
+	if (rc < 0) {
 		printk(KERN_INFO "%s: Error during configuration.\n",
 		       dev->name);
-		return error;
+		goto err_release_rfdlist_3;
 	}
 
-	/* Configure IPG I/O registers. */
-	error = ipg_io_config(dev);
-	if (error < 0) {
+	rc = ipg_io_config(dev);
+	if (rc < 0) {
 		printk(KERN_INFO "%s: Error during configuration.\n",
 		       dev->name);
-		return error;
+		goto err_release_tfdlist_4;
 	}
 
 	/* Resolve autonegotiation. */
-	if (ipg_config_autoneg(dev) < 0) {
+	if (ipg_config_autoneg(dev) < 0)
 		printk(KERN_INFO "%s: Auto-negotiation error.\n", dev->name);
-	}
+
 #ifdef JUMBO_FRAME
 	/* initialize JUMBO Frame control variable */
 	sp->Jumbo.FoundStart = 0;
@@ -1575,8 +1603,22 @@ #endif
 		   IPG_MC_TX_ENABLE), ioaddr + IPG_MACCTRL);
 
 	netif_start_queue(dev);
+out:
+	return rc;
 
-	return 0;
+err_release_tfdlist_4:
+	ipg_tx_clear(sp);
+err_release_rfdlist_3:
+	ipg_rx_clear(sp);
+err_free_tx_2:
+	pci_free_consistent(pdev, IPG_TX_RING_BYTES, sp->TFDList,
+			    sp->TFDListDMAhandle);
+err_free_rx_1:
+	pci_free_consistent(pdev, IPG_RX_RING_BYTES, sp->RFDList,
+			    sp->RFDListDMAhandle);
+err_free_irq_0:
+	free_irq(pdev->irq, dev);
+	goto out;
 }
 
 static int init_rfdlist(struct net_device *dev)
@@ -1593,13 +1635,16 @@ static int init_rfdlist(struct net_devic
 	sp->RxBuffNotReady = 0;
 
 	for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
+		if (!sp->RxBuff[i])
+			continue;
+
 		/* Free any allocated receive buffers. */
 		pci_unmap_single(sp->pdev,
 				 sp->RxBuffDMAhandle[i].dmahandle,
 				 sp->RxBuffDMAhandle[i].len,
 				 PCI_DMA_FROMDEVICE);
-		if (sp->RxBuff[i] != NULL)
-			IPG_DEV_KFREE_SKB(sp->RxBuff[i]);
+
+		IPG_DEV_KFREE_SKB(sp->RxBuff[i]);
 		sp->RxBuff[i] = NULL;
 
 		/* Clear out the RFS field. */
@@ -1727,11 +1772,11 @@ static int ipg_get_rxbuff(struct net_dev
 
 static int ipg_nic_stop(struct net_device *dev)
 {
-	/* Release resources requested by driver open function. */
+	struct ipg_nic_private *sp = netdev_priv(dev);
+	struct pci_dev *pdev = sp->pdev;
 
 	int i;
 	int error;
-	struct ipg_nic_private *sp = netdev_priv(dev);
 
 	IPG_DEBUG_MSG("_nic_stop\n");
 
@@ -1752,40 +1797,20 @@ static int ipg_nic_stop(struct net_devic
 
 	error = ipg_reset(dev, i);
 	if (error < 0) {
+		// FIXME FIXME FIXME: giant leak alert
 		return error;
 	}
 
-	/* Free all receive buffers. */
-	for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
-		pci_unmap_single(sp->pdev,
-				 sp->RxBuffDMAhandle[i].dmahandle,
-				 sp->RxBuffDMAhandle[i].len,
-				 PCI_DMA_FROMDEVICE);
-		if (sp->RxBuff[i] != NULL)
-			IPG_DEV_KFREE_SKB(sp->RxBuff[i]);
-		sp->RxBuff[i] = NULL;
-	}
+	ipg_rx_clear(sp);
 
-	/* Free all transmit buffers. */
-	for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
-		if (sp->TxBuff[i] != NULL)
-			IPG_DEV_KFREE_SKB(sp->TxBuff[i]);
-		sp->TxBuff[i] = NULL;
-	}
+	ipg_tx_clear(sp);
 
 	netif_stop_queue(dev);
 
-	/* Free memory associated with the RFDList. */
-	pci_free_consistent(sp->pdev,
-			    (sizeof(struct RFD) *
-			     IPG_RFDLIST_LENGTH),
-			    sp->RFDList, sp->RFDListDMAhandle);
-
-	/* Free memory associated with the TFDList. */
-	pci_free_consistent(sp->pdev,
-			    (sizeof(struct TFD) *
-			     IPG_TFDLIST_LENGTH),
-			    sp->TFDList, sp->TFDListDMAhandle);
+	pci_free_consistent(pdev, IPG_RX_RING_BYTES, sp->RFDList,
+			    sp->RFDListDMAhandle);
+	pci_free_consistent(pdev, IPG_TX_RING_BYTES, sp->TFDList,
+			    sp->TFDListDMAhandle);
 
 	/* Release interrupt line. */
 	free_irq(dev->irq, dev);
-- 
1.3.1


  parent reply	other threads:[~2006-05-01 23:15 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-04-27 14:29 IP1000 gigabit nic driver David Gómez
2006-04-27 18:56 ` Francois Romieu
2006-04-27 22:26   ` David Vrabel
2006-04-28  7:57     ` David Gómez
2006-04-28 10:58       ` Pekka Enberg
2006-04-28 11:37         ` David Gómez
2006-04-28 11:51           ` Pekka J Enberg
2006-04-28 11:59           ` Pekka J Enberg
2006-04-28 15:30             ` David Gómez
2006-04-28 16:08               ` Stephen Hemminger
2006-04-28 21:58             ` David Gómez
     [not found]               ` <20060428154251.23fcfc41@localhost.localdomain>
2006-04-29  7:30                 ` David Gómez
2006-04-29 10:29             ` Pekka Enberg
2006-04-29 10:35               ` Arjan van de Ven
2006-04-29 12:21               ` David Gómez
2006-04-29 20:35                 ` Pekka Enberg
2006-04-30  9:26                   ` Pekka Enberg
2006-04-30 23:40                     ` David Vrabel
2006-05-01  9:31                       ` Pekka Enberg
2006-05-03 12:43                         ` Andrew Morton
2006-05-03 13:06                           ` Pekka J Enberg
2006-05-03 14:15                             ` David Vrabel
2006-05-01  9:43                       ` Pekka Enberg
2006-05-01 11:32                       ` David Vrabel
2006-05-01 18:08                         ` Pekka Enberg
2006-05-01 23:10                           ` [PATCH 1/3] ipg: removal of unreachable code Francois Romieu
2006-05-02  6:36                             ` Pekka J Enberg
2006-05-01 23:10                           ` [PATCH 2/3] ipg: leaks in ipg_probe Francois Romieu
2006-05-02  6:41                             ` Pekka J Enberg
2006-05-02 18:33                               ` Francois Romieu
2006-05-02 19:04                                 ` Pekka Enberg
2006-05-02 22:30                                   ` [PATCH] ipg: removing more dead code David Gómez
2006-05-03 13:12                                     ` Pekka J Enberg
2006-05-03 21:00                                   ` [PATCH 2/3] ipg: leaks in ipg_probe David Gómez
2006-05-01 23:12                           ` Francois Romieu [this message]
2006-05-02  6:45                             ` [PATCH 3/3] ipg: plug leaks in the error path of ipg_nic_open Pekka J Enberg
2006-05-02 21:44                               ` [PATCH 1/2] ipg: sanitize the pci device table Francois Romieu
2006-05-02 21:45                               ` [PATCH 2/2] ipg: redundancy with mii.h Francois Romieu
2006-05-02 21:55                                 ` Francois Romieu
2006-05-03  6:16                                   ` Pekka J Enberg
2006-05-03 23:35                                     ` Francois Romieu
2006-05-04  6:52                                       ` David Vrabel
2006-05-05  0:24                                         ` Francois Romieu
2006-05-04 13:44                                       ` Pekka Enberg
2006-05-04 23:55                                         ` Francois Romieu
2006-05-20 21:03                                           ` David Vrabel
2006-05-21  7:23                                             ` Pekka Enberg
2006-05-21 10:16                                             ` Francois Romieu
2006-05-22  3:22                                               ` jesse\(建興\)
2006-05-23  6:50                                               ` jesse\(建興\)
2006-05-01 20:38                         ` IP1000 gigabit nic driver Francois Romieu
2006-05-01 20:41                           ` Lennert Buytenhek
2006-05-02  0:36                             ` David Vrabel
2006-05-01 19:39                   ` David Gómez
2006-04-29 12:58               ` David Vrabel
2006-04-28 11:59           ` Ingo Oeser
2006-04-28  7:54   ` David Gómez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060501231206.GD7419@electric-eye.fr.zoreil.com \
    --to=romieu@fr.zoreil.com \
    --cc=david@pleyades.net \
    --cc=dvrabel@cantab.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=penberg@cs.helsinki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®