Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next...
[deliverable/linux.git] / drivers / net / ethernet / intel / i40e / i40e_main.c
index 81c99e1be708d445270323ece7c6c63cbc681111..798c4e2dc6212c1327484d3ee0cb5bd1cc8be47a 100644 (file)
@@ -41,7 +41,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 1
 #define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 11
+#define DRV_VERSION_BUILD 12
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -527,6 +527,7 @@ void i40e_pf_reset_stats(struct i40e_pf *pf)
                        pf->veb[i]->stat_offsets_loaded = false;
                }
        }
+       pf->hw_csum_rx_error = 0;
 }
 
 /**
@@ -4554,23 +4555,38 @@ static u8 i40e_get_iscsi_tc_map(struct i40e_pf *pf)
  **/
 static u8 i40e_dcb_get_num_tc(struct i40e_dcbx_config *dcbcfg)
 {
+       int i, tc_unused = 0;
        u8 num_tc = 0;
-       int i;
+       u8 ret = 0;
 
        /* Scan the ETS Config Priority Table to find
         * traffic class enabled for a given priority
-        * and use the traffic class index to get the
-        * number of traffic classes enabled
+        * and create a bitmask of enabled TCs
         */
-       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
-               if (dcbcfg->etscfg.prioritytable[i] > num_tc)
-                       num_tc = dcbcfg->etscfg.prioritytable[i];
-       }
+       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
+               num_tc |= BIT(dcbcfg->etscfg.prioritytable[i]);
 
-       /* Traffic class index starts from zero so
-        * increment to return the actual count
+       /* Now scan the bitmask to check for
+        * contiguous TCs starting with TC0
         */
-       return num_tc + 1;
+       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
+               if (num_tc & BIT(i)) {
+                       if (!tc_unused) {
+                               ret++;
+                       } else {
+                               pr_err("Non-contiguous TC - Disabling DCB\n");
+                               return 1;
+                       }
+               } else {
+                       tc_unused = 1;
+               }
+       }
+
+       /* There is always at least TC0 */
+       if (!ret)
+               ret = 1;
+
+       return ret;
 }
 
 /**
@@ -4601,7 +4617,7 @@ static u8 i40e_dcb_get_enabled_tc(struct i40e_dcbx_config *dcbcfg)
 static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
 {
        struct i40e_hw *hw = &pf->hw;
-       u8 i, enabled_tc;
+       u8 i, enabled_tc = 1;
        u8 num_tc = 0;
        struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;
 
@@ -4619,8 +4635,6 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
        else
                return 1; /* Only TC0 */
 
-       /* At least have TC0 */
-       enabled_tc = (enabled_tc ? enabled_tc : 0x1);
        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
                if (enabled_tc & BIT(i))
                        num_tc++;
@@ -8676,6 +8690,28 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
        return need_reset;
 }
 
+/**
+ * i40e_clear_rss_lut - clear the rx hash lookup table
+ * @vsi: the VSI being configured
+ **/
+static void i40e_clear_rss_lut(struct i40e_vsi *vsi)
+{
+       struct i40e_pf *pf = vsi->back;
+       struct i40e_hw *hw = &pf->hw;
+       u16 vf_id = vsi->vf_id;
+       u8 i;
+
+       if (vsi->type == I40E_VSI_MAIN) {
+               for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++)
+                       wr32(hw, I40E_PFQF_HLUT(i), 0);
+       } else if (vsi->type == I40E_VSI_SRIOV) {
+               for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++)
+                       i40e_write_rx_ctl(hw, I40E_VFQF_HLUT1(i, vf_id), 0);
+       } else {
+               dev_err(&pf->pdev->dev, "Cannot set RSS LUT - invalid VSI type\n");
+       }
+}
+
 /**
  * i40e_set_features - set the netdev feature flags
  * @netdev: ptr to the netdev being adjusted
@@ -8689,6 +8725,12 @@ static int i40e_set_features(struct net_device *netdev,
        struct i40e_pf *pf = vsi->back;
        bool need_reset;
 
+       if (features & NETIF_F_RXHASH && !(netdev->features & NETIF_F_RXHASH))
+               i40e_pf_config_rss(pf);
+       else if (!(features & NETIF_F_RXHASH) &&
+                netdev->features & NETIF_F_RXHASH)
+               i40e_clear_rss_lut(vsi);
+
        if (features & NETIF_F_HW_VLAN_CTAG_RX)
                i40e_vlan_stripping_enable(vsi);
        else
This page took 0.027128 seconds and 5 git commands to generate.