[net-next PATCH 3/4] e1000e: fix close interrupt race

Previous thread: Re: [PATCH 3/3] netfilter: fix nf_logger name in ebt_ulog. by David Miller on Thursday, March 26, 2009 - 1:04 am. (1 message)

Next thread: [PATCH net-2.6 ] core: remove unneeded include in net/core/utils.c. by Rami Rosen on Thursday, March 26, 2009 - 1:10 am. (2 messages)
From: Jeff Kirsher
Date: Thursday, March 26, 2009 - 1:05 am

From: Alexander Duyck <alexander.h.duyck@intel.com>

This change updates the e1000e tx cleanup routine to more closely match
what already exists in igb and e1000.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/netdev.c |   19 ++++++++-----------
 1 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 15424ba..1797412 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -621,15 +621,16 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
 	struct e1000_buffer *buffer_info;
 	unsigned int i, eop;
 	unsigned int count = 0;
-	bool cleaned = 0;
+	bool cleaned;
 	unsigned int total_tx_bytes = 0, total_tx_packets = 0;
 
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->buffer_info[i].next_to_watch;
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
-	while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
-		for (cleaned = 0; !cleaned; ) {
+	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+	       (count < tx_ring->count)) {
+		for (cleaned = 0; !cleaned; count++) {
 			tx_desc = E1000_TX_DESC(*tx_ring, i);
 			buffer_info = &tx_ring->buffer_info[i];
 			cleaned = (i == eop);
@@ -655,10 +656,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
 
 		eop = tx_ring->buffer_info[i].next_to_watch;
 		eop_desc = E1000_TX_DESC(*tx_ring, eop);
-#define E1000_TX_WEIGHT 64
-		/* weight of a sort for tx, to avoid endless transmit cleanup */
-		if (count++ == E1000_TX_WEIGHT)
-			break;
 	}
 
 	tx_ring->next_to_clean = i;
@@ -682,8 +679,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
 		/* Detect a transmit hang in hardware, this serializes the
 		 * check with the clearing of time_stamp and movement of i */
 		adapter->detect_tx_hung = 0;
-		if (tx_ring->buffer_info[eop].time_stamp &&
-		    time_after(jiffies, ...
From: Jeff Kirsher
Date: Thursday, March 26, 2009 - 1:05 am

From: Jesse Brandeburg <jesse.brandeburg@intel.com>

e1000e (and e1000, igb, ixgbe, ixgb) all do a series of operations each
time a multicast address is added.  The flow goes something like

1) stack adds one multicast address
2) stack passes whole current list of unicast and multicast addresses to
   driver
3) driver clears entire list in hardware
4) driver programs each multicast address using iomem in a loop

This was causing multicast packets to be lost during the reprogramming
process.

reference with test program:
http://kerneltrap.org/mailarchive/linux-netdev/2009/3/14/5160514/thread

Thanks to Dave Boutcher for his report and test program.

This driver fix prepares an array all at once in memory and programs it in
one shot to the hardware, not requiring an "erase" cycle.  It would still
be possible for packets to be dropped while the receiver is off during
reprogramming.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
CC: Dave Boutcher <daveboutcher@gmail.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/lib.c |   62 +++++++++++++---------------------------------
 1 files changed, 18 insertions(+), 44 deletions(-)

diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index ac2f34e..18a4f59 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -159,41 +159,6 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
 }
 
 /**
- *  e1000_mta_set - Set multicast filter table address
- *  @hw: pointer to the HW structure
- *  @hash_value: determines the MTA register and bit to set
- *
- *  The multicast table address is a register array of 32-bit registers.
- *  The hash_value is used to determine what register the bit is in, the
- *  current value is read, the new bit is OR'd in and the new value is
- *  written back into the register.
- **/
-static void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
-{
-	u32 hash_bit, hash_reg, mta;
-
-	/*
-	 * The MTA is a ...
From: David Miller
Date: Thursday, March 26, 2009 - 1:12 am

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.
--

From: Jeff Kirsher
Date: Thursday, March 26, 2009 - 1:05 am

From: Jesse Brandeburg <jesse.brandeburg@intel.com>

As noticed by Alan Cox, it is possible for e1000e to exit its interrupt
handler or NAPI with interrupts enabled even when the driver is unloading or
being configured administratively down.

fix related to fix for: http://bugzilla.kernel.org/show_bug.cgi?id=12876

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
CC: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/netdev.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 1797412..b4ae046 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -1261,7 +1261,8 @@ static irqreturn_t e1000_msix_other(int irq, void *data)
 	u32 icr = er32(ICR);
 
 	if (!(icr & E1000_ICR_INT_ASSERTED)) {
-		ew32(IMS, E1000_IMS_OTHER);
+		if (!test_bit(__E1000_DOWN, &adapter->state))
+			ew32(IMS, E1000_IMS_OTHER);
 		return IRQ_NONE;
 	}
 
@@ -1278,7 +1279,8 @@ static irqreturn_t e1000_msix_other(int irq, void *data)
 	}
 
 no_link_interrupt:
-	ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);
+	if (!test_bit(__E1000_DOWN, &adapter->state))
+		ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);
 
 	return IRQ_HANDLED;
 }
@@ -2015,10 +2017,12 @@ clean_rx:
 		if (adapter->itr_setting & 3)
 			e1000_set_itr(adapter);
 		napi_complete(napi);
-		if (adapter->msix_entries)
-			ew32(IMS, adapter->rx_ring->ims_val);
-		else
-			e1000_irq_enable(adapter);
+		if (!test_bit(__E1000_DOWN, &adapter->state)) {
+			if (adapter->msix_entries)
+				ew32(IMS, adapter->rx_ring->ims_val);
+			else
+				e1000_irq_enable(adapter);
+		}
 	}
 
 	return work_done;

--

From: David Miller
Date: Thursday, March 26, 2009 - 1:12 am

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.
--

From: Jeff Kirsher
Date: Thursday, March 26, 2009 - 1:06 am

From: Jesse Brandeburg <jesse.brandeburg@intel.com>

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/netdev.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index b4ae046..bfb2d6c 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -48,7 +48,7 @@
 
 #include "e1000.h"
 
-#define DRV_VERSION "0.3.3.4-k2"
+#define DRV_VERSION "0.3.3.4-k4"
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 

--

From: David Miller
Date: Thursday, March 26, 2009 - 1:12 am

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.
--

From: David Miller
Date: Thursday, March 26, 2009 - 1:12 am

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.
--

Previous thread: Re: [PATCH 3/3] netfilter: fix nf_logger name in ebt_ulog. by David Miller on Thursday, March 26, 2009 - 1:04 am. (1 message)

Next thread: [PATCH net-2.6 ] core: remove unneeded include in net/core/utils.c. by Rami Rosen on Thursday, March 26, 2009 - 1:10 am. (2 messages)