ixgbe: this patch adds support for DCB to the kernel and ixgbe driver
[linux-2.6-block.git] / drivers / net / ixgbe / ixgbe_main.c
index 40108523377fbe31ff98cb3638138d701dbeeb9a..91dde9cdab6605bf32f6ccb251128d9c8d32122d 100644 (file)
@@ -404,7 +404,7 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
 
        if (adapter->netdev->features & NETIF_F_LRO &&
            skb->ip_summed == CHECKSUM_UNNECESSARY) {
-               if (adapter->vlgrp && is_vlan)
+               if (adapter->vlgrp && is_vlan && (tag != 0))
                        lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
                                                     adapter->vlgrp, tag,
                                                     rx_desc);
@@ -413,12 +413,12 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
                ring->lro_used = true;
        } else {
                if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
-                       if (adapter->vlgrp && is_vlan)
+                       if (adapter->vlgrp && is_vlan && (tag != 0))
                                vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
                        else
                                netif_receive_skb(skb);
                } else {
-                       if (adapter->vlgrp && is_vlan)
+                       if (adapter->vlgrp && is_vlan && (tag != 0))
                                vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
                        else
                                netif_rx(skb);
@@ -1670,10 +1670,12 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
         * effects of setting this bit are only that SRRCTL must be
         * fully programmed [0..15]
         */
-       rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
-       rdrxctl |= IXGBE_RDRXCTL_MVMEN;
-       IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
-
+       if (adapter->flags &
+           (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) {
+               rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+               rdrxctl |= IXGBE_RDRXCTL_MVMEN;
+               IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+       }
 
        if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
                /* Fill out redirection table */
@@ -1732,6 +1734,16 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
                ixgbe_irq_disable(adapter);
        adapter->vlgrp = grp;
 
+       /*
+        * For a DCB driver, always enable VLAN tag stripping so we can
+        * still receive traffic from a DCB-enabled host even if we're
+        * not in DCB mode.
+        */
+       ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL);
+       ctrl |= IXGBE_VLNCTRL_VME;
+       ctrl &= ~IXGBE_VLNCTRL_CFIEN;
+       IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
+
        if (grp) {
                /* enable VLAN tag insert/strip */
                ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL);
@@ -1896,6 +1908,44 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
        }
 }
 
+#ifdef CONFIG_IXGBE_DCBNL
+/*
+ * ixgbe_configure_dcb - Configure DCB hardware
+ * @adapter: ixgbe adapter struct
+ *
+ * This is called by the driver on open to configure the DCB hardware.
+ * This is also called by the gennetlink interface when reconfiguring
+ * the DCB state.
+ */
+static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 txdctl, vlnctrl;
+       int i, j;
+
+       ixgbe_dcb_check_config(&adapter->dcb_cfg);
+       ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG);
+       ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG);
+
+       /* reconfigure the hardware */
+       ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg);
+
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               j = adapter->tx_ring[i].reg_idx;
+               txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
+               /* PThresh workaround for Tx hang with DFP enabled. */
+               txdctl |= 32;
+               IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
+       }
+       /* Enable VLAN tag insert/strip */
+       vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+       vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
+       vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+       IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+       hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
+}
+
+#endif
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
@@ -1904,6 +1954,16 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
        ixgbe_set_rx_mode(netdev);
 
        ixgbe_restore_vlan(adapter);
+#ifdef CONFIG_IXGBE_DCBNL
+       if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+               netif_set_gso_max_size(netdev, 32768);
+               ixgbe_configure_dcb(adapter);
+       } else {
+               netif_set_gso_max_size(netdev, 65536);
+       }
+#else
+       netif_set_gso_max_size(netdev, 65536);
+#endif
 
        ixgbe_configure_tx(adapter);
        ixgbe_configure_rx(adapter);
@@ -1995,9 +2055,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 
        ixgbe_irq_enable(adapter);
 
-       /* enable transmits */
-       netif_tx_start_all_queues(netdev);
-
        /* bring the link up in the watchdog, this could race with our first
         * link up interrupt but shouldn't be a problem */
        adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
@@ -2260,6 +2317,11 @@ static void ixgbe_reset_task(struct work_struct *work)
        struct ixgbe_adapter *adapter;
        adapter = container_of(work, struct ixgbe_adapter, reset_task);
 
+       /* If we're already down or resetting, just bail */
+       if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+           test_bit(__IXGBE_RESETTING, &adapter->state))
+               return;
+
        adapter->tx_timeout_count++;
 
        ixgbe_reinit_locked(adapter);
