]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ixgbevf: Check if EOP has changed before using it
authorGreg Rose <gregory.v.rose@intel.com>
Fri, 3 Jun 2011 03:53:24 +0000 (03:53 +0000)
committerJoe Jin <joe.jin@oracle.com>
Thu, 17 May 2012 15:51:58 +0000 (23:51 +0800)
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 <gregory.v.rose@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Joe Jin <joe.jin@oracle.com>
drivers/net/ixgbevf/ixgbevf_main.c

index 8227c35bf5650619d6cbbeb03d1f1a627308e59b..3cb6f1398b5d6489c68abed064e7d6b039cdd751 100644 (file)
@@ -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);
        }