i40e: fix call of ndo_dflt_bridge_getlink()
[cascardo/linux.git] / drivers / net / ethernet / intel / i40e / i40e_main.c
index d0b3a1b..31c97e3 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 16
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -57,8 +57,6 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit);
 static int i40e_setup_misc_vector(struct i40e_pf *pf);
 static void i40e_determine_queue_usage(struct i40e_pf *pf);
 static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
-static void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut,
-                             u16 rss_table_size, u16 rss_size);
 static void i40e_fdir_sb_setup(struct i40e_pf *pf);
 static int i40e_veb_get_bw_info(struct i40e_veb *veb);
 
@@ -527,6 +525,7 @@ void i40e_pf_reset_stats(struct i40e_pf *pf)
                        pf->veb[i]->stat_offsets_loaded = false;
                }
        }
+       pf->hw_csum_rx_error = 0;
 }
 
 /**
@@ -1316,7 +1315,7 @@ static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
        element.vlan_tag = 0;
        /* ...and some firmware does it this way. */
        element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
-                       I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
+                       I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
        i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
 }
 
@@ -1909,7 +1908,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                        ether_addr_copy(del_list[num_del].mac_addr, f->macaddr);
                        if (f->vlan == I40E_VLAN_ANY) {
                                del_list[num_del].vlan_tag = 0;
-                               cmd_flags |= I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
+                               cmd_flags |= I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
                        } else {
                                del_list[num_del].vlan_tag =
                                        cpu_to_le16((u16)(f->vlan));
@@ -4616,7 +4615,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;
 
@@ -4634,8 +4633,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++;
@@ -4643,29 +4640,6 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
        return num_tc;
 }
 
-/**
- * i40e_pf_get_default_tc - Get bitmap for first enabled TC
- * @pf: PF being queried
- *
- * Return a bitmap for first enabled traffic class for this PF.
- **/
-static u8 i40e_pf_get_default_tc(struct i40e_pf *pf)
-{
-       u8 enabled_tc = pf->hw.func_caps.enabled_tcmap;
-       u8 i = 0;
-
-       if (!enabled_tc)
-               return 0x1; /* TC0 */
-
-       /* Find the first enabled TC */
-       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-               if (enabled_tc & BIT(i))
-                       break;
-       }
-
-       return BIT(i);
-}
-
 /**
  * i40e_pf_get_pf_tc_map - Get bitmap for enabled traffic classes
  * @pf: PF being queried
@@ -4676,7 +4650,7 @@ static u8 i40e_pf_get_tc_map(struct i40e_pf *pf)
 {
        /* If DCB is not enabled for this PF then just return default TC */
        if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
-               return i40e_pf_get_default_tc(pf);
+               return I40E_DEFAULT_TRAFFIC_CLASS;
 
        /* SFP mode we want PF to be enabled for all TCs */
        if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
@@ -4686,7 +4660,7 @@ static u8 i40e_pf_get_tc_map(struct i40e_pf *pf)
        if (pf->hw.func_caps.iscsi)
                return i40e_get_iscsi_tc_map(pf);
        else
-               return i40e_pf_get_default_tc(pf);
+               return I40E_DEFAULT_TRAFFIC_CLASS;
 }
 
 /**
@@ -5032,7 +5006,7 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf)
                if (v == pf->lan_vsi)
                        tc_map = i40e_pf_get_tc_map(pf);
                else
-                       tc_map = i40e_pf_get_default_tc(pf);
+                       tc_map = I40E_DEFAULT_TRAFFIC_CLASS;
 #ifdef I40E_FCOE
                if (pf->vsi[v]->type == I40E_VSI_FCOE)
                        tc_map = i40e_get_fcoe_tc_map(pf);
@@ -5245,7 +5219,7 @@ static int i40e_up_complete(struct i40e_vsi *vsi)
                /* reset fd counters */
                pf->fd_add_err = pf->fd_atr_cnt = 0;
                if (pf->fd_tcp_rule > 0) {
-                       pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+                       pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED;
                        if (I40E_DEBUG_FD & pf->hw.debug_mask)
                                dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 exist\n");
                        pf->fd_tcp_rule = 0;
@@ -5720,7 +5694,7 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
        u8 type;
 
        /* Not DCB capable or capability disabled */
-       if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
+       if (!(pf->flags & I40E_FLAG_DCB_CAPABLE))
                return ret;
 
        /* Ignore if event is not for Nearest Bridge */
@@ -5942,13 +5916,17 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
                                dev_info(&pf->pdev->dev, "FD Sideband/ntuple is being enabled since we have space in the table now\n");
                }
        }
