ice: add E830 HW VF mailbox message limit support
[ Upstream commit 59f4d59b25aec39a015c0949f4ec235c7a839c44 ] E830 adds hardware support to prevent the VF from overflowing the PF mailbox with VIRTCHNL messages. E830 will use the hardware feature (ICE_F_MBX_LIMIT) instead of the software solution ice_is_malicious_vf(). To prevent a VF from overflowing the PF, the PF sets the number of messages per VF that can be in the PF's mailbox queue (ICE_MBX_OVERFLOW_WATERMARK). When the PF processes a message from a VF, the PF decrements the per VF message count using the E830_MBX_VF_DEC_TRIG register. Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Stable-dep-of: 79990cf5e7ad ("ice: Fix deinitializing VF in error path") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c417b1e4d8
commit
dc44e67c6d
@@ -207,6 +207,7 @@ enum ice_feature {
|
||||
ICE_F_GNSS,
|
||||
ICE_F_ROCE_LAG,
|
||||
ICE_F_SRIOV_LAG,
|
||||
ICE_F_MBX_LIMIT,
|
||||
ICE_F_MAX
|
||||
};
|
||||
|
||||
|
||||
@@ -539,5 +539,8 @@
|
||||
#define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0)
|
||||
#define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
|
||||
#define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
|
||||
#define E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH 0x00234000
|
||||
#define E830_MBX_VF_DEC_TRIG(_VF) (0x00233800 + (_VF) * 4)
|
||||
#define E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(_VF) (0x00233000 + (_VF) * 4)
|
||||
|
||||
#endif /* _ICE_HW_AUTOGEN_H_ */
|
||||
|
||||
@@ -3880,6 +3880,9 @@ void ice_init_feature_support(struct ice_pf *pf)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pf->hw.mac_type == ICE_MAC_E830)
|
||||
ice_set_feature_support(pf, ICE_F_MBX_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1546,12 +1546,20 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type)
|
||||
ice_vf_lan_overflow_event(pf, &event);
|
||||
break;
|
||||
case ice_mbx_opc_send_msg_to_pf:
|
||||
data.num_msg_proc = i;
|
||||
data.num_pending_arq = pending;
|
||||
data.max_num_msgs_mbx = hw->mailboxq.num_rq_entries;
|
||||
data.async_watermark_val = ICE_MBX_OVERFLOW_WATERMARK;
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) {
|
||||
ice_vc_process_vf_msg(pf, &event, NULL);
|
||||
ice_mbx_vf_dec_trig_e830(hw, &event);
|
||||
} else {
|
||||
u16 val = hw->mailboxq.num_rq_entries;
|
||||
|
||||
ice_vc_process_vf_msg(pf, &event, &data);
|
||||
data.max_num_msgs_mbx = val;
|
||||
val = ICE_MBX_OVERFLOW_WATERMARK;
|
||||
data.async_watermark_val = val;
|
||||
data.num_msg_proc = i;
|
||||
data.num_pending_arq = pending;
|
||||
|
||||
ice_vc_process_vf_msg(pf, &event, &data);
|
||||
}
|
||||
break;
|
||||
case ice_aqc_opc_fw_logs_event:
|
||||
ice_get_fwlog_data(pf, &event);
|
||||
@@ -4082,7 +4090,11 @@ static int ice_init_pf(struct ice_pf *pf)
|
||||
|
||||
mutex_init(&pf->vfs.table_lock);
|
||||
hash_init(pf->vfs.table);
|
||||
ice_mbx_init_snapshot(&pf->hw);
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
wr32(&pf->hw, E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH,
|
||||
ICE_MBX_OVERFLOW_WATERMARK);
|
||||
else
|
||||
ice_mbx_init_snapshot(&pf->hw);
|
||||
|
||||
xa_init(&pf->dyn_ports);
|
||||
xa_init(&pf->sf_nums);
|
||||
|
||||
@@ -194,7 +194,8 @@ void ice_free_vfs(struct ice_pf *pf)
|
||||
}
|
||||
|
||||
/* clear malicious info since the VF is getting released */
|
||||
list_del(&vf->mbx_info.list_entry);
|
||||
if (!ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
list_del(&vf->mbx_info.list_entry);
|
||||
|
||||
mutex_unlock(&vf->cfg_lock);
|
||||
}
|
||||
|
||||
@@ -716,6 +716,23 @@ ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_reset_vf_mbx_cnt - reset VF mailbox message count
|
||||
* @vf: pointer to the VF structure
|
||||
*
|
||||
* This function clears the VF mailbox message count, and should be called on
|
||||
* VF reset.
|
||||
*/
|
||||
static void ice_reset_vf_mbx_cnt(struct ice_vf *vf)
|
||||
{
|
||||
struct ice_pf *pf = vf->pf;
|
||||
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
|
||||
else
|
||||
ice_mbx_clear_malvf(&vf->mbx_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_reset_all_vfs - reset all allocated VFs in one go
|
||||
* @pf: pointer to the PF structure
|
||||
@@ -742,7 +759,7 @@ void ice_reset_all_vfs(struct ice_pf *pf)
|
||||
|
||||
/* clear all malicious info if the VFs are getting reset */
|
||||
ice_for_each_vf(pf, bkt, vf)
|
||||
ice_mbx_clear_malvf(&vf->mbx_info);
|
||||
ice_reset_vf_mbx_cnt(vf);
|
||||
|
||||
/* If VFs have been disabled, there is no need to reset */
|
||||
if (test_and_set_bit(ICE_VF_DIS, pf->state)) {
|
||||
@@ -958,7 +975,7 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
|
||||
ice_eswitch_update_repr(&vf->repr_id, vsi);
|
||||
|
||||
/* if the VF has been reset allow it to come up again */
|
||||
ice_mbx_clear_malvf(&vf->mbx_info);
|
||||
ice_reset_vf_mbx_cnt(vf);
|
||||
|
||||
out_unlock:
|
||||
if (lag && lag->bonded && lag->primary &&
|
||||
@@ -1011,7 +1028,10 @@ void ice_initialize_vf_entry(struct ice_vf *vf)
|
||||
ice_vf_fdir_init(vf);
|
||||
|
||||
/* Initialize mailbox info for this VF */
|
||||
ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
|
||||
else
|
||||
ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
|
||||
|
||||
mutex_init(&vf->cfg_lock);
|
||||
}
|
||||
|
||||
@@ -210,6 +210,38 @@ ice_mbx_detect_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_mbx_vf_dec_trig_e830 - Decrements the VF mailbox queue counter
|
||||
* @hw: pointer to the HW struct
|
||||
* @event: pointer to the control queue receive event
|
||||
*
|
||||
* This function triggers to decrement the counter
|
||||
* MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT when the driver replenishes
|
||||
* the buffers at the PF mailbox queue.
|
||||
*/
|
||||
void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
|
||||
const struct ice_rq_event_info *event)
|
||||
{
|
||||
u16 vfid = le16_to_cpu(event->desc.retval);
|
||||
|
||||
wr32(hw, E830_MBX_VF_DEC_TRIG(vfid), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_mbx_vf_clear_cnt_e830 - Clear the VF mailbox queue count
|
||||
* @hw: pointer to the HW struct
|
||||
* @vf_id: VF ID in the PF space
|
||||
*
|
||||
* This function clears the counter MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT, and should
|
||||
* be called when a VF is created and on VF reset.
|
||||
*/
|
||||
void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id)
|
||||
{
|
||||
u32 reg = rd32(hw, E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(vf_id));
|
||||
|
||||
wr32(hw, E830_MBX_VF_DEC_TRIG(vf_id), reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_mbx_vf_state_handler - Handle states of the overflow algorithm
|
||||
* @hw: pointer to the HW struct
|
||||
|
||||
@@ -19,6 +19,9 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
|
||||
u8 *msg, u16 msglen, struct ice_sq_cd *cd);
|
||||
|
||||
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed);
|
||||
void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
|
||||
const struct ice_rq_event_info *event);
|
||||
void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id);
|
||||
int
|
||||
ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data,
|
||||
struct ice_mbx_vf_info *vf_info, bool *report_malvf);
|
||||
@@ -47,5 +50,11 @@ static inline void ice_mbx_init_snapshot(struct ice_hw *hw)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
|
||||
const struct ice_rq_event_info *event)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
#endif /* _ICE_VF_MBX_H_ */
|
||||
|
||||
@@ -4008,8 +4008,10 @@ ice_is_malicious_vf(struct ice_vf *vf, struct ice_mbx_data *mbxdata)
|
||||
* @event: pointer to the AQ event
|
||||
* @mbxdata: information used to detect VF attempting mailbox overflow
|
||||
*
|
||||
* called from the common asq/arq handler to
|
||||
* process request from VF
|
||||
* Called from the common asq/arq handler to process request from VF. When this
|
||||
* flow is used for devices with hardware VF to PF message queue overflow
|
||||
* support (ICE_F_MBX_LIMIT) mbxdata is set to NULL and ice_is_malicious_vf
|
||||
* check is skipped.
|
||||
*/
|
||||
void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
|
||||
struct ice_mbx_data *mbxdata)
|
||||
@@ -4035,7 +4037,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
|
||||
mutex_lock(&vf->cfg_lock);
|
||||
|
||||
/* Check if the VF is trying to overflow the mailbox */
|
||||
if (ice_is_malicious_vf(vf, mbxdata))
|
||||
if (mbxdata && ice_is_malicious_vf(vf, mbxdata))
|
||||
goto finish;
|
||||
|
||||
/* Check if VF is disabled. */
|
||||
|
||||
Reference in New Issue
Block a user