diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c index 59df4c9bd8f909ae16ad9ed1b6e518c9203e8edf..b5d79b40d8c5a68fc3777009881daf3948729d28 100644 --- a/drivers/net/ethernet/intel/ice/ice_base.c +++ b/drivers/net/ethernet/intel/ice/ice_base.c @@ -822,7 +822,9 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, * associated to the queue to schedule NAPI handler */ q_vector = ring->q_vector; - if (q_vector) + if (q_vector && + !(vsi->vf_id != ICE_INVAL_VFID && + ice_is_vf_disabled(&pf->vf[vsi->vf_id]))) ice_trigger_sw_intr(hw, q_vector); status = ice_dis_vsi_txq(vsi->port_info, txq_meta->vsi_idx, diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 127782345a45fde345b04f9831b2f84f862fe8ab..3bd15496a8377a44b1b2c694b23996b122e6331c 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -164,6 +164,9 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id) if (vsi->type == ICE_VSI_VF) vsi->vf_id = vf_id; + else + vsi->vf_id = ICE_INVAL_VFID; + switch (vsi->type) { case ICE_VSI_PF: vsi->alloc_txq = min3(pf->num_lan_msix, @@ -2030,6 +2033,31 @@ int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi) return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings, vsi->num_xdp_txq); } +/** + * ice_vsi_is_rx_queue_active + * @vsi: the VSI being configured + * + * Return true if at least one queue is active. + */ +bool ice_vsi_is_rx_queue_active(struct ice_vsi *vsi) +{ + struct ice_pf *pf = vsi->back; + struct ice_hw *hw = &pf->hw; + int i; + + ice_for_each_rxq(vsi, i) { + u32 rx_reg; + int pf_q; + + pf_q = vsi->rxq_map[i]; + rx_reg = rd32(hw, QRX_CTRL(pf_q)); + if (rx_reg & QRX_CTRL_QENA_STAT_M) + return true; + } + + return false; +} + /** * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not * @vsi: VSI to check whether or not VLAN pruning is enabled. diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index 3da17895a2b15051508a6cb440a578e3a458e895..f3fdadd88dad99d692a50d2757191c037cc146c7 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -107,4 +107,5 @@ 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_vsi_is_rx_queue_active(struct ice_vsi *vsi); #endif /* !_ICE_LIB_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 4f662530826420f58871ee8825361cf723ce0b02..ffcb71ccf9adb864fbf5bc68ec5ed5ee2c0e1427 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1609,7 +1609,7 @@ static void ice_handle_mdd_event(struct ice_pf *pf) */ ice_print_vf_rx_mdd_event(vf); mutex_lock(&pf->vf[i].cfg_lock); - ice_reset_vf(&pf->vf[i], false); + ice_reset_vf(&pf->vf[i], 0); mutex_unlock(&pf->vf[i].cfg_lock); } } diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index a980d337861dedc387cc5a263b906c897b94c1c6..5b3aef70ac2a763a7c1d175997e496d1d61a02b0 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -1248,7 +1248,7 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr) * * Returns true if the PF or VF is disabled, false otherwise. */ -static bool ice_is_vf_disabled(struct ice_vf *vf) +bool ice_is_vf_disabled(struct ice_vf *vf) { struct ice_pf *pf = vf->pf; @@ -1261,15 +1261,31 @@ static bool ice_is_vf_disabled(struct ice_vf *vf) test_bit(ICE_VF_STATE_DIS, vf->vf_states)); } +/** + * ice_get_vf_vsi - get VF's VSI based on the stored index + * @vf: VF used to get VSI + */ +struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf) +{ + if (vf->lan_vsi_idx == ICE_NO_VSI) + return NULL; + + return vf->pf->vsi[vf->lan_vsi_idx]; +} + /** * ice_reset_vf - Reset a particular VF * @vf: pointer to the VF structure - * @is_vflr: true if VFLR was issued, false if not + * @flags: flags controlling behavior of the reset + * + * Flags: + * ICE_VF_RESET_VFLR - Indicates a reset is due to VFLR event * - * Returns true if the VF is currently in reset, resets successfully, or resets - * are disabled and false otherwise. + * 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 + * rebuild. */ -bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) +int ice_reset_vf(struct ice_vf *vf, u32 flags) { struct ice_pf *pf = vf->pf; struct ice_vsi *vsi; @@ -1287,18 +1303,28 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) if (test_bit(__ICE_VF_RESETS_DISABLED, pf->state)) { dev_dbg(dev, "Trying to reset VF %d, but all VF resets are disabled\n", vf->vf_id); - return true; + return 0; } if (ice_is_vf_disabled(vf)) { + vsi = ice_get_vf_vsi(vf); + if (!vsi) { + dev_dbg(dev, "VF is already removed\n"); + return -EINVAL; + } + ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id); + + if (ice_vsi_is_rx_queue_active(vsi)) + ice_vsi_stop_all_rx_rings(vsi); + dev_dbg(dev, "VF is already disabled, there is no need for resetting it, telling VM, all is fine %d\n", vf->vf_id); - return true; + return 0; } /* Set VF disable bit state here, before triggering reset */ set_bit(ICE_VF_STATE_DIS, vf->vf_states); - ice_trigger_vf_reset(vf, is_vflr, false); + ice_trigger_vf_reset(vf, flags & ICE_VF_RESET_VFLR, false); vsi = pf->vsi[vf->lan_vsi_idx]; @@ -1354,12 +1380,12 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) if (ice_vf_rebuild_vsi_with_release(vf)) { dev_err(dev, "Failed to release and setup the VF%u's VSI\n", vf->vf_id); - return false; + return -EFAULT; } ice_vf_post_vsi_rebuild(vf); - return true; + return 0; } /** @@ -1738,7 +1764,7 @@ void ice_process_vflr_event(struct ice_pf *pf) if (reg & BIT(bit_idx)) { /* GLGEN_VFLRSTAT bit will be cleared in ice_reset_vf */ mutex_lock(&vf->cfg_lock); - ice_reset_vf(vf, true); + ice_reset_vf(vf, ICE_VF_RESET_VFLR); mutex_unlock(&vf->cfg_lock); } } @@ -1751,7 +1777,7 @@ void ice_process_vflr_event(struct ice_pf *pf) static void ice_vc_reset_vf(struct ice_vf *vf) { ice_vc_notify_vf_reset(vf); - ice_reset_vf(vf, false); + ice_reset_vf(vf, 0); } /** @@ -2022,7 +2048,7 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg) static void ice_vc_reset_vf_msg(struct ice_vf *vf) { if (test_bit(ICE_VF_STATE_INIT, vf->vf_states)) - ice_reset_vf(vf, false); + ice_reset_vf(vf, 0); } /** diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h index d2e935c678a147e14037ea451a4b5f0e020c0640..32eee438ef2e0ba2aa691e6d0fcd0d1c0d7ddbba 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h @@ -104,6 +104,11 @@ struct ice_vf { struct ice_mdd_vf_events mdd_tx_events; }; +/* Flags for controlling behavior of ice_reset_vf */ +enum ice_vf_reset_flags { + ICE_VF_RESET_VFLR = BIT(0), /* Indicate a VFLR reset */ +}; + #ifdef CONFIG_PCI_IOV void ice_process_vflr_event(struct ice_pf *pf); int ice_sriov_configure(struct pci_dev *pdev, int num_vfs); @@ -116,7 +121,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event); void ice_vc_notify_link_state(struct ice_pf *pf); void ice_vc_notify_reset(struct ice_pf *pf); bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr); -bool ice_reset_vf(struct ice_vf *vf, bool is_vflr); +bool ice_is_vf_disabled(struct ice_vf *vf); +int ice_reset_vf(struct ice_vf *vf, u32 flags); void ice_restore_all_vfs_msi_state(struct pci_dev *pdev); int @@ -159,12 +165,17 @@ ice_reset_all_vfs(struct ice_pf __always_unused *pf, return true; } -static inline bool -ice_reset_vf(struct ice_vf __always_unused *vf, bool __always_unused is_vflr) +static inline bool ice_is_vf_disabled(struct ice_vf *vf) { return true; } +static inline int +ice_reset_vf(struct ice_vf __always_unused *vf, u32 __always_unused flags) +{ + return 0; +} + static inline int ice_sriov_configure(struct pci_dev __always_unused *pdev, int __always_unused num_vfs)