Add enetc4_txq_wrr devarg to configure per-ring WRR weights in the NETC LEAF-level Tx scheduler (TBaMR register, bits [6:4]).
The NETC Tx scheduler has three levels: - ROOT (port/TC): strict priority + CBS (PF/port space) - MID (SI/VSI): WBFS shaping (PF space) - LEAF (Tx BDR): strict priority + frame-based WRR (VF/SI space) TBaMR is in the VF own SI space, so no Linux PF involvement is needed for PRIO or WRR configuration. Changes: - enetc_hw.h: add ENETC_TBMR_WRR_MASK, ENETC_TBMR_WRR(n) macros for TBaMR bits [6:4], and ENETC_TBMR_PRIO_MASK for bits [2:0] - enetc.h: add txq_wrr pointer to enetc_eth_hw struct - enetc4_ethdev.c: add parse_txq_wrr() and wire ENETC4_TXQ_WRR devarg through enetc4_get_devargs() and enetc4_dev_configure(); apply WRR bits in enetc4_tx_queue_setup() and enetc4_tx_queue_start() Usage: # strict priority: ring 0 highest -a 0002:00:12.0,enetc4_txq_prior="3|2|1" # WRR 2:4:1 on same-priority rings -a 0002:00:12.0,enetc4_txq_prior="1|1|1",enetc4_txq_wrr="2|4|1" Signed-off-by: Gagandeep Singh <[email protected]> --- doc/guides/rel_notes/release_26_11.rst | 1 + drivers/net/enetc/base/enetc_hw.h | 5 ++ drivers/net/enetc/enetc.h | 1 + drivers/net/enetc/enetc4_ethdev.c | 97 ++++++++++++++++++++------ 4 files changed, 82 insertions(+), 22 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index d69888aafb..3ea34523fe 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -73,6 +73,7 @@ New Features * Added SI-based port VLAN insertion (Tx) and removal (Rx) for ENETC4 PF and VF. * Updated ENETC4 VF link status reporting to use bitmask encoding. * Added TX PAUSE support for the ENETC4 VF via RX congestion mode. + * Added WRR Tx scheduler devarg (``enetc4_txq_wrr``) for ENETC4 VF ring weights. Removed Items ------------- diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h index 33d075fe59..5a71f01db9 100644 --- a/drivers/net/enetc/base/enetc_hw.h +++ b/drivers/net/enetc/base/enetc_hw.h @@ -86,6 +86,11 @@ enum enetc_bdr_type {TX, RX}; #define ENETC_RTBLENR_LEN(n) ((n) & ~0x7) #define ENETC_TBMR_EN BIT(31) +/* TBaMR[WRR] bits [6:4]: weight for same-priority ring arbitration (0=1x .. 7=8x). */ +#define ENETC_TBMR_WRR_MASK GENMASK(6, 4) +#define ENETC_TBMR_WRR(n) ((((n) - 1) & 0x7) << 4) +/* TBaMR[PRIO] bits [2:0]: strict priority (0=lowest, 7=highest). */ +#define ENETC_TBMR_PRIO_MASK GENMASK(2, 0) /* Port regs, offset: 1_0000h */ #define ENETC_PORT_BASE 0x10000 diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h index 8aaf8a7eb1..e0943d093a 100644 --- a/drivers/net/enetc/enetc.h +++ b/drivers/net/enetc/enetc.h @@ -134,6 +134,7 @@ struct enetc_eth_hw { uint32_t vsi_timeout; /* VSI-PSI message wait timeout (iterations) */ uint32_t vsi_delay; /* VSI-PSI message wait delay (us) */ uint32_t *txq_prior; /* per-queue TX priority (TBMR priority bits) */ + uint32_t *txq_wrr; /* per-queue TX WRR weight pre-shifted for TBMR[WRR] */ uint8_t nc_mode; /* 1 = non-cacheable BD memory, use _nc ops */ uint8_t rxq_intr_en; /* 1 = per-queue Rx MSI-X interrupts enabled */ /* 1 = legacy PF-to-VF link message layout (4-bit speed / 4-bit cookie), diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c index 2355522515..e490ecaf4c 100644 --- a/drivers/net/enetc/enetc4_ethdev.c +++ b/drivers/net/enetc/enetc4_ethdev.c @@ -28,22 +28,26 @@ static uint64_t dev_tx_offloads_sup = RTE_ETH_TX_OFFLOAD_UDP_TSO; #define ENETC4_TXQ_PRIORITIES "enetc4_txq_prior" +#define ENETC4_TXQ_WRR "enetc4_txq_wrr" #define ENETC4_NC_MEMORY "nc" + static int parse_txq_prior(const char *key __rte_unused, const char *value, void *opaque) { struct rte_eth_dev *dev = (struct rte_eth_dev *)opaque; struct enetc_eth_hw *hw = - ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); - char *input_str = strdup(value); + ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); + char *input_str; char *str; uint32_t i = 0; + input_str = strdup(value); if (!input_str) - return -ENOMEM; + return -1; - hw->txq_prior = calloc(hw->max_tx_queues, sizeof(uint32_t)); + rte_free(hw->txq_prior); + hw->txq_prior = rte_zmalloc(NULL, hw->max_tx_queues * sizeof(uint32_t), 0); if (!hw->txq_prior) { free(input_str); return -ENOMEM; @@ -51,7 +55,46 @@ parse_txq_prior(const char *key __rte_unused, const char *value, void *opaque) str = strtok(input_str, "|"); while (str != NULL && i < hw->max_tx_queues) { - hw->txq_prior[i++] = (uint32_t)atoi(str); + hw->txq_prior[i++] = atoi(str) & ENETC_TBMR_PRIO_MASK; + str = strtok(NULL, "|"); + } + + free(input_str); + return 0; +} + +/* Parse enetc4_txq_wrr="w0|w1|..." devarg; weight 1..8 per ring. */ +static int parse_txq_wrr(const char *key __rte_unused, const char *value, + void *opaque) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)opaque; + struct enetc_eth_hw *hw = + ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); + char *input_str; + char *str; + uint32_t i = 0; + int w; + + input_str = strdup(value); + if (!input_str) + return -1; + + rte_free(hw->txq_wrr); + hw->txq_wrr = rte_zmalloc(NULL, + hw->max_tx_queues * sizeof(uint32_t), 0); + if (!hw->txq_wrr) { + free(input_str); + return -1; + } + + str = strtok(input_str, "|"); + while (str != NULL && i < hw->max_tx_queues) { + w = atoi(str); + if (w < 1) + w = 1; + if (w > 8) + w = 8; + hw->txq_wrr[i++] = ENETC_TBMR_WRR(w); str = strtok(NULL, "|"); } @@ -97,6 +140,13 @@ enetc4_get_devargs(struct rte_eth_dev *dev, const char *key) return 0; } } + if (!strcmp(key, ENETC4_TXQ_WRR)) { + if (rte_kvargs_process(kvlist, key, + parse_txq_wrr, (void *)dev) < 0) { + rte_kvargs_free(kvlist); + return 0; + } + } if (!strcmp(key, ENETC4_NC_MEMORY)) { if (rte_kvargs_process(kvlist, key, parse_nc, (void *)dev) < 0) { @@ -109,19 +159,6 @@ enetc4_get_devargs(struct rte_eth_dev *dev, const char *key) return 0; } -/* Supported Rx offloads */ -static uint64_t dev_rx_offloads_sup = - RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | - RTE_ETH_RX_OFFLOAD_UDP_CKSUM | - RTE_ETH_RX_OFFLOAD_TCP_CKSUM | - RTE_ETH_RX_OFFLOAD_SCATTER; - -/* Supported Tx offloads */ -static uint64_t dev_tx_offloads_sup = - RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | - RTE_ETH_TX_OFFLOAD_UDP_CKSUM | - RTE_ETH_TX_OFFLOAD_TCP_CKSUM | - RTE_ETH_TX_OFFLOAD_MULTI_SEGS; static int enetc4_dev_start(struct rte_eth_dev *dev) @@ -458,7 +495,9 @@ enetc4_tx_queue_setup(struct rte_eth_dev *dev, /* apply TX queue priority if configured */ if (priv->hw.txq_prior) - tx_en |= priv->hw.txq_prior[tx_ring->index]; + tx_data |= priv->hw.txq_prior[tx_ring->index]; + if (priv->hw.txq_wrr) + tx_data |= priv->hw.txq_wrr[tx_ring->index]; /* enable ring */ enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR, tx_en); @@ -613,7 +652,6 @@ enetc4_rx_queue_setup(struct rte_eth_dev *dev, struct enetc_eth_adapter *adapter = ENETC_DEV_PRIVATE(data->dev_private); uint64_t rx_offloads = data->dev_conf.rxmode.offloads; - uint32_t rx_enable; uint32_t rsc_size; bool keep_crc; bool rsc_enable; @@ -869,7 +907,10 @@ enetc4_dev_close(struct rte_eth_dev *dev) dev->data->tx_queues[i] = NULL; } dev->data->nb_tx_queues = 0; - + rte_free(hw->txq_prior); + hw->txq_prior = NULL; + rte_free(hw->txq_wrr); + hw->txq_wrr = NULL; if (rte_eal_iova_mode() == RTE_IOVA_PA) dpaax_iova_table_depopulate(); @@ -1020,6 +1061,11 @@ enetc4_dev_configure(struct rte_eth_dev *dev) for (i = 0; i < dev->data->nb_tx_queues; i++) enetc4_rxbdr_wr(enetc_hw, i, ENETC_TBMR, ENETC_BMR_RESET); + hw->nc_mode = 0; + enetc4_get_devargs(dev, ENETC4_TXQ_PRIORITIES); + enetc4_get_devargs(dev, ENETC4_TXQ_WRR); + enetc4_get_devargs(dev, ENETC4_NC_MEMORY); + if (dev->data->nb_rx_queues <= 1) return 0; @@ -1142,7 +1188,13 @@ enetc4_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx) if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) { tx_data = enetc4_txbdr_rd(&priv->hw.hw, tx_ring->index, ENETC_TBMR); - tx_data = tx_data | ENETC_TBMR_EN; + /* Clear scheduler bits before applying fresh devarg values. */ + tx_data &= ~(ENETC_TBMR_PRIO_MASK | ENETC_TBMR_WRR_MASK); + tx_data |= ENETC_TBMR_EN; + if (priv->hw.txq_prior) + tx_data |= priv->hw.txq_prior[tx_ring->index]; + if (priv->hw.txq_wrr) + tx_data |= priv->hw.txq_wrr[tx_ring->index]; enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR, tx_data); dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED; @@ -1457,5 +1509,6 @@ RTE_PMD_REGISTER_PCI_TABLE(net_enetc4, pci_id_enetc4_map); RTE_PMD_REGISTER_KMOD_DEP(net_enetc4, "* vfio-pci"); RTE_PMD_REGISTER_PARAM_STRING(net_enetc4, ENETC4_TXQ_PRIORITIES "=<string> " + ENETC4_TXQ_WRR "=<string> " ENETC4_NC_MEMORY "=<int>"); RTE_LOG_REGISTER_DEFAULT(enetc4_logtype_pmd, NOTICE); -- 2.25.1

