ice: Introduce enabling promiscuous mode on multiple VF's
authorMichal Wilczynski <michal.wilczynski@intel.com>
Mon, 4 Jul 2022 13:12:26 +0000 (15:12 +0200)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Thu, 28 Jul 2022 18:44:22 +0000 (11:44 -0700)
In current implementation default VSI switch filter is only able to
forward traffic to a single VSI. This limits promiscuous mode with
private flag 'vf-true-promisc-support' to a single VF. Enabling it on
the second VF won't work. Also allmulticast support doesn't seem to be
properly implemented when vf-true-promisc-support is true.

Use standard ice_add_rule_internal() function that already implements
forwarding to multiple VSI's instead of constructing AQ call manually.

Add switch filter for allmulticast mode when vf-true-promisc-support is
enabled. The same filter is added regardless of the flag - it doesn't
matter for this case.

Remove unnecessary fields in switch structure. From now on book keeping
will be done by ice_add_rule_internal().

Refactor unnecessarily passed function arguments.

To test:
1) Create 2 VM's, and two VF's. Attach VF's to VM's.
2) Enable promiscuous mode on both of them and check if
   traffic is seen on both of them.

Signed-off-by: Michal Wilczynski <michal.wilczynski@intel.com>
Tested-by: Marek Szlosek <marek.szlosek@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
12 files changed:
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_eswitch.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_lib.h
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_switch.c
drivers/net/ethernet/intel/ice/ice_switch.h
drivers/net/ethernet/intel/ice/ice_type.h
drivers/net/ethernet/intel/ice/ice_vf_lib.c
drivers/net/ethernet/intel/ice/ice_vf_lib.h
drivers/net/ethernet/intel/ice/ice_virtchnl.c

index 36b440b..cc5b85a 100644 (file)
@@ -248,8 +248,6 @@ struct ice_sw {
        struct ice_pf *pf;
        u16 sw_id;              /* switch ID for this switch */
        u16 bridge_mode;        /* VEB/VEPA/Port Virtualizer */
-       struct ice_vsi *dflt_vsi;       /* default VSI for this switch */
-       u8 dflt_vsi_ena:1;      /* true if above dflt_vsi is enabled */
 };
 
 enum ice_pf_state {
index 6a463b2..e35371e 100644 (file)
@@ -133,8 +133,8 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
        if (ice_vsi_add_vlan_zero(uplink_vsi))
                goto err_def_rx;
 
-       if (!ice_is_dflt_vsi_in_use(uplink_vsi->vsw)) {
-               if (ice_set_dflt_vsi(uplink_vsi->vsw, uplink_vsi))
+       if (!ice_is_dflt_vsi_in_use(uplink_vsi->port_info)) {
+               if (ice_set_dflt_vsi(uplink_vsi))
                        goto err_def_rx;
                rule_added = true;
        }
@@ -151,7 +151,7 @@ err_override_control:
        ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
 err_override_uplink:
        if (rule_added)
-               ice_clear_dflt_vsi(uplink_vsi->vsw);
+               ice_clear_dflt_vsi(uplink_vsi);
 err_def_rx:
        ice_fltr_add_mac_and_broadcast(uplink_vsi,
                                       uplink_vsi->port_info->mac.perm_addr,
@@ -411,7 +411,7 @@ static void ice_eswitch_release_env(struct ice_pf *pf)
 
        ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_clear_allow_override);
        ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
-       ice_clear_dflt_vsi(uplink_vsi->vsw);
+       ice_clear_dflt_vsi(uplink_vsi);
        ice_fltr_add_mac_and_broadcast(uplink_vsi,
                                       uplink_vsi->port_info->mac.perm_addr,
                                       ICE_FWD_TO_VSI);
index 70335f6..340dc5a 100644 (file)
@@ -1292,7 +1292,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
         * promiscuous mode because it's not supported
         */
        if (test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, change_flags) &&
-           ice_is_any_vf_in_promisc(pf)) {
+           ice_is_any_vf_in_unicast_promisc(pf)) {
                dev_err(dev, "Changing vf-true-promisc-support flag while VF(s) are in promiscuous mode not supported\n");
                /* toggle bit back to previous state */
                change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
index bc357df..a830f7f 100644 (file)
@@ -3006,8 +3006,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
                }
        }
 
