]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/ixgbe/ixgbe_ethtool.c
ixgbe: change mac_type if statements to switch statements
[net-next-2.6.git] / drivers / net / ixgbe / ixgbe_ethtool.c
index dcebc82c6f4de3a4ae0134f802cbf5c7f8e8d302..9483faf91ea41c060b0e4186b0a20f3b0420f53e 100644 (file)
@@ -401,7 +401,7 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
 static u32 ixgbe_get_rx_csum(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       return (adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED);
+       return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
 }
 
 static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
@@ -412,11 +412,6 @@ static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
        else
                adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
 
-       if (netif_running(netdev))
-               ixgbe_reinit_locked(adapter);
-       else
-               ixgbe_reset(adapter);
-
        return 0;
 }
 
@@ -530,10 +525,20 @@ static void ixgbe_get_regs(struct net_device *netdev,
        regs_buff[32] = IXGBE_READ_REG(hw, IXGBE_FCTTV(1));
        regs_buff[33] = IXGBE_READ_REG(hw, IXGBE_FCTTV(2));
        regs_buff[34] = IXGBE_READ_REG(hw, IXGBE_FCTTV(3));
-       for (i = 0; i < 8; i++)
-               regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i));
-       for (i = 0; i < 8; i++)
-               regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i));
+       for (i = 0; i < 8; i++) {
+               switch (hw->mac.type) {
+               case ixgbe_mac_82598EB:
+                       regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i));
+                       regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i));
+                       break;
+               case ixgbe_mac_82599EB:
+                       regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i));
+                       regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i));
+                       break;
+               default:
+                       break;
+               }
+       }
        regs_buff[51] = IXGBE_READ_REG(hw, IXGBE_FCRTV);
        regs_buff[52] = IXGBE_READ_REG(hw, IXGBE_TFCS);
 
@@ -820,16 +825,19 @@ static void ixgbe_get_drvinfo(struct net_device *netdev,
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        char firmware_version[32];
 
-       strncpy(drvinfo->driver, ixgbe_driver_name, 32);
-       strncpy(drvinfo->version, ixgbe_driver_version, 32);
+       strncpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
+       strncpy(drvinfo->version, ixgbe_driver_version,
+               sizeof(drvinfo->version));
 
-       sprintf(firmware_version, "%d.%d-%d",
-               (adapter->eeprom_version & 0xF000) >> 12,
-               (adapter->eeprom_version & 0x0FF0) >> 4,
-               adapter->eeprom_version & 0x000F);
+       snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
+                (adapter->eeprom_version & 0xF000) >> 12,
+                (adapter->eeprom_version & 0x0FF0) >> 4,
+                adapter->eeprom_version & 0x000F);
 
-       strncpy(drvinfo->fw_version, firmware_version, 32);
-       strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+       strncpy(drvinfo->fw_version, firmware_version,
+               sizeof(drvinfo->fw_version));
+       strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+               sizeof(drvinfo->bus_info));
        drvinfo->n_stats = IXGBE_STATS_LEN;
        drvinfo->testinfo_len = IXGBE_TEST_LEN;
        drvinfo->regdump_len = ixgbe_get_regs_len(netdev);
@@ -902,13 +910,11 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                        memcpy(&temp_tx_ring[i], adapter->tx_ring[i],
                               sizeof(struct ixgbe_ring));
                        temp_tx_ring[i].count = new_tx_count;
-                       err = ixgbe_setup_tx_resources(adapter,
-                                                      &temp_tx_ring[i]);
+                       err = ixgbe_setup_tx_resources(&temp_tx_ring[i]);
                        if (err) {
                                while (i) {
                                        i--;
-                                       ixgbe_free_tx_resources(adapter,
-                                                             &temp_tx_ring[i]);
+                                       ixgbe_free_tx_resources(&temp_tx_ring[i]);
                                }
                                goto clear_reset;
                        }
@@ -927,13 +933,11 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                        memcpy(&temp_rx_ring[i], adapter->rx_ring[i],
                               sizeof(struct ixgbe_ring));
                        temp_rx_ring[i].count = new_rx_count;
