[net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring

Previous thread: [PATCH] net: fix unaligned memory accesses in ASIX by Giuseppe CAVALLARO on Wednesday, March 25, 2009 - 11:52 pm. (6 messages)

Next thread: Re: [PATCH 1/3] netfilter: fix warning about invalid const usage by David Miller on Thursday, March 26, 2009 - 1:03 am. (1 message)
From: Jeff Kirsher
Date: Thursday, March 26, 2009 - 12:58 am

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

This patch changes the dma mapping to better support
skb_dma_map/skb_dma_unmap and addresses and redefines the tx hang logic to
be based off of time stamp instead of if the dma field is populated

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

 drivers/net/e1000/e1000_main.c |   55 ++++++++++++++++++++++------------------
 1 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 1f390ce..e60faab 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2056,6 +2056,7 @@ static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
 		dev_kfree_skb_any(buffer_info->skb);
 		buffer_info->skb = NULL;
 	}
+	buffer_info->time_stamp = 0;
 	/* buffer_info must be completely set up in the transmit path */
 }
 
@@ -2903,24 +2904,24 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
 			unsigned int mss)
 {
 	struct e1000_hw *hw = &adapter->hw;
+	struct e1000_buffer *buffer_info;
 	unsigned int len = skb_headlen(skb);
 	unsigned int offset, size, count = 0, i;
 	unsigned int f;
-	dma_addr_t map;
+	dma_addr_t *map;
 
 	i = tx_ring->next_to_use;
 
 	if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) {
 		dev_err(&adapter->pdev->dev, "TX DMA map failed\n");
-		dev_kfree_skb(skb);
-		return -2;
+		return 0;
 	}
 
-	map = skb_shinfo(skb)->dma_maps[0];
+	map = skb_shinfo(skb)->dma_maps;
 	offset = 0;
 
 	while (len) {
-		struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i];
+		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, max_per_txd);
 		/* Workaround for Controller erratum --
 		 * descriptor for non-tso packet in a linear SKB that follows a
@@ -2953,14 +2954,18 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
 			size -= 4;
 
 		buffer_info->length = size;
-		buffer_info->dma = ...
From: Jeff Kirsher
Date: Thursday, March 26, 2009 - 12:59 am

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

The tx cleanup routine was stopping after 64 packets and this was causing
issues resulting in the ring not being completely cleaned.

This change updates the driver to clean the entire ring and if it doesn't
it then will retry on the next pass.

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

 drivers/net/e1000/e1000_main.c |   21 +++++++++------------
 1 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index e60faab..5c61b92 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3769,7 +3769,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
 	adapter->clean_rx(adapter, &adapter->rx_ring[0],
 	                  &work_done, budget);
 
-	if (tx_cleaned)
+	if (!tx_cleaned)
 		work_done = budget;
 
 	/* If budget not fully consumed, exit the polling mode */
@@ -3796,15 +3796,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 = false;
+	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 = false; !cleaned; ) {
+	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+	       (count < tx_ring->count)) {
+		for (cleaned = false; !cleaned; count++) {
 			tx_desc = E1000_TX_DESC(*tx_ring, i);
 			buffer_info = &tx_ring->buffer_info[i];
 			cleaned = (i == eop);
@@ -3827,10 +3828,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 ...
From: David Miller
Date: Thursday, March 26, 2009 - 1:02 am

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

Applied.
--

From: Jeff Kirsher
Date: Thursday, March 26, 2009 - 12:59 am

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

this is in regards to
http://bugzilla.kernel.org/show_bug.cgi?id=12876

where it appears that e1000 can leave its interrupt enabled after
exiting the driver.  Fix the bug by making the interrupt enable
paths more aware of the driver exiting.

Thanks to Alan Cox for the poke and initial investigation.

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

 drivers/net/e1000/e1000_main.c |   28 ++++++++++++++++++++++++----
 1 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 5c61b92..93b861d 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -577,12 +577,30 @@ out:
 
 void e1000_down(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
+	u32 rctl, tctl;
 
 	/* signal that we're down so the interrupt handler does not
 	 * reschedule our watchdog timer */
 	set_bit(__E1000_DOWN, &adapter->flags);
 
+	/* disable receives in the hardware */
+	rctl = er32(RCTL);
+	ew32(RCTL, rctl & ~E1000_RCTL_EN);
+	/* flush and sleep below */
+
+	/* can be netif_tx_disable when NETIF_F_LLTX is removed */
+	netif_stop_queue(netdev);
+
+	/* disable transmits in the hardware */
+	tctl = er32(TCTL);
+	tctl &= ~E1000_TCTL_EN;
+	ew32(TCTL, tctl);
+	/* flush both disables and wait for them to finish */
+	E1000_WRITE_FLUSH();
+	msleep(10);
+
 	napi_disable(&adapter->napi);
 
 	e1000_irq_disable(adapter);
@@ -595,7 +613,6 @@ void e1000_down(struct e1000_adapter *adapter)
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
 
 	e1000_reset(adapter);
 	e1000_clean_all_tx_rings(adapter);
@@ -3744,10 +3761,12 @@ static irqreturn_t e1000_intr(int irq, void *data)
 ...
From: David Miller
Date: Thursday, March 26, 2009 - 1:02 am

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

Applied.
--

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

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


Applied.
--

Previous thread: [PATCH] net: fix unaligned memory accesses in ASIX by Giuseppe CAVALLARO on Wednesday, March 25, 2009 - 11:52 pm. (6 messages)

Next thread: Re: [PATCH 1/3] netfilter: fix warning about invalid const usage by David Miller on Thursday, March 26, 2009 - 1:03 am. (1 message)