-       if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
-               ice_clear_dflt_vsi(pf->first_sw);
+       if (ice_is_vsi_dflt_vsi(vsi))
+               ice_clear_dflt_vsi(vsi);
        ice_fltr_remove_all(vsi);
        ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
        err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
@@ -3690,116 +3690,97 @@ void ice_update_rx_ring_stats(struct ice_rx_ring *rx_ring, u64 pkts, u64 bytes)
 
 /**
  * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used
- * @sw: switch to check if its default forwarding VSI is free
+ * @pi: port info of the switch with default VSI
  *
- * Return true if the default forwarding VSI is already being used, else returns
- * false signalling that it's available to use.
+ * Return true if the there is a single VSI in default forwarding VSI list
  */
-bool ice_is_dflt_vsi_in_use(struct ice_sw *sw)
+bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi)
 {
-       return (sw->dflt_vsi && sw->dflt_vsi_ena);
+       bool exists = false;
+
+       ice_check_if_dflt_vsi(pi, 0, &exists);
+       return exists;
 }
 
 /**
  * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI
- * @sw: switch for the default forwarding VSI to compare against
  * @vsi: VSI to compare against default forwarding VSI
  *
  * If this VSI passed in is the default forwarding VSI then return true, else
  * return false
  */
-bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
+bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi)
 {
-       return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena);
+       return ice_check_if_dflt_vsi(vsi->port_info, vsi->idx, NULL);
 }
 
 /**
  * ice_set_dflt_vsi - set the default forwarding VSI
- * @sw: switch used to assign the default forwarding VSI
  * @vsi: VSI getting set as the default forwarding VSI on the switch
  *
  * If the VSI passed in is already the default VSI and it's enabled just return
  * success.
  *
- * If there is already a default VSI on the switch and it's enabled then return
- * -EEXIST since there can only be one default VSI per switch.
- *
- *  Otherwise try to set the VSI passed in as the switch's default VSI and
- *  return the result.
+ * Otherwise try to set the VSI passed in as the switch's default VSI and
+ * return the result.
  */
-int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
+int ice_set_dflt_vsi(struct ice_vsi *vsi)
 {
        struct device *dev;
        int status;
 
-       if (!sw || !vsi)
+       if (!vsi)
                return -EINVAL;
 
        dev = ice_pf_to_dev(vsi->back);
 
        /* the VSI passed in is already the default VSI */
-       if (ice_is_vsi_dflt_vsi(sw, vsi)) {
+       if (ice_is_vsi_dflt_vsi(vsi)) {
                dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n",
                        vsi->vsi_num);
                return 0;
        }
 
-       /* another VSI is already the default VSI for this switch */
-       if (ice_is_dflt_vsi_in_use(sw)) {
-               dev_err(dev, "Default forwarding VSI %d already in use, disable it and try again\n",
-                       sw->dflt_vsi->vsi_num);
-               return -EEXIST;
-       }
-
-       status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX);
+       status = ice_cfg_dflt_vsi(vsi->port_info, vsi->idx, true, ICE_FLTR_RX);
        if (status) {
                dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %d\n",
                        vsi->vsi_num, status);
                return status;
        }
 
-       sw->dflt_vsi = vsi;
-       sw->dflt_vsi_ena = true;
-
        return 0;
 }
 
 /**
  * ice_clear_dflt_vsi - clear the default forwarding VSI
- * @sw: switch used to clear the default VSI
+ * @vsi: VSI to remove from filter list
  *
  * If the switch has no default VSI or it's not enabled then return error.
  *
  * Otherwise try to clear the default VSI and return the result.
  */