@@ -2269,15 +2331,31 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
 {
        int nrq = 1, ntq = 1;
        int feature_mask = 0, rss_i, rss_m;
+       int dcb_i, dcb_m;
 
        /* Number of supported queues */
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82598EB:
+               dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+               dcb_m = 0;
                rss_i = adapter->ring_feature[RING_F_RSS].indices;
                rss_m = 0;
                feature_mask |= IXGBE_FLAG_RSS_ENABLED;
+               feature_mask |= IXGBE_FLAG_DCB_ENABLED;
 
                switch (adapter->flags & feature_mask) {
+               case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED):
+                       dcb_m = 0x7 << 3;
+                       rss_i = min(8, rss_i);
+                       rss_m = 0x7;
+                       nrq = dcb_i * rss_i;
+                       ntq = min(MAX_TX_QUEUES, dcb_i * rss_i);
+                       break;
+               case (IXGBE_FLAG_DCB_ENABLED):
+                       dcb_m = 0x7 << 3;
+                       nrq = dcb_i;
+                       ntq = dcb_i;
+                       break;
                case (IXGBE_FLAG_RSS_ENABLED):
                        rss_m = 0xF;
                        nrq = rss_i;
@@ -2285,6 +2363,8 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
                        break;
                case 0:
                default:
+                       dcb_i = 0;
+                       dcb_m = 0;
                        rss_i = 0;
                        rss_m = 0;
                        nrq = 1;
@@ -2292,6 +2372,12 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
                        break;
                }
 
+               /* Sanity check, we should never have zero queues */
+               nrq = (nrq ?:1);
+               ntq = (ntq ?:1);
+
+               adapter->ring_feature[RING_F_DCB].indices = dcb_i;
+               adapter->ring_feature[RING_F_DCB].mask = dcb_m;
                adapter->ring_feature[RING_F_RSS].indices = rss_i;
                adapter->ring_feature[RING_F_RSS].mask = rss_m;
                break;
@@ -2343,6 +2429,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
                adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
                kfree(adapter->msix_entries);
                adapter->msix_entries = NULL;
