ice: add E830 HW VF mailbox message limit support

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>
This commit is contained in:
Paul Greenwalt 2024-08-20 17:26:16 -04:00 committed by Tony Nguyen
parent b699c81af0
commit 59f4d59b25
9 changed files with 96 additions and 13 deletions

View File

@ -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
};

View File

@ -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_ */

View File

@ -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);
}
/**

View File

@ -1563,12 +1563,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);
@ -4099,7 +4107,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);

View File

@ -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);
}

View File

@ -709,6 +709,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
@ -735,7 +752,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)) {
@ -951,7 +968,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 &&
@ -1004,7 +1021,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);
}

View File

@ -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

View File

@ -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_ */

View File

@ -4009,8 +4009,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)
@ -4036,7 +4038,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. */