-int ice_clear_dflt_vsi(struct ice_sw *sw)
+int ice_clear_dflt_vsi(struct ice_vsi *vsi)
 {
-       struct ice_vsi *dflt_vsi;
        struct device *dev;
        int status;
 
-       if (!sw)
+       if (!vsi)
                return -EINVAL;
 
-       dev = ice_pf_to_dev(sw->pf);
-
-       dflt_vsi = sw->dflt_vsi;
+       dev = ice_pf_to_dev(vsi->back);
 
        /* there is no default VSI configured */
-       if (!ice_is_dflt_vsi_in_use(sw))
+       if (!ice_is_dflt_vsi_in_use(vsi->port_info))
                return -ENODEV;
 
-       status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false,
+       status = ice_cfg_dflt_vsi(vsi->port_info, vsi->idx, false,
                                  ICE_FLTR_RX);
        if (status) {
                dev_err(dev, "Failed to clear the default forwarding VSI %d, error %d\n",
-                       dflt_vsi->vsi_num, status);
+                       vsi->vsi_num, status);
                return -EIO;
        }
 
-       sw->dflt_vsi = NULL;
-       sw->dflt_vsi_ena = false;
-
        return 0;
 }
 
index 0095329..8712b1d 100644 (file)
@@ -102,13 +102,10 @@ int ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set);
 
 bool ice_is_safe_mode(struct ice_pf *pf);
 bool ice_is_rdma_ena(struct ice_pf *pf);
-bool ice_is_dflt_vsi_in_use(struct ice_sw *sw);
-
-bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
-
-int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
-
-int ice_clear_dflt_vsi(struct ice_sw *sw);
+bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi);
+bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi);
+int ice_set_dflt_vsi(struct ice_vsi *vsi);
+int ice_clear_dflt_vsi(struct ice_vsi *vsi);
 int ice_set_min_bw_limit(struct ice_vsi *vsi, u64 min_tx_rate);
 int ice_set_max_bw_limit(struct ice_vsi *vsi, u64 max_tx_rate);
 int ice_get_link_speed_kbps(struct ice_vsi *vsi);
index 3137166..e56f72f 100644 (file)
@@ -410,8 +410,8 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
                clear_bit(ICE_VSI_PROMISC_CHANGED, vsi->state);
                if (vsi->current_netdev_flags & IFF_PROMISC) {
                        /* Apply Rx filter rule to get traffic from wire */
-                       if (!ice_is_dflt_vsi_in_use(pf->first_sw)) {
-                               err = ice_set_dflt_vsi(pf->first_sw, vsi);
+                       if (!ice_is_dflt_vsi_in_use(vsi->port_info)) {
+                               err = ice_set_dflt_vsi(vsi);
                                if (err && err != -EEXIST) {
                                        netdev_err(netdev, "Error %d setting default VSI %i Rx rule\n",
                                                   err, vsi->vsi_num);
@@ -424,8 +424,8 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
                        }
                } else {
                        /* Clear Rx filter to remove traffic from wire */
-                       if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi)) {
-                               err = ice_clear_dflt_vsi(pf->first_sw);
+                       if (ice_is_vsi_dflt_vsi(vsi)) {
+                               err = ice_clear_dflt_vsi(vsi);
                                if (err) {
                                        netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n",
                                                   err, vsi->vsi_num);
@@ -6990,12 +6990,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
                goto err_init_ctrlq;
        }
 
-       if (pf->first_sw->dflt_vsi_ena)
-               dev_info(dev, "Clearing default VSI, re-enable after reset completes\n");
-       /* clear the default VSI configuration if it exists */
-       pf->first_sw->dflt_vsi = NULL;
-       pf->first_sw->dflt_vsi_ena = false;
-
        ice_clear_pxe_mode(hw);
 
        err = ice_init_nvm(hw);
index 4a6a833..fce2046 100644 (file)
@@ -1762,7 +1762,8 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
            lkup_type == ICE_SW_LKUP_ETHERTYPE ||
            lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
            lkup_type == ICE_SW_LKUP_PROMISC ||
-           lkup_type == ICE_SW_LKUP_PROMISC_VLAN) {
+           lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
+           lkup_type == ICE_SW_LKUP_DFLT) {
                sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
        } else if (lkup_type == ICE_SW_LKUP_VLAN) {
                sw_buf->res_type =
@@ -2255,8 +2256,6 @@ ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
                pi->sw_id = swid;
                pi->pf_vf_num = pf_vf_num;
                pi->is_vf = is_vf;
-               pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
-               pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
                break;
        default:
                ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
@@ -2691,7 +2690,8 @@ ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
            lkup_type == ICE_SW_LKUP_ETHERTYPE ||
            lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
            lkup_type == ICE_SW_LKUP_PROMISC ||
-           lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
+           lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
+           lkup_type == ICE_SW_LKUP_DFLT)
                rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
                        ICE_AQC_SW_RULES_T_VSI_LIST_SET;
        else if (lkup_type == ICE_SW_LKUP_VLAN)
@@ -3873,7 +3873,7 @@ ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
 
 /**
  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
- * @hw: pointer to the hardware structure
+ * @pi: pointer to the port_info structure
  * @vsi_handle: VSI handle to set as default
  * @set: true to add the above mentioned switch rule, false to remove it
  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
@@ -3881,25 +3881,20 @@ ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
  * add filter rule to set/unset given VSI as default VSI for the switch
  * (represented by swid)
  */
-int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
+int
+ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
+                u8 direction)
 {
-       struct ice_sw_rule_lkup_rx_tx *s_rule;
+       struct ice_fltr_list_entry f_list_entry;
        struct ice_fltr_info f_info;
-       enum ice_adminq_opc opcode;
-       u16 s_rule_size;
+       struct ice_hw *hw = pi->hw;
        u16 hw_vsi_id;
        int status;
 
        if (!ice_is_vsi_valid(hw, vsi_handle))
                return -EINVAL;
-       hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
-
-       s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule) :
-                           ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
 
