]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ice: Add code to keep track of current dflt_vsi
authorBrett Creeley <brett.creeley@intel.com>
Thu, 12 Dec 2019 11:12:55 +0000 (03:12 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 4 Jan 2020 00:08:33 +0000 (16:08 -0800)
We can't have more than one default VSI so prevent another VSI from
overwriting the current dflt_vsi. This was achieved by adding the
following functions:

ice_is_dflt_vsi_in_use()
- Used to check if the default VSI is already being used.

ice_is_vsi_dflt_vsi()
- Used to check if VSI passed in is in fact the default VSI.

ice_set_dflt_vsi()
- Used to set the default VSI via a switch rule

ice_clear_dflt_vsi()
- Used to clear the default VSI via a switch rule.

Also, there was no need to introduce any locking because all mailbox
events and synchronization of switch filters for the PF happen in the
service task.

Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_lib.h
drivers/net/ethernet/intel/ice/ice_main.c

index 54b2c349c19530d5154b1ee2f6886591387b4802..1376219a6c7e1142140f347e966d484e7614a9aa 100644 (file)
@@ -174,6 +174,8 @@ 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_state {
index a47241e92d0bb42c2992be18cf53405a5f4d2226..b5cd275606bb18b31b90ca5ff8195cc808556d51 100644 (file)
@@ -2742,3 +2742,121 @@ cfg_mac_fltr_exit:
        ice_free_fltr_list(&vsi->back->pdev->dev, &tmp_add_list);
        return status;
 }
+
+/**
+ * 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
+ *
+ * Return true if the default forwarding VSI is already being used, else returns
+ * false signalling that it's available to use.
+ */
+bool ice_is_dflt_vsi_in_use(struct ice_sw *sw)
+{
+       return (sw->dflt_vsi && sw->dflt_vsi_ena);
+}
+
+/**
+ * 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)
+{
+       return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena);
+}
+
+/**
+ * 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.
+ */
+int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
+{
+       enum ice_status status;
+       struct device *dev;
+
+       if (!sw || !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)) {
+               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);
+       if (status) {
+               dev_err(dev,
+                       "Failed to set VSI %d as the default forwarding VSI, error %d\n",
+                       vsi->vsi_num, status);
+               return -EIO;
+       }
+
+       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
+ *
+ * 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)
+{
+       struct ice_vsi *dflt_vsi;
+       enum ice_status status;
+       struct device *dev;
+
+       if (!sw)
+               return -EINVAL;
+
+       dev = ice_pf_to_dev(sw->pf);
+
+       dflt_vsi = sw->dflt_vsi;
+
+       /* there is no default VSI configured */
+       if (!ice_is_dflt_vsi_in_use(sw))
+               return -ENODEV;
+
+       status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_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);
+               return -EIO;
+       }
+
+       sw->dflt_vsi = NULL;
+       sw->dflt_vsi_ena = false;
+
+       return 0;
+}
index 6e31e30aba3941b943a862ebcf1d5fe9f948ebf8..68fd0d4505c26c6b200e1cb6ed3ac8625028611d 100644 (file)
@@ -103,4 +103,12 @@ enum ice_status
 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_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);
 #endif /* !_ICE_LIB_H_ */
index 1fc6c350487b1bde9433d5cb74b1f8af35b16ab6..639de467f120566701ce8bb1d748c3e463bae3bc 100644 (file)
@@ -379,25 +379,29 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
                clear_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags);
                if (vsi->current_netdev_flags & IFF_PROMISC) {
                        /* Apply Rx filter rule to get traffic from wire */
-                       status = ice_cfg_dflt_vsi(hw, vsi->idx, true,
-                                                 ICE_FLTR_RX);
-                       if (status) {
-                               netdev_err(netdev, "Error setting default VSI %i Rx rule\n",
-                                          vsi->vsi_num);
-                               vsi->current_netdev_flags &= ~IFF_PROMISC;
-                               err = -EIO;
-                               goto out_promisc;
+                       if (!ice_is_dflt_vsi_in_use(pf->first_sw)) {
+                               err = ice_set_dflt_vsi(pf->first_sw, vsi);
+                               if (err && err != -EEXIST) {
+                                       netdev_err(netdev,
+                                                  "Error %d setting default VSI %i Rx rule\n",
+                                                  err, vsi->vsi_num);
+                                       vsi->current_netdev_flags &=
+                                               ~IFF_PROMISC;
+                                       goto out_promisc;
+                               }
                        }
                } else {
                        /* Clear Rx filter to remove traffic from wire */
-                       status = ice_cfg_dflt_vsi(hw, vsi->idx, false,
-                                                 ICE_FLTR_RX);
-                       if (status) {
-                               netdev_err(netdev, "Error clearing default VSI %i Rx rule\n",
-                                          vsi->vsi_num);
-                               vsi->current_netdev_flags |= IFF_PROMISC;
-                               err = -EIO;
-                               goto out_promisc;
+                       if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi)) {
+                               err = ice_clear_dflt_vsi(pf->first_sw);
+                               if (err) {
+                                       netdev_err(netdev,
+                                                  "Error %d clearing default VSI %i Rx rule\n",
+                                                  err, vsi->vsi_num);
+                                       vsi->current_netdev_flags |=
+                                               IFF_PROMISC;
+                                       goto out_promisc;
+                               }
                        }
                }
        }
@@ -4671,6 +4675,13 @@ 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);
 
        ret = ice_get_caps(hw);