-                       err = ixgbe_setup_rx_resources(adapter,
-                                                      &temp_rx_ring[i]);
+                       err = ixgbe_setup_rx_resources(&temp_rx_ring[i]);
                        if (err) {
                                while (i) {
                                        i--;
-                                       ixgbe_free_rx_resources(adapter,
-                                                             &temp_rx_ring[i]);
+                                       ixgbe_free_rx_resources(&temp_rx_ring[i]);
                                }
                                goto err_setup;
                        }
@@ -948,8 +952,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                /* tx */
                if (new_tx_count != adapter->tx_ring_count) {
                        for (i = 0; i < adapter->num_tx_queues; i++) {
-                               ixgbe_free_tx_resources(adapter,
-                                                       adapter->tx_ring[i]);
+                               ixgbe_free_tx_resources(adapter->tx_ring[i]);
                                memcpy(adapter->tx_ring[i], &temp_tx_ring[i],
                                       sizeof(struct ixgbe_ring));
                        }
@@ -959,8 +962,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                /* rx */
                if (new_rx_count != adapter->rx_ring_count) {
                        for (i = 0; i < adapter->num_rx_queues; i++) {
-                               ixgbe_free_rx_resources(adapter,
-                                                       adapter->rx_ring[i]);
+                               ixgbe_free_rx_resources(adapter->rx_ring[i]);
                                memcpy(adapter->rx_ring[i], &temp_rx_ring[i],
                                       sizeof(struct ixgbe_ring));
                        }
@@ -985,8 +987,8 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset)
        case ETH_SS_STATS:
                return IXGBE_STATS_LEN;
        case ETH_SS_NTUPLE_FILTERS:
-               return (ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
-                       ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY);
+               return ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
+                      ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY;
        default:
                return -EOPNOTSUPP;
        }
@@ -996,12 +998,11 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                                     struct ethtool_stats *stats, u64 *data)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       u64 *queue_stat;
-       int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
        struct rtnl_link_stats64 temp;
        const struct rtnl_link_stats64 *net_stats;
-       int j, k;
-       int i;
+       unsigned int start;
+       struct ixgbe_ring *ring;
+       int i, j;
        char *p = NULL;
 
        ixgbe_update_stats(adapter);
@@ -1022,16 +1023,22 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                           sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
        }
        for (j = 0; j < adapter->num_tx_queues; j++) {
-               queue_stat = (u64 *)&adapter->tx_ring[j]->stats;
-               for (k = 0; k < stat_count; k++)
-                       data[i + k] = queue_stat[k];
-               i += k;
+               ring = adapter->tx_ring[j];
+               do {
+                       start = u64_stats_fetch_begin_bh(&ring->syncp);
+                       data[i]   = ring->stats.packets;
+                       data[i+1] = ring->stats.bytes;
+               } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+               i += 2;
        }
        for (j = 0; j < adapter->num_rx_queues; j++) {
-               queue_stat = (u64 *)&adapter->rx_ring[j]->stats;
-               for (k = 0; k < stat_count; k++)
-                       data[i + k] = queue_stat[k];
-               i += k;
+               ring = adapter->rx_ring[j];
+               do {
+                       start = u64_stats_fetch_begin_bh(&ring->syncp);
+                       data[i]   = ring->stats.packets;
+                       data[i+1] = ring->stats.bytes;
+               } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+               i += 2;
        }
        if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
                for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) {
@@ -1229,12 +1236,19 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
        u32 value, before, after;
        u32 i, toggle;
 
-       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-               toggle = 0x7FFFF30F;
-               test = reg_test_82599;
-       } else {
+       switch (adapter->hw.mac.type) {
+       case ixgbe_mac_82598EB:
                toggle = 0x7FFFF3FF;
                test = reg_test_82598;
+               break;
+       case ixgbe_mac_82599EB:
+               toggle = 0x7FFFF30F;
+               test = reg_test_82599;
+               break;
+       default:
+               *data = 1;
+               return 1;
+               break;
        }
 
        /*
@@ -1435,9 +1449,7 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter)
        struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
        struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
        struct ixgbe_hw *hw = &adapter->hw;
-       struct pci_dev *pdev = adapter->pdev;
        u32 reg_ctl;
-       int i;
 
        /* shut down the DMA engines now so they can be reinitialized later */
 
@@ -1445,237 +1457,86 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter)
        reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
        reg_ctl &= ~IXGBE_RXCTRL_RXEN;
        IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_ctl);
