DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/6] net/hns3: VF support multi-TCs
@ 2025-06-11  8:18 Dengdui Huang
  2025-06-11  8:18 ` [PATCH 1/6] net/hns3: fix VF fail to config queue TC Dengdui Huang
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Dengdui Huang @ 2025-06-11  8:18 UTC (permalink / raw)
  To: dev; +Cc: stephen, lihuisong, fengchengwen, liuyonglong

This patchset adds the VF multi-TCs feature.

Chengwen Feng (6):
  net/hns3: fix VF fail to config queue TC
  net/hns3: remove duplicate struct field
  net/hns3: refactor DCB module code
  net/hns3: VF support parse max TC number
  net/hns3: VF support discover multi-TCs capability
  net/hns3: VF support multi-TCs configure

 drivers/net/hns3/hns3_cmd.c       |   5 +-
 drivers/net/hns3/hns3_cmd.h       |  10 +
 drivers/net/hns3/hns3_dcb.c       | 161 ++++++++++++----
 drivers/net/hns3/hns3_dcb.h       |   4 +
 drivers/net/hns3/hns3_dump.c      |  11 +-
 drivers/net/hns3/hns3_ethdev.c    | 132 ++-----------
 drivers/net/hns3/hns3_ethdev.h    |  12 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 297 ++++++++++++++++++++++++++++--
 drivers/net/hns3/hns3_mbx.h       |  50 ++++-
 drivers/net/hns3/hns3_rss.c       |   8 +-
 drivers/net/hns3/hns3_rxtx.c      |  26 ++-
 drivers/net/hns3/hns3_tm.c        |   6 +-
 12 files changed, 539 insertions(+), 183 deletions(-)

-- 
2.33.0


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

* [PATCH 1/6] net/hns3: fix VF fail to config queue TC
  2025-06-11  8:18 [PATCH 0/6] net/hns3: VF support multi-TCs Dengdui Huang
@ 2025-06-11  8:18 ` Dengdui Huang
  2025-06-11  8:18 ` [PATCH 2/6] net/hns3: remove duplicate struct field Dengdui Huang
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dengdui Huang @ 2025-06-11  8:18 UTC (permalink / raw)
  To: dev; +Cc: stephen, lihuisong, fengchengwen, liuyonglong

From: Chengwen Feng <fengchengwen@huawei.com>

The VF cannot configure the mapping of queue to TC by directly writing
the register. Instead, the mapping must be modified by using firmware
command.

Fixes: bba636698316 ("net/hns3: support Rx/Tx and related operations")
Cc: stable@dpdk.org

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
 drivers/net/hns3/hns3_cmd.h  |  8 ++++++++
 drivers/net/hns3/hns3_rxtx.c | 26 +++++++++++++++++++++-----
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 4d707c13b2..e21a2b652f 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -178,6 +178,7 @@ enum hns3_opcode_type {
 
 	/* TQP commands */
 	HNS3_OPC_QUERY_TX_STATUS        = 0x0B03,
+	HNS3_OPC_TQP_TX_QUEUE_TC        = 0x0B04,
 	HNS3_OPC_QUERY_RX_STATUS        = 0x0B13,
 	HNS3_OPC_CFG_COM_TQP_QUEUE      = 0x0B20,
 	HNS3_OPC_RESET_TQP_QUEUE        = 0x0B22,
@@ -970,6 +971,13 @@ struct hns3_reset_tqp_queue_cmd {
 	uint8_t rsv[19];
 };
 
+struct hns3vf_tx_ring_tc_cmd {
+	uint16_t tqp_id;
+	uint16_t rsv1;
+	uint8_t  tc_id;
+	uint8_t  rsv2[19];
+};
+
 #define HNS3_CFG_RESET_MAC_B		3
 #define HNS3_CFG_RESET_FUNC_B		7
 #define HNS3_CFG_RESET_RCB_B		1
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index f9fde3948a..785e06db9c 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -1180,12 +1180,14 @@ hns3_init_txq(struct hns3_tx_queue *txq)
 	hns3_init_tx_queue_hw(txq);
 }
 
-static void
+static int
 hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 {
+	struct hns3_cmd_desc desc;
+	struct hns3vf_tx_ring_tc_cmd *req = (struct hns3vf_tx_ring_tc_cmd *)desc.data;
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_tx_queue *txq;
-	int i, num;
+	int i, num, ret;
 
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
 		struct hns3_tc_queue_info *tc_queue = &hw->tc_queue[i];
@@ -1200,9 +1202,24 @@ hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 			if (txq == NULL)
 				continue;
 
-			hns3_write_dev(txq, HNS3_RING_TX_TC_REG, tc_queue->tc);
+			if (!hns->is_vf) {
+				hns3_write_dev(txq, HNS3_RING_TX_TC_REG, tc_queue->tc);
+				continue;
+			}
+
+			hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TQP_TX_QUEUE_TC, false);
+			req->tqp_id = rte_cpu_to_le_16(num);
+			req->tc_id  = tc_queue->tc;
+			ret = hns3_cmd_send(hw, &desc, 1);
+			if (ret != 0) {
+				hns3_err(hw, "config Tx queue (%u)'s TC failed! ret = %d.",
+					 num, ret);
+				return ret;
+			}
 		}
 	}
+
+	return 0;
 }
 
 static int
@@ -1278,9 +1295,8 @@ hns3_init_tx_queues(struct hns3_adapter *hns)
 		txq = (struct hns3_tx_queue *)hw->fkq_data.tx_queues[i];
 		hns3_init_txq(txq);
 	}
-	hns3_init_tx_ring_tc(hns);
 
-	return 0;
+	return hns3_init_tx_ring_tc(hns);
 }
 
 /*
-- 
2.33.0


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

* [PATCH 2/6] net/hns3: remove duplicate struct field
  2025-06-11  8:18 [PATCH 0/6] net/hns3: VF support multi-TCs Dengdui Huang
  2025-06-11  8:18 ` [PATCH 1/6] net/hns3: fix VF fail to config queue TC Dengdui Huang
@ 2025-06-11  8:18 ` Dengdui Huang
  2025-06-11  8:18 ` [PATCH 3/6] net/hns3: refactor DCB module code Dengdui Huang
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dengdui Huang @ 2025-06-11  8:18 UTC (permalink / raw)
  To: dev; +Cc: stephen, lihuisong, fengchengwen, liuyonglong

From: Chengwen Feng <fengchengwen@huawei.com>

The struct hns3_hw and hns3_hw.dcb_info both has num_tc field, their
meanings are the same, to ensure code readability, remove the num_tc
field of struct hns3_hw.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
 drivers/net/hns3/hns3_dcb.c       | 44 ++++++++++++-------------------
 drivers/net/hns3/hns3_dump.c      |  2 +-
 drivers/net/hns3/hns3_ethdev.c    |  4 +--
 drivers/net/hns3/hns3_ethdev.h    |  3 +--
 drivers/net/hns3/hns3_ethdev_vf.c |  2 +-
 drivers/net/hns3/hns3_tm.c        |  6 ++---
 6 files changed, 25 insertions(+), 36 deletions(-)

diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index 2f917fef9e..88c6242d66 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -623,7 +623,7 @@ hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q)
 	uint16_t used_rx_queues;
 	uint16_t i;
 
-	rx_qnum_per_tc = nb_rx_q / hw->num_tc;
+	rx_qnum_per_tc = nb_rx_q / hw->dcb_info.num_tc;
 	if (rx_qnum_per_tc > hw->rss_size_max) {
 		hns3_err(hw, "rx queue number of per tc (%u) is greater than "
 			 "value (%u) hardware supported.",
@@ -631,11 +631,11 @@ hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q)
 		return -EINVAL;
 	}
 
-	used_rx_queues = hw->num_tc * rx_qnum_per_tc;
+	used_rx_queues = hw->dcb_info.num_tc * rx_qnum_per_tc;
 	if (used_rx_queues != nb_rx_q) {
 		hns3_err(hw, "rx queue number (%u) configured must be an "
 			 "integral multiple of valid tc number (%u).",
-			 nb_rx_q, hw->num_tc);
+			 nb_rx_q, hw->dcb_info.num_tc);
 		return -EINVAL;
 	}
 	hw->alloc_rss_size = rx_qnum_per_tc;
@@ -665,12 +665,12 @@ hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_tx_q)
 	uint16_t tx_qnum_per_tc;
 	uint8_t i;
 
-	tx_qnum_per_tc = nb_tx_q / hw->num_tc;
-	used_tx_queues = hw->num_tc * tx_qnum_per_tc;
+	tx_qnum_per_tc = nb_tx_q / hw->dcb_info.num_tc;
+	used_tx_queues = hw->dcb_info.num_tc * tx_qnum_per_tc;
 	if (used_tx_queues != nb_tx_q) {
 		hns3_err(hw, "tx queue number (%u) configured must be an "
 			 "integral multiple of valid tc number (%u).",
-			 nb_tx_q, hw->num_tc);
+			 nb_tx_q, hw->dcb_info.num_tc);
 		return -EINVAL;
 	}
 
@@ -678,7 +678,7 @@ hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_tx_q)
 	hw->tx_qnum_per_tc = tx_qnum_per_tc;
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
 		tc_queue = &hw->tc_queue[i];
