DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] net/ice: fix Tx scheduler hierarchy queue accounting
@ 2026-09-04 10:51 Ciara Loftus
  2026-09-04 10:51 ` [PATCH 1/3] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Ciara Loftus @ 2026-09-04 10:51 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus

Committing a Tx scheduler (rte_tm) hierarchy on ice can grow the port's
usable Tx queue count beyond what was available when the port was first
probed. This series fixes three bugs related to this.

Ciara Loftus (3):
  net/ice: fix Tx queue capacity sizing after TM commit
  net/ice: skip TC validation if hierarchy committed
  net/ice: fix Rx queue count reporting after TM commit

 drivers/net/intel/ice/ice_ethdev.c |  9 ++++++--
 drivers/net/intel/ice/ice_ethdev.h |  3 +++
 drivers/net/intel/ice/ice_rxtx.c   | 33 ++++++++++++++++++------------
 drivers/net/intel/ice/ice_tm.c     | 10 ++++-----
 4 files changed, 35 insertions(+), 20 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1/3] net/ice: fix Tx queue capacity sizing after TM commit
  2026-09-04 10:51 [PATCH 0/3] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
@ 2026-09-04 10:51 ` Ciara Loftus
  2026-09-04 13:01   ` Bruce Richardson
  2026-09-04 10:51 ` [PATCH 2/3] net/ice: skip TC validation if hierarchy committed Ciara Loftus
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 17+ messages in thread
From: Ciara Loftus @ 2026-09-04 10:51 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus, stable

commit_new_hierarchy() computes the number of usable Tx queues (nb_qps)
by indexing the arrays nodes_created_per_level[] and hw->layer_info[] with
a value derived from ice_get_leaf_level(). nodes_created_per_level[] is
indexed by absolute hw scheduler layer, but ice_get_leaf_level() returns a
value relative to the TM hierarchy's root position, so the index used was
off by the number of hidden layers.

This under-counted the qgroup layer, causing nb_qps to be computed from a
shallower layer than the one actually holding the committed qgroup nodes.
In turn this caused rte_eth_dev_configure to reject any nb_tx_queues above
the miscalculated capacity.

Fix by converting the index to an absolute layer index.

Fixes: 715d449a965b ("net/ice: enhance Tx scheduler hierarchy support")
Cc: stable@dpdk.org

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
 drivers/net/intel/ice/ice_tm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/intel/ice/ice_tm.c b/drivers/net/intel/ice/ice_tm.c
index 2e6ef9c264f..651d6aa932d 100644
--- a/drivers/net/intel/ice/ice_tm.c
+++ b/drivers/net/intel/ice/ice_tm.c
@@ -848,7 +848,7 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 	const uint16_t new_root_level = pf->tm_conf.hidden_layers;
 	/* count nodes per hw level, not per logical */
 	uint16_t nodes_created_per_level[ICE_TM_MAX_LAYERS] = {0};
-	uint8_t q_lvl = ice_get_leaf_level(pf);
+	uint8_t q_lvl = ice_get_leaf_level(pf) + pf->tm_conf.hidden_layers;
 	uint8_t qg_lvl = q_lvl - 1;
 	struct ice_sched_node *new_vsi_root = hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0];
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/3] net/ice: skip TC validation if hierarchy committed
  2026-09-04 10:51 [PATCH 0/3] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
  2026-09-04 10:51 ` [PATCH 1/3] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
@ 2026-09-04 10:51 ` Ciara Loftus
  2026-09-04 13:11   ` Bruce Richardson
  2026-09-04 10:51 ` [PATCH 3/3] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
  2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
  3 siblings, 1 reply; 17+ messages in thread
From: Ciara Loftus @ 2026-09-04 10:51 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus, stable

Currently, ice_tx_queue_start() determines a queue's congestion domain by
scanning vsi->info.tc_mapping[] for a matching traffic class range,
rejecting the queue if no match is found.

The Tx scheduler hierarchies only ever operate on a single traffic class,
TC0, so every queue managed by a committed TM hierarchy always belongs
to domain 0. The tc_mapping[] lookup doesn't account for this, and queues
added after a TM hierarchy is committed can be incorrectly rejected.

Fix this by skipping the lookup if a hierarchy has been committed as the
domain is already known to be 0 in that case. Since TM does not support
DCB's multi-TC queue layout, also reject queue start explicitly if DCB
has configured more than one TC while a TM hierarchy is committed.

Fixes: 02b71e570294 ("net/ice: support DCB")
Cc: stable@dpdk.org

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.c |  4 ++++
 drivers/net/intel/ice/ice_ethdev.h |  2 ++
 drivers/net/intel/ice/ice_rxtx.c   | 33 ++++++++++++++++++------------
 3 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index 76b8ff0a72e..fd148848d3c 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -3963,6 +3963,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
 	ad->rx_func_type = ICE_RX_DEFAULT;
 	ad->tx_func_type = ICE_TX_DEFAULT;
 
+	pf->dcb_num_tcs = 1;
+
 	if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
 		dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
 
@@ -3992,6 +3994,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
 		if (nb_tc_used < 0)
 			return -EINVAL;
 
+		pf->dcb_num_tcs = nb_tc_used;
+
 		ctxt.info = 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");
diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 7ee3ea8a709..5914454c7c2 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -609,6 +609,8 @@ struct ice_pf {
 	uint64_t rss_hf;
 	struct ice_tm_conf tm_conf;
 	uint16_t outer_ethertype;
+	/* Number of TCs requested, 1 if DCB not configured */
+	uint8_t dcb_num_tcs;
 	/* lock prevent race condition between lsc interrupt handler
 	 * and link status update during dev_start.
 	 */
diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
index c4b5454c530..71f9155e588 100644
--- a/drivers/net/intel/ice/ice_rxtx.c
+++ b/drivers/net/intel/ice/ice_rxtx.c
@@ -839,20 +839,27 @@ 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<->CGD */
-	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 (!pf->tm_conf.committed) {
+		/* Mirror RXQ<->CGD association to TXQ<->CGD */
+		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;
 
-	if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
-		PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
+			cgd_idx++;
+		}
+		if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
+			PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
+			rte_free(txq_elem);
+			return -EINVAL;
+		}
+	} else if (pf->dcb_num_tcs > 1) {
+		/* TM only manages the TC0 scheduler subtree. */
+		PMD_DRV_LOG(ERR, "TM hierarchy is not supported together with multi-TC DCB");
 		rte_free(txq_elem);
 		return -EINVAL;
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/3] net/ice: fix Rx queue count reporting after TM commit
  2026-09-04 10:51 [PATCH 0/3] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
  2026-09-04 10:51 ` [PATCH 1/3] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
  2026-09-04 10:51 ` [PATCH 2/3] net/ice: skip TC validation if hierarchy committed Ciara Loftus
@ 2026-09-04 10:51 ` Ciara Loftus
  2026-09-04 13:33   ` Bruce Richardson
  2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
  3 siblings, 1 reply; 17+ messages in thread
From: Ciara Loftus @ 2026-09-04 10:51 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus, stable

Currently, ice_dev_info_get() assigns the value of `vsi->nb_qps` to both
`max_rx_queues` and `max_tx_queues`.

After a Tx scheduler hierarchy is committed, the value of nb_qps may grow
to reflect the VSI's larger Tx scheduler capacity. However the Tx scheduler
hierarchy change has no effect on the VSI's Rx queue allocation,
which stays fixed at its original size for the life of the port. An
application can then request more Rx queues than the VSI's actual Rx
resources support when the inflated nb_qps is assigned to `max_rx_queues`.

`vsi->nb_qps` also feeds `ice_vsi_disable_queues_intr()`, which clears
both Rx and Tx queue interrupt registers by absolute queue index on
every port stop. Once `nb_qps` grows past the VSI's fixed queue window,
this can clear interrupt registers belonging to a different VSI.

