igb, ixgbe: netdev_tx_reset_queue incorrectly called from tx init path
authorJohn Fastabend <john.r.fastabend@intel.com>
Mon, 23 Apr 2012 12:22:39 +0000 (12:22 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 4 May 2012 10:58:33 +0000 (03:58 -0700)
igb and ixgbe incorrectly call netdev_tx_reset_queue() from
i{gb|xgbe}_clean_tx_ring() this sort of works in most cases except
when the number of real tx queues changes. When the number of real
tx queues changes netdev_tx_reset_queue() only gets called on the
new number of queues so when we reduce the number of queues we risk
triggering the watchdog timer and repeated device resets.

So this is not only a cosmetic issue but causes real bugs. For
example enabling/disabling DCB or FCoE in ixgbe will trigger this.

CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Tested-by: John Bishop <johnx.bishop@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index 5ec31598ee4775708094fabcd3e1775325e65dfa..d22350055285dbd7b8cfc9754ae578d0f7e06bd0 100644 (file)
@@ -2771,8 +2771,6 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
 
        txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
        wr32(E1000_TXDCTL(reg_idx), txdctl);
-
-       netdev_tx_reset_queue(txring_txq(ring));
 }
 
 /**
@@ -3282,6 +3280,8 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
                igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
        }
 
+       netdev_tx_reset_queue(txring_txq(tx_ring));
+
        size = sizeof(struct igb_tx_buffer) * tx_ring->count;
        memset(tx_ring->tx_buffer_info, 0, size);
 
index 31a2bf76a3461f3ce307844592eb23970ebd1f43..cfe7d269590c891e9df2e4538cec504631c682f2 100644 (file)
@@ -1780,6 +1780,8 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring,
                rx_desc = IXGBE_RX_DESC(rx_ring, rx_ntc);
        }
 
+       netdev_tx_reset_queue(txring_txq(tx_ring));
+
        /* re-map buffers to ring, store next to clean values */
        ixgbe_alloc_rx_buffers(rx_ring, count);
        rx_ring->next_to_clean = rx_ntc;
index 50f0700d250da92655d4e604aa1f41d6a57565a8..467948e9ecd951dcff54d4bcf43e4adc0ddde8c0 100644 (file)
@@ -2671,8 +2671,6 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
        /* enable queue */
        IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl);
 
-       netdev_tx_reset_queue(txring_txq(ring));
-
        /* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */
        if (hw->mac.type == ixgbe_mac_82598EB &&
            !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
@@ -4167,6 +4165,8 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring)
                ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
        }
 
+       netdev_tx_reset_queue(txring_txq(tx_ring));
+
        size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
        memset(tx_ring->tx_buffer_info, 0, size);