mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 16:49:22 +00:00
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>
This commit is contained in:
parent
be0f071956
commit
cdd7549e27
1 changed files with 9 additions and 6 deletions
|
@ -2733,8 +2733,9 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
|
||||||
size -= 4;
|
size -= 4;
|
||||||
|
|
||||||
buffer_info->length = size;
|
buffer_info->length = size;
|
||||||
buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
|
/* set time_stamp *before* dma to help avoid a possible race */
|
||||||
buffer_info->time_stamp = jiffies;
|
buffer_info->time_stamp = jiffies;
|
||||||
|
buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
|
||||||
buffer_info->next_to_watch = i;
|
buffer_info->next_to_watch = i;
|
||||||
|
|
||||||
len -= size;
|
len -= size;
|
||||||
|
@ -2774,8 +2775,8 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
|
||||||
size -= 4;
|
size -= 4;
|
||||||
|
|
||||||
buffer_info->length = size;
|
buffer_info->length = size;
|
||||||
buffer_info->dma = map[f] + offset;
|
|
||||||
buffer_info->time_stamp = jiffies;
|
buffer_info->time_stamp = jiffies;
|
||||||
|
buffer_info->dma = map[f] + offset;
|
||||||
buffer_info->next_to_watch = i;
|
buffer_info->next_to_watch = i;
|
||||||
|
|
||||||
len -= size;
|
len -= size;
|
||||||
|
@ -3459,7 +3460,9 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||||
* sees the new next_to_clean.
|
* sees the new next_to_clean.
|
||||||
*/
|
*/
|
||||||
smp_mb();
|
smp_mb();
|
||||||
if (netif_queue_stopped(netdev)) {
|
|
||||||
|
if (netif_queue_stopped(netdev) &&
|
||||||
|
!(test_bit(__E1000_DOWN, &adapter->flags))) {
|
||||||
netif_wake_queue(netdev);
|
netif_wake_queue(netdev);
|
||||||
++adapter->restart_queue;
|
++adapter->restart_queue;
|
||||||
}
|
}
|
||||||
|
@ -3469,8 +3472,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||||
/* Detect a transmit hang in hardware, this serializes the
|
/* Detect a transmit hang in hardware, this serializes the
|
||||||
* check with the clearing of time_stamp and movement of i */
|
* check with the clearing of time_stamp and movement of i */
|
||||||
adapter->detect_tx_hung = false;
|
adapter->detect_tx_hung = false;
|
||||||
if (tx_ring->buffer_info[i].time_stamp &&
|
if (tx_ring->buffer_info[eop].time_stamp &&
|
||||||
time_after(jiffies, tx_ring->buffer_info[i].time_stamp +
|
time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
|
||||||
(adapter->tx_timeout_factor * HZ))
|
(adapter->tx_timeout_factor * HZ))
|
||||||
&& !(er32(STATUS) & E1000_STATUS_TXOFF)) {
|
&& !(er32(STATUS) & E1000_STATUS_TXOFF)) {
|
||||||
|
|
||||||
|
@ -3492,7 +3495,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||||
readl(hw->hw_addr + tx_ring->tdt),
|
readl(hw->hw_addr + tx_ring->tdt),
|
||||||
tx_ring->next_to_use,
|
tx_ring->next_to_use,
|
||||||
tx_ring->next_to_clean,
|
tx_ring->next_to_clean,
|
||||||
tx_ring->buffer_info[i].time_stamp,
|
tx_ring->buffer_info[eop].time_stamp,
|
||||||
eop,
|
eop,
|
||||||
jiffies,
|
jiffies,
|
||||||
eop_desc->upper.fields.status);
|
eop_desc->upper.fields.status);
|
||||||
|
|
Loading…
Reference in a new issue