[PATCH] e1000: Fix loopback logic
[safe/jmp/linux-2.6] / drivers / net / e1000 / e1000_ethtool.c
index 8f3a134..ceb9cd0 100644 (file)
@@ -39,10 +39,10 @@ extern int e1000_up(struct e1000_adapter *adapter);
 extern void e1000_down(struct e1000_adapter *adapter);
 extern void e1000_reset(struct e1000_adapter *adapter);
 extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
 extern void e1000_update_stats(struct e1000_adapter *adapter);
 
 struct e1000_stats {
@@ -80,6 +80,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "tx_deferred_ok", E1000_STAT(stats.dc) },
        { "tx_single_coll_ok", E1000_STAT(stats.scc) },
        { "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
+       { "tx_timeout_count", E1000_STAT(tx_timeout_count) },
        { "rx_long_length_errors", E1000_STAT(stats.roc) },
        { "rx_short_length_errors", E1000_STAT(stats.ruc) },
        { "rx_align_errors", E1000_STAT(stats.algnerrc) },
@@ -91,10 +92,22 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
        { "rx_long_byte_count", E1000_STAT(stats.gorcl) },
        { "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-       { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
+       { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+       { "rx_header_split", E1000_STAT(rx_hdr_split) },
+       { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
 };
-#define E1000_STATS_LEN        \
+
+#ifdef CONFIG_E1000_MQ
+#define E1000_QUEUE_STATS_LEN \
+       (((struct e1000_adapter *)netdev->priv)->num_tx_queues + \
+        ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \
+       * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t))
+#else
+#define E1000_QUEUE_STATS_LEN 0
+#endif
+#define E1000_GLOBAL_STATS_LEN \
        sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
+#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
 static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
        "Register test  (offline)", "Eeprom test    (offline)",
        "Interrupt test (offline)", "Loopback test  (offline)",
@@ -182,7 +195,15 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
 
-       if(ecmd->autoneg == AUTONEG_ENABLE) {
+       /* When SoL/IDER sessions are active, autoneg/speed/duplex
+        * cannot be changed */
+       if (e1000_check_phy_reset_block(hw)) {
+               DPRINTK(DRV, ERR, "Cannot change link characteristics "
+                       "when SoL/IDER is active.\n");
+               return -EINVAL;
+       }
+
+       if (ecmd->autoneg == AUTONEG_ENABLE) {
                hw->autoneg = 1;
                if(hw->media_type == e1000_media_type_fiber)
                        hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
@@ -546,8 +567,10 @@ e1000_set_eeprom(struct net_device *netdev,
        ret_val = e1000_write_eeprom(hw, first_word,
                                     last_word - first_word + 1, eeprom_buff);
 
-       /* Update the checksum over the first part of the EEPROM if needed */
-       if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
+       /* Update the checksum over the first part of the EEPROM if needed 
+        * and flush shadow RAM for 82573 conrollers */
+       if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) || 
+                               (hw->mac_type == e1000_82573)))
                e1000_update_eeprom_checksum(hw);
 
        kfree(eeprom_buff);
@@ -576,8 +599,8 @@ e1000_get_ringparam(struct net_device *netdev,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        e1000_mac_type mac_type = adapter->hw.mac_type;
-       struct e1000_desc_ring *txdr = &adapter->tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+       struct e1000_tx_ring *txdr = adapter->tx_ring;
+       struct e1000_rx_ring *rxdr = adapter->rx_ring;
 
        ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
                E1000_MAX_82544_RXD;
@@ -597,20 +620,40 @@ e1000_set_ringparam(struct net_device *netdev,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        e1000_mac_type mac_type = adapter->hw.mac_type;
-       struct e1000_desc_ring *txdr = &adapter->tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->rx_ring;
-       struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
-       int err;
+       struct e1000_tx_ring *txdr, *tx_old, *tx_new;
+       struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
+       int i, err, tx_ring_size, rx_ring_size;
+
+       tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
+       rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
+
+       if (netif_running(adapter->netdev))
+               e1000_down(adapter);
 
        tx_old = adapter->tx_ring;
        rx_old = adapter->rx_ring;
 
+       adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);
+       if (!adapter->tx_ring) {
+               err = -ENOMEM;
+               goto err_setup_rx;
+       }
+       memset(adapter->tx_ring, 0, tx_ring_size);
+
+       adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);
+       if (!adapter->rx_ring) {
+               kfree(adapter->tx_ring);
+               err = -ENOMEM;
+               goto err_setup_rx;
+       }
+       memset(adapter->rx_ring, 0, rx_ring_size);
+
+       txdr = adapter->tx_ring;
+       rxdr = adapter->rx_ring;
+
        if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
 
-       if(netif_running(adapter->netdev))
-               e1000_down(adapter);
-
        rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
        rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
                E1000_MAX_RXD : E1000_MAX_82544_RXD));