-       reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(0));
+       reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx));
        reg_ctl &= ~IXGBE_RXDCTL_ENABLE;
-       IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(0), reg_ctl);
+       IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx), reg_ctl);
 
        /* now Tx */
-       reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(0));
+       reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx));
        reg_ctl &= ~IXGBE_TXDCTL_ENABLE;
-       IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(0), reg_ctl);
-       if (hw->mac.type == ixgbe_mac_82599EB) {
+       IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx), reg_ctl);
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_82599EB:
                reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
                reg_ctl &= ~IXGBE_DMATXCTL_TE;
                IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl);
+               break;
+       default:
+               break;
        }
 
        ixgbe_reset(adapter);
 
-       if (tx_ring->desc && tx_ring->tx_buffer_info) {
-               for (i = 0; i < tx_ring->count; i++) {
-                       struct ixgbe_tx_buffer *buf =
-                                       &(tx_ring->tx_buffer_info[i]);
-                       if (buf->dma)
-                               dma_unmap_single(&pdev->dev, buf->dma,
-                                                buf->length, DMA_TO_DEVICE);
-                       if (buf->skb)
-                               dev_kfree_skb(buf->skb);
-               }
-       }
-
-       if (rx_ring->desc && rx_ring->rx_buffer_info) {
-               for (i = 0; i < rx_ring->count; i++) {
-                       struct ixgbe_rx_buffer *buf =
-                                       &(rx_ring->rx_buffer_info[i]);
-                       if (buf->dma)
-                               dma_unmap_single(&pdev->dev, buf->dma,
-                                                IXGBE_RXBUFFER_2048,
-                                                DMA_FROM_DEVICE);
-                       if (buf->skb)
-                               dev_kfree_skb(buf->skb);
-               }
-       }
-
-       if (tx_ring->desc) {
-               dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
-                                 tx_ring->dma);
-               tx_ring->desc = NULL;
-       }
-       if (rx_ring->desc) {
-               dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
-                                 rx_ring->dma);
-               rx_ring->desc = NULL;
-       }
-
-       kfree(tx_ring->tx_buffer_info);
-       tx_ring->tx_buffer_info = NULL;
-       kfree(rx_ring->rx_buffer_info);
-       rx_ring->rx_buffer_info = NULL;
+       ixgbe_free_tx_resources(&adapter->test_tx_ring);
+       ixgbe_free_rx_resources(&adapter->test_rx_ring);
 }
 
 static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
        struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
-       struct pci_dev *pdev = adapter->pdev;
        u32 rctl, reg_data;
-       int i, ret_val;
+       int ret_val;
+       int err;
 
        /* Setup Tx descriptor ring and Tx buffers */
+       tx_ring->count = IXGBE_DEFAULT_TXD;
+       tx_ring->queue_index = 0;
+       tx_ring->dev = &adapter->pdev->dev;
+       tx_ring->netdev = adapter->netdev;
+       tx_ring->reg_idx = adapter->tx_ring[0]->reg_idx;
+       tx_ring->numa_node = adapter->node;
+
+       err = ixgbe_setup_tx_resources(tx_ring);
+       if (err)
+               return 1;
 
-       if (!tx_ring->count)
-               tx_ring->count = IXGBE_DEFAULT_TXD;
-
-       tx_ring->tx_buffer_info = kcalloc(tx_ring->count,
-                                         sizeof(struct ixgbe_tx_buffer),
-                                         GFP_KERNEL);
-       if (!(tx_ring->tx_buffer_info)) {
-               ret_val = 1;
-               goto err_nomem;
-       }
-
-       tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
-       tx_ring->size = ALIGN(tx_ring->size, 4096);
-       tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
-                                          &tx_ring->dma, GFP_KERNEL);
-       if (!(tx_ring->desc)) {
-               ret_val = 2;
-               goto err_nomem;
-       }
-       tx_ring->next_to_use = tx_ring->next_to_clean = 0;
-
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAL(0),
-                       ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAH(0),
-                       ((u64) tx_ring->dma >> 32));
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDLEN(0),
-                       tx_ring->count * sizeof(union ixgbe_adv_tx_desc));
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDH(0), 0);
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), 0);
-
-       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
-       reg_data |= IXGBE_HLREG0_TXPADEN;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
-
-       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+       switch (adapter->hw.mac.type) {
+       case ixgbe_mac_82599EB:
                reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL);
                reg_data |= IXGBE_DMATXCTL_TE;
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data);
+               break;
+       default:
+               break;
        }
