diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-11-18 09:25:00 -0500 |
---|---|---|
committer | Luis Henriques <luis.henriques@canonical.com> | 2012-04-05 11:17:29 -0400 |
commit | 04673eceec08bebd021690a77e60abaabac38a07 (patch) | |
tree | ee86317374b073e14051b50b116062b88935e7c1 | |
parent | 43b5579781c620548de06e9179f77e9817427112 (diff) |
e1000e: Avoid wrong check on TX hang
BugLink: http://bugs.launchpad.net/bugs/971808
commit 09357b00255c233705b1cf6d76a8d147340545b8 upstream.
Based on the original patch submitted my Michael Wang
<wangyun@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 <wangyun@linux.vnet.ibm.com>
CC: Flavio Leitner <fbl@redhat.com>
Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/net/e1000e/e1000.h | 1 | ||||
-rw-r--r-- | 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 9549879e66a..8a265f3528d 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
@@ -311,6 +311,7 @@ struct e1000_adapter { | |||
311 | u32 txd_cmd; | 311 | u32 txd_cmd; |
312 | 312 | ||
313 | bool detect_tx_hung; | 313 | bool detect_tx_hung; |
314 | bool tx_hang_recheck; | ||
314 | u8 tx_timeout_factor; | 315 | u8 tx_timeout_factor; |
315 | 316 | ||
316 | u32 tx_int_delay; | 317 | u32 tx_int_delay; |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 3310c3d477d..5430a9a4a28 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -930,6 +930,7 @@ static void e1000_print_hw_hang(struct work_struct *work) | |||
930 | struct e1000_adapter *adapter = container_of(work, | 930 | struct e1000_adapter *adapter = container_of(work, |
931 | struct e1000_adapter, | 931 | struct e1000_adapter, |
932 | print_hang_task); | 932 | print_hang_task); |
933 | struct net_device *netdev = adapter->netdev; | ||
933 | struct e1000_ring *tx_ring = adapter->tx_ring; | 934 | struct e1000_ring *tx_ring = adapter->tx_ring; |
934 | unsigned int i = tx_ring->next_to_clean; | 935 | unsigned int i = tx_ring->next_to_clean; |
935 | unsigned int eop = tx_ring->buffer_info[i].next_to_watch; | 936 | unsigned int eop = tx_ring->buffer_info[i].next_to_watch; |
@@ -941,6 +942,21 @@ static void e1000_print_hw_hang(struct work_struct *work) | |||
941 | if (test_bit(__E1000_DOWN, &adapter->state)) | 942 | if (test_bit(__E1000_DOWN, &adapter->state)) |
942 | return; | 943 | return; |
943 | 944 | ||
945 | if (!adapter->tx_hang_recheck && | ||
946 | (adapter->flags2 & FLAG2_DMA_BURST)) { | ||
947 | /* May be block on write-back, flush and detect again | ||
948 | * flush pending descriptor writebacks to memory | ||
949 | */ | ||
950 | ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); | ||
951 | /* execute the writes immediately */ | ||
952 | e1e_flush(); | ||
953 | adapter->tx_hang_recheck = true; | ||
954 | return; | ||
955 | } | ||
956 | /* Real hang detected */ | ||
957 | adapter->tx_hang_recheck = false; | ||
958 | netif_stop_queue(netdev); | ||
959 | |||
944 | e1e_rphy(hw, PHY_STATUS, &phy_status); | 960 | e1e_rphy(hw, PHY_STATUS, &phy_status); |
945 | e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); | 961 | e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); |
946 | e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); | 962 | e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); |
@@ -1054,10 +1070,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
1054 | if (tx_ring->buffer_info[i].time_stamp && | 1070 | if (tx_ring->buffer_info[i].time_stamp && |
1055 | time_after(jiffies, tx_ring->buffer_info[i].time_stamp | 1071 | time_after(jiffies, tx_ring->buffer_info[i].time_stamp |
1056 | + (adapter->tx_timeout_factor * HZ)) && | 1072 | + (adapter->tx_timeout_factor * HZ)) && |
1057 | !(er32(STATUS) & E1000_STATUS_TXOFF)) { | 1073 | !(er32(STATUS) & E1000_STATUS_TXOFF)) |
1058 | schedule_work(&adapter->print_hang_task); | 1074 | schedule_work(&adapter->print_hang_task); |
1059 | netif_stop_queue(netdev); | 1075 | else |
1060 | } | 1076 | adapter->tx_hang_recheck = false; |
1061 | } | 1077 | } |
1062 | adapter->total_tx_bytes += total_tx_bytes; | 1078 | adapter->total_tx_bytes += total_tx_bytes; |
1063 | adapter->total_tx_packets += total_tx_packets; | 1079 | adapter->total_tx_packets += total_tx_packets; |
@@ -3678,6 +3694,7 @@ static int e1000_open(struct net_device *netdev) | |||
3678 | 3694 | ||
3679 | e1000_irq_enable(adapter); | 3695 | e1000_irq_enable(adapter); |
3680 | 3696 | ||
3697 | adapter->tx_hang_recheck = false; | ||
3681 | netif_start_queue(netdev); | 3698 | netif_start_queue(netdev); |
3682 | 3699 | ||
3683 | adapter->idle_check = true; | 3700 | adapter->idle_check = true; |