* [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues
@ 2009-03-26 7:58 Jeff Kirsher
2009-03-26 7:59 ` [net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring Jeff Kirsher
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Jeff Kirsher @ 2009-03-26 7:58 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
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 = map + offset;
+ buffer_info->dma = map[0] + offset;
buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;
len -= size;
offset += size;
count++;
- if (unlikely(++i == tx_ring->count)) i = 0;
+ if (len) {
+ i++;
+ if (unlikely(i == tx_ring->count))
+ i = 0;
+ }
}
for (f = 0; f < nr_frags; f++) {
@@ -2968,11 +2973,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
- map = skb_shinfo(skb)->dma_maps[f + 1];
offset = 0;
while (len) {
- struct e1000_buffer *buffer_info;
+ i++;
+ if (unlikely(i == tx_ring->count))
+ i = 0;
+
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
/* Workaround for premature desc write-backs
@@ -2988,21 +2995,18 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
size -= 4;
buffer_info->length = size;
- buffer_info->dma = map + offset;
+ buffer_info->dma = map[f + 1] + offset;
buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;
len -= size;
offset += size;
count++;
- if (unlikely(++i == tx_ring->count)) i = 0;
}
}
- i = (i == 0) ? tx_ring->count - 1 : i - 1;
tx_ring->buffer_info[i].skb = skb;
tx_ring->buffer_info[first].next_to_watch = i;
- smp_wmb();
return count;
}
@@ -3318,14 +3322,20 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (likely(skb->protocol == htons(ETH_P_IP)))
tx_flags |= E1000_TX_FLAGS_IPV4;
- e1000_tx_queue(adapter, tx_ring, tx_flags,
- e1000_tx_map(adapter, tx_ring, skb, first,
- max_per_txd, nr_frags, mss));
+ count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd,
+ nr_frags, mss);
- netdev->trans_start = jiffies;
+ if (count) {
+ e1000_tx_queue(adapter, tx_ring, tx_flags, count);
+ netdev->trans_start = jiffies;
+ /* Make sure there is space in the ring for the next send. */
+ e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
- /* Make sure there is space in the ring for the next send. */
- e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
+ } else {
+ dev_kfree_skb_any(skb);
+ tx_ring->buffer_info[first].time_stamp = 0;
+ tx_ring->next_to_use = first;
+ }
return NETDEV_TX_OK;
}
@@ -3842,12 +3852,7 @@ 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 = false;
- /*
- * read barrier to make sure that the ->dma member and time
- * stamp are updated fully
- */
- smp_rmb();
- if (tx_ring->buffer_info[eop].dma &&
+ if (tx_ring->buffer_info[eop].time_stamp &&
time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
(adapter->tx_timeout_factor * HZ))
&& !(er32(STATUS) & E1000_STATUS_TXOFF)) {
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring
2009-03-26 7:58 [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues Jeff Kirsher
@ 2009-03-26 7:59 ` Jeff Kirsher
2009-03-26 8:02 ` David Miller
2009-03-26 7:59 ` [net-next PATCH 3/3] e1000: fix close race with interrupt Jeff Kirsher
2009-03-26 8:01 ` [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues David Miller
2 siblings, 1 reply; 6+ messages in thread
From: Jeff Kirsher @ 2009-03-26 7:59 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
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 of a sort for tx, to avoid endless transmit cleanup */
- if (count++ == E1000_TX_WEIGHT)
- break;
}
tx_ring->next_to_clean = i;
@@ -3852,8 +3849,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 = false;
- if (tx_ring->buffer_info[eop].time_stamp &&
- time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
+ if (tx_ring->buffer_info[i].time_stamp &&
+ time_after(jiffies, tx_ring->buffer_info[i].time_stamp +
(adapter->tx_timeout_factor * HZ))
&& !(er32(STATUS) & E1000_STATUS_TXOFF)) {
@@ -3875,7 +3872,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
readl(hw->hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
tx_ring->next_to_clean,
- tx_ring->buffer_info[eop].time_stamp,
+ tx_ring->buffer_info[i].time_stamp,
eop,
jiffies,
eop_desc->upper.fields.status);
@@ -3886,7 +3883,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
adapter->total_tx_packets += total_tx_packets;
adapter->net_stats.tx_bytes += total_tx_bytes;
adapter->net_stats.tx_packets += total_tx_packets;
- return cleaned;
+ return (count < tx_ring->count);
}
/**
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [net-next PATCH 3/3] e1000: fix close race with interrupt
2009-03-26 7:58 [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues Jeff Kirsher
2009-03-26 7:59 ` [net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring Jeff Kirsher
@ 2009-03-26 7:59 ` Jeff Kirsher
2009-03-26 8:02 ` David Miller
2009-03-26 8:01 ` [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues David Miller
2 siblings, 1 reply; 6+ messages in thread
From: Jeff Kirsher @ 2009-03-26 7:59 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alan Cox, Jesse Brandeburg, Jeff Kirsher
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)
adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0;
__napi_schedule(&adapter->napi);
- } else
+ } else {
/* this really should not happen! if it does it is basically a
* bug, but not a hard error, so enable ints and continue */
- e1000_irq_enable(adapter);
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ e1000_irq_enable(adapter);
+ }
return IRQ_HANDLED;
}
@@ -3777,7 +3796,8 @@ static int e1000_clean(struct napi_struct *napi, int budget)
if (likely(adapter->itr_setting & 3))
e1000_set_itr(adapter);
napi_complete(napi);
- e1000_irq_enable(adapter);
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ e1000_irq_enable(adapter);
}
return work_done;
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues
2009-03-26 7:58 [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues Jeff Kirsher
2009-03-26 7:59 ` [net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring Jeff Kirsher
2009-03-26 7:59 ` [net-next PATCH 3/3] e1000: fix close race with interrupt Jeff Kirsher
@ 2009-03-26 8:01 ` David Miller
2 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2009-03-26 8:01 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, alexander.h.duyck
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 26 Mar 2009 00:58:45 -0700
> 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>
Applied.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring
2009-03-26 7:59 ` [net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring Jeff Kirsher
@ 2009-03-26 8:02 ` David Miller
0 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2009-03-26 8:02 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, alexander.h.duyck
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 26 Mar 2009 00:59:04 -0700
> 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>
Applied.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [net-next PATCH 3/3] e1000: fix close race with interrupt
2009-03-26 7:59 ` [net-next PATCH 3/3] e1000: fix close race with interrupt Jeff Kirsher
@ 2009-03-26 8:02 ` David Miller
0 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2009-03-26 8:02 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, alan, jesse.brandeburg
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 26 Mar 2009 00:59:22 -0700
> 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>
Applied.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-03-26 8:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-26 7:58 [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues Jeff Kirsher
2009-03-26 7:59 ` [net-next PATCH 2/3] e1000: cleanup clean_tx_irq routine so that it completely cleans ring Jeff Kirsher
2009-03-26 8:02 ` David Miller
2009-03-26 7:59 ` [net-next PATCH 3/3] e1000: fix close race with interrupt Jeff Kirsher
2009-03-26 8:02 ` David Miller
2009-03-26 8:01 ` [net-next PATCH 1/3] e1000: fix tx hang detect logic and address dma mapping issues David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).