-       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(0));
-       reg_data |= IXGBE_TXDCTL_ENABLE;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(0), reg_data);
-
-       for (i = 0; i < tx_ring->count; i++) {
-               union ixgbe_adv_tx_desc *desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
-               struct sk_buff *skb;
-               unsigned int size = 1024;
-
-               skb = alloc_skb(size, GFP_KERNEL);
-               if (!skb) {
-                       ret_val = 3;
-                       goto err_nomem;
-               }
-               skb_put(skb, size);
-               tx_ring->tx_buffer_info[i].skb = skb;
-               tx_ring->tx_buffer_info[i].length = skb->len;
-               tx_ring->tx_buffer_info[i].dma =
-                       dma_map_single(&pdev->dev, skb->data, skb->len,
-                                      DMA_TO_DEVICE);
-               desc->read.buffer_addr =
-                                   cpu_to_le64(tx_ring->tx_buffer_info[i].dma);
-               desc->read.cmd_type_len = cpu_to_le32(skb->len);
-               desc->read.cmd_type_len |= cpu_to_le32(IXGBE_TXD_CMD_EOP |
-                                                      IXGBE_TXD_CMD_IFCS |
-                                                      IXGBE_TXD_CMD_RS);
-               desc->read.olinfo_status = 0;
-               if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-                       desc->read.olinfo_status |=
-                                       (skb->len << IXGBE_ADVTXD_PAYLEN_SHIFT);
 
-       }
+       ixgbe_configure_tx_ring(adapter, tx_ring);
 
        /* Setup Rx Descriptor ring and Rx buffers */
-
-       if (!rx_ring->count)
-               rx_ring->count = IXGBE_DEFAULT_RXD;
-
-       rx_ring->rx_buffer_info = kcalloc(rx_ring->count,
-                                         sizeof(struct ixgbe_rx_buffer),
-                                         GFP_KERNEL);
-       if (!(rx_ring->rx_buffer_info)) {
+       rx_ring->count = IXGBE_DEFAULT_RXD;
+       rx_ring->queue_index = 0;
+       rx_ring->dev = &adapter->pdev->dev;
+       rx_ring->netdev = adapter->netdev;
+       rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx;
+       rx_ring->rx_buf_len = IXGBE_RXBUFFER_2048;
+       rx_ring->numa_node = adapter->node;
+
+       err = ixgbe_setup_rx_resources(rx_ring);
+       if (err) {
                ret_val = 4;
                goto err_nomem;
        }
 
-       rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
-       rx_ring->size = ALIGN(rx_ring->size, 4096);
-       rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
-                                          &rx_ring->dma, GFP_KERNEL);
-       if (!(rx_ring->desc)) {
-               ret_val = 5;
-               goto err_nomem;
-       }
-       rx_ring->next_to_use = rx_ring->next_to_clean = 0;
-
        rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL);
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl & ~IXGBE_RXCTRL_RXEN);
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAL(0),
-                       ((u64)rx_ring->dma & 0xFFFFFFFF));
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAH(0),
-                       ((u64) rx_ring->dma >> 32));
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDLEN(0), rx_ring->size);
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDH(0), 0);
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), 0);
 
