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

Reply via email to