-       s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
-       if (!s_rule)
-               return -ENOMEM;
+       hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
 
        memset(&f_info, 0, sizeof(f_info));
 
@@ -3907,54 +3902,80 @@ int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
        f_info.flag = direction;
        f_info.fltr_act = ICE_FWD_TO_VSI;
        f_info.fwd_id.hw_vsi_id = hw_vsi_id;
+       f_info.vsi_handle = vsi_handle;
 
        if (f_info.flag & ICE_FLTR_RX) {
                f_info.src = hw->port_info->lport;
                f_info.src_id = ICE_SRC_ID_LPORT;
-               if (!set)
-                       f_info.fltr_rule_id =
-                               hw->port_info->dflt_rx_vsi_rule_id;
        } else if (f_info.flag & ICE_FLTR_TX) {
                f_info.src_id = ICE_SRC_ID_VSI;
                f_info.src = hw_vsi_id;
-               if (!set)
-                       f_info.fltr_rule_id =
-                               hw->port_info->dflt_tx_vsi_rule_id;
        }
+       f_list_entry.fltr_info = f_info;
 
        if (set)
-               opcode = ice_aqc_opc_add_sw_rules;
+               status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT,
+                                              &f_list_entry);
        else
-               opcode = ice_aqc_opc_remove_sw_rules;
-
-       ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
-
-       status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
-       if (status || !(f_info.flag & ICE_FLTR_TX_RX))
-               goto out;
-       if (set) {
-               u16 index = le16_to_cpu(s_rule->index);
-
-               if (f_info.flag & ICE_FLTR_TX) {
-                       hw->port_info->dflt_tx_vsi_num = hw_vsi_id;
-                       hw->port_info->dflt_tx_vsi_rule_id = index;
-               } else if (f_info.flag & ICE_FLTR_RX) {
-                       hw->port_info->dflt_rx_vsi_num = hw_vsi_id;
-                       hw->port_info->dflt_rx_vsi_rule_id = index;
-               }
-       } else {
-               if (f_info.flag & ICE_FLTR_TX) {
-                       hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
-                       hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
-               } else if (f_info.flag & ICE_FLTR_RX) {
-                       hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
-                       hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
+               status = ice_remove_rule_internal(hw, ICE_SW_LKUP_DFLT,
+                                                 &f_list_entry);
+
+       return status;
+}
+
+/**
+ * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
+ * @fm_entry: filter entry to inspect
+ * @vsi_handle: VSI handle to compare with filter info
+ */
+static bool
+ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
+{
+       return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
+                fm_entry->fltr_info.vsi_handle == vsi_handle) ||
+               (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
+                fm_entry->vsi_list_info &&
+                (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
+}
+
+/**
+ * ice_check_if_dflt_vsi - check if VSI is default VSI
+ * @pi: pointer to the port_info structure
+ * @vsi_handle: vsi handle to check for in filter list
+ * @rule_exists: indicates if there are any VSI's in the rule list
+ *
+ * checks if the VSI is in a default VSI list, and also indicates
+ * if the default VSI list is empty
+ */
+bool
+ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
+                     bool *rule_exists)
+{
+       struct ice_fltr_mgmt_list_entry *fm_entry;
+       struct ice_sw_recipe *recp_list;
+       struct list_head *rule_head;
+       struct mutex *rule_lock; /* Lock to protect filter rule list */
+       bool ret = false;
+
+       recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT];
+       rule_lock = &recp_list->filt_rule_lock;
+       rule_head = &recp_list->filt_rules;
+
+       mutex_lock(rule_lock);
+
+       if (rule_exists && !list_empty(rule_head))
+               *rule_exists = true;
+
+       list_for_each_entry(fm_entry, rule_head, list_entry) {
+               if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) {
+                       ret = true;
+                       break;
                }
        }
 