Fix this by introducing `vsi->nb_tm_qps` to track the Tx scheduler
capacity as it grows, leaving `vsi->nb_qps` as the VSI's fixed
queue allocation for the life of the port. `ice_vsi_disable_queues_intr()`
is switched to `nb_used_qps`, which already tracks the actually configured
queue count.

Fixes: 715d449a965b ("net/ice: enhance Tx scheduler hierarchy support")
Cc: stable@dpdk.org

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.c | 5 +++--
 drivers/net/intel/ice/ice_ethdev.h | 1 +
 drivers/net/intel/ice/ice_tm.c     | 8 ++++----
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index fd148848d3c..149872816d8 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -1816,6 +1816,7 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 				     ret);
 			goto fail_mem;
 		}
+		vsi->nb_tm_qps = vsi->nb_qps;
 
 		break;
 	case ICE_VSI_CTRL:
@@ -2924,7 +2925,7 @@ ice_vsi_disable_queues_intr(struct ice_vsi *vsi)
 	uint16_t msix_intr, i;
 
 	/* disable interrupt and also clear all the exist config */
-	for (i = 0; i < vsi->nb_qps; i++) {
+	for (i = 0; i < vsi->nb_used_qps; i++) {
 		ICE_WRITE_REG(hw, QINT_TQCTL(vsi->base_queue + i), 0);
 		ICE_WRITE_REG(hw, QINT_RQCTL(vsi->base_queue + i), 0);
 		rte_wmb();
@@ -4628,7 +4629,7 @@ ice_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->min_rx_bufsize = ICE_BUF_SIZE_MIN;
 	dev_info->max_rx_pktlen = ICE_FRAME_SIZE_MAX;
 	dev_info->max_rx_queues = vsi->nb_qps;
-	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_tm_qps;
 	dev_info->max_mac_addrs = vsi->max_macaddrs;
 	dev_info->max_vfs = pci_dev->max_vfs;
 	dev_info->max_mtu = dev_info->max_rx_pktlen - ICE_ETH_OVERHEAD;
diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 5914454c7c2..3160c82c5e3 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -330,6 +330,7 @@ struct ice_vsi {
 	struct ice_mac_filter_list mac_list; /* macvlan filter list */
 	struct ice_vlan_filter_list vlan_list; /* vlan filter list */
 	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
+	uint16_t nb_tm_qps;      /* Number of Tx queues usable by the committed TM hierarchy */
 	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
 	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
 	uint16_t base_queue;     /* The first queue index of this VSI */
diff --git a/drivers/net/intel/ice/ice_tm.c b/drivers/net/intel/ice/ice_tm.c
index 651d6aa932d..7afe31738ba 100644
--- a/drivers/net/intel/ice/ice_tm.c
+++ b/drivers/net/intel/ice/ice_tm.c
@@ -859,9 +859,9 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 		}
 		/* TM hierarchy deleted. Restore default scheduler state. */
 		reset_hw_node_recursive(hw, hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0]);
-		pf->main_vsi->nb_qps = pf->lan_nb_qps;
+		pf->main_vsi->nb_tm_qps = pf->lan_nb_qps;
 		pf->tm_conf.committed = false;
-		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_qps);
+		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_qps);
 	}
 
 	/* handle case where VSI node needs to move DOWN the hierarchy */
@@ -889,13 +889,13 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 				nodes_created_per_level[i], i);
 	hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0] = new_vsi_root;
 
-	pf->main_vsi->nb_qps =
+	pf->main_vsi->nb_tm_qps =
 			RTE_MIN(nodes_created_per_level[qg_lvl] * hw->max_children[qg_lvl],
 				hw->layer_info[q_lvl].max_device_nodes);
 
 	pf->tm_conf.committed = true; /* set flag to be checks on queue start */
 
-	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_qps);
+	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_qps);
 }
 
 static int
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/3] net/ice: fix Tx queue capacity sizing after TM commit
  2026-09-04 10:51 ` [PATCH 1/3] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
@ 2026-09-04 13:01   ` Bruce Richardson
  0 siblings, 0 replies; 17+ messages in thread
From: Bruce Richardson @ 2026-09-04 13:01 UTC (permalink / raw)
  To: Ciara Loftus; +Cc: dev, stable

On Fri, Sep 04, 2026 at 10:51:37AM +0000, Ciara Loftus wrote:
> commit_new_hierarchy() computes the number of usable Tx queues (nb_qps)
> by indexing the arrays nodes_created_per_level[] and hw->layer_info[] with
> a value derived from ice_get_leaf_level(). nodes_created_per_level[] is
> indexed by absolute hw scheduler layer, but ice_get_leaf_level() returns a
> value relative to the TM hierarchy's root position, so the index used was
> off by the number of hidden layers.
> 
> This under-counted the qgroup layer, causing nb_qps to be computed from a
> shallower layer than the one actually holding the committed qgroup nodes.
> In turn this caused rte_eth_dev_configure to reject any nb_tx_queues above
> the miscalculated capacity.
> 
> Fix by converting the index to an absolute layer index.
> 
> Fixes: 715d449a965b ("net/ice: enhance Tx scheduler hierarchy support")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
> ---

Acked-by: Bruce Richardson <bruce.richardson@intel.com>


