Update ICE base driver
cover Update ICE base driver
A few more changes for the ICE base driver:
- Integer overflow fix
- DCB/PFC changes that were submitted earlier by Vladimir [1]
The intent is to merge these as base driver changes, with successive work to be built on top.
[1] https://patches.dpdk.org/project/dpdk/cover/[email protected]/
Chinh Cao (1):
net/ice/base: fix integer overflow on NVM init
Vladimir Medvedkin (3):
net/ice/base: add utility functions
net/ice/base: make set MAC config TC aware
net/ice/base: add support for asymmetric PFC
drivers/net/intel/ice/base/ice_common.c | 220 ++++++++++++++++++++---- drivers/net/intel/ice/base/ice_common.h | 11 ++ drivers/net/intel/ice/base/ice_dcb.c | 105 +++++++++-- drivers/net/intel/ice/base/ice_dcb.h | 16 +- drivers/net/intel/ice/base/ice_type.h | 17 +- 5 files changed, 316 insertions(+), 53 deletions(-)
--
2.47.3
PATCH 1/4 net/ice/base: fix integer overflow on NVM init
From: Chinh Cao <[email protected]>
The shadow RAM size is defined as 16-bit unsigned, which may result in overflows under certain scenarios. Fix the value to be 32-bit.
--- drivers/net/intel/ice/base/ice_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/intel/ice/base/ice_type.h +1 -1
@@ -982,7 +982,7 @@ struct ice_flash_info {struct ice_orom_info orom;/* Option ROM version info */ struct ice_nvm_info nvm;/* NVM version information */ struct ice_bank_info banks;/* Flash Bank information */ -u16 sr_words;/* Shadow RAM size in words */ +u32 sr_words;/* Shadow RAM size in words */ u32 flash_size;/* Size of available flash in bytes */ u8 blank_nvm_mode;/* is NVM empty (no FW present) */ };
Signature · 1 line
2.47.3
PATCH 2/4 net/ice/base: add utility functions
In reply to Anatoly BurakovFrom: Vladimir Medvedkin <[email protected]>
Add the following utility functions related to DCB:
* Get number of Congestion Domains per port
* Resolve Traffic Class(TC) by 802.1p VLAN User Priority(UP)
* Get absolute index of the Congestion Domain by TC
--- drivers/net/intel/ice/base/ice_common.c | 48 +++++++++++++++++++++++++ drivers/net/intel/ice/base/ice_common.h | 8 +++++ 2 files changed, 56 insertions(+)
drivers/net/intel/ice/base/ice_common.c +48 -0
@@ -6594,3 +6594,51 @@ bool ice_is_fw_auto_drop_supported(struct ice_hw *hw)return true;return false; } + +/** +* ice_get_port_max_cgd +* @hw: pointer to the hardware structure +* +* Returns the number of congestion domains (cgds) for a port +*/ +enum ice_cgd_per_port +ice_get_port_max_cgd (struct ice_hw *hw) +{ +#define ICE_8_PORTS_LINK_TOPO 0x2 +u32 link_topo =LE32_TO_CPU (rd32 (hw,GLGEN_MAC_LINK_TOPO )) & +GLGEN_MAC_LINK_TOPO_LINK_TOPO_M ; + +return (link_topo ==ICE_8_PORTS_LINK_TOPO ) ?ICE_4_CGD_PER_PORT :ICE_8_CGD_PER_PORT ; +} + +/** +* ice_get_tc_by_priority +* @hw: pointer to the hardware structure +* @prio: VLAN PCP +* +* Returns the index of Traffic Class(TC) associated with the User Priority +*/ +u8 +ice_get_tc_by_priority (struct ice_hw *hw,u8 prio) +{ +struct ice_port_info *port_info = hw->port_info; +struct ice_qos_cfg *qos_cfg = &port_info->qos_cfg; +struct ice_dcbx_cfg *local_dcb_conf = &qos_cfg->local_dcbx_cfg; + + prio &= (ICE_MAX_TRAFFIC_CLASS -1 ); + +return local_dcb_conf->etscfg.prio_table[prio]; +} + +/** +* ice_get_cgd_idx +* @hw: pointer to the hardware structure +* @tc: index of Traffic Class +* +* Returns the absolute index of the congestion domain by its TC +*/ +int +ice_get_cgd_idx (struct ice_hw *hw,u8 tc) +{ +return hw->port_info->lport *ice_get_port_max_cgd (hw) + tc; +}
drivers/net/intel/ice/base/ice_common.h +8 -0
@@ -25,6 +25,11 @@ enum ice_fw_modes { ICE_FW_MODE_ROLLBACK }; +enum ice_cgd_per_port { +ICE_4_CGD_PER_PORT =4 , +ICE_8_CGD_PER_PORT =8 +}; +int ice_init_fltr_mgmt_struct (struct ice_hw *hw);void ice_cleanup_fltr_mgmt_struct (struct ice_hw *hw);void ice_set_umac_shared (struct ice_hw *hw);
@@ -335,4 +340,7 @@ ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,bool ice_fw_supports_report_dflt_cfg (struct ice_hw *hw);/* AQ API version for FW auto drop reports */ bool ice_is_fw_auto_drop_supported (struct ice_hw *hw); +enum ice_cgd_per_port ice_get_port_max_cgd (struct ice_hw *hw); +u8 ice_get_tc_by_priority (struct ice_hw *hw,u8 prio); +int ice_get_cgd_idx (struct ice_hw *hw,u8 tc);#endif /* _ICE_COMMON_H_ */
Signature · 1 line
2.47.3
PATCH 3/4 net/ice/base: make set MAC config TC aware
In reply to Anatoly BurakovFrom: Vladimir Medvedkin <[email protected]>
Current implementation of the ice_aq_set_mac_cfg() sets Flow Control (FC) settings such as quanta and threshold only for LFC. This patch makes this function Traffic Class (TC) aware, so it can configure FC for each TC individually.
--- drivers/net/intel/ice/base/ice_common.c | 172 +++++++++++++++++++----- drivers/net/intel/ice/base/ice_common.h | 3 + drivers/net/intel/ice/base/ice_type.h | 13 ++ 3 files changed, 152 insertions(+), 36 deletions(-)
drivers/net/intel/ice/base/ice_common.c +136 -36
@@ -700,65 +700,136 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse, }/** -* ice_fill_tx_timer_and_fc_thresh +* ice_get_xoff_pause_quanta * @hw: pointer to the HW struct -* @cmd: pointer to MAC cfg structure +* @tc: index of traffic class. Relevant if @pfc is true +* @pfc: if true - use @tc to get corresponding quanta * -* Add Tx timer and FC refresh threshold info to Set MAC Config AQ command -* descriptor +* Returns u16 current configured LFC of PFC quanta value. +* If @pfc is true returns value of the corresponding @tc traffic class. +* If false returns configured LFC quanta */ -static void -ice_fill_tx_timer_and_fc_thresh (struct ice_hw *hw, -struct ice_aqc_set_mac_cfg *cmd) +static u16 +ice_get_xoff_pause_quanta (struct ice_hw *hw,u8 tc,bool pfc) { -u16 fc_thres_val, tx_timer_val; -u32 val; +u32 val =0 ; -/* We read back the transmit timer and fc threshold value of -* LFC. Thus, we will use index = -* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX. -* -* Also, because we are operating on transmit timer and fc -* threshold of LFC, we don't turn on any bit in tx_tmr_priority -*/ -#define E800_IDX_OF_LFC E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX +#define E830_CL01_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL01_PAUSE_QUANTA : E830_PRTMAC_CL01_PAUSE_QUANTA) +#define E830_CL23_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL23_PAUSE_QUANTA : E830_PRTMAC_CL23_PAUSE_QUANTA) +#define E830_CL45_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL45_PAUSE_QUANTA : E830_PRTMAC_CL45_PAUSE_QUANTA) +#define E830_CL67_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL67_PAUSE_QUANTA : E830_PRTMAC_CL67_PAUSE_QUANTA)if ((hw)->mac_type ==ICE_MAC_E830 ) { -/* Retrieve the transmit timer */ - val =rd32 (hw,E830_PRTMAC_CL01_PAUSE_QUANTA ); - tx_timer_val = val &E830_PRTMAC_CL01_PAUSE_QUANTA_CL0_PAUSE_QUANTA_M ; - cmd->tx_tmr_value =CPU_TO_LE16 (tx_timer_val); +switch (tc) { +case 0 : +case 1 : + val =rd32 (hw,E830_CL01_PAUSE_QUANTA (hw->port_info)); +break ; +case 2 : +case 3 : + val =rd32 (hw,E830_CL23_PAUSE_QUANTA (hw->port_info)); +break ; +case 4 : +case 5 : + val =rd32 (hw,E830_CL45_PAUSE_QUANTA (hw->port_info)); +break ; +case 6 : +case 7 : + val =rd32 (hw,E830_CL67_PAUSE_QUANTA (hw->port_info)); +break ; + } + +if (tc &0x1 ) + val >>=16 ; -/* Retrieve the fc threshold */ - val =rd32 (hw,E830_PRTMAC_CL01_QUANTA_THRESH ); - fc_thres_val = val &E830_PRTMAC_CL01_QUANTA_THRESH_CL0_QUANTA_THRESH_M ; }else { -/* Retrieve the transmit timer */ - val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA (E800_IDX_OF_LFC )); - tx_timer_val = val & +int prio_idx = (pfc) ? tc :E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX ; + val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA (prio_idx)) &E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M ; - cmd->tx_tmr_value =CPU_TO_LE16 (tx_timer_val); + } + +return CPU_TO_LE16 ((u16 )val); +} + +/** +* ice_get_xoff_pause_thresh +* @hw: pointer to the HW struct +* @tc: index of traffic class. Relevant if @pfc is true +* @pfc: if true - use @tc to get corresponding threshold +* +* Returns u16 current configured LFC of PFC threshold value. +* If @pfc is true returns value of the corresponding @tc traffic class. +* If false returns configured LFC threshold +*/ +static u16 +ice_get_xoff_pause_thresh (struct ice_hw *hw,u8 tc,bool pfc) +{ +u32 val =0 ; + +#define E830_CL01_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL01_QUANTA_THRESH : E830_PRTMAC_CL01_QUANTA_THRESH) +#define E830_CL23_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL23_QUANTA_THRESH : E830_PRTMAC_CL23_QUANTA_THRESH) +#define E830_CL45_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL45_QUANTA_THRESH : E830_PRTMAC_CL45_QUANTA_THRESH) +#define E830_CL67_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL67_QUANTA_THRESH : E830_PRTMAC_CL67_QUANTA_THRESH) + +if ((hw)->mac_type ==ICE_MAC_E830 ) { +switch (tc) { +case 0 : +case 1 : + val =rd32 (hw,E830_CL01_PAUSE_THRESH (hw->port_info)); +break ; +case 2 : +case 3 : + val =rd32 (hw,E830_CL23_PAUSE_THRESH (hw->port_info)); +break ; +case 4 : +case 5 : + val =rd32 (hw,E830_CL45_PAUSE_THRESH (hw->port_info)); +break ; +case 6 : +case 7 : + val =rd32 (hw,E830_CL67_PAUSE_THRESH (hw->port_info)); +break ; + } + +if (tc &0x1 ) + val >>=16 ; -/* Retrieve the fc threshold */ - val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER (E800_IDX_OF_LFC )); - fc_thres_val = val &E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M ; + }else { +int prio_idx = (pfc) ? tc :E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX ; + val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER (prio_idx)) & +E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M ; } - cmd->fc_refresh_threshold =CPU_TO_LE16 (fc_thres_val); +return CPU_TO_LE16 ((u16 )val); }/** -* ice_aq_set_mac_cfg +* ice_aq_set_mac_pfc_cfg * @hw: pointer to the HW struct * @max_frame_size: Maximum Frame Size to be supported +* @tc_bitmap: Traffic Class bitmap indicating relevant TCs for the following XOFF settings +* 0 is used of LFC. +* If any of XOFF settings is zero tc_bitmap must have not more than one bit. +* @xoff_quanta: FC XOFF Pause quanta, measured in 64byte slots. 0 means keep current value +* @xoff_thresh: FC XOFF Pause refresh threshold, specifies how many slots (64 byte) time +* before XOFF expires to send a new XOFF if CGD is still in a blocked state. +* 0 means keep current value * @auto_drop: Tell HW to drop packets if TC queue is blocked * @cd: pointer to command details structure or NULL * * Set MAC configuration (0x0603) */ int -ice_aq_set_mac_cfg (struct ice_hw *hw,u16 max_frame_size,bool auto_drop, -struct ice_sq_cd *cd) +ice_aq_set_mac_pfc_cfg (struct ice_hw *hw,u16 max_frame_size,u8 tc_bitmap, +u16 xoff_quanta,u16 xoff_thresh,bool auto_drop,struct ice_sq_cd *cd) {struct ice_aqc_set_mac_cfg *cmd;struct ice_aq_desc desc;
@@ -768,17 +839,46 @@ ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop,if (max_frame_size ==0 )return ICE_ERR_PARAM ; +/* when quanta or threshold are 0, we may read values from traffic class +* registers indicated by tc_bitmap. However, the AQC can only store +* data read from one traffic class, so check if there is at most one +* bit set to avoid ambiguity +*/ +if ((xoff_quanta ==0 || xoff_thresh ==0 ) && !ice_is_pow2 (tc_bitmap)) +return ICE_ERR_PARAM ;ice_fill_dflt_direct_cmd_desc (&desc, ice_aqc_opc_set_mac_cfg); cmd->max_frame_size =CPU_TO_LE16 (max_frame_size);if (ice_is_fw_auto_drop_supported (hw) && auto_drop) cmd->drop_opts |=ICE_AQ_SET_MAC_AUTO_DROP_BLOCKING_PKTS ; -ice_fill_tx_timer_and_fc_thresh (hw, cmd); + cmd->tx_tmr_priority = tc_bitmap; + cmd->tx_tmr_value = (xoff_quanta) ?CPU_TO_LE16 (xoff_quanta) : +ice_get_xoff_pause_quanta (hw, + (tc_bitmap) ?ice_ctz (tc_bitmap) :0 , !!tc_bitmap); + cmd->fc_refresh_threshold = (xoff_thresh) ?CPU_TO_LE16 (xoff_thresh) : +ice_get_xoff_pause_thresh (hw, + (tc_bitmap) ?ice_ctz (tc_bitmap) :0 , !!tc_bitmap);return ice_aq_send_cmd (hw, &desc,NULL ,0 , cd); } +/** +* ice_aq_set_mac_cfg +* @hw: pointer to the HW struct +* @max_frame_size: Maximum Frame Size to be supported +* @auto_drop: Tell HW to drop packets if TC queue is blocked +* @cd: pointer to command details structure or NULL +* +* Set MAC configuration (0x0603) +*/ +int +ice_aq_set_mac_cfg (struct ice_hw *hw,u16 max_frame_size,bool auto_drop, +struct ice_sq_cd *cd) +{ +return ice_aq_set_mac_pfc_cfg (hw, max_frame_size,0 ,0 ,0 , auto_drop, cd); +} +/** * ice_init_fltr_mgmt_struct - initializes filter management list and locks * @hw: pointer to the HW struct
drivers/net/intel/ice/base/ice_common.h +3 -0
@@ -223,6 +223,9 @@ int ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop, struct ice_sq_cd *cd);int +ice_aq_set_mac_pfc_cfg (struct ice_hw *hw,u16 max_frame_size,u8 tc_bitmap,u16 xoff_quanta, +u16 xoff_thresh,bool auto_drop,struct ice_sq_cd *cd); +int ice_aq_get_link_info (struct ice_port_info *pi,bool ena_lse,struct ice_link_status *link,struct ice_sq_cd *cd);int
drivers/net/intel/ice/base/ice_type.h +13 -0
@@ -28,6 +28,19 @@ static inline bool ice_is_pow2(u64 val)return val !=0 && (val & (val -1 )) ==0 ; } +/** +* ice_ctz - count trailing zeroes +* @val: unsigned integer to be validated +*/ +static inline int ice_ctz (u32 val) +{ +int i =0 ; +while (!(val & (1 << i))) + i++; + +return i; +} +/** * ice_ilog2 - Calculates integer log base 2 of a number * @n: number on which to perform operation
Signature · 1 line
2.47.3
PATCH 4/4 net/ice/base: add support for asymmetric PFC
In reply to Anatoly BurakovFrom: Vladimir Medvedkin <[email protected]>
Current implementation only supports symmetric PFC configuration. Add two more bitmasks to ice_dcb_pfc_cfg to support asymmetric PFC.
--- drivers/net/intel/ice/base/ice_dcb.c | 105 ++++++++++++++++++++++---- drivers/net/intel/ice/base/ice_dcb.h | 16 +++- drivers/net/intel/ice/base/ice_type.h | 2 + 3 files changed, 107 insertions(+), 16 deletions(-)
drivers/net/intel/ice/base/ice_dcb.c +90 -15
@@ -1129,11 +1129,13 @@ ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)* ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format * @tlv: Fill the ETS config data in IEEE format * @dcbcfg: Local store which holds the DCB Config +* @pfc_asym_mode: PFC symmetry mode * * Prepare IEEE 802.1Qaz ETS CFG TLV */ static void -ice_add_ieee_ets_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg) +ice_add_ieee_ets_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {struct ice_dcb_ets_cfg *etscfg;u8 *buf = tlv->tlvinfo;
@@ -1145,8 +1147,22 @@ ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) ICE_IEEE_ETS_TLV_LEN); tlv->typelen =HTONS (typelen); - ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) | +switch (pfc_asym_mode) { +case (ICE_SET_PFC_SYM ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) |ICE_IEEE_SUBTYPE_ETS_CFG ); +break ; +case (ICE_SET_PFC_RX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_ETS_CFG_RX ); +break ; +case (ICE_SET_PFC_TX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_ETS_CFG_TX ); +break ; +default : +return ; + } tlv->ouisubtype =HTONL (ouisubtype);/* First Octet post subtype
@@ -1162,6 +1178,9 @@ ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) maxtcwilling |= etscfg->maxtcs &ICE_IEEE_ETS_MAXTC_M ; buf[0 ] = maxtcwilling; +if (pfc_asym_mode ==ICE_SET_PFC_TX ) + etscfg = &dcbcfg->etsrec; +/* Begin adding at Priority Assignment Table (offset 1 in buf) */ ice_add_ieee_ets_common_tlv (&buf[1 ], etscfg); }
@@ -1201,11 +1220,13 @@ ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,* ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format * @tlv: Fill PFC TLV in IEEE format * @dcbcfg: Local store which holds the PFC CFG data +* @pfc_asym_mode: PFC symmetry mode * * Prepare IEEE 802.1Qaz PFC CFG TLV */ static void -ice_add_ieee_pfc_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg) +ice_add_ieee_pfc_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {u8 *buf = tlv->tlvinfo;u32 ouisubtype;
@@ -1215,8 +1236,22 @@ ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) ICE_IEEE_PFC_TLV_LEN); tlv->typelen =HTONS (typelen); - ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) | +switch (pfc_asym_mode) { +case (ICE_SET_PFC_SYM ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) |ICE_IEEE_SUBTYPE_PFC_CFG ); +break ; +case (ICE_SET_PFC_RX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_PFC_CFG_RX ); +break ; +case (ICE_SET_PFC_TX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_PFC_CFG_TX ); +break ; +default : +return ; + } tlv->ouisubtype =HTONL (ouisubtype);/* ----------------------------------------
@@ -1233,18 +1268,24 @@ ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) buf[0 ] |= dcbcfg->pfc.pfccap &0xF ; buf[1 ] = dcbcfg->pfc.pfcena; +if (pfc_asym_mode ==ICE_SET_PFC_RX ) + buf[1 ] |= dcbcfg->pfc.pfcena_asym_rx; +if (pfc_asym_mode ==ICE_SET_PFC_TX ) + buf[1 ] |= dcbcfg->pfc.pfcena_asym_tx; }/** * ice_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format * @tlv: Fill APP TLV in IEEE format * @dcbcfg: Local store which holds the APP CFG data +* @pfc_asym_mode: PFC symmetry mode * * Prepare IEEE 802.1Qaz APP CFG TLV */ static void ice_add_ieee_app_pri_tlv (struct ice_lldp_org_tlv *tlv, -struct ice_dcbx_cfg *dcbcfg) +struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {u16 typelen, len, offset =0 ;u8 priority, selector, i =0 ;
@@ -1254,8 +1295,23 @@ ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,/* No APP TLVs then just return */ if (dcbcfg->numapps ==0 )return ; - ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) | + +switch (pfc_asym_mode) { +case (ICE_SET_PFC_SYM ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) |ICE_IEEE_SUBTYPE_APP_PRI ); +break ; +case (ICE_SET_PFC_RX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_APP_PRI_RX ); +break ; +case (ICE_SET_PFC_TX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_APP_PRI_TX ); +break ; +default : +return ; + } tlv->ouisubtype =HTONL (ouisubtype);/* Move offset to App Priority Table */
@@ -1424,26 +1480,27 @@ ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)* @tlv: Fill TLV data in IEEE format * @dcbcfg: Local store which holds the DCB Config * @tlvid: Type of IEEE TLV +* @pfc_asym_mode: PFC symmetry mode * * Add tlv information */ static void ice_add_dcb_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg, -u16 tlvid) +u16 tlvid,enum ice_dcb_pfc_asym_mode pfc_asym_mode) {if (dcbcfg->pfc_mode ==ICE_QOS_MODE_VLAN ) {switch (tlvid) {case ICE_IEEE_TLV_ID_ETS_CFG : -ice_add_ieee_ets_tlv (tlv, dcbcfg); +ice_add_ieee_ets_tlv (tlv, dcbcfg, pfc_asym_mode);break ;case ICE_IEEE_TLV_ID_ETS_REC :ice_add_ieee_etsrec_tlv (tlv, dcbcfg);break ;case ICE_IEEE_TLV_ID_PFC_CFG : -ice_add_ieee_pfc_tlv (tlv, dcbcfg); +ice_add_ieee_pfc_tlv (tlv, dcbcfg, pfc_asym_mode);break ;case ICE_IEEE_TLV_ID_APP_PRI : -ice_add_ieee_app_pri_tlv (tlv, dcbcfg); +ice_add_ieee_app_pri_tlv (tlv, dcbcfg, pfc_asym_mode);break ;default :break ;
@@ -1474,10 +1531,12 @@ ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,* @lldpmib: pointer to the HW struct * @miblen: length of LLDP MIB * @dcbcfg: Local store which holds the DCB Config +* @pfc_asym_mode: PFC mode with respect to PAUSE frames direction * * Convert the DCB configuration to MIB format */ -void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg) +void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {u16 len, offset =0 , tlvid =ICE_TLV_ID_START ;struct ice_lldp_org_tlv *tlv;
@@ -1485,7 +1544,12 @@ void ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg) tlv = (struct ice_lldp_org_tlv *)lldpmib;while (1 ) { -ice_add_dcb_tlv (tlv, dcbcfg, tlvid++); +/* Asymmetric configuration does not require ETS rec TLV */ +if (tlvid ==ICE_IEEE_TLV_ID_ETS_REC && pfc_asym_mode !=ICE_SET_PFC_SYM ) { + tlvid++; +continue ; + } +ice_add_dcb_tlv (tlv, dcbcfg, tlvid++, pfc_asym_mode); typelen =NTOHS (tlv->typelen); len = (typelen &ICE_LLDP_TLV_LEN_M ) >>ICE_LLDP_TLV_LEN_S ;if (len)
@@ -1532,9 +1596,20 @@ int ice_set_dcb_cfg(struct ice_port_info *pi)if (dcbcfg->app_mode ==ICE_DCBX_APPS_NON_WILLING ) mib_type |=SET_LOCAL_MIB_TYPE_CEE_NON_WILLING ; -ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg); - ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen, -NULL ); +if ((dcbcfg->pfc.pfcena_asym_rx ^ dcbcfg->pfc.pfcena_asym_tx) ==0 ) { +ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg,ICE_SET_PFC_SYM ); + ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen,NULL ); + }else { +ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg,ICE_SET_PFC_RX ); + ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen,NULL ); +if (ret) { +ice_free (hw, lldpmib); +return ret; + } + +ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg,ICE_SET_PFC_TX ); + ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen,NULL ); + }ice_free (hw, lldpmib);
drivers/net/intel/ice/base/ice_dcb.h +15 -1
@@ -21,10 +21,17 @@#define ICE_TLV_TYPE_ORG 127#define ICE_IEEE_8021QAZ_OUI 0x0080C2 +#define ICE_IEEE_8021QAZ_OUI_ASYM 0xFFFFFFUL#define ICE_IEEE_SUBTYPE_ETS_CFG 9 +#define ICE_IEEE_SUBTYPE_ETS_CFG_RX 0x89 +#define ICE_IEEE_SUBTYPE_ETS_CFG_TX 0x99#define ICE_IEEE_SUBTYPE_ETS_REC 10#define ICE_IEEE_SUBTYPE_PFC_CFG 11 +#define ICE_IEEE_SUBTYPE_PFC_CFG_RX 0x8B +#define ICE_IEEE_SUBTYPE_PFC_CFG_TX 0x9B#define ICE_IEEE_SUBTYPE_APP_PRI 12 +#define ICE_IEEE_SUBTYPE_APP_PRI_RX 0x8C +#define ICE_IEEE_SUBTYPE_APP_PRI_TX 0x9C#define ICE_CEE_DCBX_OUI 0x001B21#define ICE_CEE_DCBX_TYPE 2
@@ -188,6 +195,12 @@ struct ice_dcbx_variables {u32 deftsaassignment; }; +enum ice_dcb_pfc_asym_mode { +ICE_SET_PFC_SYM =0 , +ICE_SET_PFC_RX , +ICE_SET_PFC_TX +}; + int ice_aq_get_lldp_mib(struct ice_hw *hw, u8 bridge_type, u8 mib_type, void *buf, u16 buf_size, u16 *local_len, u16 *remote_len,
@@ -208,7 +221,8 @@ int ice_set_dcb_cfg(struct ice_port_info *pi);void ice_get_dcb_cfg_from_mib_change (struct ice_port_info *pi,struct ice_rq_event_info *event);int ice_init_dcb (struct ice_hw *hw,bool enable_mib_change); -void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg); +void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode); int ice_query_port_ets(struct ice_port_info *pi, struct ice_aqc_port_ets_elem *buf, u16 buf_size,
drivers/net/intel/ice/base/ice_type.h +2 -0
@@ -1196,6 +1196,8 @@ struct ice_dcb_pfc_cfg {u8 mbc;u8 pfccap;u8 pfcena; +u8 pfcena_asym_rx; +u8 pfcena_asym_tx; };/* CEE or IEEE 802.1Qaz Application Priority data */
Signature · 1 line
2.47.3
v2 cover Update ICE base driver
In reply to Anatoly BurakovA few more changes for the ICE base driver:
- Integer overflow fix
- DCB/PFC changes that were submitted earlier by Vladimir [1]
The intent is to merge these as base driver changes, with successive work to be built on top.
v2:
- Fix setting MAC config when no TC's were specified
[1] https://patches.dpdk.org/project/dpdk/cover/[email protected]/
Anatoly Burakov (1):
net/ice/base: update README
Chinh Cao (1):
net/ice/base: fix integer overflow on NVM init
Vladimir Medvedkin (3):
net/ice/base: add utility functions
net/ice/base: make set MAC config TC aware
net/ice/base: add support for asymmetric PFC
drivers/net/intel/ice/base/README | 2 +- drivers/net/intel/ice/base/ice_common.c | 221 ++++++++++++++++++++---- drivers/net/intel/ice/base/ice_common.h | 11 ++ drivers/net/intel/ice/base/ice_dcb.c | 105 +++++++++-- drivers/net/intel/ice/base/ice_dcb.h | 16 +- drivers/net/intel/ice/base/ice_type.h | 17 +- 6 files changed, 318 insertions(+), 54 deletions(-)
Signature · 1 line
2.47.3
PATCH v2 1/5 net/ice/base: fix integer overflow on NVM init
From: Chinh Cao <[email protected]>
The shadow RAM size is defined as 16-bit unsigned, which may result in overflows under certain scenarios. Fix the value to be 32-bit.
--- drivers/net/intel/ice/base/ice_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/intel/ice/base/ice_type.h +1 -1
@@ -982,7 +982,7 @@ struct ice_flash_info {struct ice_orom_info orom;/* Option ROM version info */ struct ice_nvm_info nvm;/* NVM version information */ struct ice_bank_info banks;/* Flash Bank information */ -u16 sr_words;/* Shadow RAM size in words */ +u32 sr_words;/* Shadow RAM size in words */ u32 flash_size;/* Size of available flash in bytes */ u8 blank_nvm_mode;/* is NVM empty (no FW present) */ };
Signature · 1 line
2.47.3
PATCH v2 2/5 net/ice/base: add utility functions
In reply to Anatoly BurakovFrom: Vladimir Medvedkin <[email protected]>
Add the following utility functions related to DCB:
* Get number of Congestion Domains per port
* Resolve Traffic Class(TC) by 802.1p VLAN User Priority(UP)
* Get absolute index of the Congestion Domain by TC
--- drivers/net/intel/ice/base/ice_common.c | 48 +++++++++++++++++++++++++ drivers/net/intel/ice/base/ice_common.h | 8 +++++ 2 files changed, 56 insertions(+)
drivers/net/intel/ice/base/ice_common.c +48 -0
@@ -6594,3 +6594,51 @@ bool ice_is_fw_auto_drop_supported(struct ice_hw *hw)return true;return false; } + +/** +* ice_get_port_max_cgd +* @hw: pointer to the hardware structure +* +* Returns the number of congestion domains (cgds) for a port +*/ +enum ice_cgd_per_port +ice_get_port_max_cgd (struct ice_hw *hw) +{ +#define ICE_8_PORTS_LINK_TOPO 0x2 +u32 link_topo =LE32_TO_CPU (rd32 (hw,GLGEN_MAC_LINK_TOPO )) & +GLGEN_MAC_LINK_TOPO_LINK_TOPO_M ; + +return (link_topo ==ICE_8_PORTS_LINK_TOPO ) ?ICE_4_CGD_PER_PORT :ICE_8_CGD_PER_PORT ; +} + +/** +* ice_get_tc_by_priority +* @hw: pointer to the hardware structure +* @prio: VLAN PCP +* +* Returns the index of Traffic Class(TC) associated with the User Priority +*/ +u8 +ice_get_tc_by_priority (struct ice_hw *hw,u8 prio) +{ +struct ice_port_info *port_info = hw->port_info; +struct ice_qos_cfg *qos_cfg = &port_info->qos_cfg; +struct ice_dcbx_cfg *local_dcb_conf = &qos_cfg->local_dcbx_cfg; + + prio &= (ICE_MAX_TRAFFIC_CLASS -1 ); + +return local_dcb_conf->etscfg.prio_table[prio]; +} + +/** +* ice_get_cgd_idx +* @hw: pointer to the hardware structure +* @tc: index of Traffic Class +* +* Returns the absolute index of the congestion domain by its TC +*/ +int +ice_get_cgd_idx (struct ice_hw *hw,u8 tc) +{ +return hw->port_info->lport *ice_get_port_max_cgd (hw) + tc; +}
drivers/net/intel/ice/base/ice_common.h +8 -0
@@ -25,6 +25,11 @@ enum ice_fw_modes { ICE_FW_MODE_ROLLBACK }; +enum ice_cgd_per_port { +ICE_4_CGD_PER_PORT =4 , +ICE_8_CGD_PER_PORT =8 +}; +int ice_init_fltr_mgmt_struct (struct ice_hw *hw);void ice_cleanup_fltr_mgmt_struct (struct ice_hw *hw);void ice_set_umac_shared (struct ice_hw *hw);
@@ -335,4 +340,7 @@ ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,bool ice_fw_supports_report_dflt_cfg (struct ice_hw *hw);/* AQ API version for FW auto drop reports */ bool ice_is_fw_auto_drop_supported (struct ice_hw *hw); +enum ice_cgd_per_port ice_get_port_max_cgd (struct ice_hw *hw); +u8 ice_get_tc_by_priority (struct ice_hw *hw,u8 prio); +int ice_get_cgd_idx (struct ice_hw *hw,u8 tc);#endif /* _ICE_COMMON_H_ */
Signature · 1 line
2.47.3
PATCH v2 3/5 net/ice/base: make set MAC config TC aware
In reply to Anatoly BurakovFrom: Vladimir Medvedkin <[email protected]>
Current implementation of the ice_aq_set_mac_cfg() sets Flow Control (FC) settings such as quanta and threshold only for LFC. This patch makes this function Traffic Class (TC) aware, so it can configure FC for each TC individually.
---
Notes:
v2:
- Fix case when no traffic classes were specified
drivers/net/intel/ice/base/ice_common.c | 173 +++++++++++++++++++----- drivers/net/intel/ice/base/ice_common.h | 3 + drivers/net/intel/ice/base/ice_type.h | 13 ++ 3 files changed, 153 insertions(+), 36 deletions(-)
drivers/net/intel/ice/base/ice_common.c +137 -36
@@ -700,65 +700,136 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse, }/** -* ice_fill_tx_timer_and_fc_thresh +* ice_get_xoff_pause_quanta * @hw: pointer to the HW struct -* @cmd: pointer to MAC cfg structure +* @tc: index of traffic class. Relevant if @pfc is true +* @pfc: if true - use @tc to get corresponding quanta * -* Add Tx timer and FC refresh threshold info to Set MAC Config AQ command -* descriptor +* Returns u16 current configured LFC of PFC quanta value. +* If @pfc is true returns value of the corresponding @tc traffic class. +* If false returns configured LFC quanta */ -static void -ice_fill_tx_timer_and_fc_thresh (struct ice_hw *hw, -struct ice_aqc_set_mac_cfg *cmd) +static u16 +ice_get_xoff_pause_quanta (struct ice_hw *hw,u8 tc,bool pfc) { -u16 fc_thres_val, tx_timer_val; -u32 val; +u32 val =0 ; -/* We read back the transmit timer and fc threshold value of -* LFC. Thus, we will use index = -* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX. -* -* Also, because we are operating on transmit timer and fc -* threshold of LFC, we don't turn on any bit in tx_tmr_priority -*/ -#define E800_IDX_OF_LFC E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX +#define E830_CL01_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL01_PAUSE_QUANTA : E830_PRTMAC_CL01_PAUSE_QUANTA) +#define E830_CL23_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL23_PAUSE_QUANTA : E830_PRTMAC_CL23_PAUSE_QUANTA) +#define E830_CL45_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL45_PAUSE_QUANTA : E830_PRTMAC_CL45_PAUSE_QUANTA) +#define E830_CL67_PAUSE_QUANTA (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL67_PAUSE_QUANTA : E830_PRTMAC_CL67_PAUSE_QUANTA)if ((hw)->mac_type ==ICE_MAC_E830 ) { -/* Retrieve the transmit timer */ - val =rd32 (hw,E830_PRTMAC_CL01_PAUSE_QUANTA ); - tx_timer_val = val &E830_PRTMAC_CL01_PAUSE_QUANTA_CL0_PAUSE_QUANTA_M ; - cmd->tx_tmr_value =CPU_TO_LE16 (tx_timer_val); +switch (tc) { +case 0 : +case 1 : + val =rd32 (hw,E830_CL01_PAUSE_QUANTA (hw->port_info)); +break ; +case 2 : +case 3 : + val =rd32 (hw,E830_CL23_PAUSE_QUANTA (hw->port_info)); +break ; +case 4 : +case 5 : + val =rd32 (hw,E830_CL45_PAUSE_QUANTA (hw->port_info)); +break ; +case 6 : +case 7 : + val =rd32 (hw,E830_CL67_PAUSE_QUANTA (hw->port_info)); +break ; + } + +if (tc &0x1 ) + val >>=16 ; -/* Retrieve the fc threshold */ - val =rd32 (hw,E830_PRTMAC_CL01_QUANTA_THRESH ); - fc_thres_val = val &E830_PRTMAC_CL01_QUANTA_THRESH_CL0_QUANTA_THRESH_M ; }else { -/* Retrieve the transmit timer */ - val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA (E800_IDX_OF_LFC )); - tx_timer_val = val & +int prio_idx = (pfc) ? tc :E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX ; + val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA (prio_idx)) &E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M ; - cmd->tx_tmr_value =CPU_TO_LE16 (tx_timer_val); + } + +return CPU_TO_LE16 ((u16 )val); +} + +/** +* ice_get_xoff_pause_thresh +* @hw: pointer to the HW struct +* @tc: index of traffic class. Relevant if @pfc is true +* @pfc: if true - use @tc to get corresponding threshold +* +* Returns u16 current configured LFC of PFC threshold value. +* If @pfc is true returns value of the corresponding @tc traffic class. +* If false returns configured LFC threshold +*/ +static u16 +ice_get_xoff_pause_thresh (struct ice_hw *hw,u8 tc,bool pfc) +{ +u32 val =0 ; + +#define E830_CL01_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL01_QUANTA_THRESH : E830_PRTMAC_CL01_QUANTA_THRESH) +#define E830_CL23_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL23_QUANTA_THRESH : E830_PRTMAC_CL23_QUANTA_THRESH) +#define E830_CL45_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL45_QUANTA_THRESH : E830_PRTMAC_CL45_QUANTA_THRESH) +#define E830_CL67_PAUSE_THRESH (pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \ + E830_PRTMAC_200G_CL67_QUANTA_THRESH : E830_PRTMAC_CL67_QUANTA_THRESH) + +if ((hw)->mac_type ==ICE_MAC_E830 ) { +switch (tc) { +case 0 : +case 1 : + val =rd32 (hw,E830_CL01_PAUSE_THRESH (hw->port_info)); +break ; +case 2 : +case 3 : + val =rd32 (hw,E830_CL23_PAUSE_THRESH (hw->port_info)); +break ; +case 4 : +case 5 : + val =rd32 (hw,E830_CL45_PAUSE_THRESH (hw->port_info)); +break ; +case 6 : +case 7 : + val =rd32 (hw,E830_CL67_PAUSE_THRESH (hw->port_info)); +break ; + } + +if (tc &0x1 ) + val >>=16 ; -/* Retrieve the fc threshold */ - val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER (E800_IDX_OF_LFC )); - fc_thres_val = val &E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M ; + }else { +int prio_idx = (pfc) ? tc :E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX ; + val =rd32 (hw,E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER (prio_idx)) & +E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M ; } - cmd->fc_refresh_threshold =CPU_TO_LE16 (fc_thres_val); +return CPU_TO_LE16 ((u16 )val); }/** -* ice_aq_set_mac_cfg +* ice_aq_set_mac_pfc_cfg * @hw: pointer to the HW struct * @max_frame_size: Maximum Frame Size to be supported +* @tc_bitmap: Traffic Class bitmap indicating relevant TCs for the following XOFF settings +* 0 is used of LFC. +* If any of XOFF settings is zero tc_bitmap must have not more than one bit. +* @xoff_quanta: FC XOFF Pause quanta, measured in 64byte slots. 0 means keep current value +* @xoff_thresh: FC XOFF Pause refresh threshold, specifies how many slots (64 byte) time +* before XOFF expires to send a new XOFF if CGD is still in a blocked state. +* 0 means keep current value * @auto_drop: Tell HW to drop packets if TC queue is blocked * @cd: pointer to command details structure or NULL * * Set MAC configuration (0x0603) */ int -ice_aq_set_mac_cfg (struct ice_hw *hw,u16 max_frame_size,bool auto_drop, -struct ice_sq_cd *cd) +ice_aq_set_mac_pfc_cfg (struct ice_hw *hw,u16 max_frame_size,u8 tc_bitmap, +u16 xoff_quanta,u16 xoff_thresh,bool auto_drop,struct ice_sq_cd *cd) {struct ice_aqc_set_mac_cfg *cmd;struct ice_aq_desc desc;
@@ -768,17 +839,47 @@ ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop,if (max_frame_size ==0 )return ICE_ERR_PARAM ; +/* when quanta or threshold are 0, we may read values from traffic class +* registers indicated by tc_bitmap. However, the AQC can only store +* data read from one traffic class, so check if there is at most one +* bit set to avoid ambiguity +*/ +if ((xoff_quanta ==0 || xoff_thresh ==0 ) && + (tc_bitmap !=0 && !ice_is_pow2 (tc_bitmap))) +return ICE_ERR_PARAM ;ice_fill_dflt_direct_cmd_desc (&desc, ice_aqc_opc_set_mac_cfg); cmd->max_frame_size =CPU_TO_LE16 (max_frame_size);if (ice_is_fw_auto_drop_supported (hw) && auto_drop) cmd->drop_opts |=ICE_AQ_SET_MAC_AUTO_DROP_BLOCKING_PKTS ; -ice_fill_tx_timer_and_fc_thresh (hw, cmd); + cmd->tx_tmr_priority = tc_bitmap; + cmd->tx_tmr_value = (xoff_quanta) ?CPU_TO_LE16 (xoff_quanta) : +ice_get_xoff_pause_quanta (hw, + (tc_bitmap) ?ice_ctz (tc_bitmap) :0 , !!tc_bitmap); + cmd->fc_refresh_threshold = (xoff_thresh) ?CPU_TO_LE16 (xoff_thresh) : +ice_get_xoff_pause_thresh (hw, + (tc_bitmap) ?ice_ctz (tc_bitmap) :0 , !!tc_bitmap);return ice_aq_send_cmd (hw, &desc,NULL ,0 , cd); } +/** +* ice_aq_set_mac_cfg +* @hw: pointer to the HW struct +* @max_frame_size: Maximum Frame Size to be supported +* @auto_drop: Tell HW to drop packets if TC queue is blocked +* @cd: pointer to command details structure or NULL +* +* Set MAC configuration (0x0603) +*/ +int +ice_aq_set_mac_cfg (struct ice_hw *hw,u16 max_frame_size,bool auto_drop, +struct ice_sq_cd *cd) +{ +return ice_aq_set_mac_pfc_cfg (hw, max_frame_size,0 ,0 ,0 , auto_drop, cd); +} +/** * ice_init_fltr_mgmt_struct - initializes filter management list and locks * @hw: pointer to the HW struct
drivers/net/intel/ice/base/ice_common.h +3 -0
@@ -223,6 +223,9 @@ int ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop, struct ice_sq_cd *cd);int +ice_aq_set_mac_pfc_cfg (struct ice_hw *hw,u16 max_frame_size,u8 tc_bitmap,u16 xoff_quanta, +u16 xoff_thresh,bool auto_drop,struct ice_sq_cd *cd); +int ice_aq_get_link_info (struct ice_port_info *pi,bool ena_lse,struct ice_link_status *link,struct ice_sq_cd *cd);int
drivers/net/intel/ice/base/ice_type.h +13 -0
@@ -28,6 +28,19 @@ static inline bool ice_is_pow2(u64 val)return val !=0 && (val & (val -1 )) ==0 ; } +/** +* ice_ctz - count trailing zeroes +* @val: unsigned integer to be validated +*/ +static inline int ice_ctz (u32 val) +{ +int i =0 ; +while (!(val & (1 << i))) + i++; + +return i; +} +/** * ice_ilog2 - Calculates integer log base 2 of a number * @n: number on which to perform operation
Signature · 1 line
2.47.3
PATCH v2 4/5 net/ice/base: add support for asymmetric PFC
In reply to Anatoly BurakovFrom: Vladimir Medvedkin <[email protected]>
Current implementation only supports symmetric PFC configuration. Add two more bitmasks to ice_dcb_pfc_cfg to support asymmetric PFC.
--- drivers/net/intel/ice/base/ice_dcb.c | 105 ++++++++++++++++++++++---- drivers/net/intel/ice/base/ice_dcb.h | 16 +++- drivers/net/intel/ice/base/ice_type.h | 2 + 3 files changed, 107 insertions(+), 16 deletions(-)
drivers/net/intel/ice/base/ice_dcb.c +90 -15
@@ -1129,11 +1129,13 @@ ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)* ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format * @tlv: Fill the ETS config data in IEEE format * @dcbcfg: Local store which holds the DCB Config +* @pfc_asym_mode: PFC symmetry mode * * Prepare IEEE 802.1Qaz ETS CFG TLV */ static void -ice_add_ieee_ets_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg) +ice_add_ieee_ets_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {struct ice_dcb_ets_cfg *etscfg;u8 *buf = tlv->tlvinfo;
@@ -1145,8 +1147,22 @@ ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) ICE_IEEE_ETS_TLV_LEN); tlv->typelen =HTONS (typelen); - ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) | +switch (pfc_asym_mode) { +case (ICE_SET_PFC_SYM ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) |ICE_IEEE_SUBTYPE_ETS_CFG ); +break ; +case (ICE_SET_PFC_RX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_ETS_CFG_RX ); +break ; +case (ICE_SET_PFC_TX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_ETS_CFG_TX ); +break ; +default : +return ; + } tlv->ouisubtype =HTONL (ouisubtype);/* First Octet post subtype
@@ -1162,6 +1178,9 @@ ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) maxtcwilling |= etscfg->maxtcs &ICE_IEEE_ETS_MAXTC_M ; buf[0 ] = maxtcwilling; +if (pfc_asym_mode ==ICE_SET_PFC_TX ) + etscfg = &dcbcfg->etsrec; +/* Begin adding at Priority Assignment Table (offset 1 in buf) */ ice_add_ieee_ets_common_tlv (&buf[1 ], etscfg); }
@@ -1201,11 +1220,13 @@ ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,* ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format * @tlv: Fill PFC TLV in IEEE format * @dcbcfg: Local store which holds the PFC CFG data +* @pfc_asym_mode: PFC symmetry mode * * Prepare IEEE 802.1Qaz PFC CFG TLV */ static void -ice_add_ieee_pfc_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg) +ice_add_ieee_pfc_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {u8 *buf = tlv->tlvinfo;u32 ouisubtype;
@@ -1215,8 +1236,22 @@ ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) ICE_IEEE_PFC_TLV_LEN); tlv->typelen =HTONS (typelen); - ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) | +switch (pfc_asym_mode) { +case (ICE_SET_PFC_SYM ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) |ICE_IEEE_SUBTYPE_PFC_CFG ); +break ; +case (ICE_SET_PFC_RX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_PFC_CFG_RX ); +break ; +case (ICE_SET_PFC_TX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_PFC_CFG_TX ); +break ; +default : +return ; + } tlv->ouisubtype =HTONL (ouisubtype);/* ----------------------------------------
@@ -1233,18 +1268,24 @@ ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) buf[0 ] |= dcbcfg->pfc.pfccap &0xF ; buf[1 ] = dcbcfg->pfc.pfcena; +if (pfc_asym_mode ==ICE_SET_PFC_RX ) + buf[1 ] |= dcbcfg->pfc.pfcena_asym_rx; +if (pfc_asym_mode ==ICE_SET_PFC_TX ) + buf[1 ] |= dcbcfg->pfc.pfcena_asym_tx; }/** * ice_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format * @tlv: Fill APP TLV in IEEE format * @dcbcfg: Local store which holds the APP CFG data +* @pfc_asym_mode: PFC symmetry mode * * Prepare IEEE 802.1Qaz APP CFG TLV */ static void ice_add_ieee_app_pri_tlv (struct ice_lldp_org_tlv *tlv, -struct ice_dcbx_cfg *dcbcfg) +struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {u16 typelen, len, offset =0 ;u8 priority, selector, i =0 ;
@@ -1254,8 +1295,23 @@ ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,/* No APP TLVs then just return */ if (dcbcfg->numapps ==0 )return ; - ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) | + +switch (pfc_asym_mode) { +case (ICE_SET_PFC_SYM ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI <<ICE_LLDP_TLV_OUI_S ) |ICE_IEEE_SUBTYPE_APP_PRI ); +break ; +case (ICE_SET_PFC_RX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_APP_PRI_RX ); +break ; +case (ICE_SET_PFC_TX ): + ouisubtype = ((ICE_IEEE_8021QAZ_OUI_ASYM <<ICE_LLDP_TLV_OUI_S ) | +ICE_IEEE_SUBTYPE_APP_PRI_TX ); +break ; +default : +return ; + } tlv->ouisubtype =HTONL (ouisubtype);/* Move offset to App Priority Table */
@@ -1424,26 +1480,27 @@ ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)* @tlv: Fill TLV data in IEEE format * @dcbcfg: Local store which holds the DCB Config * @tlvid: Type of IEEE TLV +* @pfc_asym_mode: PFC symmetry mode * * Add tlv information */ static void ice_add_dcb_tlv (struct ice_lldp_org_tlv *tlv,struct ice_dcbx_cfg *dcbcfg, -u16 tlvid) +u16 tlvid,enum ice_dcb_pfc_asym_mode pfc_asym_mode) {if (dcbcfg->pfc_mode ==ICE_QOS_MODE_VLAN ) {switch (tlvid) {case ICE_IEEE_TLV_ID_ETS_CFG : -ice_add_ieee_ets_tlv (tlv, dcbcfg); +ice_add_ieee_ets_tlv (tlv, dcbcfg, pfc_asym_mode);break ;case ICE_IEEE_TLV_ID_ETS_REC :ice_add_ieee_etsrec_tlv (tlv, dcbcfg);break ;case ICE_IEEE_TLV_ID_PFC_CFG : -ice_add_ieee_pfc_tlv (tlv, dcbcfg); +ice_add_ieee_pfc_tlv (tlv, dcbcfg, pfc_asym_mode);break ;case ICE_IEEE_TLV_ID_APP_PRI : -ice_add_ieee_app_pri_tlv (tlv, dcbcfg); +ice_add_ieee_app_pri_tlv (tlv, dcbcfg, pfc_asym_mode);break ;default :break ;
@@ -1474,10 +1531,12 @@ ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,* @lldpmib: pointer to the HW struct * @miblen: length of LLDP MIB * @dcbcfg: Local store which holds the DCB Config +* @pfc_asym_mode: PFC mode with respect to PAUSE frames direction * * Convert the DCB configuration to MIB format */ -void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg) +void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode) {u16 len, offset =0 , tlvid =ICE_TLV_ID_START ;struct ice_lldp_org_tlv *tlv;
@@ -1485,7 +1544,12 @@ void ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg) tlv = (struct ice_lldp_org_tlv *)lldpmib;while (1 ) { -ice_add_dcb_tlv (tlv, dcbcfg, tlvid++); +/* Asymmetric configuration does not require ETS rec TLV */ +if (tlvid ==ICE_IEEE_TLV_ID_ETS_REC && pfc_asym_mode !=ICE_SET_PFC_SYM ) { + tlvid++; +continue ; + } +ice_add_dcb_tlv (tlv, dcbcfg, tlvid++, pfc_asym_mode); typelen =NTOHS (tlv->typelen); len = (typelen &ICE_LLDP_TLV_LEN_M ) >>ICE_LLDP_TLV_LEN_S ;if (len)
@@ -1532,9 +1596,20 @@ int ice_set_dcb_cfg(struct ice_port_info *pi)if (dcbcfg->app_mode ==ICE_DCBX_APPS_NON_WILLING ) mib_type |=SET_LOCAL_MIB_TYPE_CEE_NON_WILLING ; -ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg); - ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen, -NULL ); +if ((dcbcfg->pfc.pfcena_asym_rx ^ dcbcfg->pfc.pfcena_asym_tx) ==0 ) { +ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg,ICE_SET_PFC_SYM ); + ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen,NULL ); + }else { +ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg,ICE_SET_PFC_RX ); + ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen,NULL ); +if (ret) { +ice_free (hw, lldpmib); +return ret; + } + +ice_dcb_cfg_to_lldp (lldpmib, &miblen, dcbcfg,ICE_SET_PFC_TX ); + ret =ice_aq_set_lldp_mib (hw, mib_type, (void *)lldpmib, miblen,NULL ); + }ice_free (hw, lldpmib);
drivers/net/intel/ice/base/ice_dcb.h +15 -1
@@ -21,10 +21,17 @@#define ICE_TLV_TYPE_ORG 127#define ICE_IEEE_8021QAZ_OUI 0x0080C2 +#define ICE_IEEE_8021QAZ_OUI_ASYM 0xFFFFFFUL#define ICE_IEEE_SUBTYPE_ETS_CFG 9 +#define ICE_IEEE_SUBTYPE_ETS_CFG_RX 0x89 +#define ICE_IEEE_SUBTYPE_ETS_CFG_TX 0x99#define ICE_IEEE_SUBTYPE_ETS_REC 10#define ICE_IEEE_SUBTYPE_PFC_CFG 11 +#define ICE_IEEE_SUBTYPE_PFC_CFG_RX 0x8B +#define ICE_IEEE_SUBTYPE_PFC_CFG_TX 0x9B#define ICE_IEEE_SUBTYPE_APP_PRI 12 +#define ICE_IEEE_SUBTYPE_APP_PRI_RX 0x8C +#define ICE_IEEE_SUBTYPE_APP_PRI_TX 0x9C#define ICE_CEE_DCBX_OUI 0x001B21#define ICE_CEE_DCBX_TYPE 2
@@ -188,6 +195,12 @@ struct ice_dcbx_variables {u32 deftsaassignment; }; +enum ice_dcb_pfc_asym_mode { +ICE_SET_PFC_SYM =0 , +ICE_SET_PFC_RX , +ICE_SET_PFC_TX +}; + int ice_aq_get_lldp_mib(struct ice_hw *hw, u8 bridge_type, u8 mib_type, void *buf, u16 buf_size, u16 *local_len, u16 *remote_len,
@@ -208,7 +221,8 @@ int ice_set_dcb_cfg(struct ice_port_info *pi);void ice_get_dcb_cfg_from_mib_change (struct ice_port_info *pi,struct ice_rq_event_info *event);int ice_init_dcb (struct ice_hw *hw,bool enable_mib_change); -void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg); +void ice_dcb_cfg_to_lldp (u8 *lldpmib,u16 *miblen,struct ice_dcbx_cfg *dcbcfg, +enum ice_dcb_pfc_asym_mode pfc_asym_mode); int ice_query_port_ets(struct ice_port_info *pi, struct ice_aqc_port_ets_elem *buf, u16 buf_size,
drivers/net/intel/ice/base/ice_type.h +2 -0
@@ -1196,6 +1196,8 @@ struct ice_dcb_pfc_cfg {u8 mbc;u8 pfccap;u8 pfcena; +u8 pfcena_asym_rx; +u8 pfcena_asym_tx; };/* CEE or IEEE 802.1Qaz Application Priority data */
Signature · 1 line
2.47.3
PATCH v2 5/5 net/ice/base: update README
In reply to Anatoly BurakovUpdate version to indicate when last driver snapshot was generated.
--- drivers/net/intel/ice/base/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/intel/ice/base/README +1 -1
@@ -6,7 +6,7 @@ Intel® ICE driver ================== This directory contains source code of ice base driver generated on -2025-09-01 released by the team which develops +2025-10-01 released by the team which develops basic drivers for any ice NIC. The directory of base/ contains the original source package. This driver is valid for the product(s) listed below
Signature · 1 line
2.47.3
Bruce Richardson
AppliedQuoted 16 lines · Anatoly Burakov
A few more changes for the ICE base driver:
- Integer overflow fix
- DCB/PFC changes that were submitted earlier by Vladimir [1]The intent is to merge these as base driver changes, with successive work to be built on top.
v2:
- Fix setting MAC config when no TC's were specified[1] https://patches.dpdk.org/project/dpdk/cover/[email protected]/
Anatoly Burakov (1):
net/ice/base: update README
Quoted 8 lines
Chinh Cao (1):
net/ice/base: fix integer overflow on NVM initVladimir Medvedkin (3):
net/ice/base: add utility functions
net/ice/base: make set MAC config TC aware
net/ice/base: add support for asymmetric PFC
Applied to dpdk-next-net-intel,
Thanks,
/Bruce