-		if (hw->hw_tc_map & BIT(i) && i < hw->num_tc) {
+		if (hw->hw_tc_map & BIT(i) && i < hw->dcb_info.num_tc) {
 			tc_queue->enable = true;
 			tc_queue->tqp_offset = i * hw->tx_qnum_per_tc;
 			tc_queue->tqp_count = hw->tx_qnum_per_tc;
@@ -720,15 +720,15 @@ hns3_queue_to_tc_mapping(struct hns3_hw *hw, uint16_t nb_rx_q, uint16_t nb_tx_q)
 {
 	int ret;
 
-	if (nb_rx_q < hw->num_tc) {
+	if (nb_rx_q < hw->dcb_info.num_tc) {
 		hns3_err(hw, "number of Rx queues(%u) is less than number of TC(%u).",
-			 nb_rx_q, hw->num_tc);
+			 nb_rx_q, hw->dcb_info.num_tc);
 		return -EINVAL;
 	}
 
-	if (nb_tx_q < hw->num_tc) {
+	if (nb_tx_q < hw->dcb_info.num_tc) {
 		hns3_err(hw, "number of Tx queues(%u) is less than number of TC(%u).",
-			 nb_tx_q, hw->num_tc);
+			 nb_tx_q, hw->dcb_info.num_tc);
 		return -EINVAL;
 	}
 
@@ -739,15 +739,6 @@ hns3_queue_to_tc_mapping(struct hns3_hw *hw, uint16_t nb_rx_q, uint16_t nb_tx_q)
 	return hns3_tc_queue_mapping_cfg(hw, nb_tx_q);
 }
 
-static int
-hns3_dcb_update_tc_queue_mapping(struct hns3_hw *hw, uint16_t nb_rx_q,
-				 uint16_t nb_tx_q)
-{
-	hw->num_tc = hw->dcb_info.num_tc;
-
-	return hns3_queue_to_tc_mapping(hw, nb_rx_q, nb_tx_q);
-}
-
 int
 hns3_dcb_info_init(struct hns3_hw *hw)
 {
@@ -1028,7 +1019,7 @@ hns3_q_to_qs_map(struct hns3_hw *hw)
 	uint32_t i, j;
 	int ret;
 
-	for (i = 0; i < hw->num_tc; i++) {
+	for (i = 0; i < hw->dcb_info.num_tc; i++) {
 		tc_queue = &hw->tc_queue[i];
 		for (j = 0; j < tc_queue->tqp_count; j++) {
 			q_id = tc_queue->tqp_offset + j;
@@ -1053,7 +1044,7 @@ hns3_pri_q_qs_cfg(struct hns3_hw *hw)
 		return -EINVAL;
 
 	/* Cfg qs -> pri mapping */
-	for (i = 0; i < hw->num_tc; i++) {
+	for (i = 0; i < hw->dcb_info.num_tc; i++) {
 		ret = hns3_qs_to_pri_map_cfg(hw, i, i);
 		if (ret) {
 			hns3_err(hw, "qs_to_pri mapping fail: %d", ret);
@@ -1448,8 +1439,8 @@ hns3_dcb_info_cfg(struct hns3_adapter *hns)
 	for (i = 0; i < HNS3_MAX_USER_PRIO; i++)
 		hw->dcb_info.prio_tc[i] = dcb_rx_conf->dcb_tc[i];
 
-	ret = hns3_dcb_update_tc_queue_mapping(hw, hw->data->nb_rx_queues,
-					       hw->data->nb_tx_queues);
+	ret = hns3_queue_to_tc_mapping(hw, hw->data->nb_rx_queues,
+				       hw->data->nb_tx_queues);
 	if (ret)
 		hns3_err(hw, "update tc queue mapping failed, ret = %d.", ret);
 
@@ -1635,8 +1626,7 @@ hns3_dcb_init(struct hns3_hw *hw)
 		 */
 		default_tqp_num = RTE_MIN(hw->rss_size_max,
 					  hw->tqps_num / hw->dcb_info.num_tc);
-		ret = hns3_dcb_update_tc_queue_mapping(hw, default_tqp_num,
-						       default_tqp_num);
+		ret = hns3_queue_to_tc_mapping(hw, default_tqp_num, default_tqp_num);
 		if (ret) {
 			hns3_err(hw,
 				 "update tc queue mapping failed, ret = %d.",
@@ -1673,7 +1663,7 @@ hns3_update_queue_map_configure(struct hns3_adapter *hns)
 	if ((uint32_t)mq_mode & RTE_ETH_MQ_RX_DCB_FLAG)
 		return 0;
 
-	ret = hns3_dcb_update_tc_queue_mapping(hw, nb_rx_q, nb_tx_q);
+	ret = hns3_queue_to_tc_mapping(hw, nb_rx_q, nb_tx_q);
 	if (ret) {
 		hns3_err(hw, "failed to update tc queue mapping, ret = %d.",
 			 ret);
diff --git a/drivers/net/hns3/hns3_dump.c b/drivers/net/hns3/hns3_dump.c
index f21d32e6a2..6c43ec486e 100644
--- a/drivers/net/hns3/hns3_dump.c
+++ b/drivers/net/hns3/hns3_dump.c
@@ -914,7 +914,7 @@ hns3_is_link_fc_mode(struct hns3_adapter *hns)
 	if (hw->current_fc_status == HNS3_FC_STATUS_PFC)
 		return false;
 
-	if (hw->num_tc > 1 && !pf->support_multi_tc_pause)
+	if (hw->dcb_info.num_tc > 1 && !pf->support_multi_tc_pause)
 		return false;
 
 	return true;
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 50c6ed0744..6b8fd3383a 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -5432,7 +5432,7 @@ hns3_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 		return -EOPNOTSUPP;
 	}
 
-	if (hw->num_tc > 1 && !pf->support_multi_tc_pause) {
+	if (hw->dcb_info.num_tc > 1 && !pf->support_multi_tc_pause) {
 		hns3_err(hw, "in multi-TC scenarios, MAC pause is not supported.");
 		return -EOPNOTSUPP;
 	}
@@ -5509,7 +5509,7 @@ hns3_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
 	for (i = 0; i < dcb_info->nb_tcs; i++)
 		dcb_info->tc_bws[i] = hw->dcb_info.pg_info[0].tc_dwrr[i];
 
-	for (i = 0; i < hw->num_tc; i++) {
+	for (i = 0; i < hw->dcb_info.num_tc; i++) {
 		dcb_info->tc_queue.tc_rxq[0][i].base = hw->alloc_rss_size * i;
 		dcb_info->tc_queue.tc_txq[0][i].base =
 						hw->tc_queue[i].tqp_offset;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index d164b9e38c..e4160f6eae 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -130,7 +130,7 @@ struct hns3_tc_info {
 };
 
 struct hns3_dcb_info {
-	uint8_t num_tc;
+	uint8_t num_tc;     /* Total number of enabled TCs */
 	uint8_t num_pg;     /* It must be 1 if vNET-Base schd */
 	uint8_t pg_dwrr[HNS3_PG_NUM];
 	uint8_t prio_tc[HNS3_MAX_USER_PRIO];
@@ -534,7 +534,6 @@ struct hns3_hw {
 	uint16_t rss_ind_tbl_size;
 	uint16_t rss_key_size;
 
-	uint8_t num_tc;             /* Total number of enabled TCs */
 	uint8_t hw_tc_map;
 	enum hns3_fc_mode requested_fc_mode; /* FC mode requested by user */
 	struct hns3_dcb_info dcb_info;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index ea9225cd26..5f4ae1d979 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -854,7 +854,7 @@ hns3vf_get_basic_info(struct hns3_hw *hw)
 
 	basic_info = (struct hns3_basic_info *)resp_msg;
 	hw->hw_tc_map = basic_info->hw_tc_map;
-	hw->num_tc = hns3vf_get_num_tc(hw);
+	hw->dcb_info.num_tc = hns3vf_get_num_tc(hw);
 	hw->pf_vf_if_version = basic_info->pf_vf_if_version;
 	hns3vf_update_caps(hw, basic_info->caps);
 
diff --git a/drivers/net/hns3/hns3_tm.c b/drivers/net/hns3/hns3_tm.c
index 1c2ad71133..fe97b4ab92 100644
--- a/drivers/net/hns3/hns3_tm.c
+++ b/drivers/net/hns3/hns3_tm.c
@@ -519,13 +519,13 @@ hns3_tm_tc_node_add(struct rte_eth_dev *dev, uint32_t node_id,
 
 	if (node_id >= pf->tm_conf.nb_nodes_max - 1 ||
 	    node_id < pf->tm_conf.nb_leaf_nodes_max ||
-	    hns3_tm_calc_node_tc_no(&pf->tm_conf, node_id) >= hw->num_tc) {
+	    hns3_tm_calc_node_tc_no(&pf->tm_conf, node_id) >= hw->dcb_info.num_tc) {
 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
 		error->message = "invalid tc node ID";
 		return -EINVAL;
 	}
 
-	if (pf->tm_conf.nb_tc_node >= hw->num_tc) {
+	if (pf->tm_conf.nb_tc_node >= hw->dcb_info.num_tc) {
 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
 		error->message = "too many TCs";
 		return -EINVAL;
@@ -974,7 +974,7 @@ hns3_tm_configure_check(struct hns3_hw *hw, struct rte_tm_error *error)
 		}
 
 		if (hns3_tm_calc_node_tc_no(tm_conf, tm_node->id) >=
-			hw->num_tc) {
+			hw->dcb_info.num_tc) {
 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
 			error->message = "node's TC not exist";
 			return false;
-- 
2.33.0


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

* [PATCH 3/6] net/hns3: refactor DCB module code
  2025-06-11  8:18 [PATCH 0/6] net/hns3: VF support multi-TCs Dengdui Huang
  2025-06-11  8:18 ` [PATCH 1/6] net/hns3: fix VF fail to config queue TC Dengdui Huang
  2025-06-11  8:18 ` [PATCH 2/6] net/hns3: remove duplicate struct field Dengdui Huang
@ 2025-06-11  8:18 ` Dengdui Huang
  2025-06-11  8:18 ` [PATCH 4/6] net/hns3: VF support parse max TC number Dengdui Huang
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dengdui Huang @ 2025-06-11  8:18 UTC (permalink / raw)
  To: dev; +Cc: stephen, lihuisong, fengchengwen, liuyonglong

From: Chengwen Feng <fengchengwen@huawei.com>

The DCB-related fields span in multiple structures, this patch moves
them into struct hns3_dcb_info.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
 drivers/net/hns3/hns3_dcb.c       | 13 +++++------
 drivers/net/hns3/hns3_ethdev.c    | 38 +++++++++++++++----------------
 drivers/net/hns3/hns3_ethdev.h    |  8 +++----
 drivers/net/hns3/hns3_ethdev_vf.c |  4 ++--
 drivers/net/hns3/hns3_rss.c       |  8 +++----
 5 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index 88c6242d66..9a1f4120d0 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -678,7 +678,7 @@ hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_tx_q)
 	hw->tx_qnum_per_tc = tx_qnum_per_tc;
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
 		tc_queue = &hw->tc_queue[i];
-		if (hw->hw_tc_map & BIT(i) && i < hw->dcb_info.num_tc) {
+		if (hw->dcb_info.hw_tc_map & BIT(i) && i < hw->dcb_info.num_tc) {
 			tc_queue->enable = true;
 			tc_queue->tqp_offset = i * hw->tx_qnum_per_tc;
 			tc_queue->tqp_count = hw->tx_qnum_per_tc;
@@ -762,7 +762,7 @@ hns3_dcb_info_init(struct hns3_hw *hw)
 		if (i != 0)
 			continue;
 
-		hw->dcb_info.pg_info[i].tc_bit_map = hw->hw_tc_map;
+		hw->dcb_info.pg_info[i].tc_bit_map = hw->dcb_info.hw_tc_map;
 		for (k = 0; k < hw->dcb_info.num_tc; k++)
 			hw->dcb_info.pg_info[i].tc_dwrr[k] = BW_MAX_PERCENT;
 	}
@@ -1395,15 +1395,14 @@ static int
 hns3_dcb_info_cfg(struct hns3_adapter *hns)
 {
 	struct rte_eth_dcb_rx_conf *dcb_rx_conf;
-	struct hns3_pf *pf = &hns->pf;
 	struct hns3_hw *hw = &hns->hw;
 	uint8_t tc_bw, bw_rest;
 	uint8_t i, j;
 	int ret;
 
 	dcb_rx_conf = &hw->data->dev_conf.rx_adv_conf.dcb_rx_conf;
-	pf->local_max_tc = (uint8_t)dcb_rx_conf->nb_tcs;
-	pf->pfc_max = (uint8_t)dcb_rx_conf->nb_tcs;
+	hw->dcb_info.local_max_tc = (uint8_t)dcb_rx_conf->nb_tcs;
+	hw->dcb_info.pfc_max = (uint8_t)dcb_rx_conf->nb_tcs;
 
 	/* Config pg0 */
 	memset(hw->dcb_info.pg_info, 0,
@@ -1412,7 +1411,7 @@ hns3_dcb_info_cfg(struct hns3_adapter *hns)
 	hw->dcb_info.pg_info[0].pg_id = 0;
 	hw->dcb_info.pg_info[0].pg_sch_mode = HNS3_SCH_MODE_DWRR;
 	hw->dcb_info.pg_info[0].bw_limit = hw->max_tm_rate;
-	hw->dcb_info.pg_info[0].tc_bit_map = hw->hw_tc_map;
+	hw->dcb_info.pg_info[0].tc_bit_map = hw->dcb_info.hw_tc_map;
 
 	/* Each tc has same bw for valid tc by default */
 	tc_bw = BW_MAX_PERCENT / hw->dcb_info.num_tc;
@@ -1482,7 +1481,7 @@ hns3_dcb_info_update(struct hns3_adapter *hns, uint8_t num_tc)
 		bit_map = 1;
 		hw->dcb_info.num_tc = 1;
 	}
-	hw->hw_tc_map = bit_map;
+	hw->dcb_info.hw_tc_map = bit_map;
 
 	return hns3_dcb_info_cfg(hns);
 }
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 6b8fd3383a..5af11d9228 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -1876,7 +1876,6 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 	enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode;
 	enum rte_eth_tx_mq_mode tx_mq_mode = dev->data->dev_conf.txmode.mq_mode;
 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	struct rte_eth_dcb_rx_conf *dcb_rx_conf;
 	struct rte_eth_dcb_tx_conf *dcb_tx_conf;
 	uint8_t num_tc;
@@ -1894,9 +1893,9 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 	dcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
 	dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
 	if ((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
-		if (dcb_rx_conf->nb_tcs > pf->tc_max) {
+		if (dcb_rx_conf->nb_tcs > hw->dcb_info.tc_max) {
 			hns3_err(hw, "nb_tcs(%u) > max_tc(%u) driver supported.",
-				 dcb_rx_conf->nb_tcs, pf->tc_max);
+				 dcb_rx_conf->nb_tcs, hw->dcb_info.tc_max);
 			return -EINVAL;
 		}
 
@@ -2837,25 +2836,25 @@ hns3_get_board_configuration(struct hns3_hw *hw)
 		return ret;
 	}
 
-	pf->tc_max = cfg.tc_num;
-	if (pf->tc_max > HNS3_MAX_TC_NUM || pf->tc_max < 1) {
+	hw->dcb_info.tc_max = cfg.tc_num;
+	if (hw->dcb_info.tc_max > HNS3_MAX_TC_NUM || hw->dcb_info.tc_max < 1) {
 		PMD_INIT_LOG(WARNING,
 			     "Get TC num(%u) from flash, set TC num to 1",
-			     pf->tc_max);
-		pf->tc_max = 1;
+			     hw->dcb_info.tc_max);
+		hw->dcb_info.tc_max = 1;
 	}
 
 	/* Dev does not support DCB */
 	if (!hns3_dev_get_support(hw, DCB)) {
-		pf->tc_max = 1;
-		pf->pfc_max = 0;
+		hw->dcb_info.tc_max = 1;
+		hw->dcb_info.pfc_max = 0;
 	} else
-		pf->pfc_max = pf->tc_max;
+		hw->dcb_info.pfc_max = hw->dcb_info.tc_max;
 
 	hw->dcb_info.num_tc = 1;
 	hw->alloc_rss_size = RTE_MIN(hw->rss_size_max,
 				     hw->tqps_num / hw->dcb_info.num_tc);
-	hns3_set_bit(hw->hw_tc_map, 0, 1);
+	hns3_set_bit(hw->dcb_info.hw_tc_map, 0, 1);
 	pf->tx_sch_mode = HNS3_FLAG_TC_BASE_SCH_MODE;
 
 	pf->wanted_umv_size = cfg.umv_space;
@@ -3025,7 +3024,7 @@ hns3_tx_buffer_calc(struct hns3_hw *hw, struct hns3_pkt_buf_alloc *buf_alloc)
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
 		priv = &buf_alloc->priv_buf[i];
 
-		if (hw->hw_tc_map & BIT(i)) {
+		if (hw->dcb_info.hw_tc_map & BIT(i)) {
 			if (total_size < pf->tx_buf_size)
 				return -ENOMEM;
 
@@ -3076,7 +3075,7 @@ hns3_get_tc_num(struct hns3_hw *hw)
 	uint8_t i;
 
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++)
-		if (hw->hw_tc_map & BIT(i))
+		if (hw->dcb_info.hw_tc_map & BIT(i))
 			cnt++;
 	return cnt;
 }
@@ -3136,7 +3135,7 @@ hns3_get_no_pfc_priv_num(struct hns3_hw *hw,
 
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
 		priv = &buf_alloc->priv_buf[i];
-		if (hw->hw_tc_map & BIT(i) &&
+		if (hw->dcb_info.hw_tc_map & BIT(i) &&
 		    !(hw->dcb_info.hw_pfc_map & BIT(i)) && priv->enable)
 			cnt++;
 	}
@@ -3235,7 +3234,7 @@ hns3_rx_buf_calc_all(struct hns3_hw *hw, bool max,
 		priv->wl.high = 0;
 		priv->buf_size = 0;
 
-		if (!(hw->hw_tc_map & BIT(i)))
+		if (!(hw->dcb_info.hw_tc_map & BIT(i)))
 			continue;
 
 		priv->enable = 1;
@@ -3274,7 +3273,7 @@ hns3_drop_nopfc_buf_till_fit(struct hns3_hw *hw,
 	for (i = HNS3_MAX_TC_NUM - 1; i >= 0; i--) {
 		priv = &buf_alloc->priv_buf[i];
 		mask = BIT((uint8_t)i);
-		if (hw->hw_tc_map & mask &&
+		if (hw->dcb_info.hw_tc_map & mask &&
 		    !(hw->dcb_info.hw_pfc_map & mask)) {
 			/* Clear the no pfc TC private buffer */
 			priv->wl.low = 0;
@@ -3311,7 +3310,7 @@ hns3_drop_pfc_buf_till_fit(struct hns3_hw *hw,
 	for (i = HNS3_MAX_TC_NUM - 1; i >= 0; i--) {
 		priv = &buf_alloc->priv_buf[i];
 		mask = BIT((uint8_t)i);
-		if (hw->hw_tc_map & mask && hw->dcb_info.hw_pfc_map & mask) {
+		if (hw->dcb_info.hw_tc_map & mask && hw->dcb_info.hw_pfc_map & mask) {
 			/* Reduce the number of pfc TC with private buffer */
 			priv->wl.low = 0;
 			priv->enable = 0;
@@ -3369,7 +3368,7 @@ hns3_only_alloc_priv_buff(struct hns3_hw *hw,
 		priv->wl.high = 0;
 		priv->buf_size = 0;
 
-		if (!(hw->hw_tc_map & BIT(i)))
+		if (!(hw->dcb_info.hw_tc_map & BIT(i)))
 			continue;
 
 		priv->enable = 1;
@@ -5494,13 +5493,12 @@ static int
 hns3_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
 {
 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	enum rte_eth_rx_mq_mode mq_mode = dev->data->dev_conf.rxmode.mq_mode;
 	int i;
 
 	rte_spinlock_lock(&hw->lock);
 	if ((uint32_t)mq_mode & RTE_ETH_MQ_RX_DCB_FLAG)
-		dcb_info->nb_tcs = pf->local_max_tc;
+		dcb_info->nb_tcs = hw->dcb_info.local_max_tc;
 	else
 		dcb_info->nb_tcs = 1;
 
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index e4160f6eae..d7a55c134f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -130,7 +130,11 @@ struct hns3_tc_info {
 };
 
 struct hns3_dcb_info {
+	uint8_t tc_max;     /* max number of tc driver supported */
 	uint8_t num_tc;     /* Total number of enabled TCs */
+	uint8_t hw_tc_map;
+	uint8_t local_max_tc; /* max number of local tc */
+	uint8_t pfc_max;
 	uint8_t num_pg;     /* It must be 1 if vNET-Base schd */
 	uint8_t pg_dwrr[HNS3_PG_NUM];
 	uint8_t prio_tc[HNS3_MAX_USER_PRIO];
@@ -534,7 +538,6 @@ struct hns3_hw {
 	uint16_t rss_ind_tbl_size;
 	uint16_t rss_key_size;
 
-	uint8_t hw_tc_map;
 	enum hns3_fc_mode requested_fc_mode; /* FC mode requested by user */
 	struct hns3_dcb_info dcb_info;
 	enum hns3_fc_status current_fc_status; /* current flow control status */
@@ -831,9 +834,6 @@ struct hns3_pf {
 	uint16_t mps; /* Max packet size */
 
 	uint8_t tx_sch_mode;
-	uint8_t tc_max; /* max number of tc driver supported */
-	uint8_t local_max_tc; /* max number of local tc */
-	uint8_t pfc_max;
 	uint16_t pause_time;
 	bool support_fc_autoneg;       /* support FC autonegotiate */
 	bool support_multi_tc_pause;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 5f4ae1d979..1cb8a9ccc1 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -830,7 +830,7 @@ hns3vf_get_num_tc(struct hns3_hw *hw)
 	uint32_t i;
 
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
-		if (hw->hw_tc_map & BIT(i))
+		if (hw->dcb_info.hw_tc_map & BIT(i))
 			num_tc++;
 	}
 	return num_tc;
@@ -853,7 +853,7 @@ hns3vf_get_basic_info(struct hns3_hw *hw)
 	}
 
 	basic_info = (struct hns3_basic_info *)resp_msg;
-	hw->hw_tc_map = basic_info->hw_tc_map;
+	hw->dcb_info.hw_tc_map = basic_info->hw_tc_map;
 	hw->dcb_info.num_tc = hns3vf_get_num_tc(hw);
 	hw->pf_vf_if_version = basic_info->pf_vf_if_version;
 	hns3vf_update_caps(hw, basic_info->caps);
diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c
index 3eae4caf52..508b3e26d0 100644
--- a/drivers/net/hns3/hns3_rss.c
+++ b/drivers/net/hns3/hns3_rss.c
@@ -940,13 +940,13 @@ hns3_set_rss_tc_mode_entry(struct hns3_hw *hw, uint8_t *tc_valid,
 			 * has to enable the unused TC by using TC0 queue
 			 * mapping configuration.
 			 */
-			tc_valid[i] = (hw->hw_tc_map & BIT(i)) ?
-					!!(hw->hw_tc_map & BIT(i)) : 1;
+			tc_valid[i] = (hw->dcb_info.hw_tc_map & BIT(i)) ?
+					!!(hw->dcb_info.hw_tc_map & BIT(i)) : 1;
 			tc_size[i] = roundup_size;
-			tc_offset[i] = (hw->hw_tc_map & BIT(i)) ?
+			tc_offset[i] = (hw->dcb_info.hw_tc_map & BIT(i)) ?
 					rss_size * i : 0;
 		} else {
-			tc_valid[i] = !!(hw->hw_tc_map & BIT(i));
+			tc_valid[i] = !!(hw->dcb_info.hw_tc_map & BIT(i));
 			tc_size[i] = tc_valid[i] ? roundup_size : 0;
 			tc_offset[i] = tc_valid[i] ? rss_size * i : 0;
 		}
-- 
2.33.0


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

* [PATCH 4/6] net/hns3: VF support parse max TC number
  2025-06-11  8:18 [PATCH 0/6] net/hns3: VF support multi-TCs Dengdui Huang
                   ` (2 preceding siblings ...)
  2025-06-11  8:18 ` [PATCH 3/6] net/hns3: refactor DCB module code Dengdui Huang
@ 2025-06-11  8:18 ` Dengdui Huang
  2025-06-11  8:18 ` [PATCH 5/6] net/hns3: VF support discover multi-TCs capability Dengdui Huang
  2025-06-11  8:19 ` [PATCH 6/6] net/hns3: VF support multi-TCs configure Dengdui Huang
  5 siblings, 0 replies; 7+ messages in thread
From: Dengdui Huang @ 2025-06-11  8:18 UTC (permalink / raw)
  To: dev; +Cc: stephen, lihuisong, fengchengwen, liuyonglong

From: Chengwen Feng <fengchengwen@huawei.com>

The mailbox message HNS3_MBX_GET_BASIC_INFO can obtain the maximum
number of TCs of the device. The VF does not support multiple TCs,
therefore, this field is not saved.

Now the VF needs to support multiple TCs, therefore, this field needs
to be saved.

This commit also support dump the TC info.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
 drivers/net/hns3/hns3_dump.c      | 2 ++
 drivers/net/hns3/hns3_ethdev_vf.c | 1 +
 drivers/net/hns3/hns3_mbx.h       | 2 +-
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_dump.c b/drivers/net/hns3/hns3_dump.c
index 6c43ec486e..63c6b4ef2c 100644
--- a/drivers/net/hns3/hns3_dump.c
+++ b/drivers/net/hns3/hns3_dump.c
@@ -209,6 +209,7 @@ hns3_get_device_basic_info(FILE *file, struct rte_eth_dev *dev)
 		"  - Device Base Info:\n"
 		"\t  -- name: %s\n"
 		"\t  -- adapter_state=%s\n"
+		"\t  -- tc_max=%u tc_num=%u\n"
 		"\t  -- nb_rx_queues=%u nb_tx_queues=%u\n"
 		"\t  -- total_tqps_num=%u tqps_num=%u intr_tqps_num=%u\n"
 		"\t  -- rss_size_max=%u alloc_rss_size=%u tx_qnum_per_tc=%u\n"
@@ -221,6 +222,7 @@ hns3_get_device_basic_info(FILE *file, struct rte_eth_dev *dev)
 		"\t  -- intr_conf: lsc=%u rxq=%u\n",
 		dev->data->name,
 		hns3_get_adapter_state_name(hw->adapter_state),
+		hw->dcb_info.tc_max, hw->dcb_info.num_tc,
 		dev->data->nb_rx_queues, dev->data->nb_tx_queues,
 		hw->total_tqps_num, hw->tqps_num, hw->intr_tqps_num,
 		hw->rss_size_max, hw->alloc_rss_size, hw->tx_qnum_per_tc,
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 1cb8a9ccc1..632409c5d0 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -853,6 +853,7 @@ hns3vf_get_basic_info(struct hns3_hw *hw)
 	}
 
 	basic_info = (struct hns3_basic_info *)resp_msg;
+	hw->dcb_info.tc_max = basic_info->tc_max;
 	hw->dcb_info.hw_tc_map = basic_info->hw_tc_map;
 	hw->dcb_info.num_tc = hns3vf_get_num_tc(hw);
 	hw->pf_vf_if_version = basic_info->pf_vf_if_version;
diff --git a/drivers/net/hns3/hns3_mbx.h b/drivers/net/hns3/hns3_mbx.h
index c73f34fb32..651c6b9023 100644
--- a/drivers/net/hns3/hns3_mbx.h
+++ b/drivers/net/hns3/hns3_mbx.h
@@ -53,7 +53,7 @@ enum HNS3_MBX_OPCODE {
 
 struct hns3_basic_info {
 	uint8_t hw_tc_map;
-	uint8_t rsv;
+	uint8_t tc_max;
 	uint16_t pf_vf_if_version;
 	/* capabilities of VF dependent on PF */
 	uint32_t caps;
-- 
2.33.0


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

* [PATCH 5/6] net/hns3: VF support discover multi-TCs capability
  2025-06-11  8:18 [PATCH 0/6] net/hns3: VF support multi-TCs Dengdui Huang
                   ` (3 preceding siblings ...)
  2025-06-11  8:18 ` [PATCH 4/6] net/hns3: VF support parse max TC number Dengdui Huang
@ 2025-06-11  8:18 ` Dengdui Huang
  2025-06-11  8:19 ` [PATCH 6/6] net/hns3: VF support multi-TCs configure Dengdui Huang
  5 siblings, 0 replies; 7+ messages in thread
From: Dengdui Huang @ 2025-06-11  8:18 UTC (permalink / raw)
  To: dev; +Cc: stephen, lihuisong, fengchengwen, liuyonglong

From: Chengwen Feng <fengchengwen@huawei.com>

The VF multi-TCs feature depends on firmware and PF driver, the
capability was set when:
1) Firmware report VF multi-TCs flag.
2) PF driver report VF multi-TCs flag.
3) PF driver support query multi-TCs info mailbox message.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
 drivers/net/hns3/hns3_cmd.c       |  5 ++++-
 drivers/net/hns3/hns3_cmd.h       |  2 ++
 drivers/net/hns3/hns3_dump.c      |  3 ++-
 drivers/net/hns3/hns3_ethdev.h    |  1 +
 drivers/net/hns3/hns3_ethdev_vf.c | 33 +++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_mbx.h       |  7 +++++++
 6 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c
index 398b75384e..ad4ef9e189 100644
--- a/drivers/net/hns3/hns3_cmd.c
+++ b/drivers/net/hns3/hns3_cmd.c
@@ -482,7 +482,8 @@ static void
 hns3_parse_capability(struct hns3_hw *hw,
 		      struct hns3_query_version_cmd *cmd)
 {
-	uint32_t caps = rte_le_to_cpu_32(cmd->caps[0]);
+	uint64_t caps = ((uint64_t)rte_le_to_cpu_32(cmd->caps[1]) << 32) |
+			rte_le_to_cpu_32(cmd->caps[0]);
 
 	if (hns3_get_bit(caps, HNS3_CAPS_FD_QUEUE_REGION_B))
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_FD_QUEUE_REGION_B,
@@ -524,6 +525,8 @@ hns3_parse_capability(struct hns3_hw *hw,
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_FC_AUTO_B, 1);
 	if (hns3_get_bit(caps, HNS3_CAPS_GRO_B))
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_GRO_B, 1);
+	if (hns3_get_bit(caps, HNS3_CAPS_VF_MULTI_TCS_B))
+		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_VF_MULTI_TCS_B, 1);
 }
 
 static uint32_t
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index e21a2b652f..2a2ec155ea 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -326,6 +326,7 @@ enum HNS3_CAPS_BITS {
 	HNS3_CAPS_TM_B = 19,
 	HNS3_CAPS_GRO_B = 20,
 	HNS3_CAPS_FC_AUTO_B = 30,
+	HNS3_CAPS_VF_MULTI_TCS_B = 34,
 };
 
 /* Capabilities of VF dependent on the PF */
@@ -335,6 +336,7 @@ enum HNS3VF_CAPS_BITS {
 	 * in kernel side PF.
 	 */
 	HNS3VF_CAPS_VLAN_FLT_MOD_B = 0,
+	HNS3VF_CAPS_MULTI_TCS_B = 1,
 };
 
 enum HNS3_API_CAP_BITS {
diff --git a/drivers/net/hns3/hns3_dump.c b/drivers/net/hns3/hns3_dump.c
index 63c6b4ef2c..678279e2ac 100644
--- a/drivers/net/hns3/hns3_dump.c
+++ b/drivers/net/hns3/hns3_dump.c
@@ -105,7 +105,8 @@ hns3_get_dev_feature_capability(FILE *file, struct hns3_hw *hw)
 		{HNS3_DEV_SUPPORT_TM_B, "TM"},
 		{HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B, "VF VLAN FILTER MOD"},
 		{HNS3_DEV_SUPPORT_FC_AUTO_B, "FC AUTO"},
-		{HNS3_DEV_SUPPORT_GRO_B, "GRO"}
+		{HNS3_DEV_SUPPORT_GRO_B, "GRO"},
+		{HNS3_DEV_SUPPORT_VF_MULTI_TCS_B, "VF MULTI TCS"},
 	};
 	uint32_t i;
 
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index d7a55c134f..d602bfa02f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -916,6 +916,7 @@ enum hns3_dev_cap {
 	HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B,
 	HNS3_DEV_SUPPORT_FC_AUTO_B,
 	HNS3_DEV_SUPPORT_GRO_B,
+	HNS3_DEV_SUPPORT_VF_MULTI_TCS_B,
 };
 
 #define hns3_dev_get_support(hw, _name) \
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 632409c5d0..41d8252540 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -815,12 +815,45 @@ hns3vf_get_queue_info(struct hns3_hw *hw)
 	return hns3vf_check_tqp_info(hw);
 }
 
+static void
+hns3vf_update_multi_tcs_cap(struct hns3_hw *hw, uint32_t pf_multi_tcs_bit)
+{
+	uint8_t resp_msg[HNS3_MBX_MAX_RESP_DATA_SIZE];
+	struct hns3_vf_to_pf_msg req;
+	int ret;
+
+	if (!hns3_dev_get_support(hw, VF_MULTI_TCS))
+		return;
+
+	if (pf_multi_tcs_bit == 0) {
+		/*
+		 * Early PF driver versions may don't report
+		 * HNS3VF_CAPS_MULTI_TCS_B when VF query basic info, so clear
+		 * the corresponding capability bit.
+		 */
+		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_VF_MULTI_TCS_B, 0);
+		return;
+	}
+
+	/*
+	 * Early PF driver versions may also report HNS3VF_CAPS_MULTI_TCS_B
+	 * when VF query basic info, but they don't support query TC info
+	 * mailbox message, so clear the corresponding capability bit.
+	 */
+	hns3vf_mbx_setup(&req, HNS3_MBX_GET_TC, HNS3_MBX_GET_PRIO_MAP);
+	ret = hns3vf_mbx_send(hw, &req, true, resp_msg, sizeof(resp_msg));
+	if (ret)
+		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_VF_MULTI_TCS_B, 0);
+}
+
 static void
 hns3vf_update_caps(struct hns3_hw *hw, uint32_t caps)
 {
 	if (hns3_get_bit(caps, HNS3VF_CAPS_VLAN_FLT_MOD_B))
 		hns3_set_bit(hw->capability,
 				HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B, 1);
+
+	hns3vf_update_multi_tcs_cap(hw, hns3_get_bit(caps, HNS3VF_CAPS_MULTI_TCS_B));
 }
 
 static int
diff --git a/drivers/net/hns3/hns3_mbx.h b/drivers/net/hns3/hns3_mbx.h
index 651c6b9023..eec3dd2c7e 100644
--- a/drivers/net/hns3/hns3_mbx.h
+++ b/drivers/net/hns3/hns3_mbx.h
@@ -48,6 +48,9 @@ enum HNS3_MBX_OPCODE {
 
 	HNS3_MBX_HANDLE_VF_TBL = 38,    /* (VF -> PF) store/clear hw cfg tbl */
 	HNS3_MBX_GET_RING_VECTOR_MAP,   /* (VF -> PF) get ring-to-vector map */
+
+	HNS3_MBX_GET_TC = 47,           /* (VF -> PF) get tc info of PF configured */
+
 	HNS3_MBX_PUSH_LINK_STATUS = 201, /* (IMP -> PF) get port link status */
 };
 
@@ -59,6 +62,10 @@ struct hns3_basic_info {
 	uint32_t caps;
 };
 
+enum hns3_mbx_get_tc_subcode {
+	HNS3_MBX_GET_PRIO_MAP = 0, /* query priority to tc map */
+};
+
 /* below are per-VF mac-vlan subcodes */
 enum hns3_mbx_mac_vlan_subcode {
 	HNS3_MBX_MAC_VLAN_UC_MODIFY = 0,        /* modify UC mac addr */
-- 
2.33.0


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

* [PATCH 6/6] net/hns3: VF support multi-TCs configure
  2025-06-11  8:18 [PATCH 0/6] net/hns3: VF support multi-TCs Dengdui Huang
                   ` (4 preceding siblings ...)
  2025-06-11  8:18 ` [PATCH 5/6] net/hns3: VF support discover multi-TCs capability Dengdui Huang
@ 2025-06-11  8:19 ` Dengdui Huang
  5 siblings, 0 replies; 7+ messages in thread
From: Dengdui Huang @ 2025-06-11  8:19 UTC (permalink / raw)
  To: dev; +Cc: stephen, lihuisong, fengchengwen, liuyonglong

From: Chengwen Feng <fengchengwen@huawei.com>

If VF has the multi-TCs capability, then application could configure the
multi-TCs feature through the DCB interface. Because VF does not have
its own ETS and PFC components, the constraints are as follows:

1. The DCB configuration (struct rte_eth_dcb_rx_conf and
   rte_eth_dcb_tx_conf) must be the same as that of the PF.
2. VF does not support RTE_ETH_DCB_PFC_SUPPORT configuration.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
 drivers/net/hns3/hns3_dcb.c       | 106 ++++++++++++
 drivers/net/hns3/hns3_dcb.h       |   4 +
 drivers/net/hns3/hns3_dump.c      |   6 +-
 drivers/net/hns3/hns3_ethdev.c    |  98 +-----------
 drivers/net/hns3/hns3_ethdev_vf.c | 257 ++++++++++++++++++++++++++++--
 drivers/net/hns3/hns3_mbx.h       |  41 +++++
 6 files changed, 404 insertions(+), 108 deletions(-)

diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index 9a1f4120d0..6d2945d9c5 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -1800,3 +1800,109 @@ hns3_fc_enable(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 
 	return ret;
 }
+
+int
+hns3_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_eth_rx_mq_mode mq_mode = dev->data->dev_conf.rxmode.mq_mode;
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	int i;
+
+	if (hns->is_vf && !hns3_dev_get_support(hw, VF_MULTI_TCS))
+		return -ENOTSUP;
+
+	rte_spinlock_lock(&hw->lock);
+	if ((uint32_t)mq_mode & RTE_ETH_MQ_RX_DCB_FLAG)
+		dcb_info->nb_tcs = hw->dcb_info.local_max_tc;
+	else
+		dcb_info->nb_tcs = 1;
+
+	for (i = 0; i < HNS3_MAX_USER_PRIO; i++)
+		dcb_info->prio_tc[i] = hw->dcb_info.prio_tc[i];
+	for (i = 0; i < dcb_info->nb_tcs; i++)
+		dcb_info->tc_bws[i] = hw->dcb_info.pg_info[0].tc_dwrr[i];
+
+	for (i = 0; i < hw->dcb_info.num_tc; i++) {
+		dcb_info->tc_queue.tc_rxq[0][i].base = hw->alloc_rss_size * i;
+		dcb_info->tc_queue.tc_txq[0][i].base =
+						hw->tc_queue[i].tqp_offset;
+		dcb_info->tc_queue.tc_rxq[0][i].nb_queue = hw->alloc_rss_size;
+		dcb_info->tc_queue.tc_txq[0][i].nb_queue =
+						hw->tc_queue[i].tqp_count;
+	}
+	rte_spinlock_unlock(&hw->lock);
+
+	return 0;
+}
+
+int
+hns3_check_dev_mq_mode(struct rte_eth_dev *dev)
+{
+	enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode;
+	enum rte_eth_tx_mq_mode tx_mq_mode = dev->data->dev_conf.txmode.mq_mode;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct rte_eth_dcb_rx_conf *dcb_rx_conf;
+	struct rte_eth_dcb_tx_conf *dcb_tx_conf;
+	uint8_t num_tc;
+	int max_tc = 0;
+	int i;
+
+	if (((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
+	    (tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB ||
+	     tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_ONLY)) {
+		hns3_err(hw, "VMDQ is not supported, rx_mq_mode = %d, tx_mq_mode = %d.",
+			 rx_mq_mode, tx_mq_mode);
+		return -EOPNOTSUPP;
+	}
+
+	dcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
+	dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
+	if ((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
+		if (dcb_rx_conf->nb_tcs > hw->dcb_info.tc_max) {
+			hns3_err(hw, "nb_tcs(%u) > max_tc(%u) driver supported.",
+				 dcb_rx_conf->nb_tcs, hw->dcb_info.tc_max);
+			return -EINVAL;
+		}
+
+		/*
+		 * The PF driver supports only four or eight TCs. But the
+		 * number of TCs supported by the VF driver is flexible,
+		 * therefore, only the number of TCs in the PF is verified.
+		 */
+		if (!hns->is_vf && !(dcb_rx_conf->nb_tcs == HNS3_4_TCS ||
+				     dcb_rx_conf->nb_tcs == HNS3_8_TCS)) {
+			hns3_err(hw, "on RTE_ETH_MQ_RX_DCB_RSS mode, "
+				 "nb_tcs(%d) != %d or %d in rx direction.",
+				 dcb_rx_conf->nb_tcs, HNS3_4_TCS, HNS3_8_TCS);
+			return -EINVAL;
+		}
+
+		if (dcb_rx_conf->nb_tcs != dcb_tx_conf->nb_tcs) {
+			hns3_err(hw, "num_tcs(%d) of tx is not equal to rx(%d)",
+				 dcb_tx_conf->nb_tcs, dcb_rx_conf->nb_tcs);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < HNS3_MAX_USER_PRIO; i++) {
+			if (dcb_rx_conf->dcb_tc[i] != dcb_tx_conf->dcb_tc[i]) {
+				hns3_err(hw, "dcb_tc[%d] = %u in rx direction, "
+					 "is not equal to one in tx direction.",
+					 i, dcb_rx_conf->dcb_tc[i]);
+				return -EINVAL;
+			}
+			if (dcb_rx_conf->dcb_tc[i] > max_tc)
+				max_tc = dcb_rx_conf->dcb_tc[i];
+		}
+
+		num_tc = max_tc + 1;
+		if (num_tc > dcb_rx_conf->nb_tcs) {
+			hns3_err(hw, "max num_tc(%u) mapped > nb_tcs(%u)",
+				 num_tc, dcb_rx_conf->nb_tcs);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
diff --git a/drivers/net/hns3/hns3_dcb.h b/drivers/net/hns3/hns3_dcb.h
index d5bb5edf4d..552e9c3026 100644
--- a/drivers/net/hns3/hns3_dcb.h
+++ b/drivers/net/hns3/hns3_dcb.h
@@ -215,4 +215,8 @@ int hns3_update_queue_map_configure(struct hns3_adapter *hns);
 int hns3_port_shaper_update(struct hns3_hw *hw, uint32_t speed);
 uint8_t hns3_txq_mapped_tc_get(struct hns3_hw *hw, uint16_t txq_no);
 
+int hns3_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info);
+
+int hns3_check_dev_mq_mode(struct rte_eth_dev *dev);
+
 #endif /* HNS3_DCB_H */
diff --git a/drivers/net/hns3/hns3_dump.c b/drivers/net/hns3/hns3_dump.c
index 678279e2ac..0e978dee60 100644
--- a/drivers/net/hns3/hns3_dump.c
+++ b/drivers/net/hns3/hns3_dump.c
@@ -210,7 +210,7 @@ hns3_get_device_basic_info(FILE *file, struct rte_eth_dev *dev)
 		"  - Device Base Info:\n"
 		"\t  -- name: %s\n"
 		"\t  -- adapter_state=%s\n"
-		"\t  -- tc_max=%u tc_num=%u\n"
+		"\t  -- tc_max=%u tc_num=%u dwrr[%u %u %u %u]\n"
 		"\t  -- nb_rx_queues=%u nb_tx_queues=%u\n"
 		"\t  -- total_tqps_num=%u tqps_num=%u intr_tqps_num=%u\n"
 		"\t  -- rss_size_max=%u alloc_rss_size=%u tx_qnum_per_tc=%u\n"
@@ -224,6 +224,10 @@ hns3_get_device_basic_info(FILE *file, struct rte_eth_dev *dev)
 		dev->data->name,
 		hns3_get_adapter_state_name(hw->adapter_state),
 		hw->dcb_info.tc_max, hw->dcb_info.num_tc,
+		hw->dcb_info.pg_info[0].tc_dwrr[0],
+		hw->dcb_info.pg_info[0].tc_dwrr[1],
+		hw->dcb_info.pg_info[0].tc_dwrr[2],
+		hw->dcb_info.pg_info[0].tc_dwrr[3],
 		dev->data->nb_rx_queues, dev->data->nb_tx_queues,
 		hw->total_tqps_num, hw->tqps_num, hw->intr_tqps_num,
 		hw->rss_size_max, hw->alloc_rss_size, hw->tx_qnum_per_tc,
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 5af11d9228..a809a47423 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -1870,71 +1870,6 @@ hns3_remove_mc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-static int
-hns3_check_mq_mode(struct rte_eth_dev *dev)
-{
-	enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode;
-	enum rte_eth_tx_mq_mode tx_mq_mode = dev->data->dev_conf.txmode.mq_mode;
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_eth_dcb_rx_conf *dcb_rx_conf;
-	struct rte_eth_dcb_tx_conf *dcb_tx_conf;
-	uint8_t num_tc;
-	int max_tc = 0;
-	int i;
-
-	if (((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
-	    (tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB ||
-	     tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_ONLY)) {
-		hns3_err(hw, "VMDQ is not supported, rx_mq_mode = %d, tx_mq_mode = %d.",
-			 rx_mq_mode, tx_mq_mode);
-		return -EOPNOTSUPP;
-	}
-
-	dcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
-	dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
-	if ((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
-		if (dcb_rx_conf->nb_tcs > hw->dcb_info.tc_max) {
-			hns3_err(hw, "nb_tcs(%u) > max_tc(%u) driver supported.",
-				 dcb_rx_conf->nb_tcs, hw->dcb_info.tc_max);
-			return -EINVAL;
-		}
-
-		if (!(dcb_rx_conf->nb_tcs == HNS3_4_TCS ||
-		      dcb_rx_conf->nb_tcs == HNS3_8_TCS)) {
-			hns3_err(hw, "on RTE_ETH_MQ_RX_DCB_RSS mode, "
-				 "nb_tcs(%d) != %d or %d in rx direction.",
-				 dcb_rx_conf->nb_tcs, HNS3_4_TCS, HNS3_8_TCS);
-			return -EINVAL;
-		}
-
-		if (dcb_rx_conf->nb_tcs != dcb_tx_conf->nb_tcs) {
-			hns3_err(hw, "num_tcs(%d) of tx is not equal to rx(%d)",
-				 dcb_tx_conf->nb_tcs, dcb_rx_conf->nb_tcs);
-			return -EINVAL;
-		}
-
-		for (i = 0; i < HNS3_MAX_USER_PRIO; i++) {
-			if (dcb_rx_conf->dcb_tc[i] != dcb_tx_conf->dcb_tc[i]) {
-				hns3_err(hw, "dcb_tc[%d] = %u in rx direction, "
-					 "is not equal to one in tx direction.",
-					 i, dcb_rx_conf->dcb_tc[i]);
-				return -EINVAL;
-			}
-			if (dcb_rx_conf->dcb_tc[i] > max_tc)
-				max_tc = dcb_rx_conf->dcb_tc[i];
-		}
-
-		num_tc = max_tc + 1;
-		if (num_tc > dcb_rx_conf->nb_tcs) {
-			hns3_err(hw, "max num_tc(%u) mapped > nb_tcs(%u)",
-				 num_tc, dcb_rx_conf->nb_tcs);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
 static int
 hns3_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id, bool en,
 			   enum hns3_ring_type queue_type, uint16_t queue_id)
@@ -2033,7 +1968,7 @@ hns3_check_dev_conf(struct rte_eth_dev *dev)
 	struct rte_eth_conf *conf = &dev->data->dev_conf;
 	int ret;
 
-	ret = hns3_check_mq_mode(dev);
+	ret = hns3_check_dev_mq_mode(dev);
 	if (ret)
 		return ret;
 
@@ -5489,37 +5424,6 @@ hns3_priority_flow_ctrl_set(struct rte_eth_dev *dev,
 	return ret;
 }
 
-static int
-hns3_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	enum rte_eth_rx_mq_mode mq_mode = dev->data->dev_conf.rxmode.mq_mode;
-	int i;
-
-	rte_spinlock_lock(&hw->lock);
-	if ((uint32_t)mq_mode & RTE_ETH_MQ_RX_DCB_FLAG)
-		dcb_info->nb_tcs = hw->dcb_info.local_max_tc;
-	else
-		dcb_info->nb_tcs = 1;
-
-	for (i = 0; i < HNS3_MAX_USER_PRIO; i++)
-		dcb_info->prio_tc[i] = hw->dcb_info.prio_tc[i];
-	for (i = 0; i < dcb_info->nb_tcs; i++)
-		dcb_info->tc_bws[i] = hw->dcb_info.pg_info[0].tc_dwrr[i];
-
-	for (i = 0; i < hw->dcb_info.num_tc; i++) {
-		dcb_info->tc_queue.tc_rxq[0][i].base = hw->alloc_rss_size * i;
-		dcb_info->tc_queue.tc_txq[0][i].base =
-						hw->tc_queue[i].tqp_offset;
-		dcb_info->tc_queue.tc_rxq[0][i].nb_queue = hw->alloc_rss_size;
-		dcb_info->tc_queue.tc_txq[0][i].nb_queue =
-						hw->tc_queue[i].tqp_count;
-	}
-	rte_spinlock_unlock(&hw->lock);
-
-	return 0;
-}
-
 static int
 hns3_reinit_dev(struct hns3_adapter *hns)
 {
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 41d8252540..f9ef3dbb06 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -379,6 +379,236 @@ hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id,
 	return ret;
 }
 
+static int
+hns3vf_set_multi_tc(struct hns3_hw *hw, const struct hns3_mbx_tc_config *config)
+{
+	struct hns3_mbx_tc_config *payload;
+	struct hns3_vf_to_pf_msg req;
+	int ret;
+
+	hns3vf_mbx_setup(&req, HNS3_MBX_SET_TC, 0);
+	payload = (struct hns3_mbx_tc_config *)req.data;
+	memcpy(payload, config, sizeof(*payload));
+	payload->prio_tc_map = rte_cpu_to_le_32(config->prio_tc_map);
+	ret = hns3vf_mbx_send(hw, &req, true, NULL, 0);
+	if (ret)
+		hns3_err(hw, "failed to set multi-tc, ret = %d.", ret);
+
+	return ret;
+}
+
+static int
+hns3vf_unset_multi_tc(struct hns3_hw *hw)
+{
+	struct hns3_mbx_tc_config *paylod;
+	struct hns3_vf_to_pf_msg req;
+	int ret;
+
+	hns3vf_mbx_setup(&req, HNS3_MBX_SET_TC, 0);
+	paylod = (struct hns3_mbx_tc_config *)req.data;
+	paylod->tc_dwrr[0] = HNS3_ETS_DWRR_MAX;
+	paylod->num_tc = 1;
+	ret = hns3vf_mbx_send(hw, &req, true, NULL, 0);
+	if (ret)
+		hns3_err(hw, "failed to unset multi-tc, ret = %d.", ret);
+
+	return ret;
+}
+
+static int
+hns3vf_check_multi_tc_config(struct rte_eth_dev *dev, const struct hns3_mbx_tc_config *info)
+{
+	struct rte_eth_dcb_rx_conf *rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t prio_tc_map = info->prio_tc_map;
+	uint8_t map;
+	int i;
+
+	if (rx_conf->nb_tcs != info->num_tc) {
+		hns3_err(hw, "num_tcs(%d) is not equal to PF config(%u)!",
+			 rx_conf->nb_tcs, info->num_tc);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < HNS3_MAX_USER_PRIO; i++) {
+		map = prio_tc_map & HNS3_MBX_PRIO_MASK;
+		prio_tc_map >>= HNS3_MBX_PRIO_SHIFT;
+		if (rx_conf->dcb_tc[i] != map) {
+			hns3_err(hw, "dcb_tc[%d] = %u is not equal to PF config(%u)!",
+				 i, rx_conf->dcb_tc[i], map);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int
+hns3vf_get_multi_tc_info(struct hns3_hw *hw, struct hns3_mbx_tc_config *info)
+{
+	uint8_t resp_msg[HNS3_MBX_MAX_RESP_DATA_SIZE];
+	struct hns3_mbx_tc_prio_map *map = (struct hns3_mbx_tc_prio_map *)resp_msg;
+	struct hns3_mbx_tc_ets_info *ets = (struct hns3_mbx_tc_ets_info *)resp_msg;
+	struct hns3_vf_to_pf_msg req;
+	int i, ret;
+
+	memset(info, 0, sizeof(*info));
+
+	hns3vf_mbx_setup(&req, HNS3_MBX_GET_TC, HNS3_MBX_GET_PRIO_MAP);
+	ret = hns3vf_mbx_send(hw, &req, true, resp_msg, sizeof(resp_msg));
+	if (ret) {
+		hns3_err(hw, "failed to get multi-tc prio map, ret = %d.", ret);
+		return ret;
+	}
+	info->prio_tc_map = rte_le_to_cpu_32(map->prio_tc_map);
+
+	hns3vf_mbx_setup(&req, HNS3_MBX_GET_TC, HNS3_MBX_GET_ETS_INFO);
+	ret = hns3vf_mbx_send(hw, &req, true, resp_msg, sizeof(resp_msg));
+	if (ret) {
+		hns3_err(hw, "failed to get multi-tc ETS info, ret = %d.", ret);
+		return ret;
+	}
+	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
+		if (ets->sch_mode[i] == HNS3_ETS_SCHED_MODE_INVALID)
+			continue;
+		info->tc_dwrr[i] = ets->sch_mode[i];
+		info->num_tc++;
+		if (ets->sch_mode[i] > 0)
+			info->tc_sch_mode |= 1u << i;
+	}
+
+	return 0;
+}
+
+static void
+hns3vf_update_dcb_info(struct hns3_hw *hw, const struct hns3_mbx_tc_config *info)
+{
+	uint32_t prio_tc_map;
+	uint8_t map;
+	int i;
+
+	hw->dcb_info.local_max_tc = hw->dcb_info.num_tc;
+	hw->dcb_info.hw_tc_map = (1u << hw->dcb_info.num_tc) - 1u;
+	memset(hw->dcb_info.pg_info[0].tc_dwrr, 0, sizeof(hw->dcb_info.pg_info[0].tc_dwrr));
+
+	if (hw->dcb_info.num_tc == 1) {
+		memset(hw->dcb_info.prio_tc, 0, sizeof(hw->dcb_info.prio_tc));
+		hw->dcb_info.pg_info[0].tc_dwrr[0] = HNS3_ETS_DWRR_MAX;
+		return;
+	}
+
+	if (info == NULL)
+		return;
+
+	prio_tc_map = info->prio_tc_map;
+	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
+		map = prio_tc_map & HNS3_MBX_PRIO_MASK;
+		prio_tc_map >>= HNS3_MBX_PRIO_SHIFT;
+		hw->dcb_info.prio_tc[i] = map;
+	}
+	for (i = 0; i < hw->dcb_info.num_tc; i++)
+		hw->dcb_info.pg_info[0].tc_dwrr[i] = info->tc_dwrr[i];
+}
+
+static int
+hns3vf_setup_dcb(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mbx_tc_config info;
+	int ret;
+
+	if (!hns3_dev_get_support(hw, VF_MULTI_TCS)) {
+		hns3_err(hw, "this port does not support dcb configurations.");
+		return -ENOTSUP;
+	}
+
+	if (dev->data->dev_conf.dcb_capability_en & RTE_ETH_DCB_PFC_SUPPORT) {
+		hns3_err(hw, "VF don't support PFC!");
+		return -ENOTSUP;
+	}
+
+	ret = hns3vf_get_multi_tc_info(hw, &info);
+	if (ret)
+		return ret;
+
+	ret = hns3vf_check_multi_tc_config(dev, &info);
+	if (ret)
+		return ret;
+
+	/*
+	 * If multiple-TCs have been configured, cancel the configuration
+	 * first. Otherwise, the configuration will fail.
+	 */
+	if (hw->dcb_info.num_tc > 1) {
+		ret = hns3vf_unset_multi_tc(hw);
+		if (ret)
+			return ret;
+		hw->dcb_info.num_tc = 1;
+		hns3vf_update_dcb_info(hw, NULL);
+	}
+
+	ret = hns3vf_set_multi_tc(hw, &info);
+	if (ret)
+		return ret;
+
+	hw->dcb_info.num_tc = info.num_tc;
+	hns3vf_update_dcb_info(hw, &info);
+
+	return hns3_queue_to_tc_mapping(hw, hw->data->nb_rx_queues, hw->data->nb_rx_queues);
+}
+
+static int
+hns3vf_unset_dcb(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	int ret;
+
+	if (hw->dcb_info.num_tc > 1) {
+		ret = hns3vf_unset_multi_tc(hw);
+		if (ret)
+			return ret;
+	}
+
+	hw->dcb_info.num_tc = 1;
+	hns3vf_update_dcb_info(hw, NULL);
+
+	return hns3_queue_to_tc_mapping(hw, hw->data->nb_rx_queues, hw->data->nb_rx_queues);
+}
+
+static int
+hns3vf_config_dcb(struct rte_eth_dev *dev)
+{
+	struct rte_eth_conf *conf = &dev->data->dev_conf;
+	uint32_t rx_mq_mode = conf->rxmode.mq_mode;
+	int ret;
+
+	if (rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG)
+		ret = hns3vf_setup_dcb(dev);
+	else
+		ret = hns3vf_unset_dcb(dev);
+
+	return ret;
+}
+
+static int
+hns3vf_check_dev_conf(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_eth_conf *conf = &dev->data->dev_conf;
+	int ret;
+
+	ret = hns3_check_dev_mq_mode(dev);
+	if (ret)
+		return ret;
+
+	if (conf->link_speeds & RTE_ETH_LINK_SPEED_FIXED) {
+		hns3_err(hw, "setting link speed/duplex not supported");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 static int
 hns3vf_dev_configure(struct rte_eth_dev *dev)
 {
@@ -412,11 +642,13 @@ hns3vf_dev_configure(struct rte_eth_dev *dev)
 	}
 
 	hw->adapter_state = HNS3_NIC_CONFIGURING;
-	if (conf->link_speeds & RTE_ETH_LINK_SPEED_FIXED) {
-		hns3_err(hw, "setting link speed/duplex not supported");
-		ret = -EINVAL;
+	ret = hns3vf_check_dev_conf(dev);
+	if (ret)
+		goto cfg_err;
+
+	ret = hns3vf_config_dcb(dev);
+	if (ret)
 		goto cfg_err;
-	}
 
 	/* When RSS is not configured, redirect the packet queue 0 */
 	if ((uint32_t)mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) {
@@ -1496,6 +1728,15 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)
 	return ret;
 }
 
+static void
+hns3vf_notify_uninit(struct hns3_hw *hw)
+{
+	struct hns3_vf_to_pf_msg req;
+
+	hns3vf_mbx_setup(&req, HNS3_MBX_VF_UNINIT, 0);
+	(void)hns3vf_mbx_send(hw, &req, false, NULL, 0);
+}
+
 static void
 hns3vf_uninit_vf(struct rte_eth_dev *eth_dev)
 {
@@ -1515,6 +1756,7 @@ hns3vf_uninit_vf(struct rte_eth_dev *eth_dev)
 	rte_intr_disable(pci_dev->intr_handle);
 	hns3_intr_unregister(pci_dev->intr_handle, hns3vf_interrupt_handler,
 			     eth_dev);
+	(void)hns3vf_notify_uninit(hw);
 	hns3_cmd_uninit(hw);
 	hns3_cmd_destroy_queue(hw);
 	hw->io_base = NULL;
@@ -1652,14 +1894,8 @@ static int
 hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 {
 	struct hns3_hw *hw = &hns->hw;
-	uint16_t nb_rx_q = hw->data->nb_rx_queues;
-	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	int ret;
 
-	ret = hns3_queue_to_tc_mapping(hw, nb_rx_q, nb_tx_q);
-	if (ret)
-		return ret;
-
 	hns3_enable_rxd_adv_layout(hw);
 
 	ret = hns3_init_queues(hns, reset_queue);
@@ -2240,6 +2476,7 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.vlan_filter_set    = hns3vf_vlan_filter_set,
 	.vlan_offload_set   = hns3vf_vlan_offload_set,
 	.get_reg            = hns3_get_regs,
+	.get_dcb_info       = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
 	.tx_done_cleanup    = hns3_tx_done_cleanup,
 	.eth_dev_priv_dump  = hns3_eth_dev_priv_dump,
diff --git a/drivers/net/hns3/hns3_mbx.h b/drivers/net/hns3/hns3_mbx.h
index eec3dd2c7e..73ff5020fe 100644
--- a/drivers/net/hns3/hns3_mbx.h
+++ b/drivers/net/hns3/hns3_mbx.h
@@ -9,6 +9,8 @@
 
 #include <rte_spinlock.h>
 
+#include "hns3_cmd.h"
+
 enum HNS3_MBX_OPCODE {
 	HNS3_MBX_RESET = 0x01,          /* (VF -> PF) assert reset */
 	HNS3_MBX_ASSERTING_RESET,       /* (PF -> VF) PF is asserting reset */
@@ -45,11 +47,13 @@ enum HNS3_MBX_OPCODE {
 	HNS3_MBX_PUSH_VLAN_INFO = 34,   /* (PF -> VF) push port base vlan */
 
 	HNS3_MBX_PUSH_PROMISC_INFO = 36, /* (PF -> VF) push vf promisc info */
+	HNS3_MBX_VF_UNINIT,              /* (VF -> PF) vf is unintializing */
 
 	HNS3_MBX_HANDLE_VF_TBL = 38,    /* (VF -> PF) store/clear hw cfg tbl */
 	HNS3_MBX_GET_RING_VECTOR_MAP,   /* (VF -> PF) get ring-to-vector map */
 
 	HNS3_MBX_GET_TC = 47,           /* (VF -> PF) get tc info of PF configured */
+	HNS3_MBX_SET_TC,                /* (VF -> PF) set tc */
 
 	HNS3_MBX_PUSH_LINK_STATUS = 201, /* (IMP -> PF) get port link status */
 };
@@ -64,7 +68,44 @@ struct hns3_basic_info {
 
 enum hns3_mbx_get_tc_subcode {
 	HNS3_MBX_GET_PRIO_MAP = 0, /* query priority to tc map */
+	HNS3_MBX_GET_ETS_INFO,     /* query ets info */
+};
+
+struct hns3_mbx_tc_prio_map {
+	/*
+	 * Each four bits correspond to one priority's TC.
+	 * Bit0-3 correspond to priority-0's TC, bit4-7 correspond to
+	 * priority-1's TC, and so on.
+	 */
+	uint32_t prio_tc_map;
+};
+
+#define HNS3_ETS_SCHED_MODE_INVALID	255
+#define HNS3_ETS_DWRR_MAX		100
+struct hns3_mbx_tc_ets_info {
+	uint8_t sch_mode[HNS3_MAX_TC_NUM]; /* 1~100: DWRR, 0: SP; 255-invalid */
+};
+
+#pragma pack(1)
+#define HNS3_MBX_PRIO_SHIFT	4
+#define HNS3_MBX_PRIO_MASK	0xFu
+struct hns3_mbx_tc_config {
+	/*
+	 * Each four bits correspond to one priority's TC.
+	 * Bit0-3 correspond to priority-0's TC, bit4-7 correspond to
+	 * priority-1's TC, and so on.
+	 */
+	uint32_t prio_tc_map;
+	uint8_t tc_dwrr[HNS3_MAX_TC_NUM];
+	uint8_t num_tc;
+	/*
+	 * Each bit correspond to one TC's scheduling mode, 0 means SP
+	 * scheduling mode, 1 means DWRR scheduling mode.
+	 * Bit0 corresponds to TC0, bit1 corresponds to TC1, and so on.
+	 */
+	uint8_t tc_sch_mode;
 };
+#pragma pack()
 
 /* below are per-VF mac-vlan subcodes */
 enum hns3_mbx_mac_vlan_subcode {
-- 
2.33.0


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

end of thread, other threads:[~2025-06-11  8:19 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-11  8:18 [PATCH 0/6] net/hns3: VF support multi-TCs Dengdui Huang
2025-06-11  8:18 ` [PATCH 1/6] net/hns3: fix VF fail to config queue TC Dengdui Huang
2025-06-11  8:18 ` [PATCH 2/6] net/hns3: remove duplicate struct field Dengdui Huang
2025-06-11  8:18 ` [PATCH 3/6] net/hns3: refactor DCB module code Dengdui Huang
2025-06-11  8:18 ` [PATCH 4/6] net/hns3: VF support parse max TC number Dengdui Huang
2025-06-11  8:18 ` [PATCH 5/6] net/hns3: VF support discover multi-TCs capability Dengdui Huang
2025-06-11  8:19 ` [PATCH 6/6] net/hns3: VF support multi-TCs configure Dengdui Huang

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).