>  drivers/net/intel/ice/ice_tm.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/intel/ice/ice_tm.c b/drivers/net/intel/ice/ice_tm.c
> index 2e6ef9c264f..651d6aa932d 100644
> --- a/drivers/net/intel/ice/ice_tm.c
> +++ b/drivers/net/intel/ice/ice_tm.c
> @@ -848,7 +848,7 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
>  	const uint16_t new_root_level = pf->tm_conf.hidden_layers;
>  	/* count nodes per hw level, not per logical */
>  	uint16_t nodes_created_per_level[ICE_TM_MAX_LAYERS] = {0};
> -	uint8_t q_lvl = ice_get_leaf_level(pf);
> +	uint8_t q_lvl = ice_get_leaf_level(pf) + pf->tm_conf.hidden_layers;
>  	uint8_t qg_lvl = q_lvl - 1;
>  	struct ice_sched_node *new_vsi_root = hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0];
>  
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/3] net/ice: skip TC validation if hierarchy committed
  2026-09-04 10:51 ` [PATCH 2/3] net/ice: skip TC validation if hierarchy committed Ciara Loftus
@ 2026-09-04 13:11   ` Bruce Richardson
  2026-09-07 11:14     ` Loftus, Ciara
  0 siblings, 1 reply; 17+ messages in thread
From: Bruce Richardson @ 2026-09-04 13:11 UTC (permalink / raw)
  To: Ciara Loftus; +Cc: dev, stable

On Fri, Sep 04, 2026 at 10:51:38AM +0000, Ciara Loftus wrote:
> Currently, ice_tx_queue_start() determines a queue's congestion domain by
> scanning vsi->info.tc_mapping[] for a matching traffic class range,
> rejecting the queue if no match is found.
> 
> The Tx scheduler hierarchies only ever operate on a single traffic class,
> TC0, so every queue managed by a committed TM hierarchy always belongs
> to domain 0. The tc_mapping[] lookup doesn't account for this, and queues
> added after a TM hierarchy is committed can be incorrectly rejected.
> 
> Fix this by skipping the lookup if a hierarchy has been committed as the
> domain is already known to be 0 in that case. Since TM does not support
> DCB's multi-TC queue layout, also reject queue start explicitly if DCB
> has configured more than one TC while a TM hierarchy is committed.
> 
> Fixes: 02b71e570294 ("net/ice: support DCB")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
> ---
>  drivers/net/intel/ice/ice_ethdev.c |  4 ++++
>  drivers/net/intel/ice/ice_ethdev.h |  2 ++
>  drivers/net/intel/ice/ice_rxtx.c   | 33 ++++++++++++++++++------------
>  3 files changed, 26 insertions(+), 13 deletions(-)
> 

Did you hit this in testing, or was it just via code review or AI review?
Fix looks good anyway.

Acked-by: Bruce Richardson <bruce.richardson@intel.com>


> diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
> index 76b8ff0a72e..fd148848d3c 100644
> --- a/drivers/net/intel/ice/ice_ethdev.c
> +++ b/drivers/net/intel/ice/ice_ethdev.c
> @@ -3963,6 +3963,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
>  	ad->rx_func_type = ICE_RX_DEFAULT;
>  	ad->tx_func_type = ICE_TX_DEFAULT;
>  
> +	pf->dcb_num_tcs = 1;
> +
>  	if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
>  		dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
>  
> @@ -3992,6 +3994,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
>  		if (nb_tc_used < 0)
>  			return -EINVAL;
>  
> +		pf->dcb_num_tcs = nb_tc_used;
> +
>  		ctxt.info = 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");
> diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
> index 7ee3ea8a709..5914454c7c2 100644
> --- a/drivers/net/intel/ice/ice_ethdev.h
> +++ b/drivers/net/intel/ice/ice_ethdev.h
> @@ -609,6 +609,8 @@ struct ice_pf {
>  	uint64_t rss_hf;
>  	struct ice_tm_conf tm_conf;
>  	uint16_t outer_ethertype;
> +	/* Number of TCs requested, 1 if DCB not configured */
> +	uint8_t dcb_num_tcs;
>  	/* lock prevent race condition between lsc interrupt handler
>  	 * and link status update during dev_start.
>  	 */
> diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
> index c4b5454c530..71f9155e588 100644
> --- a/drivers/net/intel/ice/ice_rxtx.c
> +++ b/drivers/net/intel/ice/ice_rxtx.c
> @@ -839,20 +839,27 @@ 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<->CGD */
> -	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 (!pf->tm_conf.committed) {
> +		/* Mirror RXQ<->CGD association to TXQ<->CGD */
> +		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;
>  
> -	if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> -		PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> +			cgd_idx++;
> +		}
> +		if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> +			PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> +			rte_free(txq_elem);
> +			return -EINVAL;
> +		}
> +	} else if (pf->dcb_num_tcs > 1) {
> +		/* TM only manages the TC0 scheduler subtree. */
> +		PMD_DRV_LOG(ERR, "TM hierarchy is not supported together with multi-TC DCB");
>  		rte_free(txq_elem);
>  		return -EINVAL;
>  	}
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/3] net/ice: fix Rx queue count reporting after TM commit
  2026-09-04 10:51 ` [PATCH 3/3] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
@ 2026-09-04 13:33   ` Bruce Richardson
  2026-09-07 11:16     ` Loftus, Ciara
  0 siblings, 1 reply; 17+ messages in thread
From: Bruce Richardson @ 2026-09-04 13:33 UTC (permalink / raw)
  To: Ciara Loftus; +Cc: dev, stable

On Fri, Sep 04, 2026 at 10:51:39AM +0000, Ciara Loftus wrote:
> Currently, ice_dev_info_get() assigns the value of `vsi->nb_qps` to both
> `max_rx_queues` and `max_tx_queues`.
> 
> After a Tx scheduler hierarchy is committed, the value of nb_qps may grow
> to reflect the VSI's larger Tx scheduler capacity. However the Tx scheduler
> hierarchy change has no effect on the VSI's Rx queue allocation,
> which stays fixed at its original size for the life of the port. An
> application can then request more Rx queues than the VSI's actual Rx
> resources support when the inflated nb_qps is assigned to `max_rx_queues`.
> 
> `vsi->nb_qps` also feeds `ice_vsi_disable_queues_intr()`, which clears
> both Rx and Tx queue interrupt registers by absolute queue index on
> every port stop. Once `nb_qps` grows past the VSI's fixed queue window,
> this can clear interrupt registers belonging to a different VSI.
> 
> Fix this by introducing `vsi->nb_tm_qps` to track the Tx scheduler

Just a nit on naming here. For the tm block it doesn't deal with
queue-pairs so much as Tx queues, so the variable should probably be named
nb_tm_txqs instead.

However, that opens a wider renaming question - rather than tracking a
generic nb_qps and nb_tm_qps(nb_tm_txqs), might it be better to have vsi
variables separately called "nb_rxqs" and "nb_txqs" and ignore the whole
"tm" part of it?

> capacity as it grows, leaving `vsi->nb_qps` as the VSI's fixed
> queue allocation for the life of the port. `ice_vsi_disable_queues_intr()`
> is switched to `nb_used_qps`, which already tracks the actually configured
> queue count.
> 
> Fixes: 715d449a965b ("net/ice: enhance Tx scheduler hierarchy support")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
> ---
>  drivers/net/intel/ice/ice_ethdev.c | 5 +++--
>  drivers/net/intel/ice/ice_ethdev.h | 1 +
>  drivers/net/intel/ice/ice_tm.c     | 8 ++++----
>  3 files changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
> index fd148848d3c..149872816d8 100644
> --- a/drivers/net/intel/ice/ice_ethdev.c
> +++ b/drivers/net/intel/ice/ice_ethdev.c
> @@ -1816,6 +1816,7 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
>  				     ret);
>  			goto fail_mem;
>  		}
> +		vsi->nb_tm_qps = vsi->nb_qps;
>  
>  		break;
>  	case ICE_VSI_CTRL:
> @@ -2924,7 +2925,7 @@ ice_vsi_disable_queues_intr(struct ice_vsi *vsi)
>  	uint16_t msix_intr, i;
>  
>  	/* disable interrupt and also clear all the exist config */
> -	for (i = 0; i < vsi->nb_qps; i++) {
> +	for (i = 0; i < vsi->nb_used_qps; i++) {
>  		ICE_WRITE_REG(hw, QINT_TQCTL(vsi->base_queue + i), 0);
>  		ICE_WRITE_REG(hw, QINT_RQCTL(vsi->base_queue + i), 0);
>  		rte_wmb();
> @@ -4628,7 +4629,7 @@ ice_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>  	dev_info->min_rx_bufsize = ICE_BUF_SIZE_MIN;
>  	dev_info->max_rx_pktlen = ICE_FRAME_SIZE_MAX;
>  	dev_info->max_rx_queues = vsi->nb_qps;
> -	dev_info->max_tx_queues = vsi->nb_qps;
> +	dev_info->max_tx_queues = vsi->nb_tm_qps;
>  	dev_info->max_mac_addrs = vsi->max_macaddrs;
>  	dev_info->max_vfs = pci_dev->max_vfs;
>  	dev_info->max_mtu = dev_info->max_rx_pktlen - ICE_ETH_OVERHEAD;
> diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
> index 5914454c7c2..3160c82c5e3 100644
> --- a/drivers/net/intel/ice/ice_ethdev.h
> +++ b/drivers/net/intel/ice/ice_ethdev.h
> @@ -330,6 +330,7 @@ struct ice_vsi {
>  	struct ice_mac_filter_list mac_list; /* macvlan filter list */
>  	struct ice_vlan_filter_list vlan_list; /* vlan filter list */
>  	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
> +	uint16_t nb_tm_qps;      /* Number of Tx queues usable by the committed TM hierarchy */
>  	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
>  	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
>  	uint16_t base_queue;     /* The first queue index of this VSI */
> diff --git a/drivers/net/intel/ice/ice_tm.c b/drivers/net/intel/ice/ice_tm.c
> index 651d6aa932d..7afe31738ba 100644
> --- a/drivers/net/intel/ice/ice_tm.c
> +++ b/drivers/net/intel/ice/ice_tm.c
> @@ -859,9 +859,9 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
>  		}
>  		/* TM hierarchy deleted. Restore default scheduler state. */
>  		reset_hw_node_recursive(hw, hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0]);
> -		pf->main_vsi->nb_qps = pf->lan_nb_qps;
> +		pf->main_vsi->nb_tm_qps = pf->lan_nb_qps;
>  		pf->tm_conf.committed = false;
> -		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_qps);
> +		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_qps);
>  	}
>  
>  	/* handle case where VSI node needs to move DOWN the hierarchy */
> @@ -889,13 +889,13 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
>  				nodes_created_per_level[i], i);
>  	hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0] = new_vsi_root;
>  
> -	pf->main_vsi->nb_qps =
> +	pf->main_vsi->nb_tm_qps =
>  			RTE_MIN(nodes_created_per_level[qg_lvl] * hw->max_children[qg_lvl],
>  				hw->layer_info[q_lvl].max_device_nodes);
>  
>  	pf->tm_conf.committed = true; /* set flag to be checks on queue start */
>  
> -	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_qps);
> +	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_qps);
>  }
>  
>  static int

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH 2/3] net/ice: skip TC validation if hierarchy committed
  2026-09-04 13:11   ` Bruce Richardson
@ 2026-09-07 11:14     ` Loftus, Ciara
  0 siblings, 0 replies; 17+ messages in thread
