/**
  * ice_vsi_alloc - Allocates the next available struct VSI in the PF
  * @pf: board private structure
- * @pi: pointer to the port_info instance
- * @vsi_type: type of VSI
- * @ch: ptr to channel
- * @vf: VF for ICE_VSI_VF and ICE_VSI_CTRL
+ * @params: parameters to use when allocating the new VSI
  *
  * The VF pointer is used for ICE_VSI_VF and ICE_VSI_CTRL. For ICE_VSI_CTRL,
  * it may be NULL in the case there is no association with a VF. For
  * returns a pointer to a VSI on success, NULL on failure.
  */
 static struct ice_vsi *
-ice_vsi_alloc(struct ice_pf *pf, struct ice_port_info *pi,
-             enum ice_vsi_type vsi_type, struct ice_channel *ch,
-             struct ice_vf *vf)
+ice_vsi_alloc(struct ice_pf *pf, struct ice_vsi_cfg_params *params)
 {
        struct device *dev = ice_pf_to_dev(pf);
        struct ice_vsi *vsi = NULL;
 
-       if (WARN_ON(vsi_type == ICE_VSI_VF && !vf))
+       if (WARN_ON(params->type == ICE_VSI_VF && !params->vf))
                return NULL;
 
        /* Need to protect the allocation of the VSIs at the PF level */
        if (!vsi)
                goto unlock_pf;
 
-       vsi->type = vsi_type;
+       vsi->type = params->type;
        vsi->back = pf;
-       vsi->port_info = pi;
+       vsi->port_info = params->pi;
        /* For VSIs which don't have a connected VF, this will be NULL */
-       vsi->vf = vf;
+       vsi->vf = params->vf;
        set_bit(ICE_VSI_DOWN, vsi->state);
 
        /* fill slot and make note of the index */
                                         pf->next_vsi);
 
        if (vsi->type == ICE_VSI_CTRL) {
-               if (vf) {
-                       vf->ctrl_vsi_idx = vsi->idx;
+               if (vsi->vf) {
+                       WARN_ON(vsi->vf->ctrl_vsi_idx != ICE_NO_VSI);
+                       vsi->vf->ctrl_vsi_idx = vsi->idx;
                } else {
                        WARN_ON(pf->ctrl_vsi_idx != ICE_NO_VSI);
                        pf->ctrl_vsi_idx = vsi->idx;
 /**
  * ice_vsi_init - Create and initialize a VSI
  * @vsi: the VSI being configured
- * @init_vsi: flag, tell if VSI need to be initialized
+ * @vsi_flags: VSI configuration flags
+ *
+ * Set ICE_FLAG_VSI_INIT to initialize a new VSI context, clear it to
+ * reconfigure an existing context.
  *
  * This initializes a VSI context depending on the VSI type to be added and
  * passes it down to the add_vsi aq command to create a new VSI.
  */
-static int ice_vsi_init(struct ice_vsi *vsi, int init_vsi)
+static int ice_vsi_init(struct ice_vsi *vsi, u32 vsi_flags)
 {
        struct ice_pf *pf = vsi->back;
        struct ice_hw *hw = &pf->hw;
                /* if updating VSI context, make sure to set valid_section:
                 * to indicate which section of VSI context being updated
                 */
-               if (!(init_vsi & ICE_VSI_FLAG_INIT))
+               if (!(vsi_flags & ICE_VSI_FLAG_INIT))
                        ctxt->info.valid_sections |=
                                cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
        }
                if (ret)
                        goto out;
 
-               if (!(init_vsi & ICE_VSI_FLAG_INIT))
+               if (!(vsi_flags & ICE_VSI_FLAG_INIT))
                        /* means VSI being updated */
                        /* must to indicate which section of VSI context are
                         * being modified
                        cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
        }
 
-       if (init_vsi & ICE_VSI_FLAG_INIT) {
+       if (vsi_flags & ICE_VSI_FLAG_INIT) {
                ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL);
                if (ret) {
                        dev_err(dev, "Add VSI failed, err %d\n", ret);
 /**
  * ice_vsi_cfg_def - configure default VSI based on the type
  * @vsi: pointer to VSI
- * @ch: ptr to channel
- * @init_vsi: is this an initialization or a reconfigure of the VSI
+ * @params: the parameters to configure this VSI with
  */
 static int
-ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_channel *ch, int init_vsi)
+ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
 {
        struct device *dev = ice_pf_to_dev(vsi->back);
        struct ice_pf *pf = vsi->back;
 
        vsi->vsw = pf->first_sw;
 
-       ret = ice_vsi_alloc_def(vsi, ch);
+       ret = ice_vsi_alloc_def(vsi, params->ch);
        if (ret)
                return ret;
 
        ice_vsi_set_tc_cfg(vsi);
 
        /* create the VSI */
-       ret = ice_vsi_init(vsi, init_vsi);
+       ret = ice_vsi_init(vsi, params->flags);
        if (ret)
                goto unroll_get_qs;
 
 /**
  * ice_vsi_cfg - configure VSI and tc on it
  * @vsi: pointer to VSI
- * @vf: pointer to VF to which this VSI connects. This field is used primarily
- *      for the ICE_VSI_VF type. Other VSI types should pass NULL.
- * @ch: ptr to channel
- * @init_vsi: is this an initialization or a reconfigure of the VSI
+ * @params: parameters used to configure this VSI
  */
-int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vf *vf, struct ice_channel *ch,
-               int init_vsi)
+int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
 {
        int ret;
 
-       ret = ice_vsi_cfg_def(vsi, ch, init_vsi);
+       ret = ice_vsi_cfg_def(vsi, params);
        if (ret)
                return ret;
 
 /**
  * ice_vsi_setup - Set up a VSI by a given type
  * @pf: board private structure
- * @pi: pointer to the port_info instance
- * @vsi_type: VSI type
- * @vf: pointer to VF to which this VSI connects. This field is used primarily
- *      for the ICE_VSI_VF type. Other VSI types should pass NULL.
- * @ch: ptr to channel
+ * @params: parameters to use when creating the VSI
  *
  * This allocates the sw VSI structure and its queue resources.
  *
  * success, NULL on failure.
  */
 struct ice_vsi *
-ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
-             enum ice_vsi_type vsi_type, struct ice_vf *vf,
-             struct ice_channel *ch)
+ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params)
 {
        struct device *dev = ice_pf_to_dev(pf);
        struct ice_vsi *vsi;
        int ret;
 
-       vsi = ice_vsi_alloc(pf, pi, vsi_type, ch, vf);
+       /* ice_vsi_setup can only initialize a new VSI, and we must have
+        * a port_info structure for it.
+        */
+       if (WARN_ON(!(params->flags & ICE_VSI_FLAG_INIT)) ||
+           WARN_ON(!params->pi))
+               return NULL;
+
+       vsi = ice_vsi_alloc(pf, params);
        if (!vsi) {
                dev_err(dev, "could not allocate VSI\n");
                return NULL;
        }
 
-       ret = ice_vsi_cfg(vsi, vf, ch, ICE_VSI_FLAG_INIT);
+       ret = ice_vsi_cfg(vsi, params);
        if (ret)
                goto err_vsi_cfg;
 
        return vsi;
 
 err_vsi_cfg:
-       if (vsi_type == ICE_VSI_VF)
+       if (params->type == ICE_VSI_VF)
                ice_enable_lag(pf->lag);
        ice_vsi_free(vsi);
 
 /**
  * ice_vsi_rebuild - Rebuild VSI after reset
  * @vsi: VSI to be rebuild
- * @init_vsi: flag, tell if VSI need to be initialized
+ * @vsi_flags: flags used for VSI rebuild flow
+ *
+ * Set vsi_flags to ICE_VSI_FLAG_INIT to initialize a new VSI, or
+ * ICE_VSI_FLAG_NO_INIT to rebuild an existing VSI in hardware.
  *
  * Returns 0 on success and negative value on failure
  */
-int ice_vsi_rebuild(struct ice_vsi *vsi, int init_vsi)
+int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)
 {
+       struct ice_vsi_cfg_params params = {};
        struct ice_coalesce_stored *coalesce;
        int ret, prev_txq, prev_rxq;
        int prev_num_q_vectors = 0;
        if (!vsi)
                return -EINVAL;
 
+       params = ice_vsi_to_params(vsi);
+       params.flags = vsi_flags;
+
        pf = vsi->back;
        if (WARN_ON(vsi->type == ICE_VSI_VF && !vsi->vf))
                return -EINVAL;
        prev_rxq = vsi->num_rxq;
 
        ice_vsi_decfg(vsi);
-       ret = ice_vsi_cfg_def(vsi, vsi->ch, init_vsi);
+       ret = ice_vsi_cfg_def(vsi, ¶ms);
        if (ret)
                goto err_vsi_cfg;
 
        ret = ice_vsi_cfg_tc_lan(pf, vsi);
        if (ret) {
-               if (init_vsi & ICE_VSI_FLAG_INIT) {
+               if (vsi_flags & ICE_VSI_FLAG_INIT) {
                        ret = -EIO;
                        goto err_vsi_cfg_tc_lan;
                } else {
 
 #include "ice.h"
 #include "ice_vlan.h"
 
+/* Flags used for VSI configuration and rebuild */
+#define ICE_VSI_FLAG_INIT      BIT(0)
+#define ICE_VSI_FLAG_NO_INIT   0
+
+/**
+ * struct ice_vsi_cfg_params - VSI configuration parameters
+ * @pi: pointer to the port_info instance for the VSI
+ * @ch: pointer to the channel structure for the VSI, may be NULL
+ * @vf: pointer to the VF associated with this VSI, may be NULL
+ * @type: the type of VSI to configure
+ * @flags: VSI flags used for rebuild and configuration
+ *
+ * Parameter structure used when configuring a new VSI.
+ */
+struct ice_vsi_cfg_params {
+       struct ice_port_info *pi;
+       struct ice_channel *ch;
+       struct ice_vf *vf;
+       enum ice_vsi_type type;
+       u32 flags;
+};
+
+/**
+ * ice_vsi_to_params - Get parameters for an existing VSI
+ * @vsi: the VSI to get parameters for
+ *
+ * Fill a parameter structure for reconfiguring a VSI with its current
+ * parameters, such as during a rebuild operation.
+ */
+static inline struct ice_vsi_cfg_params ice_vsi_to_params(struct ice_vsi *vsi)
+{
+       struct ice_vsi_cfg_params params = {};
+
+       params.pi = vsi->port_info;
+       params.ch = vsi->ch;
+       params.vf = vsi->vf;
+       params.type = vsi->type;
+
+       return params;
+}
+
 const char *ice_vsi_type_str(enum ice_vsi_type vsi_type);
 
 bool ice_pf_state_is_nominal(struct ice_pf *pf);
 void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc);
 
 struct ice_vsi *
-ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
-             enum ice_vsi_type vsi_type, struct ice_vf *vf,
-             struct ice_channel *ch);
+ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params);
 
 void ice_napi_del(struct ice_vsi *vsi);
 
 int
 ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id);
 
-#define ICE_VSI_FLAG_INIT      BIT(0)
-#define ICE_VSI_FLAG_NO_INIT   0
-int ice_vsi_rebuild(struct ice_vsi *vsi, int init_vsi);
-int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vf *vf,
-               struct ice_channel *ch, int init_vsi);
+int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
+int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params);
 
 bool ice_is_reset_in_progress(unsigned long *state);
 int ice_wait_for_reset(struct ice_pf *pf, unsigned long timeout);
 
 static struct ice_vsi *
 ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
 {
-       return ice_vsi_setup(pf, pi, ICE_VSI_PF, NULL, NULL);
+       struct ice_vsi_cfg_params params = {};
+
+       params.type = ICE_VSI_PF;
+       params.pi = pi;
+       params.flags = ICE_VSI_FLAG_INIT;
+
+       return ice_vsi_setup(pf, ¶ms);
 }
 
 static struct ice_vsi *
 ice_chnl_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
                   struct ice_channel *ch)
 {
-       return ice_vsi_setup(pf, pi, ICE_VSI_CHNL, NULL, ch);
+       struct ice_vsi_cfg_params params = {};
+
+       params.type = ICE_VSI_CHNL;
+       params.pi = pi;
+       params.ch = ch;
+       params.flags = ICE_VSI_FLAG_INIT;
+
+       return ice_vsi_setup(pf, ¶ms);
 }
 
 /**
 static struct ice_vsi *
 ice_ctrl_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
 {
-       return ice_vsi_setup(pf, pi, ICE_VSI_CTRL, NULL, NULL);
+       struct ice_vsi_cfg_params params = {};
+
+       params.type = ICE_VSI_CTRL;
+       params.pi = pi;
+       params.flags = ICE_VSI_FLAG_INIT;
+
+       return ice_vsi_setup(pf, ¶ms);
 }
 
 /**
 struct ice_vsi *
 ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
 {
-       return ice_vsi_setup(pf, pi, ICE_VSI_LB, NULL, NULL);
+       struct ice_vsi_cfg_params params = {};
+
+       params.type = ICE_VSI_LB;
+       params.pi = pi;
+       params.flags = ICE_VSI_FLAG_INIT;
+
+       return ice_vsi_setup(pf, ¶ms);
 }
 
 /**
  */
 int ice_load(struct ice_pf *pf)
 {
+       struct ice_vsi_cfg_params params = {};
        struct ice_vsi *vsi;
        int err;
 
                return err;
 
        vsi = ice_get_main_vsi(pf);
-       err = ice_vsi_cfg(vsi, NULL, NULL, ICE_VSI_FLAG_INIT);
+
+       params = ice_vsi_to_params(vsi);
+       params.flags = ICE_VSI_FLAG_INIT;
+
+       err = ice_vsi_cfg(vsi, ¶ms);
        if (err)
                goto err_vsi_cfg;