diff options
author | Greg Rose <gregory.v.rose@intel.com> | 2011-06-03 05:53:24 +0200 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-27 08:31:09 +0200 |
commit | 98b9e48fca11c8aa54b25c02d3329392b52db8ab (patch) | |
tree | 9fe0adc6cb1cef157878c35a11f75ca37fcdfc9b /drivers | |
parent | e1000e: convert to netdev features/hw_features API (diff) | |
download | linux-98b9e48fca11c8aa54b25c02d3329392b52db8ab.tar.xz linux-98b9e48fca11c8aa54b25c02d3329392b52db8ab.zip |
ixgbevf: Check if EOP has changed before using it
There is a chance that between the time EOP is read and the time it is
used another transmit on a different CPU could have run and completed,
thus leaving EOP in a bad state.
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index b1e1c2daf5f9..936532fa42ad 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -203,6 +203,9 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter, (count < tx_ring->work_limit)) { bool cleaned = false; rmb(); /* read buffer_info after eop_desc */ + /* eop could change between read and DD-check */ + if (unlikely(eop != tx_ring->tx_buffer_info[i].next_to_watch)) + goto cont_loop; for ( ; !cleaned; count++) { struct sk_buff *skb; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); @@ -232,6 +235,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter, i = 0; } +cont_loop: eop = tx_ring->tx_buffer_info[i].next_to_watch; eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); } |