From: Loftus, Ciara @ 2026-09-07 11:14 UTC (permalink / raw)
  To: Richardson, Bruce; +Cc: dev@dpdk.org, stable@dpdk.org

> On Fri, Sep 04, 2026 at 10:51:38AM +0000, Ciara Loftus wrote:
> > Currently, ice_tx_queue_start() determines a queue's congestion domain by
> > scanning vsi->info.tc_mapping[] for a matching traffic class range,
> > rejecting the queue if no match is found.
> >
> > The Tx scheduler hierarchies only ever operate on a single traffic class,
> > TC0, so every queue managed by a committed TM hierarchy always belongs
> > to domain 0. The tc_mapping[] lookup doesn't account for this, and queues
> > added after a TM hierarchy is committed can be incorrectly rejected.
> >
> > Fix this by skipping the lookup if a hierarchy has been committed as the
> > domain is already known to be 0 in that case. Since TM does not support
> > DCB's multi-TC queue layout, also reject queue start explicitly if DCB
> > has configured more than one TC while a TM hierarchy is committed.
> >
> > Fixes: 02b71e570294 ("net/ice: support DCB")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
> > ---
> >  drivers/net/intel/ice/ice_ethdev.c |  4 ++++
> >  drivers/net/intel/ice/ice_ethdev.h |  2 ++
> >  drivers/net/intel/ice/ice_rxtx.c   | 33 ++++++++++++++++++------------
> >  3 files changed, 26 insertions(+), 13 deletions(-)
> >
> 
> Did you hit this in testing, or was it just via code review or AI review?
> Fix looks good anyway.

Yes I hit this in testing. If you create a Tx scheduler hierarchy that
increases the number of usable Tx queues beyond what was available at dev
probe, and then try to start one of the queues beyond the original limit,
the error path is hit in ice_tx_queue_start(), since only the original
queues are covered by tc_mapping[]. That array is sized once at VSI
creation and never grows to reflect the queues TM makes available
afterward.

> 
> Acked-by: Bruce Richardson <bruce.richardson@intel.com>
> 
> 
> > diff --git a/drivers/net/intel/ice/ice_ethdev.c
> b/drivers/net/intel/ice/ice_ethdev.c
> > index 76b8ff0a72e..fd148848d3c 100644
> > --- a/drivers/net/intel/ice/ice_ethdev.c
> > +++ b/drivers/net/intel/ice/ice_ethdev.c
> > @@ -3963,6 +3963,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
> >  	ad->rx_func_type = ICE_RX_DEFAULT;
> >  	ad->tx_func_type = ICE_TX_DEFAULT;
> >
> > +	pf->dcb_num_tcs = 1;
> > +
> >  	if (dev->data->dev_conf.rxmode.mq_mode &
> RTE_ETH_MQ_RX_RSS_FLAG)
> >  		dev->data->dev_conf.rxmode.offloads |=
> RTE_ETH_RX_OFFLOAD_RSS_HASH;
> >
> > @@ -3992,6 +3994,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
> >  		if (nb_tc_used < 0)
> >  			return -EINVAL;
> >
> > +		pf->dcb_num_tcs = nb_tc_used;
> > +
> >  		ctxt.info = 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");
> > diff --git a/drivers/net/intel/ice/ice_ethdev.h
> b/drivers/net/intel/ice/ice_ethdev.h
> > index 7ee3ea8a709..5914454c7c2 100644
> > --- a/drivers/net/intel/ice/ice_ethdev.h
> > +++ b/drivers/net/intel/ice/ice_ethdev.h
> > @@ -609,6 +609,8 @@ struct ice_pf {
> >  	uint64_t rss_hf;
> >  	struct ice_tm_conf tm_conf;
> >  	uint16_t outer_ethertype;
> > +	/* Number of TCs requested, 1 if DCB not configured */
> > +	uint8_t dcb_num_tcs;
> >  	/* lock prevent race condition between lsc interrupt handler
> >  	 * and link status update during dev_start.
> >  	 */
> > diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
> > index c4b5454c530..71f9155e588 100644
> > --- a/drivers/net/intel/ice/ice_rxtx.c
> > +++ b/drivers/net/intel/ice/ice_rxtx.c
> > @@ -839,20 +839,27 @@ 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<->CGD */
> > -	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 (!pf->tm_conf.committed) {
> > +		/* Mirror RXQ<->CGD association to TXQ<->CGD */
> > +		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;
> >
> > -	if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> > -		PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
> > +			cgd_idx++;
> > +		}
> > +		if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
> > +			PMD_DRV_LOG(ERR, "Bad queue mapping
> configuration");
> > +			rte_free(txq_elem);
> > +			return -EINVAL;
> > +		}
> > +	} else if (pf->dcb_num_tcs > 1) {
> > +		/* TM only manages the TC0 scheduler subtree. */
> > +		PMD_DRV_LOG(ERR, "TM hierarchy is not supported together
> with multi-TC DCB");
> >  		rte_free(txq_elem);
> >  		return -EINVAL;
> >  	}
> > --
> > 2.43.0
> >

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH 3/3] net/ice: fix Rx queue count reporting after TM commit
  2026-09-04 13:33   ` Bruce Richardson
@ 2026-09-07 11:16     ` Loftus, Ciara
  0 siblings, 0 replies; 17+ messages in thread
From: Loftus, Ciara @ 2026-09-07 11:16 UTC (permalink / raw)
  To: Richardson, Bruce; +Cc: dev@dpdk.org, stable@dpdk.org

> Subject: Re: [PATCH 3/3] net/ice: fix Rx queue count reporting after TM
> commit
> 
> On Fri, Sep 04, 2026 at 10:51:39AM +0000, Ciara Loftus wrote:
> > Currently, ice_dev_info_get() assigns the value of `vsi->nb_qps` to both
> > `max_rx_queues` and `max_tx_queues`.
> >
> > After a Tx scheduler hierarchy is committed, the value of nb_qps may grow
> > to reflect the VSI's larger Tx scheduler capacity. However the Tx scheduler
> > hierarchy change has no effect on the VSI's Rx queue allocation,
> > which stays fixed at its original size for the life of the port. An
> > application can then request more Rx queues than the VSI's actual Rx
> > resources support when the inflated nb_qps is assigned to `max_rx_queues`.
> >
> > `vsi->nb_qps` also feeds `ice_vsi_disable_queues_intr()`, which clears
> > both Rx and Tx queue interrupt registers by absolute queue index on
> > every port stop. Once `nb_qps` grows past the VSI's fixed queue window,
> > this can clear interrupt registers belonging to a different VSI.
> >
> > Fix this by introducing `vsi->nb_tm_qps` to track the Tx scheduler
> 
> Just a nit on naming here. For the tm block it doesn't deal with
> queue-pairs so much as Tx queues, so the variable should probably be named
> nb_tm_txqs instead.

