| From 09357b00255c233705b1cf6d76a8d147340545b8 Mon Sep 17 00:00:00 2001 |
| From: Jeff Kirsher <jeffrey.t.kirsher@intel.com> |
| Date: Fri, 18 Nov 2011 14:25:00 +0000 |
| Subject: e1000e: Avoid wrong check on TX hang |
| |
| From: Jeff Kirsher <jeffrey.t.kirsher@intel.com> |
| |
| 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> |
| |
| --- |
| drivers/net/ethernet/intel/e1000e/e1000.h | 1 + |
| drivers/net/ethernet/intel/e1000e/netdev.c | 23 ++++++++++++++++++++--- |
| 2 files changed, 21 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/net/ethernet/intel/e1000e/e1000.h |
| +++ b/drivers/net/ethernet/intel/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; |
| --- a/drivers/net/ethernet/intel/e1000e/netdev.c |
| +++ b/drivers/net/ethernet/intel/e1000e/netdev.c |
| @@ -1030,6 +1030,7 @@ static void e1000_print_hw_hang(struct w |
| 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; |
| @@ -1041,6 +1042,21 @@ static void e1000_print_hw_hang(struct w |
| 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); |
| @@ -1154,10 +1170,10 @@ static bool e1000_clean_tx_irq(struct e1 |
| 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; |
| @@ -3782,6 +3798,7 @@ static int e1000_open(struct net_device |
| |
| e1000_irq_enable(adapter); |
| |
| + adapter->tx_hang_recheck = false; |
| netif_start_queue(netdev); |
| |
| adapter->idle_check = true; |