diff options
| author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2009-09-25 08:18:07 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-09-26 23:15:42 -0400 |
| commit | cdd7549e27bf5e8abc4e19d5e8d110b8252b4fe4 (patch) | |
| tree | 20682463abca2954c6a50ec1ac77971e989becc3 | |
| parent | be0f071956e2142e2e88e9d6d5655ba1c75d07c8 (diff) | |
e1000: fix tx waking queue after queue stopped during shutdown
This fix closes a race where the adapter can be shutting down while
hard_start_xmit is being called and interrupts are being handled.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/e1000/e1000_main.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 11508afdfdb9..8c64363faaf3 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -2733,8 +2733,9 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
| 2733 | size -= 4; | 2733 | size -= 4; |
| 2734 | 2734 | ||
| 2735 | buffer_info->length = size; | 2735 | buffer_info->length = size; |
| 2736 | buffer_info->dma = skb_shinfo(skb)->dma_head + offset; | 2736 | /* set time_stamp *before* dma to help avoid a possible race */ |
| 2737 | buffer_info->time_stamp = jiffies; | 2737 | buffer_info->time_stamp = jiffies; |
| 2738 | buffer_info->dma = skb_shinfo(skb)->dma_head + offset; | ||
| 2738 | buffer_info->next_to_watch = i; | 2739 | buffer_info->next_to_watch = i; |
| 2739 | 2740 | ||
| 2740 | len -= size; | 2741 | len -= size; |
| @@ -2774,8 +2775,8 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
| 2774 | size -= 4; | 2775 | size -= 4; |
| 2775 | 2776 | ||
| 2776 | buffer_info->length = size; | 2777 | buffer_info->length = size; |
| 2777 | buffer_info->dma = map[f] + offset; | ||
| 2778 | buffer_info->time_stamp = jiffies; | 2778 | buffer_info->time_stamp = jiffies; |
| 2779 | buffer_info->dma = map[f] + offset; | ||
| 2779 | buffer_info->next_to_watch = i; | 2780 | buffer_info->next_to_watch = i; |
| 2780 | 2781 | ||
| 2781 | len -= size; | 2782 | len -= size; |
| @@ -3459,7 +3460,9 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
| 3459 | * sees the new next_to_clean. | 3460 | * sees the new next_to_clean. |
| 3460 | */ | 3461 | */ |
| 3461 | smp_mb(); | 3462 | smp_mb(); |
| 3462 | if (netif_queue_stopped(netdev)) { | 3463 | |
| 3464 | if (netif_queue_stopped(netdev) && | ||
| 3465 | !(test_bit(__E1000_DOWN, &adapter->flags))) { | ||
| 3463 | netif_wake_queue(netdev); | 3466 | netif_wake_queue(netdev); |
| 3464 | ++adapter->restart_queue; | 3467 | ++adapter->restart_queue; |
| 3465 | } | 3468 | } |
| @@ -3469,8 +3472,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
| 3469 | /* Detect a transmit hang in hardware, this serializes the | 3472 | /* Detect a transmit hang in hardware, this serializes the |
| 3470 | * check with the clearing of time_stamp and movement of i */ | 3473 | * check with the clearing of time_stamp and movement of i */ |
| 3471 | adapter->detect_tx_hung = false; | 3474 | adapter->detect_tx_hung = false; |
| 3472 | if (tx_ring->buffer_info[i].time_stamp && | 3475 | if (tx_ring->buffer_info[eop].time_stamp && |
| 3473 | time_after(jiffies, tx_ring->buffer_info[i].time_stamp + | 3476 | time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + |
| 3474 | (adapter->tx_timeout_factor * HZ)) | 3477 | (adapter->tx_timeout_factor * HZ)) |
| 3475 | && !(er32(STATUS) & E1000_STATUS_TXOFF)) { | 3478 | && !(er32(STATUS) & E1000_STATUS_TXOFF)) { |
| 3476 | 3479 | ||
| @@ -3492,7 +3495,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
| 3492 | readl(hw->hw_addr + tx_ring->tdt), | 3495 | readl(hw->hw_addr + tx_ring->tdt), |
| 3493 | tx_ring->next_to_use, | 3496 | tx_ring->next_to_use, |
| 3494 | tx_ring->next_to_clean, | 3497 | tx_ring->next_to_clean, |
| 3495 | tx_ring->buffer_info[i].time_stamp, | 3498 | tx_ring->buffer_info[eop].time_stamp, |
| 3496 | eop, | 3499 | eop, |
| 3497 | jiffies, | 3500 | jiffies, |
| 3498 | eop_desc->upper.fields.status); | 3501 | eop_desc->upper.fields.status); |
