# fixed in 3.0.y. see also bug#663533
tags 657689 + upstream patch moreinfo fixed-upstream
quit

Matthew Ingersoll wrote:

> Searching around, this may already be fixed elsewhere.  See the following
> reports:
>
> https://bugzilla.redhat.com/show_bug.cgi?id=785806
>
> http://www.mail-archive.com/e1000-devel@lists.sourceforge.net/msg04658.html

Thanks.  Sounds worth a try.  Please test the attached patch, for example
following instructions from [1].

Hope that helps,
Jonathan

[1] 
http://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s-common-official
or the corresponding page from the debian-kernel-handbook package
From: Jeff Kirsher <jeffrey.t.kirs...@intel.com>
Date: Fri, 18 Nov 2011 14:25:00 +0000
Subject: e1000e: Avoid wrong check on TX hang

commit 09357b00255c233705b1cf6d76a8d147340545b8 upstream.

Based on the original patch submitted my Michael Wang
<wang...@linux.vnet.ibm.com>.
Descriptors may not be write-back while checking TX hang with flag
FLAG2_DMA_BURST on.
So when we detect hang, we just flush the descriptor and detect
again for once.

-v2 change 1 to true and 0 to false and remove extra ()

CC: Michael Wang <wang...@linux.vnet.ibm.com>
CC: Flavio Leitner <f...@redhat.com>
Acked-by: Jesse Brandeburg <jesse.brandeb...@intel.com>
Tested-by: Aaron Brown <aaron.f.br...@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirs...@intel.com>
Signed-off-by: Jonathan Nieder <jrnie...@gmail.com>
---
 drivers/net/e1000e/e1000.h  |    1 +
 drivers/net/e1000e/netdev.c |   23 ++++++++++++++++++++---
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index e610e1369053..687f176114e7 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -309,6 +309,7 @@ struct e1000_adapter {
        u32 txd_cmd;
 
        bool detect_tx_hung;
+       bool tx_hang_recheck;
        u8 tx_timeout_factor;
 
        u32 tx_int_delay;
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index dcdc472c363b..9c2cd8bfde3b 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -928,6 +928,7 @@ static void e1000_print_hw_hang(struct work_struct *work)
        struct e1000_adapter *adapter = container_of(work,
                                                     struct e1000_adapter,
                                                     print_hang_task);
+       struct net_device *netdev = adapter->netdev;
        struct e1000_ring *tx_ring = adapter->tx_ring;
        unsigned int i = tx_ring->next_to_clean;
        unsigned int eop = tx_ring->buffer_info[i].next_to_watch;
@@ -939,6 +940,21 @@ static void e1000_print_hw_hang(struct work_struct *work)
        if (test_bit(__E1000_DOWN, &adapter->state))
                return;
 
+       if (!adapter->tx_hang_recheck &&
+           (adapter->flags2 & FLAG2_DMA_BURST)) {
+               /* May be block on write-back, flush and detect again
+                * flush pending descriptor writebacks to memory
+                */
+               ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+               /* execute the writes immediately */
+               e1e_flush();
+               adapter->tx_hang_recheck = true;
+               return;
+       }
+       /* Real hang detected */
+       adapter->tx_hang_recheck = false;
+       netif_stop_queue(netdev);
+
        e1e_rphy(hw, PHY_STATUS, &phy_status);
        e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status);
        e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status);
@@ -1052,10 +1068,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter 
*adapter)
                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)) {
+                   !(er32(STATUS) & E1000_STATUS_TXOFF))
                        schedule_work(&adapter->print_hang_task);
-                       netif_stop_queue(netdev);
-               }
+               else
+                       adapter->tx_hang_recheck = false;
        }
        adapter->total_tx_bytes += total_tx_bytes;
        adapter->total_tx_packets += total_tx_packets;
@@ -3665,6 +3681,7 @@ static int e1000_open(struct net_device *netdev)
 
        e1000_irq_enable(adapter);
 
+       adapter->tx_hang_recheck = false;
        netif_start_queue(netdev);
 
        adapter->idle_check = true;
-- 
1.7.10

Reply via email to