+1

> 
> However, that opens a wider renaming question - rather than tracking a
> generic nb_qps and nb_tm_qps(nb_tm_txqs), might it be better to have vsi
> variables separately called "nb_rxqs" and "nb_txqs" and ignore the whole
> "tm" part of it?

I think that makes sense. I'll add that change as a fourth patch and you can
see what you think. nb_qps is used in a few different places in the driver,
mostly on init paths, so there is a little bit of churn.

> 
> > capacity as it grows, leaving `vsi->nb_qps` as the VSI's fixed
> > queue allocation for the life of the port. `ice_vsi_disable_queues_intr()`
> > is switched to `nb_used_qps`, which already tracks the actually configured
> > queue count.
> >


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting
  2026-09-04 10:51 [PATCH 0/3] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
                   ` (2 preceding siblings ...)
  2026-09-04 10:51 ` [PATCH 3/3] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
@ 2026-09-07 13:07 ` Ciara Loftus
  2026-09-07 13:07   ` [PATCH v2 1/4] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
                     ` (4 more replies)
  3 siblings, 5 replies; 17+ messages in thread
From: Ciara Loftus @ 2026-09-07 13:07 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus

Committing a Tx scheduler (rte_tm) hierarchy on ice can grow the port's
usable Tx queue count beyond what was available when the port was first
probed. This series fixes three bugs related to this, and makes a
cosmetic change by renaming variables related to queue counting.

v2:
* Variable renaming in patch 3 nb_tm_qps -> nb_tm_txqs
* Added a forth patch to split VSI qps variable into separate Rx/Tx
varaibles

Ciara Loftus (4):
  net/ice: fix Tx queue capacity sizing after TM commit
  net/ice: skip TC validation if hierarchy committed
  net/ice: fix Rx queue count reporting after TM commit
  net/ice: split VSI queue count into Rx/Tx

 drivers/net/intel/ice/ice_ethdev.c | 42 ++++++++++++++++--------------
 drivers/net/intel/ice/ice_ethdev.h |  5 +++-
 drivers/net/intel/ice/ice_rxtx.c   | 33 ++++++++++++++---------
 drivers/net/intel/ice/ice_tm.c     | 10 +++----
 4 files changed, 51 insertions(+), 39 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 1/4] net/ice: fix Tx queue capacity sizing after TM commit
  2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
@ 2026-09-07 13:07   ` Ciara Loftus
  2026-09-07 13:07   ` [PATCH v2 2/4] net/ice: skip TC validation if hierarchy committed Ciara Loftus
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Ciara Loftus @ 2026-09-07 13:07 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus, stable, Bruce Richardson

commit_new_hierarchy() computes the number of usable Tx queues (nb_qps)
by indexing the arrays nodes_created_per_level[] and hw->layer_info[] with
a value derived from ice_get_leaf_level(). nodes_created_per_level[] is
indexed by absolute hw scheduler layer, but ice_get_leaf_level() returns a
value relative to the TM hierarchy's root position, so the index used was
off by the number of hidden layers.

This under-counted the qgroup layer, causing nb_qps to be computed from a
shallower layer than the one actually holding the committed qgroup nodes.
In turn this caused rte_eth_dev_configure to reject any nb_tx_queues above
the miscalculated capacity.

Fix by converting the index to an absolute layer index.

Fixes: 715d449a965b ("net/ice: enhance Tx scheduler hierarchy support")
Cc: stable@dpdk.org

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 drivers/net/intel/ice/ice_tm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/intel/ice/ice_tm.c b/drivers/net/intel/ice/ice_tm.c
index 2e6ef9c264f..651d6aa932d 100644
--- a/drivers/net/intel/ice/ice_tm.c
+++ b/drivers/net/intel/ice/ice_tm.c
@@ -848,7 +848,7 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 	const uint16_t new_root_level = pf->tm_conf.hidden_layers;
 	/* count nodes per hw level, not per logical */
 	uint16_t nodes_created_per_level[ICE_TM_MAX_LAYERS] = {0};
-	uint8_t q_lvl = ice_get_leaf_level(pf);
+	uint8_t q_lvl = ice_get_leaf_level(pf) + pf->tm_conf.hidden_layers;
 	uint8_t qg_lvl = q_lvl - 1;
 	struct ice_sched_node *new_vsi_root = hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0];
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 2/4] net/ice: skip TC validation if hierarchy committed
  2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
  2026-09-07 13:07   ` [PATCH v2 1/4] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
@ 2026-09-07 13:07   ` Ciara Loftus
  2026-09-07 13:07   ` [PATCH v2 3/4] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Ciara Loftus @ 2026-09-07 13:07 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus, stable, Bruce Richardson

Currently, ice_tx_queue_start() determines a queue's congestion domain by
scanning vsi->info.tc_mapping[] for a matching traffic class range,
rejecting the queue if no match is found.

The Tx scheduler hierarchies only ever operate on a single traffic class,
TC0, so every queue managed by a committed TM hierarchy always belongs
to domain 0. The tc_mapping[] lookup doesn't account for this, and queues
added after a TM hierarchy is committed can be incorrectly rejected.

Fix this by skipping the lookup if a hierarchy has been committed as the
domain is already known to be 0 in that case. Since TM does not support
DCB's multi-TC queue layout, also reject queue start explicitly if DCB
has configured more than one TC while a TM hierarchy is committed.

Fixes: 02b71e570294 ("net/ice: support DCB")
Cc: stable@dpdk.org

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.c |  4 ++++
 drivers/net/intel/ice/ice_ethdev.h |  2 ++
 drivers/net/intel/ice/ice_rxtx.c   | 33 ++++++++++++++++++------------
 3 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index 76b8ff0a72e..fd148848d3c 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -3963,6 +3963,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
 	ad->rx_func_type = ICE_RX_DEFAULT;
 	ad->tx_func_type = ICE_TX_DEFAULT;
 
+	pf->dcb_num_tcs = 1;
+
 	if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
 		dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
 
@@ -3992,6 +3994,8 @@ ice_dev_configure(struct rte_eth_dev *dev)
 		if (nb_tc_used < 0)
 			return -EINVAL;
 
+		pf->dcb_num_tcs = nb_tc_used;
+
 		ctxt.info = 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");
diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 7ee3ea8a709..5914454c7c2 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -609,6 +609,8 @@ struct ice_pf {
 	uint64_t rss_hf;
 	struct ice_tm_conf tm_conf;
 	uint16_t outer_ethertype;
+	/* Number of TCs requested, 1 if DCB not configured */
+	uint8_t dcb_num_tcs;
 	/* lock prevent race condition between lsc interrupt handler
 	 * and link status update during dev_start.
 	 */
diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
index c4b5454c530..71f9155e588 100644
--- a/drivers/net/intel/ice/ice_rxtx.c
+++ b/drivers/net/intel/ice/ice_rxtx.c
@@ -839,20 +839,27 @@ 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<->CGD */
-	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 (!pf->tm_conf.committed) {
+		/* Mirror RXQ<->CGD association to TXQ<->CGD */
+		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;
 
-	if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
-		PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
+			cgd_idx++;
+		}
+		if (cgd_idx >= ICE_MAX_TRAFFIC_CLASS) {
+			PMD_DRV_LOG(ERR, "Bad queue mapping configuration");
+			rte_free(txq_elem);
+			return -EINVAL;
+		}
+	} else if (pf->dcb_num_tcs > 1) {
+		/* TM only manages the TC0 scheduler subtree. */
+		PMD_DRV_LOG(ERR, "TM hierarchy is not supported together with multi-TC DCB");
 		rte_free(txq_elem);
 		return -EINVAL;
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 3/4] net/ice: fix Rx queue count reporting after TM commit
  2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
  2026-09-07 13:07   ` [PATCH v2 1/4] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
  2026-09-07 13:07   ` [PATCH v2 2/4] net/ice: skip TC validation if hierarchy committed Ciara Loftus
