ice: introduce ICE_VF_RESET_LOCK flag
authorJacob Keller <jacob.e.keller@intel.com>
Wed, 23 Feb 2022 00:27:09 +0000 (16:27 -0800)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 15 Mar 2022 20:23:02 +0000 (13:23 -0700)
The ice_reset_vf function performs actions which must be taken only
while holding the VF configuration lock. Some flows already acquired the
lock, while other flows must acquire it just for the reset function. Add
the ICE_VF_RESET_LOCK flag to the function so that it can handle taking
and releasing the lock instead at the appropriate scope.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_sriov.c
drivers/net/ethernet/intel/ice/ice_vf_lib.c
drivers/net/ethernet/intel/ice/ice_vf_lib.h

index 2e23fdc099e09877784014361a06056b8b9aab4e..d458932839a32892e9a9fd9e0f8cd83104998205 100644 (file)
@@ -1823,9 +1823,7 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
                                 * reset, so print the event prior to reset.
                                 */
                                ice_print_vf_rx_mdd_event(vf);
-                               mutex_lock(&vf->cfg_lock);
-                               ice_reset_vf(vf, 0);
-                               mutex_unlock(&vf->cfg_lock);
+                               ice_reset_vf(vf, ICE_VF_RESET_LOCK);
                        }
                }
        }
index 46d656d385c4813639a549b18d0dcebc1e76b869..f74474f8af99c02f8052b16b980b4749f1de90e6 100644 (file)
@@ -1366,12 +1366,9 @@ void ice_process_vflr_event(struct ice_pf *pf)
                bit_idx = (hw->func_caps.vf_base_id + vf->vf_id) % 32;
                /* read GLGEN_VFLRSTAT register to find out the flr VFs */
                reg = rd32(hw, GLGEN_VFLRSTAT(reg_idx));
-               if (reg & BIT(bit_idx)) {
+               if (reg & BIT(bit_idx))
                        /* GLGEN_VFLRSTAT bit will be cleared in ice_reset_vf */
-                       mutex_lock(&vf->cfg_lock);
-                       ice_reset_vf(vf, ICE_VF_RESET_VFLR);
-                       mutex_unlock(&vf->cfg_lock);
-               }
+                       ice_reset_vf(vf, ICE_VF_RESET_VFLR | ICE_VF_RESET_LOCK);
        }
        mutex_unlock(&pf->vfs.table_lock);
 }
@@ -1453,10 +1450,7 @@ ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event)
        if (!vf)
                return;
 
-       mutex_lock(&vf->cfg_lock);
-       ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
-       mutex_unlock(&vf->cfg_lock);
-
+       ice_reset_vf(vf, ICE_VF_RESET_NOTIFY | ICE_VF_RESET_LOCK);
        ice_put_vf(vf);
 }
 
index dce32bc194a0a91226f9e85a9fc6aaa15854712a..c584f5123ba72bb0bebd03515bb9eb4ce938f693 100644 (file)
@@ -473,6 +473,7 @@ static void ice_notify_vf_reset(struct ice_vf *vf)
  * Flags:
  *   ICE_VF_RESET_VFLR - Indicates a reset is due to VFLR event
  *   ICE_VF_RESET_NOTIFY - Send VF a notification prior to reset
+ *   ICE_VF_RESET_LOCK - Acquire VF cfg_lock before resetting
  *
  * Returns 0 if the VF is currently in reset, if the resets are disabled, or
  * if the VF resets successfully. Returns an error code if the VF fails to
@@ -485,10 +486,9 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
        struct device *dev;
        struct ice_hw *hw;
        u8 promisc_m;
+       int err = 0;
        bool rsd;
 
-       lockdep_assert_held(&vf->cfg_lock);
-
        dev = ice_pf_to_dev(pf);
        hw = &pf->hw;
 
@@ -507,6 +507,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                return 0;
        }
 
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_lock(&vf->cfg_lock);
+       else
+               lockdep_assert_held(&vf->cfg_lock);
+
        /* Set VF disable bit state here, before triggering reset */
        set_bit(ICE_VF_STATE_DIS, vf->vf_states);
        ice_trigger_vf_reset(vf, flags & ICE_VF_RESET_VFLR, false);
@@ -564,7 +569,8 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
        if (vf->vf_ops->vsi_rebuild(vf)) {
                dev_err(dev, "Failed to release and setup the VF%u's VSI\n",
                        vf->vf_id);
-               return -EFAULT;
+               err = -EFAULT;
+               goto out_unlock;
        }
 
        vf->vf_ops->post_vsi_rebuild(vf);
@@ -578,7 +584,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                dev_dbg(dev, "failed to clear malicious VF state for VF %u\n",
                        vf->vf_id);
 
-       return 0;
+out_unlock:
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_unlock(&vf->cfg_lock);
+
+       return err;
 }
 
 /**
index efa523b25bf8097952524b90c026d261b5623366..831b667dc5b2c1886de686e80d0ffca7714a8b5e 100644 (file)
@@ -137,6 +137,7 @@ struct ice_vf {
 enum ice_vf_reset_flags {
        ICE_VF_RESET_VFLR = BIT(0), /* Indicate a VFLR reset */
        ICE_VF_RESET_NOTIFY = BIT(1), /* Notify VF prior to reset */
+       ICE_VF_RESET_LOCK = BIT(2), /* Acquire the VF cfg_lock */
 };
 
 static inline u16 ice_vf_get_port_vlan_id(struct ice_vf *vf)