-       /* Wait for some more space to be available to turn on ATR */
+
+       /* Wait for some more space to be available to turn on ATR. We also
+        * must check that no existing ntuple rules for TCP are in effect
+        */
        if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM * 2)) {
                if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
-                   (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED)) {
+                   (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED) &&
+                   (pf->fd_tcp_rule == 0)) {
                        pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
                        if (I40E_DEBUG_FD & pf->hw.debug_mask)
-                               dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table now\n");
+                               dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table and there are no conflicting ntuple rules\n");
                }
        }
 
@@ -5979,9 +5957,6 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
        int fd_room;
        int reg;
 
-       if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)))
-               return;
-
        if (!time_after(jiffies, pf->fd_flush_timestamp +
                                 (I40E_MIN_FD_FLUSH_INTERVAL * HZ)))
                return;
@@ -6001,7 +5976,7 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
        }
 
        pf->fd_flush_timestamp = jiffies;
-       pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+       pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED;
        /* flush all filters */
        wr32(&pf->hw, I40E_PFQF_CTL_1,
             I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
@@ -6021,7 +5996,7 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
                /* replay sideband filters */
                i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]);
                if (!disable_atr)
-                       pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
+                       pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
                clear_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
                if (I40E_DEBUG_FD & pf->hw.debug_mask)
                        dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n");
@@ -6055,9 +6030,6 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
        if (test_bit(__I40E_DOWN, &pf->state))
                return;
 
-       if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)))
-               return;
-
        if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
                i40e_fdir_flush_and_replay(pf);
 
@@ -7157,9 +7129,9 @@ static void i40e_sync_udp_filters_subtask(struct i40e_pf *pf)
                        pf->pending_udp_bitmap &= ~BIT_ULL(i);
                        port = pf->udp_ports[i].index;
                        if (port)
-                               ret = i40e_aq_add_udp_tunnel(hw, ntohs(port),
-                                                    pf->udp_ports[i].type,
-                                                    NULL, NULL);
+                               ret = i40e_aq_add_udp_tunnel(hw, port,
+                                                       pf->udp_ports[i].type,
+                                                       NULL, NULL);
                        else
                                ret = i40e_aq_del_udp_tunnel(hw, i, NULL);
 
@@ -7646,7 +7618,6 @@ static int i40e_init_msix(struct i40e_pf *pf)
                        vectors_left--;
                } else {
                        pf->num_fdsb_msix = 0;
-                       pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
                }
        }
 
@@ -7666,6 +7637,8 @@ static int i40e_init_msix(struct i40e_pf *pf)
 #endif
        /* can we reserve enough for iWARP? */
        if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
+               iwarp_requested = pf->num_iwarp_msix;
+
                if (!vectors_left)
                        pf->num_iwarp_msix = 0;
                else if (vectors_left < pf->num_iwarp_msix)
@@ -7679,18 +7652,23 @@ static int i40e_init_msix(struct i40e_pf *pf)
                int vmdq_vecs_wanted = pf->num_vmdq_vsis * pf->num_vmdq_qps;
                int vmdq_vecs = min_t(int, vectors_left, vmdq_vecs_wanted);
 