-       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
-       reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
-
-       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
-       reg_data &= ~IXGBE_HLREG0_LPBK;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
-
-       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RDRXCTL);
-#define IXGBE_RDRXCTL_RDMTS_MASK    0x00000003 /* Receive Descriptor Minimum
-                                                  Threshold Size mask */
-       reg_data &= ~IXGBE_RDRXCTL_RDMTS_MASK;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDRXCTL, reg_data);
-
-       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MCSTCTRL);
-#define IXGBE_MCSTCTRL_MO_MASK      0x00000003 /* Multicast Offset mask */
-       reg_data &= ~IXGBE_MCSTCTRL_MO_MASK;
-       reg_data |= adapter->hw.mac.mc_filter_type;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_MCSTCTRL, reg_data);
-
-       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(0));
-       reg_data |= IXGBE_RXDCTL_ENABLE;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data);
-       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-               int j = adapter->rx_ring[0]->reg_idx;
-               u32 k;
-               for (k = 0; k < 10; k++) {
-                       if (IXGBE_READ_REG(&adapter->hw,
-                                          IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE)
-                               break;
-                       else
-                               msleep(1);
-               }
-       }
+       ixgbe_configure_rx_ring(adapter, rx_ring);
 
        rctl |= IXGBE_RXCTRL_RXEN | IXGBE_RXCTRL_DMBYPS;
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl);
 
-       for (i = 0; i < rx_ring->count; i++) {
-               union ixgbe_adv_rx_desc *rx_desc =
-                                                IXGBE_RX_DESC_ADV(*rx_ring, i);
-               struct sk_buff *skb;
-
-               skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
-               if (!skb) {
-                       ret_val = 6;
-                       goto err_nomem;
-               }
-               skb_reserve(skb, NET_IP_ALIGN);
-               rx_ring->rx_buffer_info[i].skb = skb;
-               rx_ring->rx_buffer_info[i].dma =
-                       dma_map_single(&pdev->dev, skb->data,
-                                      IXGBE_RXBUFFER_2048, DMA_FROM_DEVICE);
-               rx_desc->read.pkt_addr =
-                               cpu_to_le64(rx_ring->rx_buffer_info[i].dma);
-               memset(skb->data, 0x00, skb->len);
-       }
-
        return 0;
 
 err_nomem:
@@ -1689,16 +1550,21 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter)
        u32 reg_data;
 
        /* right now we only support MAC loopback in the driver */
-
-       /* Setup MAC loopback */
        reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+       /* Setup MAC loopback */
        reg_data |= IXGBE_HLREG0_LPBK;
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
 
+       reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+       reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
+       IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
+
        reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC);
        reg_data &= ~IXGBE_AUTOC_LMS_MASK;
        reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU;
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data);
+       IXGBE_WRITE_FLUSH(&adapter->hw);
+       msleep(10);
 
        /* Disable Atlas Tx lanes; re-enabled in reset path */
        if (hw->mac.type == ixgbe_mac_82598EB) {
@@ -1756,15 +1622,80 @@ static int ixgbe_check_lbtest_frame(struct sk_buff *skb,
        return 13;
 }
 
+static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring,
+                                  struct ixgbe_ring *tx_ring,
+                                  unsigned int size)
+{
+       union ixgbe_adv_rx_desc *rx_desc;
+       struct ixgbe_rx_buffer *rx_buffer_info;
+       struct ixgbe_tx_buffer *tx_buffer_info;
+       const int bufsz = rx_ring->rx_buf_len;
+       u32 staterr;
+       u16 rx_ntc, tx_ntc, count = 0;
+
+       /* initialize next to clean and descriptor values */
+       rx_ntc = rx_ring->next_to_clean;
+       tx_ntc = tx_ring->next_to_clean;
+       rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+       staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+
+       while (staterr & IXGBE_RXD_STAT_DD) {
+               /* check Rx buffer */
+               rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
+
+               /* unmap Rx buffer, will be remapped by alloc_rx_buffers */
+               dma_unmap_single(rx_ring->dev,
+                                rx_buffer_info->dma,
+                                bufsz,
+                                DMA_FROM_DEVICE);
+               rx_buffer_info->dma = 0;
+
+               /* verify contents of skb */
+               if (!ixgbe_check_lbtest_frame(rx_buffer_info->skb, size))
+                       count++;
+
+               /* unmap buffer on Tx side */
+               tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
+               ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
+
+               /* increment Rx/Tx next to clean counters */
+               rx_ntc++;
+               if (rx_ntc == rx_ring->count)
+                       rx_ntc = 0;
+               tx_ntc++;
+               if (tx_ntc == tx_ring->count)
+                       tx_ntc = 0;
+
+               /* fetch next descriptor */
+               rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+               staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+       }
+
+       /* re-map buffers to ring, store next to clean values */
+       ixgbe_alloc_rx_buffers(rx_ring, count);
+       rx_ring->next_to_clean = rx_ntc;
+       tx_ring->next_to_clean = tx_ntc;
+
+       return count;
+}
+
 static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
        struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
