Commit 24cbc904 authored by Mallikarjuna R Chilakala's avatar Mallikarjuna R Chilakala Committed by Jeff Garzik

[PATCH] e1000: Avoid race between e1000_watchdog

3 Avoid race condition between e1000_watchdog and e1000_clean_tx_irq
Signed-off-by: default avatarMallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
Signed-off-by: default avatarGanesh Venkatesan <ganesh.venkatesan@intel.com>
Signed-off-by: default avatarJohn Ronciak <john.ronciak@intel.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 1992e926
...@@ -222,6 +222,7 @@ struct e1000_adapter { ...@@ -222,6 +222,7 @@ struct e1000_adapter {
uint32_t tx_fifo_size; uint32_t tx_fifo_size;
atomic_t tx_fifo_stall; atomic_t tx_fifo_stall;
boolean_t pcix_82544; boolean_t pcix_82544;
boolean_t detect_tx_hung;
/* RX */ /* RX */
struct e1000_desc_ring rx_ring; struct e1000_desc_ring rx_ring;
......
...@@ -1432,7 +1432,6 @@ e1000_watchdog(unsigned long data) ...@@ -1432,7 +1432,6 @@ e1000_watchdog(unsigned long data)
struct e1000_adapter *adapter = (struct e1000_adapter *) data; struct e1000_adapter *adapter = (struct e1000_adapter *) data;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *txdr = &adapter->tx_ring;
unsigned int i;
uint32_t link; uint32_t link;
e1000_check_for_link(&adapter->hw); e1000_check_for_link(&adapter->hw);
...@@ -1512,12 +1511,8 @@ e1000_watchdog(unsigned long data) ...@@ -1512,12 +1511,8 @@ e1000_watchdog(unsigned long data)
/* Cause software interrupt to ensure rx ring is cleaned */ /* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
/* Early detection of hung controller */ /* Force detection of hung controller every watchdog period*/
i = txdr->next_to_clean; adapter->detect_tx_hung = TRUE;
if(txdr->buffer_info[i].dma &&
time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
netif_stop_queue(netdev);
/* Reset the timer */ /* Reset the timer */
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
...@@ -2245,6 +2240,16 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) ...@@ -2245,6 +2240,16 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
netif_wake_queue(netdev); netif_wake_queue(netdev);
spin_unlock(&adapter->tx_lock); spin_unlock(&adapter->tx_lock);
if(adapter->detect_tx_hung) {
/* 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[i].dma &&
time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) &&
!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
netif_stop_queue(netdev);
}
return cleaned; return cleaned;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment