* [PATCH 0/6] Enable DCB/PFC support for ICE PMD
@ 2025-08-07 12:22 Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 1/6] net/ice/base: add utility functions Vladimir Medvedkin
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Vladimir Medvedkin @ 2025-08-07 12:22 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov
This series introduces an initial implementation of DCB and PFC to the ICE PMD.
This includes adding support for TCs in ice_aq_set_mac_cfg() and asymmetric DCB/PFC configuration in base code.
Current implementation relies on current API and has a number of limitation and assumptions such as:
- Symmetric DCB configuration with respect to RX/TX, only dcb_rx_conf is used
- All TCs are configured equally with respect to BW they share
- No support for Low Latency TCs
- All existing queues are split evenly across TCs. Number of queues must be power of 2 and be no less than configured nb_tcs
- TX queues assigned to TCs the same way as RX queues
Vladimir Medvedkin (6):
net/ice/base: add utility functions
net/ice/base: make set MAC config TC aware
net/ice/base: add supports for assymetric PFC
net/ice: enable DCB support
net/ice: enable PFC support
net/ice: add PFC statistics
drivers/net/intel/ice/base/ice_common.c | 175 ++++++++---
drivers/net/intel/ice/base/ice_common.h | 12 +-
drivers/net/intel/ice/base/ice_dcb.c | 96 +++++-
drivers/net/intel/ice/base/ice_dcb.h | 16 +-
drivers/net/intel/ice/base/ice_type.h | 2 +
drivers/net/intel/ice/ice_ethdev.c | 370 +++++++++++++++++++++++-
drivers/net/intel/ice/ice_rxtx.c | 21 ++
7 files changed, 631 insertions(+), 61 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/6] net/ice/base: add utility functions
2025-08-07 12:22 [PATCH 0/6] Enable DCB/PFC support for ICE PMD Vladimir Medvedkin
@ 2025-08-07 12:22 ` Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 2/6] net/ice/base: make set MAC config TC aware Vladimir Medvedkin
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Medvedkin @ 2025-08-07 12:22 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov
Add the following function 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 the TC
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
drivers/net/intel/ice/base/ice_common.c | 27 +++++++++++++++++++++++++
drivers/net/intel/ice/base/ice_common.h | 8 ++++++++
2 files changed, 35 insertions(+)
diff --git a/drivers/net/intel/ice/base/ice_common.c b/drivers/net/intel/ice/base/ice_common.c
index dfc2fd69e7..58e1b76214 100644
--- a/drivers/net/intel/ice/base/ice_common.c
+++ b/drivers/net/intel/ice/base/ice_common.c
@@ -6579,3 +6579,30 @@ bool ice_is_fw_auto_drop_supported(struct ice_hw *hw)
return true;
return false;
}
+
+enum ice_cgd_per_port
+ice_get_port_max_cgd(struct ice_hw *hw)
+{
+#define ICE_8_PORTS_LINK_TOPO 0x2
+ u32 link_topo = 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;
+}
+
+u8
+ice_get_tc_by_up(struct ice_hw *hw, u8 up)
+{
+ 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;
+
+ up &= (ICE_MAX_TRAFFIC_CLASS - 1);
+
+ return local_dcb_conf->etscfg.prio_table[up];
+}
+
+int
+ice_get_cgd_idx(struct ice_hw *hw, u8 tc)
+{
+ return hw->port_info->lport * ice_get_port_max_cgd(hw) + tc;
+}
diff --git a/drivers/net/intel/ice/base/ice_common.h b/drivers/net/intel/ice/base/ice_common.h
index f7e7ff5aaf..2d4f4871e6 100644
--- a/drivers/net/intel/ice/base/ice_common.h
+++ b/drivers/net/intel/ice/base/ice_common.h
@@ -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_up(struct ice_hw *hw, u8 up);
+int ice_get_cgd_idx(struct ice_hw *hw, u8 tc);
#endif /* _ICE_COMMON_H_ */
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/6] net/ice/base: make set MAC config TC aware
2025-08-07 12:22 [PATCH 0/6] Enable DCB/PFC support for ICE PMD Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 1/6] net/ice/base: add utility functions Vladimir Medvedkin
@ 2025-08-07 12:22 ` Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 3/6] net/ice/base: add supports for assymetric PFC Vladimir Medvedkin
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Medvedkin @ 2025-08-07 12:22 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov
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.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
drivers/net/intel/ice/base/ice_common.c | 148 +++++++++++++++++-------
drivers/net/intel/ice/base/ice_common.h | 4 +-
drivers/net/intel/ice/ice_ethdev.c | 2 +-
3 files changed, 109 insertions(+), 45 deletions(-)
diff --git a/drivers/net/intel/ice/base/ice_common.c b/drivers/net/intel/ice/base/ice_common.c
index 58e1b76214..22777ab36b 100644
--- a/drivers/net/intel/ice/base/ice_common.c
+++ b/drivers/net/intel/ice/base/ice_common.c
@@ -690,66 +690,119 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
return 0;
}
-/**
- * ice_fill_tx_timer_and_fc_thresh
- * @hw: pointer to the HW struct
- * @cmd: pointer to MAC cfg structure
- *
- * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
- * descriptor
- */
-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;
+#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)
- /* 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
+ if ((hw)->mac_type == ICE_MAC_E830) {
+ 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;
+ }
+
+ val = LE32_TO_CPU(val);
+ if (tc & 0x1)
+ val >>= 16;
+
+ } else {
+ int prio_idx = (pfc) ? tc : E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX;
+ val = LE32_TO_CPU(rd32(hw, E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(prio_idx)) &
+ E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M);
+ }
+
+ return (u16)val;
+}
+
+
+static u16
+ice_get_xoff_pause_thresh(struct ice_hw *hw, u8 tc, bool pfc)
+{
+ u32 val;
+
+#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) {
- /* 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);
-
- /* 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;
+ 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;
+ }
+
+ val = LE32_TO_CPU(val);
+ if (tc & 0x1)
+ val >>= 16;
+
} else {
- /* Retrieve the transmit timer */
- val = rd32(hw, E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(E800_IDX_OF_LFC));
- tx_timer_val = val &
- E800_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
- cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
-
- /* 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;
+ int prio_idx = (pfc) ? tc : E800_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX;
+ val = LE32_TO_CPU(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 (u16)val;
}
/**
* ice_aq_set_mac_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_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;
@@ -759,13 +812,24 @@ 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;
+ if ((xoff_quanta == 0 || xoff_thresh == 0) && tc_bitmap != 0 &&
+ (__builtin_popcount(tc_bitmap) > 1))
+ 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) ? xoff_quanta :
+ ice_get_xoff_pause_quanta(hw,
+ (tc_bitmap) ? __builtin_ctz(tc_bitmap) : 0, !!tc_bitmap);
+ cmd->fc_refresh_threshold = (xoff_thresh) ? xoff_thresh :
+ ice_get_xoff_pause_thresh(hw,
+ (tc_bitmap) ? __builtin_ctz(tc_bitmap) : 0, !!tc_bitmap);
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}
@@ -1072,7 +1136,7 @@ int ice_init_hw(struct ice_hw *hw)
goto err_unroll_fltr_mgmt_struct;
/* enable jumbo frame support at MAC level */
- status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, false,
+ status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, 0, 0, 0, false,
NULL);
if (status)
goto err_unroll_fltr_mgmt_struct;
diff --git a/drivers/net/intel/ice/base/ice_common.h b/drivers/net/intel/ice/base/ice_common.h
index 2d4f4871e6..32342ac005 100644
--- a/drivers/net/intel/ice/base/ice_common.h
+++ b/drivers/net/intel/ice/base/ice_common.h
@@ -220,8 +220,8 @@ int
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd);
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_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);
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index 513777e372..c152da4fc1 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -4039,7 +4039,7 @@ ice_dev_start(struct rte_eth_dev *dev)
ICE_FRAME_SIZE_MAX;
/* Set the max frame size to HW*/
- ice_aq_set_mac_cfg(hw, max_frame_size, false, NULL);
+ ice_aq_set_mac_cfg(hw, max_frame_size, 0, 0, 0, false, NULL);
if (ad->devargs.pps_out_ena) {
ret = ice_pps_out_cfg(hw, pin_idx, timer);
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/6] net/ice/base: add supports for assymetric PFC
2025-08-07 12:22 [PATCH 0/6] Enable DCB/PFC support for ICE PMD Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 1/6] net/ice/base: add utility functions Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 2/6] net/ice/base: make set MAC config TC aware Vladimir Medvedkin
@ 2025-08-07 12:22 ` Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 4/6] net/ice: enable DCB support Vladimir Medvedkin
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Medvedkin @ 2025-08-07 12:22 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov
Current implementation supports only symmetric PFC configuration.
In this patch two bitmasks for asymmetric PFC were added to the
struct ice_dcb_pfc_cfg.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
drivers/net/intel/ice/base/ice_dcb.c | 96 ++++++++++++++++++++++-----
drivers/net/intel/ice/base/ice_dcb.h | 16 ++++-
drivers/net/intel/ice/base/ice_type.h | 2 +
3 files changed, 98 insertions(+), 16 deletions(-)
diff --git a/drivers/net/intel/ice/base/ice_dcb.c b/drivers/net/intel/ice/base/ice_dcb.c
index e97f35b4cf..5b75236156 100644
--- a/drivers/net/intel/ice/base/ice_dcb.c
+++ b/drivers/net/intel/ice/base/ice_dcb.c
@@ -1133,7 +1133,8 @@ ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)
* 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 +1146,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 +1177,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);
}
@@ -1205,7 +1223,8 @@ ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,
* 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 +1234,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,6 +1266,10 @@ 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;
}
/**
@@ -1244,7 +1281,8 @@ ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
*/
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 +1292,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 */
@@ -1429,21 +1482,21 @@ ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
*/
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 +1527,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_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 +1540,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 +1592,15 @@ 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);
+ 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);
diff --git a/drivers/net/intel/ice/base/ice_dcb.h b/drivers/net/intel/ice/base/ice_dcb.h
index c2c48ae8bb..3d3ad4b650 100644
--- a/drivers/net/intel/ice/base/ice_dcb.h
+++ b/drivers/net/intel/ice/base/ice_dcb.h
@@ -21,10 +21,17 @@
#define ICE_TLV_TYPE_ORG 127
#define ICE_IEEE_8021QAZ_OUI 0x0080C2
+#define ICE_IEEE_8021QAZ_OUI_ASYM 0xffffff
#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,
diff --git a/drivers/net/intel/ice/base/ice_type.h b/drivers/net/intel/ice/base/ice_type.h
index ae3b944d6e..e4b3efc157 100644
--- a/drivers/net/intel/ice/base/ice_type.h
+++ b/drivers/net/intel/ice/base/ice_type.h
@@ -1183,6 +1183,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 */
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/6] net/ice: enable DCB support
2025-08-07 12:22 [PATCH 0/6] Enable DCB/PFC support for ICE PMD Vladimir Medvedkin
` (2 preceding siblings ...)
2025-08-07 12:22 ` [PATCH 3/6] net/ice/base: add supports for assymetric PFC Vladimir Medvedkin
@ 2025-08-07 12:22 ` Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 5/6] net/ice: enable PFC support Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 6/6] net/ice: add PFC statistics Vladimir Medvedkin
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Medvedkin @ 2025-08-07 12:22 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov
This patch adds support for Data Center Bridging (DCB)
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
drivers/net/intel/ice/ice_ethdev.c | 182 +++++++++++++++++++++++++++++
drivers/net/intel/ice/ice_rxtx.c | 21 ++++
2 files changed, 203 insertions(+)
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index c152da4fc1..8aabf21bf6 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -194,6 +194,7 @@ static int ice_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa);
static int ice_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa);
static const uint32_t *ice_buffer_split_supported_hdr_ptypes_get(struct rte_eth_dev *dev,
size_t *no_of_elements);
+static int ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info);
static const struct rte_pci_id pci_id_ice_map[] = {
{ RTE_PCI_DEVICE(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823L_BACKPLANE) },
@@ -324,6 +325,7 @@ static const struct eth_dev_ops ice_eth_dev_ops = {
.fec_get = ice_fec_get,
.fec_set = ice_fec_set,
.buffer_split_supported_hdr_ptypes_get = ice_buffer_split_supported_hdr_ptypes_get,
+ .get_dcb_info = ice_get_dcb_info,
};
/* store statistics names and its offset in stats structure */
@@ -2826,6 +2828,29 @@ ice_dev_stop(struct rte_eth_dev *dev)
return 0;
}
+static void
+ice_deinit_dcb(struct rte_eth_dev *dev)
+{
+ struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ 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;
+ u8 max_tcs = local_dcb_conf->etscfg.maxtcs;
+ int ret;
+
+ if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG ||
+ dev->data->dev_conf.txmode.mq_mode == RTE_ETH_MQ_TX_DCB))
+ return;
+
+ memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
+ local_dcb_conf->etscfg.maxtcs = max_tcs;
+ local_dcb_conf->etscfg.tcbwtable[0] = 100;
+ local_dcb_conf->etsrec.tcbwtable[0] = 100;
+ ret = ice_set_dcb_cfg(port_info);
+ if (ret)
+ PMD_DRV_LOG(ERR, "Failed to disable DCB");
+}
+
static int
ice_dev_close(struct rte_eth_dev *dev)
{
@@ -2860,6 +2885,7 @@ ice_dev_close(struct rte_eth_dev *dev)
if (!ad->is_safe_mode)
ice_flow_uninit(ad);
+ ice_deinit_dcb(dev);
/* release all queue resource */
ice_free_queues(dev);
@@ -3670,6 +3696,35 @@ static int ice_init_rss(struct ice_pf *pf)
return -EINVAL;
}
+static int
+check_dcb_conf(int is_8_ports, struct rte_eth_dcb_rx_conf *dcb_conf)
+{
+ uint32_t tc_map = 0;
+ int i;
+
+ enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
+ if (nb_tcs != RTE_ETH_4_TCS && nb_tcs != RTE_ETH_8_TCS) {
+ PMD_DRV_LOG(ERR, "Wrong number of TCs in DCB config");
+ return -1;
+ }
+
+ if (nb_tcs == RTE_ETH_8_TCS && is_8_ports) {
+ PMD_DRV_LOG(ERR, "Wrong number of TCs in DCB config");
+ return -1;
+ }
+
+ /* Check if associated TS are not in continuous range */
+ for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++)
+ tc_map |= 1 << (dcb_conf->dcb_tc[i] & 0x7);
+
+ if (!rte_is_power_of_2(tc_map + 1)) {
+ PMD_DRV_LOG(ERR, "Bad VLAN UP to TC association in DCB config");
+ return -1;
+ }
+
+ return rte_popcount32(tc_map);
+}
+
static int
ice_dev_configure(struct rte_eth_dev *dev)
{
@@ -3695,6 +3750,133 @@ ice_dev_configure(struct rte_eth_dev *dev)
}
}
+ if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
+ struct ice_hw *hw = ICE_PF_TO_HW(pf);
+ struct ice_vsi *vsi = pf->main_vsi;
+ 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;
+ struct ice_vsi_ctx ctxt;
+ struct rte_eth_dcb_rx_conf *dcb_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
+ int i, bw_share_percent, bw_share_left;
+ enum rte_eth_nb_tcs nb_tcs = dcb_conf->nb_tcs;
+ int nb_tc_used, queues_per_tc;
+ uint16_t total_q_nb;
+
+ nb_tc_used = check_dcb_conf(ice_get_port_max_cgd(hw) == ICE_4_CGD_PER_PORT,
+ dcb_conf);
+ if (nb_tc_used < 0)
+ return -EINVAL;
+
+ rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ if (rte_le_to_cpu_16(ctxt.info.mapping_flags) == ICE_AQ_VSI_Q_MAP_NONCONTIG) {
+ PMD_DRV_LOG(ERR, "VSI configured with non contiguous queues, DCB is not supported");
+ return -EINVAL;
+ }
+
+ total_q_nb = dev->data->nb_rx_queues;
+ queues_per_tc = total_q_nb / nb_tc_used;
+ if ((total_q_nb % nb_tc_used != 0) || (!rte_is_power_of_2(queues_per_tc))) {
+ PMD_DRV_LOG(ERR, "Wrong number of queues for DCB configuration");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nb_tc_used; i++) {
+ ctxt.info.tc_mapping[i] = rte_cpu_to_le_16((i * queues_per_tc <<
+ ICE_AQ_VSI_TC_Q_OFFSET_S) |
+ (rte_log2_u32(queues_per_tc) << ICE_AQ_VSI_TC_Q_NUM_S));
+ }
+
+ memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
+
+ local_dcb_conf->etscfg.maxtcs = nb_tcs;
+
+ /* Associate each VLAN UP with particular TC */
+ for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ local_dcb_conf->etscfg.prio_table[i] = dcb_conf->dcb_tc[i];
+ local_dcb_conf->etsrec.prio_table[i] = dcb_conf->dcb_tc[i];
+ }
+
+ /*
+ * Since current API does not support setting ETS BW Share and Scheduler
+ * configure all TC as ETS and evenly share load across all existing TC
+ **/
+ bw_share_percent = 100 / nb_tc_used;
+ for (i = 0; i < nb_tc_used; i++) {
+ /* Per TC bandwidth table (all valued must add up to 100%), valid on ETS */
+ local_dcb_conf->etscfg.tcbwtable[i] = bw_share_percent;
+ local_dcb_conf->etsrec.tcbwtable[i] = bw_share_percent;
+
+ /**< Transmission Selection Algorithm. 0 - Strict prio, 2 - ETS */
+ local_dcb_conf->etscfg.tsatable[i] = 2;
+ local_dcb_conf->etsrec.tsatable[i] = 2;
+ }
+
+ bw_share_left = 100 - bw_share_percent * nb_tc_used;
+ for (i = 0; i < bw_share_left; i++) {
+ local_dcb_conf->etscfg.tcbwtable[i]++;
+ local_dcb_conf->etsrec.tcbwtable[i]++;
+ }
+
+ local_dcb_conf->pfc.pfccap = nb_tcs;
+ local_dcb_conf->pfc.pfcena = 0;
+
+ ret = ice_set_dcb_cfg(port_info);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to configure DCB for PF");
+ return ret;
+ }
+
+ /* Update VSI queue allocatios per TC */
+ ctxt.info.valid_sections = rte_cpu_to_le_16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
+ ctxt.info.mapping_flags = ICE_AQ_VSI_Q_MAP_CONTIG;
+
+ ret = ice_update_vsi(hw, vsi->idx, &ctxt, NULL);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to configure queue mapping");
+ return ret;
+ }
+
+ ctxt.info.valid_sections = 0;
+ rte_memcpy(&vsi->info, &ctxt.info, sizeof(vsi->info));
+
+ hw->port_info->fc.current_mode = ICE_FC_PFC;
+ }
+
+ return 0;
+}
+
+static int
+ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
+{
+ struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct ice_hw *hw = ICE_PF_TO_HW(pf);
+ struct ice_port_info *port_info = hw->port_info;
+ struct ice_qos_cfg *qos_cfg = &port_info->qos_cfg;
+ struct ice_dcbx_cfg *dcb_conf = &qos_cfg->local_dcbx_cfg;
+ struct ice_vsi *vsi = pf->main_vsi;
+ struct ice_vsi_ctx ctxt;
+
+ rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ if (ctxt.info.mapping_flags == ICE_AQ_VSI_Q_MAP_NONCONTIG) {
+ PMD_DRV_LOG(ERR, "VSI configured with non contiguous queues, DCB is not supported");
+ return -ENOTSUP;
+ }
+
+ dcb_info->nb_tcs = dcb_conf->etscfg.maxtcs;
+ for (int i = 0; i < dcb_info->nb_tcs; i++) {
+ dcb_info->prio_tc[i] = dcb_conf->etscfg.prio_table[i];
+ dcb_info->tc_bws[i] = dcb_conf->etscfg.tcbwtable[i];
+ /* Using VMDQ pool zero since DCB+VMDQ is not supported */
+ uint16_t tc_rx_q_map = rte_le_to_cpu_16(ctxt.info.tc_mapping[i]);
+ dcb_info->tc_queue.tc_rxq[0][i].base = tc_rx_q_map & ICE_AQ_VSI_TC_Q_OFFSET_M;
+ dcb_info->tc_queue.tc_rxq[0][i].nb_queue =
+ 1 << ((tc_rx_q_map & ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
+
+ dcb_info->tc_queue.tc_txq[0][i].base = dcb_info->tc_queue.tc_rxq[0][i].base;
+ dcb_info->tc_queue.tc_txq[0][i].nb_queue = dcb_info->tc_queue.tc_rxq[0][i].nb_queue;
+ }
+
return 0;
}
diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
index da508592aa..451816affd 100644
--- a/drivers/net/intel/ice/ice_rxtx.c
+++ b/drivers/net/intel/ice/ice_rxtx.c
@@ -795,6 +795,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
struct ice_tlan_ctx tx_ctx;
int buf_len;
struct ice_adapter *ad = ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+ u16 q_base, q_range, cgd_idx = 0;
PMD_INIT_FUNC_TRACE();
@@ -839,6 +840,26 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
tx_ctx.legacy_int = 1; /* Legacy or Advanced Host Interface */
tx_ctx.tsyn_ena = 1;
+ /* Mirror RXQ<->CGD association to TXQ<->CDG */
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ q_base = rte_le_to_cpu_16(vsi->info.tc_mapping[i]) & ICE_AQ_VSI_TC_Q_OFFSET_M;
+ q_range = 1 << ((rte_le_to_cpu_16(vsi->info.tc_mapping[i]) &
+ ICE_AQ_VSI_TC_Q_NUM_M) >> ICE_AQ_VSI_TC_Q_NUM_S);
+
+ if (q_base <= tx_queue_id && tx_queue_id < q_base + q_range)
+ break;
+
+ cgd_idx++;
+ }
+
+ if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
+ PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
+ rte_free(txq_elem);
+ return -EINVAL;
+ }
+
+ tx_ctx.cgd_num = cgd_idx;
+
ice_set_ctx(hw, (uint8_t *)&tx_ctx, txq_elem->txqs[0].txq_ctx,
ice_tlan_ctx_info);
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 5/6] net/ice: enable PFC support
2025-08-07 12:22 [PATCH 0/6] Enable DCB/PFC support for ICE PMD Vladimir Medvedkin
` (3 preceding siblings ...)
2025-08-07 12:22 ` [PATCH 4/6] net/ice: enable DCB support Vladimir Medvedkin
@ 2025-08-07 12:22 ` Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 6/6] net/ice: add PFC statistics Vladimir Medvedkin
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Medvedkin @ 2025-08-07 12:22 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov
This patch add support for Priority Flow Control (PFC)
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
drivers/net/intel/ice/ice_ethdev.c | 125 ++++++++++++++++++++++++++++-
1 file changed, 124 insertions(+), 1 deletion(-)
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index 8aabf21bf6..b3be2e7c7e 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -99,6 +99,11 @@ static struct proto_xtr_ol_flag ice_proto_xtr_ol_flag_params[] = {
#define ICE_COMMS_PKG_NAME "ICE COMMS Package"
#define ICE_MAX_RES_DESC_NUM 1024
+#define ICE_MAC_E810_MAX_WATERMARK 143744U
+#define ICE_MAC_E830_MAX_WATERMARK 259103U
+#define ICE_MAC_TC_MAX_WATERMARK (((hw)->mac_type == ICE_MAC_E830) ? \
+ ICE_MAC_E830_MAX_WATERMARK : ICE_MAC_E810_MAX_WATERMARK)
+
static int ice_dev_configure(struct rte_eth_dev *dev);
static int ice_dev_start(struct rte_eth_dev *dev);
static int ice_dev_stop(struct rte_eth_dev *dev);
@@ -195,6 +200,7 @@ static int ice_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa);
static const uint32_t *ice_buffer_split_supported_hdr_ptypes_get(struct rte_eth_dev *dev,
size_t *no_of_elements);
static int ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info);
+static int ice_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf);
static const struct rte_pci_id pci_id_ice_map[] = {
{ RTE_PCI_DEVICE(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823L_BACKPLANE) },
@@ -326,6 +332,7 @@ static const struct eth_dev_ops ice_eth_dev_ops = {
.fec_set = ice_fec_set,
.buffer_split_supported_hdr_ptypes_get = ice_buffer_split_supported_hdr_ptypes_get,
.get_dcb_info = ice_get_dcb_info,
+ .priority_flow_ctrl_set = ice_priority_flow_ctrl_set,
};
/* store statistics names and its offset in stats structure */
@@ -2831,17 +2838,33 @@ ice_dev_stop(struct rte_eth_dev *dev)
static void
ice_deinit_dcb(struct rte_eth_dev *dev)
{
+ struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
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;
+ int i, ret, cgd_idx;
+ uint16_t max_frame_size;
u8 max_tcs = local_dcb_conf->etscfg.maxtcs;
- int ret;
+ u8 tc;
if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_DCB_FLAG ||
dev->data->dev_conf.txmode.mq_mode == RTE_ETH_MQ_TX_DCB))
return;
+ for (i = 0; i < max_tcs; i++) {
+ tc = ice_get_tc_by_up(hw, i);
+ cgd_idx = ice_get_cgd_idx(hw, tc);
+ wr32(hw, GLRPB_TCHW(cgd_idx), ICE_MAC_TC_MAX_WATERMARK);
+ wr32(hw, GLRPB_TCLW(cgd_idx), ICE_MAC_TC_MAX_WATERMARK);
+ }
+ max_frame_size = pf->dev_data->mtu ?
+ pf->dev_data->mtu + ICE_ETH_OVERHEAD : ICE_FRAME_SIZE_MAX;
+ ret = ice_aq_set_mac_cfg(hw, max_frame_size, UINT8_MAX, UINT16_MAX,
+ INT16_MAX + 1, false, NULL);
+ if (ret)
+ PMD_DRV_LOG(ERR, "Failed to set mac config on DCB deinit");
+
memset(local_dcb_conf, 0, sizeof(*local_dcb_conf));
local_dcb_conf->etscfg.maxtcs = max_tcs;
local_dcb_conf->etscfg.tcbwtable[0] = 100;
@@ -3880,6 +3903,106 @@ ice_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
return 0;
}
+static int
+ice_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf)
+{
+ struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct ice_hw *hw = ICE_PF_TO_HW(pf);
+ struct ice_port_info *port_info = hw->port_info;
+ struct ice_qos_cfg *qos_cfg = &port_info->qos_cfg;
+ struct ice_dcbx_cfg *dcb_conf = &qos_cfg->local_dcbx_cfg;
+ int ret;
+
+ dcb_conf->pfc_mode = ICE_QOS_MODE_VLAN;
+ dcb_conf->pfc.willing = 0;
+ /** pfccap should alreeady be set by DCB config, check if zero */
+ if (dcb_conf->pfc.pfccap == 0) {
+ PMD_DRV_LOG(ERR, "DCB is not configured on the port, can not set PFC");
+ return -EINVAL;
+ }
+
+ ret = ice_aq_set_pfc_mode(hw, ICE_AQC_PFC_VLAN_BASED_PFC, NULL);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to enable PFC in VLAN mode");
+ return ret;
+ }
+
+ u8 tc = ice_get_tc_by_up(hw, pfc_conf->priority);
+
+ switch (pfc_conf->fc.mode) {
+ case (RTE_ETH_FC_NONE):
+ dcb_conf->pfc.pfcena &= ~(1 << tc);
+ dcb_conf->pfc.pfcena_asym_rx &= ~(1 << tc);
+ dcb_conf->pfc.pfcena_asym_tx &= ~(1 << tc);
+ break;
+ case (RTE_ETH_FC_RX_PAUSE):
+ dcb_conf->pfc.pfcena &= ~(1 << tc);
+ dcb_conf->pfc.pfcena_asym_rx |= (1 << tc);
+ dcb_conf->pfc.pfcena_asym_tx &= ~(1 << tc);
+ break;
+ case (RTE_ETH_FC_TX_PAUSE):
+ dcb_conf->pfc.pfcena &= ~(1 << tc);
+ dcb_conf->pfc.pfcena_asym_rx &= ~(1 << tc);
+ dcb_conf->pfc.pfcena_asym_tx |= (1 << tc);
+ break;
+ case (RTE_ETH_FC_FULL):
+ dcb_conf->pfc.pfcena |= (1 << tc);
+ dcb_conf->pfc.pfcena_asym_rx &= ~(1 << tc);
+ dcb_conf->pfc.pfcena_asym_tx &= ~(1 << tc);
+ break;
+ }
+
+ ret = ice_set_dcb_cfg(port_info);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to configure DCB for PF");
+ return ret;
+ }
+
+ /* Update high and low watermarks */
+ u32 high_watermark = pfc_conf->fc.high_water;
+ if (high_watermark > ICE_MAC_TC_MAX_WATERMARK)
+ high_watermark = ICE_MAC_TC_MAX_WATERMARK;
+
+ u32 low_watermark = pfc_conf->fc.low_water;
+ if (low_watermark > ICE_MAC_TC_MAX_WATERMARK)
+ low_watermark = ICE_MAC_TC_MAX_WATERMARK;
+
+ int cgd_idx = ice_get_cgd_idx(hw, tc);
+
+ if (high_watermark)
+ wr32(hw, GLRPB_TCHW(cgd_idx), high_watermark);
+ if (low_watermark)
+ wr32(hw, GLRPB_TCLW(cgd_idx), low_watermark);
+
+ /* Update pause quanta */
+ uint16_t max_frame_size = pf->dev_data->mtu ?
+ pf->dev_data->mtu + ICE_ETH_OVERHEAD :
+ ICE_FRAME_SIZE_MAX;
+ ret = ice_aq_set_mac_cfg(hw, max_frame_size, 1 << tc, pfc_conf->fc.pause_time,
+ (pfc_conf->fc.pause_time + 1) / 2, false, NULL);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Can not update MAC configuration");
+ return ret;
+ }
+
+ /* Update forwarding of the non FC MAC control frames settings */
+ if ((hw)->mac_type == ICE_MAC_E830) {
+#define E830_MAC_COMMAND_CONFIG(pi) (((pi)->phy.link_info.link_speed == ICE_AQ_LINK_SPEED_200GB) ? \
+ E830_PRTMAC_200G_COMMAND_CONFIG : E830_PRTMAC_COMMAND_CONFIG)
+
+ u32 mac_config = rd32(hw, E830_MAC_COMMAND_CONFIG(port_info));
+
+ if (pfc_conf->fc.mac_ctrl_frame_fwd)
+ mac_config |= E830_PRTMAC_COMMAND_CONFIG_CNTL_FRM_ENA_M;
+ else
+ mac_config &= ~E830_PRTMAC_COMMAND_CONFIG_CNTL_FRM_ENA_M;
+
+ wr32(hw, E830_MAC_COMMAND_CONFIG(port_info), mac_config);
+ }
+
+ return 0;
+}
+
static void
__vsi_queues_bind_intr(struct ice_vsi *vsi, uint16_t msix_vect,
int base_queue, int nb_queue)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 6/6] net/ice: add PFC statistics
2025-08-07 12:22 [PATCH 0/6] Enable DCB/PFC support for ICE PMD Vladimir Medvedkin
` (4 preceding siblings ...)
2025-08-07 12:22 ` [PATCH 5/6] net/ice: enable PFC support Vladimir Medvedkin
@ 2025-08-07 12:22 ` Vladimir Medvedkin
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Medvedkin @ 2025-08-07 12:22 UTC (permalink / raw)
To: dev; +Cc: bruce.richardson, anatoly.burakov
Expose PFC statistics in xstats.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
drivers/net/intel/ice/ice_ethdev.c | 63 ++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index b3be2e7c7e..7ac1c0872a 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -380,6 +380,46 @@ static const struct ice_xstats_name_off ice_hw_port_strings[] = {
{"rx_xon_packets", offsetof(struct ice_hw_port_stats, link_xon_rx)},
{"tx_xoff_packets", offsetof(struct ice_hw_port_stats, link_xoff_tx)},
{"rx_xoff_packets", offsetof(struct ice_hw_port_stats, link_xoff_rx)},
+ {"priority_xon_rx_tc0", offsetof(struct ice_hw_port_stats, priority_xon_rx[0])},
+ {"priority_xon_rx_tc1", offsetof(struct ice_hw_port_stats, priority_xon_rx[1])},
+ {"priority_xon_rx_tc2", offsetof(struct ice_hw_port_stats, priority_xon_rx[2])},
+ {"priority_xon_rx_tc3", offsetof(struct ice_hw_port_stats, priority_xon_rx[3])},
+ {"priority_xon_rx_tc4", offsetof(struct ice_hw_port_stats, priority_xon_rx[4])},
+ {"priority_xon_rx_tc5", offsetof(struct ice_hw_port_stats, priority_xon_rx[5])},
+ {"priority_xon_rx_tc6", offsetof(struct ice_hw_port_stats, priority_xon_rx[6])},
+ {"priority_xon_rx_tc7", offsetof(struct ice_hw_port_stats, priority_xon_rx[7])},
+ {"priority_xoff_rx_tc0", offsetof(struct ice_hw_port_stats, priority_xoff_rx[0])},
+ {"priority_xoff_rx_tc1", offsetof(struct ice_hw_port_stats, priority_xoff_rx[1])},
+ {"priority_xoff_rx_tc2", offsetof(struct ice_hw_port_stats, priority_xoff_rx[2])},
+ {"priority_xoff_rx_tc3", offsetof(struct ice_hw_port_stats, priority_xoff_rx[3])},
+ {"priority_xoff_rx_tc4", offsetof(struct ice_hw_port_stats, priority_xoff_rx[4])},
+ {"priority_xoff_rx_tc5", offsetof(struct ice_hw_port_stats, priority_xoff_rx[5])},
+ {"priority_xoff_rx_tc6", offsetof(struct ice_hw_port_stats, priority_xoff_rx[6])},
+ {"priority_xoff_rx_tc7", offsetof(struct ice_hw_port_stats, priority_xoff_rx[7])},
+ {"priority_xon_tx_tc0", offsetof(struct ice_hw_port_stats, priority_xon_tx[0])},
+ {"priority_xon_tx_tc1", offsetof(struct ice_hw_port_stats, priority_xon_tx[1])},
+ {"priority_xon_tx_tc2", offsetof(struct ice_hw_port_stats, priority_xon_tx[2])},
+ {"priority_xon_tx_tc3", offsetof(struct ice_hw_port_stats, priority_xon_tx[3])},
+ {"priority_xon_tx_tc4", offsetof(struct ice_hw_port_stats, priority_xon_tx[4])},
+ {"priority_xon_tx_tc5", offsetof(struct ice_hw_port_stats, priority_xon_tx[5])},
+ {"priority_xon_tx_tc6", offsetof(struct ice_hw_port_stats, priority_xon_tx[6])},
+ {"priority_xon_tx_tc7", offsetof(struct ice_hw_port_stats, priority_xon_tx[7])},
+ {"priority_xoff_tx_tc0", offsetof(struct ice_hw_port_stats, priority_xoff_tx[0])},
+ {"priority_xoff_tx_tc1", offsetof(struct ice_hw_port_stats, priority_xoff_tx[1])},
+ {"priority_xoff_tx_tc2", offsetof(struct ice_hw_port_stats, priority_xoff_tx[2])},
+ {"priority_xoff_tx_tc3", offsetof(struct ice_hw_port_stats, priority_xoff_tx[3])},
+ {"priority_xoff_tx_tc4", offsetof(struct ice_hw_port_stats, priority_xoff_tx[4])},
+ {"priority_xoff_tx_tc5", offsetof(struct ice_hw_port_stats, priority_xoff_tx[5])},
+ {"priority_xoff_tx_tc6", offsetof(struct ice_hw_port_stats, priority_xoff_tx[6])},
+ {"priority_xoff_tx_tc7", offsetof(struct ice_hw_port_stats, priority_xoff_tx[7])},
+ {"priority_xon_2_xoff_tc0", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
+ {"priority_xon_2_xoff_tc1", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
+ {"priority_xon_2_xoff_tc2", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
+ {"priority_xon_2_xoff_tc3", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
+ {"priority_xon_2_xoff_tc4", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
+ {"priority_xon_2_xoff_tc5", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
+ {"priority_xon_2_xoff_tc6", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
+ {"priority_xon_2_xoff_tc7", offsetof(struct ice_hw_port_stats, priority_xon_2_xoff[0])},
{"rx_size_64_packets", offsetof(struct ice_hw_port_stats, rx_size_64)},
{"rx_size_65_to_127_packets", offsetof(struct ice_hw_port_stats,
rx_size_127)},
@@ -6669,6 +6709,29 @@ ice_read_stats_registers(struct ice_pf *pf, struct ice_hw *hw)
/* GLPRT_MSPDC not supported */
/* GLPRT_XEC not supported */
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ ice_stat_update_40(hw, GLPRT_PXONRXC_H(hw->port_info->lport, i),
+ GLPRT_PXONRXC(hw->port_info->lport, i),
+ pf->offset_loaded, &os->priority_xon_rx[i],
+ &ns->priority_xon_rx[i]);
+ ice_stat_update_40(hw, GLPRT_PXONTXC_H(hw->port_info->lport, i),
+ GLPRT_PXONTXC(hw->port_info->lport, i),
+ pf->offset_loaded, &os->priority_xon_tx[i],
+ &ns->priority_xon_tx[i]);
+ ice_stat_update_40(hw, GLPRT_PXOFFRXC_H(hw->port_info->lport, i),
+ GLPRT_PXOFFRXC(hw->port_info->lport, i),
+ pf->offset_loaded, &os->priority_xoff_rx[i],
+ &ns->priority_xoff_rx[i]);
+ ice_stat_update_40(hw, GLPRT_PXOFFTXC_H(hw->port_info->lport, i),
+ GLPRT_PXOFFTXC(hw->port_info->lport, i),
+ pf->offset_loaded, &os->priority_xoff_tx[i],
+ &ns->priority_xoff_tx[i]);
+ ice_stat_update_40(hw, GLPRT_RXON2OFFCNT_H(hw->port_info->lport, i),
+ GLPRT_RXON2OFFCNT(hw->port_info->lport, i),
+ pf->offset_loaded, &os->priority_xon_2_xoff[i],
+ &ns->priority_xon_2_xoff[i]);
+ }
+
pf->offset_loaded = true;
if (pf->main_vsi)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-08-07 12:23 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-07 12:22 [PATCH 0/6] Enable DCB/PFC support for ICE PMD Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 1/6] net/ice/base: add utility functions Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 2/6] net/ice/base: make set MAC config TC aware Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 3/6] net/ice/base: add supports for assymetric PFC Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 4/6] net/ice: enable DCB support Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 5/6] net/ice: enable PFC support Vladimir Medvedkin
2025-08-07 12:22 ` [PATCH 6/6] net/ice: add PFC statistics Vladimir Medvedkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).