@ 2026-09-07 13:07   ` Ciara Loftus
  2026-09-09 12:45     ` Bruce Richardson
  2026-09-07 13:07   ` [PATCH v2 4/4] net/ice: split VSI queue count into Rx/Tx Ciara Loftus
  2026-09-10 13:20   ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Bruce Richardson
  4 siblings, 1 reply; 17+ messages in thread
From: Ciara Loftus @ 2026-09-07 13:07 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus, stable

Currently, ice_dev_info_get() assigns the value of `vsi->nb_qps` to both
`max_rx_queues` and `max_tx_queues`.

After a Tx scheduler hierarchy is committed, the value of nb_qps may grow
to reflect the VSI's larger Tx scheduler capacity. However the Tx scheduler
hierarchy change has no effect on the VSI's Rx queue allocation,
which stays fixed at its original size for the life of the port. An
application can then request more Rx queues than the VSI's actual Rx
resources support when the inflated nb_qps is assigned to `max_rx_queues`.

`vsi->nb_qps` also feeds `ice_vsi_disable_queues_intr()`, which clears
both Rx and Tx queue interrupt registers by absolute queue index on
every port stop. Once `nb_qps` grows past the VSI's fixed queue window,
this can clear interrupt registers belonging to a different VSI.

Fix this by introducing `vsi->nb_tm_txqs` to track the Tx scheduler
capacity as it grows, leaving `vsi->nb_qps` as the VSI's fixed
queue allocation for the life of the port. `ice_vsi_disable_queues_intr()`
is switched to `nb_used_qps`, which already tracks the actually configured
queue count.

Fixes: 715d449a965b ("net/ice: enhance Tx scheduler hierarchy support")
Cc: stable@dpdk.org

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
v2:
* renamed nb_tm_qps to nb_tm_txqs
---
 drivers/net/intel/ice/ice_ethdev.c | 5 +++--
 drivers/net/intel/ice/ice_ethdev.h | 1 +
 drivers/net/intel/ice/ice_tm.c     | 8 ++++----
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index fd148848d3c..b7ccace623b 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -1816,6 +1816,7 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 				     ret);
 			goto fail_mem;
 		}
+		vsi->nb_tm_txqs = vsi->nb_qps;
 
 		break;
 	case ICE_VSI_CTRL:
@@ -2924,7 +2925,7 @@ ice_vsi_disable_queues_intr(struct ice_vsi *vsi)
 	uint16_t msix_intr, i;
 
 	/* disable interrupt and also clear all the exist config */
-	for (i = 0; i < vsi->nb_qps; i++) {
+	for (i = 0; i < vsi->nb_used_qps; i++) {
 		ICE_WRITE_REG(hw, QINT_TQCTL(vsi->base_queue + i), 0);
 		ICE_WRITE_REG(hw, QINT_RQCTL(vsi->base_queue + i), 0);
 		rte_wmb();
@@ -4628,7 +4629,7 @@ ice_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->min_rx_bufsize = ICE_BUF_SIZE_MIN;
 	dev_info->max_rx_pktlen = ICE_FRAME_SIZE_MAX;
 	dev_info->max_rx_queues = vsi->nb_qps;
-	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_tm_txqs;
 	dev_info->max_mac_addrs = vsi->max_macaddrs;
 	dev_info->max_vfs = pci_dev->max_vfs;
 	dev_info->max_mtu = dev_info->max_rx_pktlen - ICE_ETH_OVERHEAD;
diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 5914454c7c2..f8e18e68f08 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -330,6 +330,7 @@ struct ice_vsi {
 	struct ice_mac_filter_list mac_list; /* macvlan filter list */
 	struct ice_vlan_filter_list vlan_list; /* vlan filter list */
 	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
+	uint16_t nb_tm_txqs;     /* Number of Tx queues usable by the committed TM hierarchy */
 	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
 	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
 	uint16_t base_queue;     /* The first queue index of this VSI */
diff --git a/drivers/net/intel/ice/ice_tm.c b/drivers/net/intel/ice/ice_tm.c
index 651d6aa932d..48bc1f39426 100644
--- a/drivers/net/intel/ice/ice_tm.c
+++ b/drivers/net/intel/ice/ice_tm.c
@@ -859,9 +859,9 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 		}
 		/* TM hierarchy deleted. Restore default scheduler state. */
 		reset_hw_node_recursive(hw, hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0]);
-		pf->main_vsi->nb_qps = pf->lan_nb_qps;
+		pf->main_vsi->nb_tm_txqs = pf->lan_nb_qps;
 		pf->tm_conf.committed = false;
-		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_qps);
+		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_txqs);
 	}
 
 	/* handle case where VSI node needs to move DOWN the hierarchy */
@@ -889,13 +889,13 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 				nodes_created_per_level[i], i);
 	hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0] = new_vsi_root;
 
-	pf->main_vsi->nb_qps =
+	pf->main_vsi->nb_tm_txqs =
 			RTE_MIN(nodes_created_per_level[qg_lvl] * hw->max_children[qg_lvl],
 				hw->layer_info[q_lvl].max_device_nodes);
 
 	pf->tm_conf.committed = true; /* set flag to be checks on queue start */
 
-	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_qps);
+	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_txqs);
 }
 
 static int
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 4/4] net/ice: split VSI queue count into Rx/Tx
  2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
                     ` (2 preceding siblings ...)
  2026-09-07 13:07   ` [PATCH v2 3/4] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
@ 2026-09-07 13:07   ` Ciara Loftus
  2026-09-09 12:47     ` Bruce Richardson
  2026-09-10 13:20   ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Bruce Richardson
  4 siblings, 1 reply; 17+ messages in thread
From: Ciara Loftus @ 2026-09-07 13:07 UTC (permalink / raw)
  To: dev; +Cc: Ciara Loftus

The number of rxqs and txqs ie. "queue pairs" was tracked in a single
variable `vsi->nb_qps` prior to this commit. A second variable `nb_tm_txqs`
was then introduced to track the number of txqs independently of the rxqs,
since the TM hierarchy could grow the number of txqs beyond the initial
symmetric allocation. Since the number of rxqs and txqs can diverge, it
doesn't make much sense to maintain the `vsi->nb_qps` variable anymore.
This commit drops that variable and instead introduces two variables
`vsi->nb_txqs` and `vsi->nb_rxqs` to track txqs and rxqs separately.

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
 drivers/net/intel/ice/ice_ethdev.c | 37 ++++++++++++++----------------
 drivers/net/intel/ice/ice_ethdev.h |  4 ++--
 drivers/net/intel/ice/ice_tm.c     |  8 +++----
 3 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index b7ccace623b..22578c9f28d 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -1002,10 +1002,10 @@ ice_vsi_config_tc_queue_mapping(struct ice_hw *hw, struct ice_vsi *vsi,
 
 	/* vector 0 is reserved and 1 vector for ctrl vsi */
 	if (vsi->adapter->hw.func_caps.common_cap.num_msix_vectors < 2) {
-		vsi->nb_qps = 0;
+		vsi->nb_rxqs = 0;
 	} else {
-		vsi->nb_qps = RTE_MIN(vsi->nb_qps, ICE_MAX_Q_PER_TC);
-		vsi->nb_qps = RTE_MIN(vsi->nb_qps,
+		vsi->nb_rxqs = RTE_MIN(vsi->nb_rxqs, ICE_MAX_Q_PER_TC);
+		vsi->nb_rxqs = RTE_MIN(vsi->nb_rxqs,
 			(uint16_t)vsi->adapter->hw.func_caps.common_cap.num_msix_vectors - 2);
 
 		/* cap max QPs to what the HW reports as num-children for each layer.
@@ -1017,13 +1017,13 @@ ice_vsi_config_tc_queue_mapping(struct ice_hw *hw, struct ice_vsi *vsi,
 		uint32_t max_sched_vsi_nodes = 1;
 		for (uint8_t i = hw->sw_entry_point_layer; i < hw->num_tx_sched_layers - 1; i++) {
 			max_sched_vsi_nodes *= hw->max_children[i];
-			if (max_sched_vsi_nodes >= vsi->nb_qps)
+			if (max_sched_vsi_nodes >= vsi->nb_rxqs)
 				break;
 		}
-		vsi->nb_qps = RTE_MIN(vsi->nb_qps, max_sched_vsi_nodes);
+		vsi->nb_rxqs = RTE_MIN(vsi->nb_rxqs, max_sched_vsi_nodes);
 	}
 
-	/* nb_qps(hex)  -> fls */
+	/* nb_rxqs(hex)  -> fls */
 	/* 0000		-> 0 */
 	/* 0001		-> 0 */
 	/* 0002		-> 1 */
@@ -1034,7 +1034,7 @@ ice_vsi_config_tc_queue_mapping(struct ice_hw *hw, struct ice_vsi *vsi,
 	/* 0021 ~ 0040	-> 6 */
 	/* 0041 ~ 0080	-> 7 */
 	/* 0081 ~ 0100	-> 8 */
-	fls = (vsi->nb_qps == 0) ? 0 : rte_fls_u32(vsi->nb_qps - 1);
+	fls = (vsi->nb_rxqs == 0) ? 0 : rte_fls_u32(vsi->nb_rxqs - 1);
 
 	qp_idx = 0;
 	/* Set tc and queue mapping with VSI */
@@ -1045,7 +1045,7 @@ ice_vsi_config_tc_queue_mapping(struct ice_hw *hw, struct ice_vsi *vsi,
 	/* Associate queue number with VSI */
 	info->mapping_flags |= rte_cpu_to_le_16(ICE_AQ_VSI_Q_MAP_CONTIG);
 	info->q_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
-	info->q_mapping[1] = rte_cpu_to_le_16(vsi->nb_qps);
+	info->q_mapping[1] = rte_cpu_to_le_16(vsi->nb_rxqs);
 	info->valid_sections |=
 		rte_cpu_to_le_16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
 	/* Set the info.ingress_table and info.egress_table
@@ -1753,7 +1753,7 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 	memset(&vsi_ctx, 0, sizeof(vsi_ctx));
 	switch (type) {
 	case ICE_VSI_PF:
-		vsi->nb_qps = pf->lan_nb_qps;
+		vsi->nb_rxqs = pf->lan_nb_qps;
 		vsi->base_queue = 1;
 		ice_vsi_config_default_rss(&vsi_ctx.info);
 		vsi_ctx.alloc_from_pool = true;
@@ -1816,11 +1816,11 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 				     ret);
 			goto fail_mem;
 		}
-		vsi->nb_tm_txqs = vsi->nb_qps;
+		vsi->nb_txqs = vsi->nb_rxqs;
 
 		break;
 	case ICE_VSI_CTRL:
-		vsi->nb_qps = pf->fdir_nb_qps;
+		vsi->nb_rxqs = pf->fdir_nb_qps;
 		vsi->base_queue = ICE_FDIR_QUEUE_ID;
 		vsi_ctx.alloc_from_pool = true;
 		vsi_ctx.flags = ICE_AQ_VSI_TYPE_PF;
@@ -1841,6 +1841,7 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 				     ret);
 			goto fail_mem;
 		}
+		vsi->nb_txqs = vsi->nb_rxqs;
 		break;
 	default:
 		/* for other types of VSI */
@@ -1851,14 +1852,14 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 	/* VF has MSIX interrupt in VF range, don't allocate here */
 	if (type == ICE_VSI_PF) {
 		ret = ice_res_pool_alloc(&pf->msix_pool,
-					 RTE_MIN(vsi->nb_qps,
+					 RTE_MIN(vsi->nb_rxqs,
 						 RTE_MAX_RXTX_INTR_VEC_ID));
 		if (ret < 0) {
 			PMD_INIT_LOG(ERR, "VSI MAIN %d get heap failed %d",
 				     vsi->vsi_id, ret);
 		}
 		vsi->msix_intr = ret;
-		vsi->nb_msix = RTE_MIN(vsi->nb_qps, RTE_MAX_RXTX_INTR_VEC_ID);
+		vsi->nb_msix = RTE_MIN(vsi->nb_rxqs, RTE_MAX_RXTX_INTR_VEC_ID);
 	} else if (type == ICE_VSI_CTRL) {
 		ret = ice_res_pool_alloc(&pf->msix_pool, 1);
 		if (ret < 0) {
@@ -1900,11 +1901,7 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 	}
 
 	/* At the beginning, only TC0. */
-	/* What we need here is the maximum number of the TX queues.
-	 * Currently vsi->nb_qps means it.
-	 * Correct it if any change.
-	 */
-	max_txqs[0] = vsi->nb_qps;
+	max_txqs[0] = vsi->nb_txqs;
 	ret = ice_cfg_vsi_lan(hw->port_info, vsi->idx,
 			      tc_bitmap, max_txqs);
 	if (ret != ICE_SUCCESS)
@@ -4628,8 +4625,8 @@ ice_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
 	dev_info->min_rx_bufsize = ICE_BUF_SIZE_MIN;
 	dev_info->max_rx_pktlen = ICE_FRAME_SIZE_MAX;
-	dev_info->max_rx_queues = vsi->nb_qps;
-	dev_info->max_tx_queues = vsi->nb_tm_txqs;
+	dev_info->max_rx_queues = vsi->nb_rxqs;
+	dev_info->max_tx_queues = vsi->nb_txqs;
 	dev_info->max_mac_addrs = vsi->max_macaddrs;
 	dev_info->max_vfs = pci_dev->max_vfs;
 	dev_info->max_mtu = dev_info->max_rx_pktlen - ICE_ETH_OVERHEAD;
diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index f8e18e68f08..1d038016afc 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -329,8 +329,8 @@ struct ice_vsi {
 	uint16_t mac_num;        /* Total mac number */
 	struct ice_mac_filter_list mac_list; /* macvlan filter list */
 	struct ice_vlan_filter_list vlan_list; /* vlan filter list */
-	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
-	uint16_t nb_tm_txqs;     /* Number of Tx queues usable by the committed TM hierarchy */
+	uint16_t nb_rxqs;        /* Number of Rx queues VSI can occupy */
+	uint16_t nb_txqs;        /* Number of Tx queues VSI can occupy, grows with TM hierarchy */
 	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
 	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
 	uint16_t base_queue;     /* The first queue index of this VSI */
diff --git a/drivers/net/intel/ice/ice_tm.c b/drivers/net/intel/ice/ice_tm.c
index 48bc1f39426..d93704dd3f9 100644
--- a/drivers/net/intel/ice/ice_tm.c
+++ b/drivers/net/intel/ice/ice_tm.c
@@ -859,9 +859,9 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 		}
 		/* TM hierarchy deleted. Restore default scheduler state. */
 		reset_hw_node_recursive(hw, hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0]);
-		pf->main_vsi->nb_tm_txqs = pf->lan_nb_qps;
+		pf->main_vsi->nb_txqs = pf->lan_nb_qps;
 		pf->tm_conf.committed = false;
-		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_txqs);
+		return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_txqs);
 	}
 
 	/* handle case where VSI node needs to move DOWN the hierarchy */
@@ -889,13 +889,13 @@ commit_new_hierarchy(struct rte_eth_dev *dev)
 				nodes_created_per_level[i], i);
 	hw->vsi_ctx[pf->main_vsi->idx]->sched.vsi_node[0] = new_vsi_root;
 
-	pf->main_vsi->nb_tm_txqs =
+	pf->main_vsi->nb_txqs =
 			RTE_MIN(nodes_created_per_level[qg_lvl] * hw->max_children[qg_lvl],
 				hw->layer_info[q_lvl].max_device_nodes);
 
 	pf->tm_conf.committed = true; /* set flag to be checks on queue start */
 
-	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_tm_txqs);
+	return ice_alloc_lan_q_ctx(hw, 0, 0, pf->main_vsi->nb_txqs);
 }
 
 static int
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 3/4] net/ice: fix Rx queue count reporting after TM commit
  2026-09-07 13:07   ` [PATCH v2 3/4] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