-       struct pci_dev *pdev = adapter->pdev;
-       int i, j, k, l, lc, good_cnt, ret_val = 0;
-       unsigned long time;
+       int i, j, lc, good_cnt, ret_val = 0;
+       unsigned int size = 1024;
+       netdev_tx_t tx_ret_val;
+       struct sk_buff *skb;
+
+       /* allocate test skb */
+       skb = alloc_skb(size, GFP_KERNEL);
+       if (!skb)
+               return 11;
 
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), rx_ring->count - 1);
+       /* place data into test skb */
+       ixgbe_create_lbtest_frame(skb, size);
+       skb_put(skb, size);
 
        /*
         * Calculate the loop count based on the largest descriptor ring
@@ -1777,54 +1708,38 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
        else
                lc = ((rx_ring->count / 64) * 2) + 1;
 
-       k = l = 0;
        for (j = 0; j <= lc; j++) {
-               for (i = 0; i < 64; i++) {
-                       ixgbe_create_lbtest_frame(
-                                       tx_ring->tx_buffer_info[k].skb,
-                                       1024);
-                       dma_sync_single_for_device(&pdev->dev,
-                               tx_ring->tx_buffer_info[k].dma,
-                               tx_ring->tx_buffer_info[k].length,
-                               DMA_TO_DEVICE);
-                       if (unlikely(++k == tx_ring->count))
-                               k = 0;
-               }
-               IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), k);
-               msleep(200);
-               /* set the start time for the receive */
-               time = jiffies;
+               /* reset count of good packets */
                good_cnt = 0;
-               do {
-                       /* receive the sent packets */
-                       dma_sync_single_for_cpu(&pdev->dev,
-                                       rx_ring->rx_buffer_info[l].dma,
-                                       IXGBE_RXBUFFER_2048,
-                                       DMA_FROM_DEVICE);
-                       ret_val = ixgbe_check_lbtest_frame(
-                                       rx_ring->rx_buffer_info[l].skb, 1024);
-                       if (!ret_val)
+
+               /* place 64 packets on the transmit queue*/
+               for (i = 0; i < 64; i++) {
+                       skb_get(skb);
+                       tx_ret_val = ixgbe_xmit_frame_ring(skb,
+                                                          adapter,
+                                                          tx_ring);
+                       if (tx_ret_val == NETDEV_TX_OK)
                                good_cnt++;
-                       if (++l == rx_ring->count)
-                               l = 0;
-                       /*
-                        * time + 20 msecs (200 msecs on 2.4) is more than
-                        * enough time to complete the receives, if it's
-                        * exceeded, break and error off
-                        */
-               } while (good_cnt < 64 && jiffies < (time + 20));
+               }
+
                if (good_cnt != 64) {
-                       /* ret_val is the same as mis-compare */
-                       ret_val = 13;
+                       ret_val = 12;
                        break;
                }
-               if (jiffies >= (time + 20)) {
-                       /* Error code for time out error */
-                       ret_val = 14;
+
+               /* allow 200 milliseconds for packets to go from Tx to Rx */
+               msleep(200);
+
+               good_cnt = ixgbe_clean_test_rings(rx_ring, tx_ring, size);
+               if (good_cnt != 64) {
+                       ret_val = 13;
                        break;
                }
        }
 
+       /* free the original skb */
+       kfree_skb(skb);
+
        return ret_val;
 }
 
@@ -2085,6 +2000,41 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
        return 0;
 }
 
+/*
+ * this function must be called before setting the new value of
+ * rx_itr_setting
+ */
+static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter,
+                            struct ethtool_coalesce *ec)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
+               return false;
+
+       /* if interrupt rate is too high then disable RSC */
+       if (ec->rx_coalesce_usecs != 1 &&
+           ec->rx_coalesce_usecs <= 1000000/IXGBE_MAX_RSC_INT_RATE) {
+               if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
+                       e_info(probe, "rx-usecs set too low, "
+                                     "disabling RSC\n");
+                       adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
+                       return true;
+               }
+       } else {
+               /* check the feature flag value and enable RSC if necessary */
+               if ((netdev->features & NETIF_F_LRO) &&
+                   !(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) {
+                       e_info(probe, "rx-usecs set to %d, "
+                                     "re-enabling RSC\n",
+                              ec->rx_coalesce_usecs);
+                       adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
+                       return true;
+               }
+       }
+       return false;
+}
+
 static int ixgbe_set_coalesce(struct net_device *netdev,
                               struct ethtool_coalesce *ec)
 {
@@ -2102,17 +2052,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq;
 
        if (ec->rx_coalesce_usecs > 1) {
-               u32 max_int;
-               if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
-                       max_int = IXGBE_MAX_RSC_INT_RATE;
-               else
-                       max_int = IXGBE_MAX_INT_RATE;
-
                /* check the limits */
-               if ((1000000/ec->rx_coalesce_usecs > max_int) ||
+               if ((1000000/ec->rx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
                    (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
                        return -EINVAL;
 
+               /* check the old value and enable RSC if necessary */
+               need_reset = ixgbe_update_rsc(adapter, ec);
+
                /* store the value in ints/second */
                adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
 
@@ -2121,32 +2068,21 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                /* clear the lower bit as its used for dynamic state */
                adapter->rx_itr_setting &= ~1;
        } else if (ec->rx_coalesce_usecs == 1) {
+               /* check the old value and enable RSC if necessary */
+               need_reset = ixgbe_update_rsc(adapter, ec);
+
                /* 1 means dynamic mode */
                adapter->rx_eitr_param = 20000;
                adapter->rx_itr_setting = 1;
        } else {
+               /* check the old value and enable RSC if necessary */
+               need_reset = ixgbe_update_rsc(adapter, ec);
                /*
                 * any other value means disable eitr, which is best
                 * served by setting the interrupt rate very high
                 */
                adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
                adapter->rx_itr_setting = 0;
-
-               /*
-                * if hardware RSC is enabled, disable it when
-                * setting low latency mode, to avoid errata, assuming
-                * that when the user set low latency mode they want
-                * it at the cost of anything else
-                */
-               if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
-                       adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
-                       if (netdev->features & NETIF_F_LRO) {
-                               netdev->features &= ~NETIF_F_LRO;
-                               e_info(probe, "rx-usecs set to 0, "
-                                      "disabling RSC\n");
-                       }
-                       need_reset = true;
-               }
        }
 
        if (ec->tx_coalesce_usecs > 1) {
@@ -2218,20 +2154,30 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
        bool need_reset = false;
        int rc;
 
-       rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE);
+#ifdef CONFIG_IXGBE_DCB
+       if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
+           !(data & ETH_FLAG_RXVLAN))
+               return -EINVAL;
+#endif
+
+       need_reset = (data & ETH_FLAG_RXVLAN) !=
+                    (netdev->features & NETIF_F_HW_VLAN_RX);
+
+       rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO |
+                                       ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN);
        if (rc)
                return rc;
 
        /* if state changes we need to update adapter->flags and reset */
-       if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) {
-               /*
-                * cast both to bool and verify if they are set the same
-                * but only enable RSC if itr is non-zero, as
-                * itr=0 and RSC are mutually exclusive
-                */
-               if (((!!(data & ETH_FLAG_LRO)) !=
-                    (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) &&
-                   adapter->rx_itr_setting) {
+       if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) &&
+           (!!(data & ETH_FLAG_LRO) !=
+            !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
+               if ((data & ETH_FLAG_LRO) &&
+                   (!adapter->rx_itr_setting ||
+                    (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) {
+                       e_info(probe, "rx-usecs set too low, "
+                                     "not enabling RSC.\n");
+               } else {
                        adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
                        switch (adapter->hw.mac.type) {
                        case ixgbe_mac_82599EB:
@@ -2240,11 +2186,6 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
                        default:
                                break;
                        }
-               } else if (!adapter->rx_itr_setting) {
-                       netdev->features &= ~NETIF_F_LRO;
-                       if (data & ETH_FLAG_LRO)
-                               e_info(probe, "rx-usecs set to 0, "
-                                      "LRO/RSC cannot be enabled.\n");
                }
        }