From: Norbert Zulinski <norbertx.zulinski@intel.com> mainline inclusion from mainline-v6.1-rc5 commit f23df5220d2bf8d5e639f074b76f206a736d09e1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBP3Y9 CVE: CVE-2022-49722 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ---------------------- Previously, during removal of trusted VF when VF is down there was number of spurious interrupt equal to number of queues on VF. Add check if VF already has inactive queues. If VF is disabled and has inactive rx queues then do not disable rx queues. Add check in ice_vsi_stop_tx_ring if it's VF's vsi and if VF is disabled. Fixes: efe41860008e ("ice: Fix memory corruption in VF driver") Signed-off-by: Norbert Zulinski <norbertx.zulinski@intel.com> Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com> Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Conflicts: drivers/net/ethernet/intel/ice/ice_lib.h drivers/net/ethernet/intel/ice/ice_lib.c drivers/net/ethernet/intel/ice/ice_vf_lib.c drivers/net/ethernet/intel/ice/ice_base.c drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h [Conflicts due to previous commits 177ef7f1e2a0('ice: base subfunction aux driver') not merged.] Signed-off-by: Liu Chuang <liuchuang40@huawei.com> Signed-off-by: Xiaomeng Zhang <zhangxiaomeng13@huawei.com> --- drivers/net/ethernet/intel/ice/ice_base.c | 4 ++- drivers/net/ethernet/intel/ice/ice_lib.c | 25 +++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_lib.h | 1 + .../net/ethernet/intel/ice/ice_virtchnl_pf.c | 7 ++++-- .../net/ethernet/intel/ice/ice_virtchnl_pf.h | 1 + 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c index 59df4c9bd8f9..b5d79b40d8c5 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 127782345a45..ee7078a36597 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2030,6 +2030,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 3da17895a2b1..f3fdadd88dad 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_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 32d32294ca08..5b3aef70ac2a 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; @@ -1313,7 +1313,10 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) return -EINVAL; } ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id); - ice_vsi_stop_all_rx_rings(vsi); + + 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 0; diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h index 43e9e10d846e..527d8b35cddf 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h @@ -121,6 +121,7 @@ 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_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); -- 2.34.1