diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 2e23fdc099e0..d458932839a3 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -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); } } } diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c index 46d656d385c4..f74474f8af99 100644 --- a/drivers/net/ethernet/intel/ice/ice_sriov.c +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c @@ -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); } diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index dce32bc194a0..c584f5123ba7 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -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; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h index efa523b25bf8..831b667dc5b2 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h @@ -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)