@ 2026-09-09 12:45     ` Bruce Richardson
  0 siblings, 0 replies; 17+ messages in thread
From: Bruce Richardson @ 2026-09-09 12:45 UTC (permalink / raw)
  To: Ciara Loftus; +Cc: dev, stable

On Mon, Sep 07, 2026 at 01:07:49PM +0000, Ciara Loftus wrote:
> Currently, ice_dev_info_get() assigns the value of `vsi->nb_qps` to both
> `max_rx_queues` and `max_tx_queues`.
> 
> After a Tx scheduler hierarchy is committed, the value of nb_qps may grow
> to reflect the VSI's larger Tx scheduler capacity. However the Tx scheduler
> hierarchy change has no effect on the VSI's Rx queue allocation,
> which stays fixed at its original size for the life of the port. An
> application can then request more Rx queues than the VSI's actual Rx
> resources support when the inflated nb_qps is assigned to `max_rx_queues`.
> 
> `vsi->nb_qps` also feeds `ice_vsi_disable_queues_intr()`, which clears
> both Rx and Tx queue interrupt registers by absolute queue index on
> every port stop. Once `nb_qps` grows past the VSI's fixed queue window,
> this can clear interrupt registers belonging to a different VSI.
> 
> Fix this by introducing `vsi->nb_tm_txqs` to track the Tx scheduler
> capacity as it grows, leaving `vsi->nb_qps` as the VSI's fixed
> queue allocation for the life of the port. `ice_vsi_disable_queues_intr()`
> is switched to `nb_used_qps`, which already tracks the actually configured
> queue count.
> 
> Fixes: 715d449a965b ("net/ice: enhance Tx scheduler hierarchy support")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
> v2:
> * renamed nb_tm_qps to nb_tm_txqs
> ---
>  drivers/net/intel/ice/ice_ethdev.c | 5 +++--
>  drivers/net/intel/ice/ice_ethdev.h | 1 +
>  drivers/net/intel/ice/ice_tm.c     | 8 ++++----
>  3 files changed, 8 insertions(+), 6 deletions(-)
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 4/4] net/ice: split VSI queue count into Rx/Tx
  2026-09-07 13:07   ` [PATCH v2 4/4] net/ice: split VSI queue count into Rx/Tx Ciara Loftus