-out:
-       devm_kfree(ice_hw_to_dev(hw), s_rule);
-       return status;
+       mutex_unlock(rule_lock);
+
+       return ret;
 }
 
 /**
@@ -4074,21 +4095,6 @@ int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
 }
 
 /**
- * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
- * @fm_entry: filter entry to inspect
- * @vsi_handle: VSI handle to compare with filter info
- */
-static bool
-ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
-{
-       return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
-                fm_entry->fltr_info.vsi_handle == vsi_handle) ||
-               (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
-                fm_entry->vsi_list_info &&
-                (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
-}
-
-/**
  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
  * @hw: pointer to the hardware structure
  * @vsi_handle: VSI handle to remove filters from
index 59488e3..68d8e8a 100644 (file)
@@ -359,7 +359,13 @@ int ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable);
 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle);
 
 /* Promisc/defport setup for VSIs */
-int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction);
+int
+ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
+                u8 direction);
+bool
+ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
+                     bool *rule_exists);
+
 int
 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
                    u16 vid);
index f2a518a..861b643 100644 (file)
@@ -693,10 +693,6 @@ struct ice_port_info {
 #define ICE_SCHED_PORT_STATE_READY     0x1
        u8 lport;
 #define ICE_LPORT_MASK                 0xff
-       u16 dflt_tx_vsi_rule_id;
-       u16 dflt_tx_vsi_num;
-       u16 dflt_rx_vsi_rule_id;
-       u16 dflt_rx_vsi_num;
        struct ice_fc_info fc;
        struct ice_mac_info mac;
        struct ice_phy_info phy;
index 7adf9dd..9038d26 100644 (file)
@@ -271,13 +271,14 @@ static int ice_vf_rebuild_vsi(struct ice_vf *vf)
 }
 
 /**
- * ice_is_any_vf_in_promisc - check if any VF(s) are in promiscuous mode
+ * ice_is_any_vf_in_unicast_promisc - check if any VF(s)
+ * are in unicast promiscuous mode
  * @pf: PF structure for accessing VF(s)
  *
- * Return false if no VF(s) are in unicast and/or multicast promiscuous mode,
+ * Return false if no VF(s) are in unicast promiscuous mode,
  * else return true
  */
-bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
+bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf)
 {
        bool is_vf_promisc = false;
        struct ice_vf *vf;
@@ -286,8 +287,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
        rcu_read_lock();
        ice_for_each_vf_rcu(pf, bkt, vf) {
                /* found a VF that has promiscuous mode configured */
-               if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
-                   test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) {
+               if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) {
                        is_vf_promisc = true;
                        break;
                }
index 1b4380d..1acb35c 100644 (file)
@@ -214,7 +214,7 @@ struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
 bool ice_is_vf_disabled(struct ice_vf *vf);
 int ice_check_vf_ready_for_cfg(struct ice_vf *vf);
 void ice_set_vf_state_qs_dis(struct ice_vf *vf);
-bool ice_is_any_vf_in_promisc(struct ice_pf *pf);
+bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf);
 int
 ice_vf_set_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m);
 int