+               adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
                adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
                ixgbe_set_num_queues(adapter);
        } else {
@@ -2362,15 +2449,42 @@ static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
 {
        int feature_mask = 0, rss_i;
        int i, txr_idx, rxr_idx;
+       int dcb_i;
 
        /* Number of supported queues */
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82598EB:
+               dcb_i = adapter->ring_feature[RING_F_DCB].indices;
                rss_i = adapter->ring_feature[RING_F_RSS].indices;
                txr_idx = 0;
                rxr_idx = 0;
+               feature_mask |= IXGBE_FLAG_DCB_ENABLED;
                feature_mask |= IXGBE_FLAG_RSS_ENABLED;
                switch (adapter->flags & feature_mask) {
+               case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED):
+                       for (i = 0; i < dcb_i; i++) {
+                               int j;
+                               /* Rx first */
+                               for (j = 0; j < adapter->num_rx_queues; j++) {
+                                       adapter->rx_ring[rxr_idx].reg_idx =
+                                               i << 3 | j;
+                                       rxr_idx++;
+                               }
+                               /* Tx now */
+                               for (j = 0; j < adapter->num_tx_queues; j++) {
+                                       adapter->tx_ring[txr_idx].reg_idx =
+                                               i << 2 | (j >> 1);
+                                       if (j & 1)
+                                               txr_idx++;
+                               }
+                       }
+               case (IXGBE_FLAG_DCB_ENABLED):
+                       /* the number of queues is assumed to be symmetric */
+                       for (i = 0; i < dcb_i; i++) {
+                               adapter->rx_ring[i].reg_idx = i << 3;
+                               adapter->tx_ring[i].reg_idx = i << 2;
+                       }
+                       break;
                case (IXGBE_FLAG_RSS_ENABLED):
                        for (i = 0; i < adapter->num_rx_queues; i++)
                                adapter->rx_ring[i].reg_idx = i;
@@ -2395,7 +2509,7 @@ static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
  * number of queues at compile-time.  The polling_netdev array is
  * intended for Multiqueue, but should work fine with a single queue.
  **/
-static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
+static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
 {
        int i;
 
@@ -2465,6 +2579,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
        adapter->msix_entries = kcalloc(v_budget,
                                        sizeof(struct msix_entry), GFP_KERNEL);
        if (!adapter->msix_entries) {
+               adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
                adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
                ixgbe_set_num_queues(adapter);
                kfree(adapter->tx_ring);
@@ -2505,7 +2620,7 @@ out:
        return err;
 }
 
-static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
+void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
 {
        if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
                adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
@@ -2529,7 +2644,7 @@ static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
  * - Hardware queue count (num_*_queues)
  *   - defined by miscellaneous hardware support/features (RSS, etc.)
  **/
-static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
+int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
 {
        int err;
 
@@ -2577,6 +2692,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        struct pci_dev *pdev = adapter->pdev;
        unsigned int rss;
+#ifdef CONFIG_IXGBE_DCBNL
+       int j;
+       struct tc_configuration *tc;
+#endif
 
        /* PCI config space info */
 
@@ -2590,6 +2709,27 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
        rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
        adapter->ring_feature[RING_F_RSS].indices = rss;
        adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+       adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
+
+#ifdef CONFIG_IXGBE_DCBNL
+       /* Configure DCB traffic classes */
+       for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
+               tc = &adapter->dcb_cfg.tc_config[j];
+               tc->path[DCB_TX_CONFIG].bwg_id = 0;
+               tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1);
+               tc->path[DCB_RX_CONFIG].bwg_id = 0;
+               tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
+               tc->dcb_pfc = pfc_disabled;
+       }
+       adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
+       adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
+       adapter->dcb_cfg.rx_pba_cfg = pba_equal;
+       adapter->dcb_cfg.round_robin_enable = false;
+       adapter->dcb_set_bitmap = 0x00;
+       ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
+                          adapter->ring_feature[RING_F_DCB].indices);
+
+#endif
        if (hw->mac.ops.get_media_type &&
            (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper))
                adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
@@ -2967,7 +3107,7 @@ static int ixgbe_close(struct net_device *netdev)
  * @adapter: private struct
  * helper function to napi_add each possible q_vector->napi
  */
-static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
+void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
 {
        int q_idx, q_vectors;
        int (*poll)(struct napi_struct *, int);
@@ -2988,7 +3128,7 @@ static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
        }
 }
 
-static void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
+void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
 {
        int q_idx;
        int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -3109,6 +3249,18 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
                adapter->stats.mpc[i] += mpc;
                total_mpc += adapter->stats.mpc[i];
                adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+               adapter->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+               adapter->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+               adapter->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+               adapter->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+               adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw,
+                                                           IXGBE_PXONRXC(i));
+               adapter->stats.pxontxc[i] += IXGBE_READ_REG(hw,
+                                                           IXGBE_PXONTXC(i));
+               adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw,
+                                                           IXGBE_PXOFFRXC(i));
+               adapter->stats.pxofftxc[i] += IXGBE_READ_REG(hw,
+                                                           IXGBE_PXOFFTXC(i));
        }
        adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
        /* work around hardware counting issue */
@@ -3248,6 +3400,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
                                 (FLOW_TX ? "TX" : "None"))));
 
                        netif_carrier_on(netdev);
+                       netif_tx_wake_all_queues(netdev);
                } else {
                        /* Force detection of hung controller */
                        adapter->detect_tx_hung = true;
@@ -3258,6 +3411,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
                if (netif_carrier_ok(netdev)) {
                        DPRINTK(LINK, INFO, "NIC Link is Down\n");
                        netif_carrier_off(netdev);
+                       netif_tx_stop_all_queues(netdev);
                }
        }
 
@@ -3604,6 +3758,14 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
                tx_flags |= vlan_tx_tag_get(skb);
+               if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+                       tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
+                       tx_flags |= (skb->queue_mapping << 13);
+               }
+               tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
+               tx_flags |= IXGBE_TX_FLAGS_VLAN;
+       } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+               tx_flags |= (skb->queue_mapping << 13);
                tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
                tx_flags |= IXGBE_TX_FLAGS_VLAN;
        }
@@ -3878,6 +4040,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        netdev->vlan_features |= NETIF_F_IP_CSUM;
        netdev->vlan_features |= NETIF_F_SG;
 
+       if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
+               adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+
+#ifdef CONFIG_IXGBE_DCBNL
+       netdev->dcbnl_ops = &dcbnl_ops;
+#endif
+
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
@@ -3946,6 +4115,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        }
 
        netif_carrier_off(netdev);
+       netif_tx_stop_all_queues(netdev);
 
        ixgbe_napi_add_all(adapter);