From: Greg Rose Date: Fri, 3 Jun 2011 03:53:24 +0000 (+0000) Subject: ixgbevf: Check if EOP has changed before using it X-Git-Tag: v2.6.39-400.9.0~423^2~19^2~11^2~77 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=70ddbd79c4a4c1273b8346e29a05a6bcbcefdf23;p=users%2Fjedix%2Flinux-maple.git 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. (cherry picked from commit 98b9e48fca11c8aa54b25c02d3329392b52db8ab) Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: Joe Jin --- diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 8227c35bf565..3cb6f1398b5d 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -206,6 +206,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); @@ -235,6 +238,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); }