@@ -621,11 +664,16 @@ e1000_set_ringparam(struct net_device *netdev,
                E1000_MAX_TXD : E1000_MAX_82544_TXD));
        E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); 
 
+       for (i = 0; i < adapter->num_tx_queues; i++)
+               txdr[i].count = txdr->count;
+       for (i = 0; i < adapter->num_rx_queues; i++)
+               rxdr[i].count = rxdr->count;
+
        if(netif_running(adapter->netdev)) {
                /* Try to get new resources before deleting old */
-               if((err = e1000_setup_rx_resources(adapter)))
+               if ((err = e1000_setup_all_rx_resources(adapter)))
                        goto err_setup_rx;
-               if((err = e1000_setup_tx_resources(adapter)))
+               if ((err = e1000_setup_all_tx_resources(adapter)))
                        goto err_setup_tx;
 
                /* save the new, restore the old in order to free it,
@@ -635,8 +683,10 @@ e1000_set_ringparam(struct net_device *netdev,
                tx_new = adapter->tx_ring;
                adapter->rx_ring = rx_old;
                adapter->tx_ring = tx_old;
-               e1000_free_rx_resources(adapter);
-               e1000_free_tx_resources(adapter);
+               e1000_free_all_rx_resources(adapter);
+               e1000_free_all_tx_resources(adapter);
+               kfree(tx_old);
+               kfree(rx_old);
                adapter->rx_ring = rx_new;
                adapter->tx_ring = tx_new;
                if((err = e1000_up(adapter)))
@@ -645,7 +695,7 @@ e1000_set_ringparam(struct net_device *netdev,
 
        return 0;
 err_setup_tx:
-       e1000_free_rx_resources(adapter);
+       e1000_free_all_rx_resources(adapter);
 err_setup_rx:
        adapter->rx_ring = rx_old;
        adapter->tx_ring = tx_old;
@@ -696,6 +746,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
         * Some bits that get toggled are ignored.
         */
         switch (adapter->hw.mac_type) {
+       /* there are several bits on newer hardware that are r/w */
+       case e1000_82571:
+       case e1000_82572:
+               toggle = 0x7FFFF3FF;
+               break;
        case e1000_82573:
                toggle = 0x7FFFF033;
                break;
@@ -898,8 +953,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 static void
 e1000_free_desc_rings(struct e1000_adapter *adapter)
 {
-       struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+       struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+       struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        int i;
 
@@ -925,24 +980,27 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
                }
        }
 
-       if(txdr->desc)
+       if(txdr->desc) {
                pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
-       if(rxdr->desc)
+               txdr->desc = NULL;
+       }
+       if(rxdr->desc) {
                pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+               rxdr->desc = NULL;
+       }
 
-       if(txdr->buffer_info)
-               kfree(txdr->buffer_info);
-       if(rxdr->buffer_info)
-               kfree(rxdr->buffer_info);
-
+       kfree(txdr->buffer_info);
+       txdr->buffer_info = NULL;
+       kfree(rxdr->buffer_info);
+       rxdr->buffer_info = NULL;
        return;
 }
 
 static int
 e1000_setup_desc_rings(struct e1000_adapter *adapter)
 {
-       struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+       struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+       struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        uint32_t rctl;
        int size, i, ret_val;
@@ -1245,6 +1303,8 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
        case e1000_82541_rev_2:
        case e1000_82547:
        case e1000_82547_rev_2:
+       case e1000_82571:
+       case e1000_82572:
        case e1000_82573:
                return e1000_integrated_phy_loopback(adapter);
                break;
@@ -1266,22 +1326,33 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
 static int
 e1000_setup_loopback_test(struct e1000_adapter *adapter)
 {
+       struct e1000_hw *hw = &adapter->hw;
        uint32_t rctl;
 
-       if(adapter->hw.media_type == e1000_media_type_fiber ||
-          adapter->hw.media_type == e1000_media_type_internal_serdes) {
-               if(adapter->hw.mac_type == e1000_82545 ||
-                  adapter->hw.mac_type == e1000_82546 ||
-                  adapter->hw.mac_type == e1000_82545_rev_3 ||
-                  adapter->hw.mac_type == e1000_82546_rev_3)
+       if (hw->media_type == e1000_media_type_fiber ||
+           hw->media_type == e1000_media_type_internal_serdes) {
+               switch (hw->mac_type) {
+               case e1000_82545:
+               case e1000_82546:
+               case e1000_82545_rev_3:
+               case e1000_82546_rev_3:
                        return e1000_set_phy_loopback(adapter);
-               else {
-                       rctl = E1000_READ_REG(&adapter->hw, RCTL);
+                       break;
+               case e1000_82571:
+               case e1000_82572:
+#define E1000_SERDES_LB_ON 0x410
+                       e1000_set_phy_loopback(adapter);
+                       E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+                       msec_delay(10);
+                       return 0;
+                       break;
+               default:
+                       rctl = E1000_READ_REG(hw, RCTL);
                        rctl |= E1000_RCTL_LBM_TCVR;
-                       E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+                       E1000_WRITE_REG(hw, RCTL, rctl);
                        return 0;
                }
-       } else if(adapter->hw.media_type == e1000_media_type_copper)
+       } else if (hw->media_type == e1000_media_type_copper)
                return e1000_set_phy_loopback(adapter);
 
        return 7;
@@ -1290,27 +1361,38 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
 static void
 e1000_loopback_cleanup(struct e1000_adapter *adapter)
 {
+       struct e1000_hw *hw = &adapter->hw;
        uint32_t rctl;
        uint16_t phy_reg;
 
-       rctl = E1000_READ_REG(&adapter->hw, RCTL);
+       rctl = E1000_READ_REG(hw, RCTL);
        rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
-       E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
-
-       if(adapter->hw.media_type == e1000_media_type_copper ||
-          ((adapter->hw.media_type == e1000_media_type_fiber ||
-            adapter->hw.media_type == e1000_media_type_internal_serdes) &&
-           (adapter->hw.mac_type == e1000_82545 ||
-            adapter->hw.mac_type == e1000_82546 ||
-            adapter->hw.mac_type == e1000_82545_rev_3 ||
-            adapter->hw.mac_type == e1000_82546_rev_3))) {
-               adapter->hw.autoneg = TRUE;
-               e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
-               if(phy_reg & MII_CR_LOOPBACK) {
+       E1000_WRITE_REG(hw, RCTL, rctl);
+
+       switch (hw->mac_type) {
+       case e1000_82571:
+       case e1000_82572:
+               if (hw->media_type == e1000_media_type_fiber ||
+                   hw->media_type == e1000_media_type_internal_serdes) {
+#define E1000_SERDES_LB_OFF 0x400
+                       E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+                       msec_delay(10);
+                       break;
+               }
+               /* Fall Through */
+       case e1000_82545:
+       case e1000_82546:
+       case e1000_82545_rev_3:
+       case e1000_82546_rev_3:
+       default:
+               hw->autoneg = TRUE;
+               e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
+               if (phy_reg & MII_CR_LOOPBACK) {
                        phy_reg &= ~MII_CR_LOOPBACK;
-                       e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
-                       e1000_phy_reset(&adapter->hw);
+                       e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
+                       e1000_phy_reset(hw);
                }
+               break;
        }
 }
 
@@ -1340,8 +1422,8 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
 static int
 e1000_run_loopback_test(struct e1000_adapter *adapter)
 {
-       struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-       struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+       struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+       struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        int i, j, k, l, lc, good_cnt, ret_val=0;
        unsigned long time;
@@ -1405,12 +1487,25 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
 static int
 e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
 {
-       if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
-       if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
+       /* PHY loopback cannot be performed if SoL/IDER
+        * sessions are active */
+       if (e1000_check_phy_reset_block(&adapter->hw)) {
+               DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
+                       "when SoL/IDER is active.\n");
+               *data = 0;
+               goto out;
+       }
+
+       if ((*data = e1000_setup_desc_rings(adapter)))
+               goto out;
+       if ((*data = e1000_setup_loopback_test(adapter)))
+               goto err_loopback;
        *data = e1000_run_loopback_test(adapter);
        e1000_loopback_cleanup(adapter);
-       e1000_free_desc_rings(adapter);
+
 err_loopback:
+       e1000_free_desc_rings(adapter);
+out:
        return *data;
 }
 
@@ -1509,6 +1604,7 @@ e1000_diag_test(struct net_device *netdev,
                data[2] = 0;
                data[3] = 0;
        }
+       msleep_interruptible(4 * 1000);
 }
 
 static void
@@ -1625,7 +1721,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
        if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
                data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
 
-       if(adapter->hw.mac_type < e1000_82573) {
+       if(adapter->hw.mac_type < e1000_82571) {
                if(!adapter->blink_timer.function) {
                        init_timer(&adapter->blink_timer);
                        adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1635,13 +1731,21 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
                mod_timer(&adapter->blink_timer, jiffies);
                msleep_interruptible(data * 1000);
                del_timer_sync(&adapter->blink_timer);
-       }
-       else {
-               E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
-                       E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | 
-                       (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
-                       (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
-                       (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
+       } else if (adapter->hw.mac_type < e1000_82573) {
+               E1000_WRITE_REG(&adapter->hw, LEDCTL,
+                       (E1000_LEDCTL_LED2_BLINK_RATE |
+                        E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+                        (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+                        (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+                        (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+               msleep_interruptible(data * 1000);
+       } else {
+               E1000_WRITE_REG(&adapter->hw, LEDCTL,
+                       (E1000_LEDCTL_LED2_BLINK_RATE |
+                        E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
+                        (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+                        (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
+                        (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
                msleep_interruptible(data * 1000);
        }
 
@@ -1674,19 +1778,43 @@ e1000_get_ethtool_stats(struct net_device *netdev,
                struct ethtool_stats *stats, uint64_t *data)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
+#ifdef CONFIG_E1000_MQ
+       uint64_t *queue_stat;
+       int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t);
+       int j, k;
+#endif
        int i;
 
        e1000_update_stats(adapter);
-       for(i = 0; i < E1000_STATS_LEN; i++) {
-               char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;  
-               data[i] = (e1000_gstrings_stats[i].sizeof_stat == 
+       for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+               char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+               data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
                        sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
        }
+#ifdef CONFIG_E1000_MQ
+       for (j = 0; j < adapter->num_tx_queues; j++) {
+               queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats;
+               for (k = 0; k < stat_count; k++)
+                       data[i + k] = queue_stat[k];
+               i += k;
+       }
+       for (j = 0; j < adapter->num_rx_queues; j++) {
+               queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats;
+               for (k = 0; k < stat_count; k++)
+                       data[i + k] = queue_stat[k];
+               i += k;
+       }
+#endif
+/*     BUG_ON(i != E1000_STATS_LEN); */
 }
 
 static void 
 e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
 {
+#ifdef CONFIG_E1000_MQ
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+#endif
+       uint8_t *p = data;
        int i;
 
        switch(stringset) {
@@ -1695,16 +1823,31 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
                        E1000_TEST_LEN*ETH_GSTRING_LEN);
                break;
        case ETH_SS_STATS:
-               for (i=0; i < E1000_STATS_LEN; i++) {
-                       memcpy(data + i * ETH_GSTRING_LEN, 
-                       e1000_gstrings_stats[i].stat_string,
-                       ETH_GSTRING_LEN);
+               for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+                       memcpy(p, e1000_gstrings_stats[i].stat_string,
+                              ETH_GSTRING_LEN);
+                       p += ETH_GSTRING_LEN;
                }
+#ifdef CONFIG_E1000_MQ
+               for (i = 0; i < adapter->num_tx_queues; i++) {
+                       sprintf(p, "tx_queue_%u_packets", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "tx_queue_%u_bytes", i);
+                       p += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < adapter->num_rx_queues; i++) {
+                       sprintf(p, "rx_queue_%u_packets", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "rx_queue_%u_bytes", i);
+                       p += ETH_GSTRING_LEN;
+               }
+#endif
+/*             BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
                break;
        }
 }
 
-struct ethtool_ops e1000_ethtool_ops = {
+static struct ethtool_ops e1000_ethtool_ops = {
        .get_settings           = e1000_get_settings,
        .set_settings           = e1000_set_settings,
        .get_drvinfo            = e1000_get_drvinfo,