-               /* if we're short on vectors for what's desired, we limit
-                * the queues per vmdq.  If this is still more than are
-                * available, the user will need to change the number of
-                * queues/vectors used by the PF later with the ethtool
-                * channels command
-                */
-               if (vmdq_vecs < vmdq_vecs_wanted)
-                       pf->num_vmdq_qps = 1;
-               pf->num_vmdq_msix = pf->num_vmdq_qps;
+               if (!vectors_left) {
+                       pf->num_vmdq_msix = 0;
+                       pf->num_vmdq_qps = 0;
+               } else {
+                       /* if we're short on vectors for what's desired, we limit
+                        * the queues per vmdq.  If this is still more than are
+                        * available, the user will need to change the number of
+                        * queues/vectors used by the PF later with the ethtool
+                        * channels command
+                        */
+                       if (vmdq_vecs < vmdq_vecs_wanted)
+                               pf->num_vmdq_qps = 1;
+                       pf->num_vmdq_msix = pf->num_vmdq_qps;
 
-               v_budget += vmdq_vecs;
-               vectors_left -= vmdq_vecs;
+                       v_budget += vmdq_vecs;
+                       vectors_left -= vmdq_vecs;
+               }
        }
 
        pf->msix_entries = kcalloc(v_budget, sizeof(struct msix_entry),
@@ -7702,25 +7680,11 @@ static int i40e_init_msix(struct i40e_pf *pf)
                pf->msix_entries[i].entry = i;
        v_actual = i40e_reserve_msix_vectors(pf, v_budget);
 
-       if (v_actual != v_budget) {
-               /* If we have limited resources, we will start with no vectors
-                * for the special features and then allocate vectors to some
-                * of these features based on the policy and at the end disable
-                * the features that did not get any vectors.
-                */
-               iwarp_requested = pf->num_iwarp_msix;
-               pf->num_iwarp_msix = 0;
-#ifdef I40E_FCOE
-               pf->num_fcoe_qps = 0;
-               pf->num_fcoe_msix = 0;
-#endif
-               pf->num_vmdq_msix = 0;
-       }
-
        if (v_actual < I40E_MIN_MSIX) {
                pf->flags &= ~I40E_FLAG_MSIX_ENABLED;
                kfree(pf->msix_entries);
                pf->msix_entries = NULL;
+               pci_disable_msix(pf->pdev);
                return -ENODEV;
 
        } else if (v_actual == I40E_MIN_MSIX) {
@@ -7730,9 +7694,16 @@ static int i40e_init_msix(struct i40e_pf *pf)
                pf->num_lan_qps = 1;
                pf->num_lan_msix = 1;
 
-       } else if (v_actual != v_budget) {
+       } else if (!vectors_left) {
+               /* If we have limited resources, we will start with no vectors
+                * for the special features and then allocate vectors to some
+                * of these features based on the policy and at the end disable
+                * the features that did not get any vectors.
+                */
                int vec;
 
+               dev_info(&pf->pdev->dev,
+                        "MSI-X vector limit reached, attempting to redistribute vectors\n");
                /* reserve the misc vector */
                vec = v_actual - 1;
 
@@ -7740,7 +7711,10 @@ static int i40e_init_msix(struct i40e_pf *pf)
                pf->num_vmdq_msix = 1;    /* force VMDqs to only one vector */
                pf->num_vmdq_vsis = 1;
                pf->num_vmdq_qps = 1;
-               pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
+#ifdef I40E_FCOE
+               pf->num_fcoe_qps = 0;
+               pf->num_fcoe_msix = 0;
+#endif
 
                /* partition out the remaining vectors */
                switch (vec) {
@@ -7772,9 +7746,14 @@ static int i40e_init_msix(struct i40e_pf *pf)
                                pf->num_vmdq_vsis = min_t(int, (vec / 2),
                                                  I40E_DEFAULT_NUM_VMDQ_VSI);
                        }
+                       if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
+                               pf->num_fdsb_msix = 1;
+                               vec--;
+                       }
                        pf->num_lan_msix = min_t(int,
                               (vec - (pf->num_iwarp_msix + pf->num_vmdq_vsis)),
                                                              pf->num_lan_msix);
+                       pf->num_lan_qps = pf->num_lan_msix;
 #ifdef I40E_FCOE
                        /* give one vector to FCoE */
                        if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
@@ -7786,6 +7765,11 @@ static int i40e_init_msix(struct i40e_pf *pf)
                }
        }
 
+       if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
+           (pf->num_fdsb_msix == 0)) {
+               dev_info(&pf->pdev->dev, "Sideband Flowdir disabled, not enough MSI-X vectors\n");
+               pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
+       }
        if ((pf->flags & I40E_FLAG_VMDQ_ENABLED) &&
            (pf->num_vmdq_msix == 0)) {
                dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n");
@@ -7804,6 +7788,13 @@ static int i40e_init_msix(struct i40e_pf *pf)
                pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
        }
 #endif
+       i40e_debug(&pf->hw, I40E_DEBUG_INIT,
+                  "MSI-X vector distribution: PF %d, VMDq %d, FDSB %d, iWARP %d\n",
+                  pf->num_lan_msix,
+                  pf->num_vmdq_msix * pf->num_vmdq_vsis,
+                  pf->num_fdsb_msix,
+                  pf->num_iwarp_msix);
+
        return v_actual;
 }
 