@@ -260,7 +260,7 @@ static inline void ice_set_vf_state_qs_dis(struct ice_vf *vf)
 {
 }
 
-static inline bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
+static inline bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf)
 {
        return false;
 }
index b2b5d2e..47ce713 100644 (file)
@@ -999,6 +999,7 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
        int mcast_err = 0, ucast_err = 0;
        struct ice_pf *pf = vf->pf;
        struct ice_vsi *vsi;
+       u8 mcast_m, ucast_m;
        struct device *dev;
        int ret = 0;
 
@@ -1045,39 +1046,40 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
                goto error_param;
        }
 
+       if (ice_vf_is_port_vlan_ena(vf) ||
+           ice_vsi_has_non_zero_vlans(vsi)) {
+               mcast_m = ICE_MCAST_VLAN_PROMISC_BITS;
+               ucast_m = ICE_UCAST_VLAN_PROMISC_BITS;
+       } else {
+               mcast_m = ICE_MCAST_PROMISC_BITS;
+               ucast_m = ICE_UCAST_PROMISC_BITS;
+       }
+
        if (!test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags)) {
-               bool set_dflt_vsi = alluni || allmulti;
+               if (alluni) {
+                       /* in this case we're turning on promiscuous mode */
+                       ret = ice_set_dflt_vsi(vsi);
+               } else {
+                       /* in this case we're turning off promiscuous mode */
+                       if (ice_is_dflt_vsi_in_use(vsi->port_info))
+                               ret = ice_clear_dflt_vsi(vsi);
+               }
 
-               if (set_dflt_vsi && !ice_is_dflt_vsi_in_use(pf->first_sw))
-                       /* only attempt to set the default forwarding VSI if
-                        * it's not currently set
-                        */
-                       ret = ice_set_dflt_vsi(pf->first_sw, vsi);
-               else if (!set_dflt_vsi &&
-                        ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
-                       /* only attempt to free the default forwarding VSI if we
-                        * are the owner
-                        */
-                       ret = ice_clear_dflt_vsi(pf->first_sw);
+               /* in this case we're turning on/off only
+                * allmulticast
+                */
+               if (allmulti)
+                       mcast_err = ice_vf_set_vsi_promisc(vf, vsi, mcast_m);
+               else
+                       mcast_err = ice_vf_clear_vsi_promisc(vf, vsi, mcast_m);
 
                if (ret) {
-                       dev_err(dev, "%sable VF %d as the default VSI failed, error %d\n",
-                               set_dflt_vsi ? "en" : "dis", vf->vf_id, ret);
+                       dev_err(dev, "Turning on/off promiscuous mode for VF %d failed, error: %d\n",
+                               vf->vf_id, ret);
                        v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
                        goto error_param;
                }
        } else {
-               u8 mcast_m, ucast_m;
-
-               if (ice_vf_is_port_vlan_ena(vf) ||
-                   ice_vsi_has_non_zero_vlans(vsi)) {
-                       mcast_m = ICE_MCAST_VLAN_PROMISC_BITS;
-                       ucast_m = ICE_UCAST_VLAN_PROMISC_BITS;
-               } else {
-                       mcast_m = ICE_MCAST_PROMISC_BITS;
-                       ucast_m = ICE_UCAST_PROMISC_BITS;
-               }
-
                if (alluni)
                        ucast_err = ice_vf_set_vsi_promisc(vf, vsi, ucast_m);
                else
@@ -1102,6 +1104,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
                                            vf->vf_states))
                        dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n",
                                 vf->vf_id);
+       } else {
+               dev_err(dev, "Error while modifying multicast promiscuous mode for VF %u, error: %d\n",
+                       vf->vf_id, mcast_err);
        }
 
        if (!ucast_err) {
@@ -1114,6 +1119,9 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
                                            vf->vf_states))
                        dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n",
                                 vf->vf_id);
+       } else {
+               dev_err(dev, "Error while modifying unicast promiscuous mode for VF %u, error: %d\n",
+                       vf->vf_id, ucast_err);
        }
 
 error_param: