[PATCH] e1000: Avoid race between e1000_watchdog
Linux Kernel Mailing List <[email protected]> Thu, 24 Feb 2005 05:40:41 +0000
| Newsgroups | gmane.linux.kernel.commits.2-4 |
|---|---|
| Message-ID | <[email protected]> |
ChangeSet 1.1548.1.3, 2005/02/24 00:40:41-05:00, [email protected] [PATCH] e1000: Avoid race between e1000_watchdog 3 Avoid race condition between e1000_watchdog and e1000_clean_tx_irq Signed-off-by: Mallikarjuna R Chilakala <[email protected]> Signed-off-by: Ganesh Venkatesan <[email protected]> Signed-off-by: John Ronciak <[email protected]> Signed-off-by: Jeff Garzik <[email protected]> e1000.h | 1 + e1000_main.c | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h --- a/drivers/net/e1000/e1000.h 2005-03-04 12:02:48 -08:00 +++ b/drivers/net/e1000/e1000.h 2005-03-04 12:02:48 -08:00 @@ -224,6 +224,7 @@ uint32_t tx_fifo_size; atomic_t tx_fifo_stall; boolean_t pcix_82544; + boolean_t detect_tx_hung; /* RX */ struct e1000_desc_ring rx_ring; diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c 2005-03-04 12:02:48 -08:00 +++ b/drivers/net/e1000/e1000_main.c 2005-03-04 12:02:48 -08:00 @@ -1422,7 +1422,6 @@ struct e1000_adapter *adapter = (struct e1000_adapter *) data; struct net_device *netdev = adapter->netdev; struct e1000_desc_ring *txdr = &adapter->tx_ring; - unsigned int i; uint32_t link; e1000_check_for_link(&adapter->hw); @@ -1502,12 +1501,8 @@ /* Cause software interrupt to ensure rx ring is cleaned */ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); - /* Early detection of hung controller */ - i = txdr->next_to_clean; - 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); + /* Force detection of hung controller every watchdog period*/ + adapter->detect_tx_hung = TRUE; /* Reset the timer */ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); @@ -2226,6 +2221,16 @@ netif_wake_queue(netdev); 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; }