@@ -7990,72 +7981,34 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)
 static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed,
                              u8 *lut, u16 lut_size)
 {
-       struct i40e_aqc_get_set_rss_key_data rss_key;
        struct i40e_pf *pf = vsi->back;
        struct i40e_hw *hw = &pf->hw;
-       bool pf_lut = false;
-       u8 *rss_lut;
-       int ret, i;
-
-       memcpy(&rss_key, seed, sizeof(rss_key));
-
-       rss_lut = kzalloc(pf->rss_table_size, GFP_KERNEL);
-       if (!rss_lut)
-               return -ENOMEM;
-
-       /* Populate the LUT with max no. of queues in round robin fashion */
-       for (i = 0; i < vsi->rss_table_size; i++)
-               rss_lut[i] = i % vsi->rss_size;
+       int ret = 0;
 
-       ret = i40e_aq_set_rss_key(hw, vsi->id, &rss_key);
-       if (ret) {
-               dev_info(&pf->pdev->dev,
-                        "Cannot set RSS key, err %s aq_err %s\n",
-                        i40e_stat_str(&pf->hw, ret),
-                        i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
-               goto config_rss_aq_out;
+       if (seed) {
+               struct i40e_aqc_get_set_rss_key_data *seed_dw =
+                       (struct i40e_aqc_get_set_rss_key_data *)seed;
+               ret = i40e_aq_set_rss_key(hw, vsi->id, seed_dw);
+               if (ret) {
+                       dev_info(&pf->pdev->dev,
+                                "Cannot set RSS key, err %s aq_err %s\n",
+                                i40e_stat_str(hw, ret),
+                                i40e_aq_str(hw, hw->aq.asq_last_status));
+                       return ret;
+               }
        }
+       if (lut) {
+               bool pf_lut = vsi->type == I40E_VSI_MAIN ? true : false;
 
-       if (vsi->type == I40E_VSI_MAIN)
-               pf_lut = true;
-
-       ret = i40e_aq_set_rss_lut(hw, vsi->id, pf_lut, rss_lut,
-                                 vsi->rss_table_size);
-       if (ret)
-               dev_info(&pf->pdev->dev,
-                        "Cannot set RSS lut, err %s aq_err %s\n",
-                        i40e_stat_str(&pf->hw, ret),
-                        i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
-
-config_rss_aq_out:
-       kfree(rss_lut);
-       return ret;
-}
-
-/**
- * i40e_vsi_config_rss - Prepare for VSI(VMDq) RSS if used
- * @vsi: VSI structure
- **/
-static int i40e_vsi_config_rss(struct i40e_vsi *vsi)
-{
-       u8 seed[I40E_HKEY_ARRAY_SIZE];
-       struct i40e_pf *pf = vsi->back;
-       u8 *lut;
-       int ret;
-
-       if (!(pf->flags & I40E_FLAG_RSS_AQ_CAPABLE))
-               return 0;
-
-       lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
-       if (!lut)
-               return -ENOMEM;
-
-       i40e_fill_rss_lut(pf, lut, vsi->rss_table_size, vsi->rss_size);
-       netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE);
-       vsi->rss_size = min_t(int, pf->alloc_rss_size, vsi->num_queue_pairs);
-       ret = i40e_config_rss_aq(vsi, seed, lut, vsi->rss_table_size);
-       kfree(lut);
-
+               ret = i40e_aq_set_rss_lut(hw, vsi->id, pf_lut, lut, lut_size);
+               if (ret) {
+                       dev_info(&pf->pdev->dev,
+                                "Cannot set RSS lut, err %s aq_err %s\n",
+                                i40e_stat_str(hw, ret),
+                                i40e_aq_str(hw, hw->aq.asq_last_status));
+                       return ret;
+               }
+       }
        return ret;
 }
 
@@ -8105,6 +8058,46 @@ static int i40e_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed,
        return ret;
 }
 
+/**
+ * i40e_vsi_config_rss - Prepare for VSI(VMDq) RSS if used
+ * @vsi: VSI structure
+ **/
+static int i40e_vsi_config_rss(struct i40e_vsi *vsi)
+{
+       u8 seed[I40E_HKEY_ARRAY_SIZE];
+       struct i40e_pf *pf = vsi->back;
+       u8 *lut;
+       int ret;
+
+       if (!(pf->flags & I40E_FLAG_RSS_AQ_CAPABLE))
+               return 0;
+
+       if (!vsi->rss_size)
+               vsi->rss_size = min_t(int, pf->alloc_rss_size,
+                                     vsi->num_queue_pairs);
+       if (!vsi->rss_size)
+               return -EINVAL;
+
+       lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
+       if (!lut)
+               return -ENOMEM;
+       /* Use the user configured hash keys and lookup table if there is one,
+        * otherwise use default
+        */
+       if (vsi->rss_lut_user)
+               memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
+       else
+               i40e_fill_rss_lut(pf, lut, vsi->rss_table_size, vsi->rss_size);
+       if (vsi->rss_hkey_user)
+               memcpy(seed, vsi->rss_hkey_user, I40E_HKEY_ARRAY_SIZE);
+       else
+               netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE);
+       ret = i40e_config_rss_aq(vsi, seed, lut, vsi->rss_table_size);
+       kfree(lut);
+
+       return ret;
+}
+
 /**
  * i40e_config_rss_reg - Configure RSS keys and lut by writing registers
  * @vsi: Pointer to vsi structure
@@ -8243,8 +8236,8 @@ int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
  * @rss_table_size: Lookup table size
  * @rss_size: Range of queue number for hashing
  */
-static void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut,
-                             u16 rss_table_size, u16 rss_size)
+void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut,
+                      u16 rss_table_size, u16 rss_size)
 {
        u16 i;
 
@@ -8285,6 +8278,8 @@ static int i40e_pf_config_rss(struct i40e_pf *pf)
        if (!vsi->rss_size)
                vsi->rss_size = min_t(int, pf->alloc_rss_size,
                                      vsi->num_queue_pairs);
+       if (!vsi->rss_size)
+               return -EINVAL;
 
        lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
        if (!lut)
@@ -8609,7 +8604,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
                             I40E_FLAG_WB_ON_ITR_CAPABLE |
                             I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |
                             I40E_FLAG_NO_PCI_LINK_CHECK |
-                            I40E_FLAG_100M_SGMII_CAPABLE |
                             I40E_FLAG_USE_SET_LLDP_MIB |
                             I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
        } else if ((pf->hw.aq.api_maj_ver > 1) ||
@@ -8684,17 +8678,39 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
                /* reset fd counters */
                pf->fd_add_err = pf->fd_atr_cnt = pf->fd_tcp_rule = 0;
                pf->fdir_pf_active_filters = 0;
-               pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
-               if (I40E_DEBUG_FD & pf->hw.debug_mask)
-                       dev_info(&pf->pdev->dev, "ATR re-enabled.\n");
                /* if ATR was auto disabled it can be re-enabled. */
                if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
-                   (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED))
+                   (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED)) {
                        pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+                       if (I40E_DEBUG_FD & pf->hw.debug_mask)
+                               dev_info(&pf->pdev->dev, "ATR re-enabled.\n");
+               }
        }
        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
@@ -8708,6 +8724,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
@@ -9012,7 +9034,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                return 0;
 
        return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode,
-                                      nlflags, 0, 0, filter_mask, NULL);
+                                      0, 0, nlflags, filter_mask, NULL);
 }
 
 /* Hardware supports L4 tunnel length of 128B (=2^7) which includes
@@ -11309,11 +11331,7 @@ static void i40e_remove(struct pci_dev *pdev)
        }
 
        /* shutdown the adminq */
-       ret_code = i40e_shutdown_adminq(hw);
-       if (ret_code)
-               dev_warn(&pdev->dev,
-                        "Failed to destroy the Admin Queue resources: %d\n",
-                        ret_code);
+       i40e_shutdown_adminq(hw);
 
        /* destroy the locks only once, here */
        mutex_destroy(&hw->aq.arq_mutex);
@@ -11360,6 +11378,12 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev,
 
        dev_info(&pdev->dev, "%s: error %d\n", __func__, error);
 
+       if (!pf) {
+               dev_info(&pdev->dev,
+                        "Cannot recover - error happened during device probe\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
        /* shutdown all operations */
        if (!test_bit(__I40E_SUSPENDED, &pf->state)) {
                rtnl_lock();
@@ -11582,7 +11606,8 @@ static int __init i40e_init_module(void)
         * it can't be any worse than using the system workqueue which
         * was already single threaded
         */
-       i40e_wq = create_singlethread_workqueue(i40e_driver_name);
+       i40e_wq = alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1,
+                                 i40e_driver_name);
        if (!i40e_wq) {
                pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
                return -ENOMEM;