@ 2026-09-09 12:47     ` Bruce Richardson
  0 siblings, 0 replies; 17+ messages in thread
From: Bruce Richardson @ 2026-09-09 12:47 UTC (permalink / raw)
  To: Ciara Loftus; +Cc: dev

On Mon, Sep 07, 2026 at 01:07:50PM +0000, Ciara Loftus wrote:
> The number of rxqs and txqs ie. "queue pairs" was tracked in a single
> variable `vsi->nb_qps` prior to this commit. A second variable `nb_tm_txqs`
> was then introduced to track the number of txqs independently of the rxqs,
> since the TM hierarchy could grow the number of txqs beyond the initial
> symmetric allocation. Since the number of rxqs and txqs can diverge, it
> doesn't make much sense to maintain the `vsi->nb_qps` variable anymore.
> This commit drops that variable and instead introduces two variables
> `vsi->nb_txqs` and `vsi->nb_rxqs` to track txqs and rxqs separately.
> 
> Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
> ---
>  drivers/net/intel/ice/ice_ethdev.c | 37 ++++++++++++++----------------
>  drivers/net/intel/ice/ice_ethdev.h |  4 ++--
>  drivers/net/intel/ice/ice_tm.c     |  8 +++----
>  3 files changed, 23 insertions(+), 26 deletions(-)
> 
Acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting
  2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
                     ` (3 preceding siblings ...)
  2026-09-07 13:07   ` [PATCH v2 4/4] net/ice: split VSI queue count into Rx/Tx Ciara Loftus
@ 2026-09-10 13:20   ` Bruce Richardson
  4 siblings, 0 replies; 17+ messages in thread
From: Bruce Richardson @ 2026-09-10 13:20 UTC (permalink / raw)
  To: Ciara Loftus; +Cc: dev

On Mon, Sep 07, 2026 at 01:07:46PM +0000, Ciara Loftus wrote:
> Committing a Tx scheduler (rte_tm) hierarchy on ice can grow the port's
> usable Tx queue count beyond what was available when the port was first
> probed. This series fixes three bugs related to this, and makes a
> cosmetic change by renaming variables related to queue counting.
> 
> v2:
> * Variable renaming in patch 3 nb_tm_qps -> nb_tm_txqs
> * Added a forth patch to split VSI qps variable into separate Rx/Tx
> varaibles
> 
> Ciara Loftus (4):
>   net/ice: fix Tx queue capacity sizing after TM commit
>   net/ice: skip TC validation if hierarchy committed
>   net/ice: fix Rx queue count reporting after TM commit
>   net/ice: split VSI queue count into Rx/Tx
> 
Series applied to dpdk-next-net-intel.
Thanks,
/Bruce

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-09-10 13:20 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-04 10:51 [PATCH 0/3] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
2026-09-04 10:51 ` [PATCH 1/3] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
2026-09-04 13:01   ` Bruce Richardson
2026-09-04 10:51 ` [PATCH 2/3] net/ice: skip TC validation if hierarchy committed Ciara Loftus
2026-09-04 13:11   ` Bruce Richardson
2026-09-07 11:14     ` Loftus, Ciara
2026-09-04 10:51 ` [PATCH 3/3] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
2026-09-04 13:33   ` Bruce Richardson
2026-09-07 11:16     ` Loftus, Ciara
2026-09-07 13:07 ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Ciara Loftus
2026-09-07 13:07   ` [PATCH v2 1/4] net/ice: fix Tx queue capacity sizing after TM commit Ciara Loftus
2026-09-07 13:07   ` [PATCH v2 2/4] net/ice: skip TC validation if hierarchy committed Ciara Loftus
2026-09-07 13:07   ` [PATCH v2 3/4] net/ice: fix Rx queue count reporting after TM commit Ciara Loftus
2026-09-09 12:45     ` Bruce Richardson
2026-09-07 13:07   ` [PATCH v2 4/4] net/ice: split VSI queue count into Rx/Tx Ciara Loftus
2026-09-09 12:47     ` Bruce Richardson
2026-09-10 13:20   ` [PATCH v2 0/4] net/ice: fix Tx scheduler hierarchy queue accounting Bruce Richardson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox