DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver
@ 2020-09-29 11:09 Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
                   ` (9 more replies)
  0 siblings, 10 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

This series are updates and fixes for hns3 PMD driver.

Chengchang Tang (1):
  net/hns3: support start and stop Tx or Rx queue

Hongbo Zheng (2):
  net/hns3: check return value when reading PCI config space
  net/hns3: remove redundant return value assignments

Huisong Li (3):
  net/hns3: expand the number of queues for one TC up to 512
  net/hns3: offload calculating the shapping para to firmware
  net/hns3: set max scheduling rate based on actual board

Wei Hu (Xavier) (3):
  net/hns3: maximize the queue number
  net/hns3: fix error type when validating RSS flow action
  net/hns3: set suitable type when initial flow error struct

 config/rte_config.h               |   3 +
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_cmd.h       |  28 +-
 drivers/net/hns3/hns3_dcb.c       | 205 +++++++++---
 drivers/net/hns3/hns3_dcb.h       |  60 +++-
 drivers/net/hns3/hns3_ethdev.c    | 214 +++++++++---
 drivers/net/hns3/hns3_ethdev.h    |  32 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 214 ++++++++----
 drivers/net/hns3/hns3_fdir.c      |   6 +-
 drivers/net/hns3/hns3_flow.c      |  97 +++---
 drivers/net/hns3/hns3_intr.c      |   1 -
 drivers/net/hns3/hns3_regs.c      |   4 +-
 drivers/net/hns3/hns3_regs.h      |   5 +
 drivers/net/hns3/hns3_rss.c       |  34 +-
 drivers/net/hns3/hns3_rss.h       |   5 +-
 drivers/net/hns3/hns3_rxtx.c      | 675 +++++++++++++++++++++++++++++++-------
 drivers/net/hns3/hns3_rxtx.h      |  18 +-
 drivers/net/hns3/hns3_stats.c     |  73 ++++-
 drivers/net/hns3/hns3_stats.h     |   6 +-
 19 files changed, 1281 insertions(+), 401 deletions(-)

-- 
2.9.5


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

* [dpdk-dev] [PATCH 1/9] net/hns3: expand the number of queues for one TC up to 512
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 2/9] net/hns3: maximize the queue number Wei Hu (Xavier)
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Huisong Li <lihuisong@huawei.com>

The maximum number of queues for one TC hns3 PF PMD driver supported is 64
based on hns3 network engine with revison_id equals 0x21, while it is
expanded up to 512 on hns3 network engine with revision_id equals 0x30.

So the following points need to be modified to maintain better
compatibility.
1) Using a extended rss_size_max field as the maximum queue number of one
   TC PF driver supported.
2) The data type of the RSS redirection table needs to be changed from
   uint8_t to uint16_t.
3) rss_tc_mode modification
   The bitwidth of tc_offset, meaning the rx queue index, has to expand
   from 10 bit to 11 bits. The tc_size, meaning the exponent with base 2
   of queues supported on TC, needs to expand from 3 bits to 4 bits.
4) RSS indirection table modification
   Currently, a field with 7 bits width is used to record the queue index
   for RSS indirection table. It means that PF needs to expand the queue
   index field to 9 bits. As the RSS indirection table config command
   reserved 4 bytes to configure the RSS queue index, a extern field can be
   added. So an entries of RSS indirection table queue index has two fields
   to set: rss_result_l and rss_result_h, while rss_result_l records the
   lower 8 bits and rss_result_h records the higher 1 bit.

In addition, 2~4 modifications is also compatible with hns3 VF PMD driver.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_cmd.h    | 17 ++++++++++++-----
 drivers/net/hns3/hns3_ethdev.c | 16 ++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |  2 ++
 drivers/net/hns3/hns3_fdir.c   |  1 -
 drivers/net/hns3/hns3_flow.c   |  8 +++-----
 drivers/net/hns3/hns3_rss.c    | 34 +++++++++++++++++++++++++---------
 drivers/net/hns3/hns3_rss.h    |  5 +++--
 7 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 0b531d9..dd50484 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -441,6 +441,8 @@ struct hns3_umv_spc_alc_cmd {
 #define HNS3_CFG_SPEED_ABILITY_M	GENMASK(7, 0)
 #define HNS3_CFG_UMV_TBL_SPACE_S	16
 #define HNS3_CFG_UMV_TBL_SPACE_M	GENMASK(31, 16)
+#define HNS3_CFG_EXT_RSS_SIZE_S		0
+#define HNS3_CFG_EXT_RSS_SIZE_M		GENMASK(3, 0)
 
 #define HNS3_ACCEPT_TAG1_B		0
 #define HNS3_ACCEPT_UNTAG1_B		1
@@ -567,20 +569,25 @@ struct hns3_rss_input_tuple_cmd {
 	uint8_t rsv[16];
 };
 
-#define HNS3_RSS_CFG_TBL_SIZE	16
+#define HNS3_RSS_CFG_TBL_SIZE		16
+#define HNS3_RSS_CFG_TBL_SIZE_H		4
+#define HNS3_RSS_CFG_TBL_BW_H		2
+#define HNS3_RSS_CFG_TBL_BW_L		8
 
 /* Configure the indirection table, opcode:0x0D07 */
 struct hns3_rss_indirection_table_cmd {
 	uint16_t start_table_index;  /* Bit3~0 must be 0x0. */
 	uint16_t rss_set_bitmap;
-	uint8_t rsv[4];
-	uint8_t rss_result[HNS3_RSS_CFG_TBL_SIZE];
+	uint8_t rss_result_h[HNS3_RSS_CFG_TBL_SIZE_H];
+	uint8_t rss_result_l[HNS3_RSS_CFG_TBL_SIZE];
 };
 
 #define HNS3_RSS_TC_OFFSET_S		0
-#define HNS3_RSS_TC_OFFSET_M		(0x3ff << HNS3_RSS_TC_OFFSET_S)
+#define HNS3_RSS_TC_OFFSET_M		GENMASK(10, 0)
+#define HNS3_RSS_TC_SIZE_MSB_S		11
+#define HNS3_RSS_TC_SIZE_MSB_OFFSET	3
 #define HNS3_RSS_TC_SIZE_S		12
-#define HNS3_RSS_TC_SIZE_M		(0x7 << HNS3_RSS_TC_SIZE_S)
+#define HNS3_RSS_TC_SIZE_M		GENMASK(14, 12)
 #define HNS3_RSS_TC_VALID_B		15
 
 /* Configure the tc_size and tc_offset, opcode:0x0D08 */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 99bcc7a..c45b1b3 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2709,6 +2709,7 @@ hns3_parse_cfg(struct hns3_cfg *cfg, struct hns3_cmd_desc *desc)
 {
 	struct hns3_cfg_param_cmd *req;
 	uint64_t mac_addr_tmp_high;
+	uint8_t ext_rss_size_max;
 	uint64_t mac_addr_tmp;
 	uint32_t i;
 
@@ -2761,6 +2762,21 @@ hns3_parse_cfg(struct hns3_cfg *cfg, struct hns3_cmd_desc *desc)
 					HNS3_CFG_UMV_TBL_SPACE_S);
 	if (!cfg->umv_space)
 		cfg->umv_space = HNS3_DEFAULT_UMV_SPACE_PER_PF;
+
+	ext_rss_size_max = hns3_get_field(rte_le_to_cpu_32(req->param[2]),
+					       HNS3_CFG_EXT_RSS_SIZE_M,
+					       HNS3_CFG_EXT_RSS_SIZE_S);
+
+	/*
+	 * Field ext_rss_size_max obtained from firmware will be more flexible
+	 * for future changes and expansions, which is an exponent of 2, instead
+	 * of reading out directly. If this field is not zero, hns3 PF PMD
+	 * driver uses it as rss_size_max under one TC. Device, whose revision
+	 * id is greater than or equal to PCI_REVISION_ID_HIP09_A, obtains the
+	 * maximum number of queues supported under a TC through this field.
+	 */
+	if (ext_rss_size_max)
+		cfg->rss_size_max = 1U << ext_rss_size_max;
 }
 
 /* hns3_get_board_cfg: query the static parameter from NCL_config file in flash
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index c2d0a75..3c5ccc7 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -64,6 +64,8 @@
 #define HNS3_HIP08_MIN_TX_PKT_LEN	33
 #define HNS3_HIP09_MIN_TX_PKT_LEN	9
 
+#define HNS3_BITS_PER_BYTE	8
+
 #define HNS3_4_TCS			4
 #define HNS3_8_TCS			8
 
diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c
index 65ab19d..e6a065b 100644
--- a/drivers/net/hns3/hns3_fdir.c
+++ b/drivers/net/hns3/hns3_fdir.c
@@ -125,7 +125,6 @@ static const struct key_info tuple_key_info[] = {
 	{INNER_SCTP_TAG, 32},
 };
 
-#define HNS3_BITS_PER_BYTE	8
 #define MAX_KEY_LENGTH		400
 #define MAX_200B_KEY_LENGTH	200
 #define MAX_META_DATA_LENGTH	16
diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index 2cdfb68..f8e5f05 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -1531,15 +1531,14 @@ hns3_update_indir_table(struct rte_eth_dev *dev,
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	uint8_t indir_tbl[HNS3_RSS_IND_TBL_SIZE];
+	uint16_t indir_tbl[HNS3_RSS_IND_TBL_SIZE];
 	uint16_t j, allow_rss_queues;
-	uint8_t queue_id;
 	uint32_t i;
 
 	allow_rss_queues = RTE_MIN(dev->data->nb_rx_queues, hw->rss_size_max);
 	/* Fill in redirection table */
 	memcpy(indir_tbl, hw->rss_info.rss_indirection_tbl,
-	       HNS3_RSS_IND_TBL_SIZE);
+	       sizeof(hw->rss_info.rss_indirection_tbl));
 	for (i = 0, j = 0; i < HNS3_RSS_IND_TBL_SIZE; i++, j++) {
 		j %= num;
 		if (conf->queue[j] >= allow_rss_queues) {
@@ -1549,8 +1548,7 @@ hns3_update_indir_table(struct rte_eth_dev *dev,
 				 allow_rss_queues);
 			return -EINVAL;
 		}
-		queue_id = conf->queue[j];
-		indir_tbl[i] = queue_id;
+		indir_tbl[i] = conf->queue[j];
 	}
 
 	return hns3_set_rss_indir_table(hw, indir_tbl, HNS3_RSS_IND_TBL_SIZE);
diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c
index 5b51512..a8b8143 100644
--- a/drivers/net/hns3/hns3_rss.c
+++ b/drivers/net/hns3/hns3_rss.c
@@ -266,11 +266,15 @@ hns3_set_rss_input_tuple(struct hns3_hw *hw)
  * Used to configure the indirection table of rss.
  */
 int
-hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
+hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size)
 {
 	struct hns3_rss_indirection_table_cmd *req;
 	struct hns3_cmd_desc desc;
-	int ret, i, j, num;
+	uint8_t qid_msb_off;
+	uint8_t qid_msb_val;
+	uint16_t q_id;
+	uint16_t i, j;
+	int ret;
 
 	req = (struct hns3_rss_indirection_table_cmd *)desc.data;
 
@@ -281,9 +285,17 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
 				rte_cpu_to_le_16(i * HNS3_RSS_CFG_TBL_SIZE);
 		req->rss_set_bitmap = rte_cpu_to_le_16(HNS3_RSS_SET_BITMAP_MSK);
 		for (j = 0; j < HNS3_RSS_CFG_TBL_SIZE; j++) {
-			num = i * HNS3_RSS_CFG_TBL_SIZE + j;
-			req->rss_result[j] = indir[num];
+			q_id = indir[i * HNS3_RSS_CFG_TBL_SIZE + j];
+			req->rss_result_l[j] = q_id & 0xff;
+
+			qid_msb_off =
+				j * HNS3_RSS_CFG_TBL_BW_H / HNS3_BITS_PER_BYTE;
+			qid_msb_val = (q_id >> HNS3_RSS_CFG_TBL_BW_L & 0x1)
+					<< (j * HNS3_RSS_CFG_TBL_BW_H %
+					HNS3_BITS_PER_BYTE);
+			req->rss_result_h[qid_msb_off] |= qid_msb_val;
 		}
+
 		ret = hns3_cmd_send(hw, &desc, 1);
 		if (ret) {
 			hns3_err(hw,
@@ -294,7 +306,8 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
 	}
 
 	/* Update redirection table of hw */
-	memcpy(hw->rss_info.rss_indirection_tbl, indir,	HNS3_RSS_IND_TBL_SIZE);
+	memcpy(hw->rss_info.rss_indirection_tbl, indir,
+	       sizeof(hw->rss_info.rss_indirection_tbl));
 
 	return 0;
 }
@@ -302,10 +315,11 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
 int
 hns3_rss_reset_indir_table(struct hns3_hw *hw)
 {
-	uint8_t *lut;
+	uint16_t *lut;
 	int ret;
 
-	lut = rte_zmalloc("hns3_rss_lut", HNS3_RSS_IND_TBL_SIZE, 0);
+	lut = rte_zmalloc("hns3_rss_lut",
+			  HNS3_RSS_IND_TBL_SIZE * sizeof(uint16_t), 0);
 	if (lut == NULL) {
 		hns3_err(hw, "No hns3_rss_lut memory can be allocated");
 		return -ENOMEM;
@@ -487,7 +501,7 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
 	uint16_t i, indir_size = HNS3_RSS_IND_TBL_SIZE; /* Table size is 512 */
-	uint8_t indirection_tbl[HNS3_RSS_IND_TBL_SIZE];
+	uint16_t indirection_tbl[HNS3_RSS_IND_TBL_SIZE];
 	uint16_t idx, shift, allow_rss_queues;
 	int ret;
 
@@ -499,7 +513,7 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
 	}
 	rte_spinlock_lock(&hw->lock);
 	memcpy(indirection_tbl, rss_cfg->rss_indirection_tbl,
-		HNS3_RSS_IND_TBL_SIZE);
+	       sizeof(rss_cfg->rss_indirection_tbl));
 	allow_rss_queues = RTE_MIN(dev->data->nb_rx_queues, hw->rss_size_max);
 	for (i = 0; i < reta_size; i++) {
 		idx = i / RTE_RETA_GROUP_SIZE;
@@ -598,6 +612,8 @@ hns3_set_rss_tc_mode(struct hns3_hw *hw)
 		hns3_set_bit(mode, HNS3_RSS_TC_VALID_B, (tc_valid[i] & 0x1));
 		hns3_set_field(mode, HNS3_RSS_TC_SIZE_M, HNS3_RSS_TC_SIZE_S,
 			       tc_size[i]);
+		if (tc_size[i] >> HNS3_RSS_TC_SIZE_MSB_OFFSET > 0)
+			hns3_set_bit(mode, HNS3_RSS_TC_SIZE_MSB_S, 1);
 		hns3_set_field(mode, HNS3_RSS_TC_OFFSET_M, HNS3_RSS_TC_OFFSET_S,
 			       tc_offset[i]);
 
diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h
index 8fa1b30..b5ac8ae 100644
--- a/drivers/net/hns3/hns3_rss.h
+++ b/drivers/net/hns3/hns3_rss.h
@@ -45,7 +45,7 @@ struct hns3_rss_conf {
 	uint8_t hash_algo; /* hash function type definited by hardware */
 	uint8_t key[HNS3_RSS_KEY_SIZE];  /* Hash key */
 	struct hns3_rss_tuple_cfg rss_tuple_sets;
-	uint8_t rss_indirection_tbl[HNS3_RSS_IND_TBL_SIZE]; /* Shadow table */
+	uint16_t rss_indirection_tbl[HNS3_RSS_IND_TBL_SIZE]; /* Shadow table */
 	uint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */
 	bool valid; /* check if RSS rule is valid */
 };
@@ -97,7 +97,8 @@ int hns3_dev_rss_reta_query(struct rte_eth_dev *dev,
 			    struct rte_eth_rss_reta_entry64 *reta_conf,
 			    uint16_t reta_size);
 void hns3_set_default_rss_args(struct hns3_hw *hw);
-int hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size);
+int hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir,
+			     uint16_t size);
 int hns3_rss_reset_indir_table(struct hns3_hw *hw);
 int hns3_config_rss(struct hns3_adapter *hns);
 void hns3_rss_uninit(struct hns3_adapter *hns);
-- 
2.9.5


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

* [dpdk-dev] [PATCH 2/9] net/hns3: maximize the queue number
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 3/9] net/hns3: fix error type when validating RSS flow action Wei Hu (Xavier)
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: "Wei Hu (Xavier)" <xavier.huwei@huawei.com>

The maximum number of queues for hns3 PF and VF driver is 64 based on hns3
network engine with revision_id equals 0x21. Based on hns3 network engine
with revision_id equals 0x30, the hns3 PF PMD driver can support up to 1280
queues, and hns3 VF PMD driver can support up to 128 queues.

The following points need to be modified to support maximizing queue number
and maintain better compatibility:
1) Maximizing the number of queues for hns3 PF and VF PMD driver
   In current version, VF is not supported when PF is driven by hns3 PMD
   driver. If maximum queue numbers allocated to PF PMD drvier is less than
   total tqps_num allocated to this port, all remaining number of queues
   are mapped to VF function, which is unreasonable. So we fix that all
   remaining number of queues are mapped to PF function.

   Using RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF which comes from configuration
   file to limit the queue number allocated to PF device based on hns3
   network engine with revision_id greater than 0x30. And PF device still
   keep the maximun 64 queues based on hns3 network engine with revision_id
   equals 0x21.

   Remove restriction of the macro HNS3_MAX_TQP_NUM_PER_FUNC on the maximum
   number of queues in hns3 VF PMD driver and use the value allocated by
   hns3 PF kernel netdev driver.

2) According to the queue number allocated to PF device, a variable array
   for Rx and Tx queue is dynamically allocated to record the statistics of
   Rx and Tx queues during the .dev_init ops implementation function.
3) Add an extended field in hns3_pf_res_cmd to support the case that
   numbers of queue are greater than 1024.
4) Use new base address of Rx or Tx queue if QUEUE_ID of Rx or Tx queue is
   greater than 1024.
5) Remove queue id mask and use all bits of actual queue_id as the queue_id
   to configure hardware.
6) Currently, 0~9 bits of qset_id in hns3_nq_to_qs_link_cmd used to record
   actual qset id and 10 bit as VLD bit are configured to hardware. So we
   also need to use 11~15 bits when actual qset_id is greater than 1024.
7) The number of queue sets based on different network engine are
   different. We use it to calculate group number and configure to hardware
   in the backpressure configuration.
8) Adding check operations for number of Rx and Tx queue user configured
   when mapping queue to tc Rx queue numbers under a single TC must be
   less than rss_size_max supported by a single TC. Rx and Tx queue numbers
   are allocated to every TC by avarage. So Rx and Tx queue numbers must be
   an integer multiple of 2, or redundant queues are not available.
9) We can specify which packets enter the queue with a specific queue
   number, when creating flow table rules by rte_flow api. Currently,
   driver uses 0~9 bits to record the queue_id. So it is necessary to
   extend one bit field to record queue_id and configure to hardware, if
   the queue_id is greater than 1024.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 config/rte_config.h               |   3 +
 drivers/net/hns3/hns3_cmd.h       |   7 +-
 drivers/net/hns3/hns3_dcb.c       | 138 +++++++++++++++++++++++++++++++-------
 drivers/net/hns3/hns3_dcb.h       |  21 +++---
 drivers/net/hns3/hns3_ethdev.c    | 100 +++++++++++++++++++--------
 drivers/net/hns3/hns3_ethdev.h    |  30 ++++++++-
 drivers/net/hns3/hns3_ethdev_vf.c |  59 +++++++++-------
 drivers/net/hns3/hns3_fdir.c      |   5 ++
 drivers/net/hns3/hns3_regs.c      |   2 +-
 drivers/net/hns3/hns3_regs.h      |   3 +
 drivers/net/hns3/hns3_rxtx.c      |  28 ++++++--
 drivers/net/hns3/hns3_rxtx.h      |   2 +
 drivers/net/hns3/hns3_stats.c     |  73 +++++++++++++++-----
 drivers/net/hns3/hns3_stats.h     |   6 +-
 14 files changed, 362 insertions(+), 115 deletions(-)

diff --git a/config/rte_config.h b/config/rte_config.h
index 0bae630..03d90d7 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -117,6 +117,9 @@
 /* fm10k defines */
 #define RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE 1
 
+/* hns3 defines */
+#define RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF 256
+
 /* i40e defines */
 #define RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC 1
 #undef RTE_LIBRTE_I40E_16BYTE_RX_DESC
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index dd50484..ecca75c 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -9,7 +9,6 @@
 #define HNS3_CMDQ_RX_INVLD_B		0
 #define HNS3_CMDQ_RX_OUTVLD_B		1
 #define HNS3_CMD_DESC_ALIGNMENT		4096
-#define HNS3_QUEUE_ID_MASK		0x1ff
 #define HNS3_CMD_FLAG_NEXT		BIT(2)
 
 struct hns3_hw;
@@ -388,7 +387,8 @@ struct hns3_pf_res_cmd {
 	uint16_t pf_own_fun_number;
 	uint16_t tx_buf_size;
 	uint16_t dv_buf_size;
-	uint16_t tqp_num_ext;
+	/* number of queues that exceed 1024 */
+	uint16_t ext_tqp_num;
 	uint16_t roh_pf_intr_vector_number;
 	uint32_t rsv[1];
 };
@@ -671,7 +671,6 @@ struct hns3_config_mac_speed_dup_cmd {
 	uint8_t rsv[22];
 };
 
-#define HNS3_RING_ID_MASK		GENMASK(9, 0)
 #define HNS3_TQP_ENABLE_B		0
 
 #define HNS3_MAC_CFG_AN_EN_B		0
@@ -835,7 +834,7 @@ struct hns3_dev_specs_0_cmd {
 	uint32_t max_tm_rate;
 };
 
-#define HNS3_MAX_TQP_NUM_PER_FUNC	64
+#define HNS3_MAX_TQP_NUM_HIP08_PF	64
 #define HNS3_DEFAULT_TX_BUF		0x4000    /* 16k  bytes */
 #define HNS3_TOTAL_PKT_BUF		0x108000  /* 1.03125M bytes */
 #define HNS3_DEFAULT_DV			0xA000    /* 40k byte */
diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index c1be49e..fecedff 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -576,21 +576,31 @@ hns3_dcb_pri_shaper_cfg(struct hns3_hw *hw)
 	return ret;
 }
 
-void
+static int
 hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q)
 {
 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
 	uint16_t rx_qnum_per_tc;
+	uint16_t used_rx_queues;
 	int i;
 
 	rx_qnum_per_tc = nb_rx_q / hw->num_tc;
-	rx_qnum_per_tc = RTE_MIN(hw->rss_size_max, rx_qnum_per_tc);
-	if (hw->alloc_rss_size != rx_qnum_per_tc) {
-		hns3_info(hw, "rss size changes from %u to %u",
-			  hw->alloc_rss_size, rx_qnum_per_tc);
-		hw->alloc_rss_size = rx_qnum_per_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.",
+			 rx_qnum_per_tc, hw->rss_size_max);
+		return -EINVAL;
 	}
-	hw->used_rx_queues = hw->num_tc * hw->alloc_rss_size;
+
+	used_rx_queues = hw->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);
+		return -EINVAL;
+	}
+	hw->alloc_rss_size = rx_qnum_per_tc;
+	hw->used_rx_queues = used_rx_queues;
 
 	/*
 	 * When rss size is changed, we need to update rss redirection table
@@ -604,15 +614,29 @@ hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q)
 			rss_cfg->rss_indirection_tbl[i] =
 							i % hw->alloc_rss_size;
 	}
+
+	return 0;
 }
 
-void
-hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue)
+static int
+hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_tx_q)
 {
 	struct hns3_tc_queue_info *tc_queue;
+	uint16_t used_tx_queues;
+	uint16_t tx_qnum_per_tc;
 	uint8_t i;
 
-	hw->tx_qnum_per_tc = nb_queue / hw->num_tc;
+	tx_qnum_per_tc = nb_tx_q / hw->num_tc;
+	used_tx_queues = hw->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);
+		return -EINVAL;
+	}
+
+	hw->used_tx_queues = used_tx_queues;
+	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) {
@@ -628,22 +652,39 @@ hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue)
 			tc_queue->tc = 0;
 		}
 	}
-	hw->used_tx_queues = hw->num_tc * hw->tx_qnum_per_tc;
+
+	return 0;
 }
 
-static void
+int
+hns3_queue_to_tc_mapping(struct hns3_hw *hw, uint16_t nb_rx_q, uint16_t nb_tx_q)
+{
+	int ret;
+
+	ret = hns3_set_rss_size(hw, nb_rx_q);
+	if (ret)
+		return ret;
+
+	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)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct hns3_pf *pf = &hns->pf;
+	int ret;
 
 	hw->num_tc = hw->dcb_info.num_tc;
-	hns3_set_rss_size(hw, nb_rx_q);
-	hns3_tc_queue_mapping_cfg(hw, nb_tx_q);
+	ret = hns3_queue_to_tc_mapping(hw, nb_rx_q, nb_tx_q);
+	if (ret)
+		return ret;
 
 	if (!hns->is_vf)
 		memcpy(pf->prio_tc, hw->dcb_info.prio_tc, HNS3_MAX_USER_PRIO);
+
+	return 0;
 }
 
 int
@@ -886,13 +927,35 @@ hns3_q_to_qs_map_cfg(struct hns3_hw *hw, uint16_t q_id, uint16_t qs_id)
 {
 	struct hns3_nq_to_qs_link_cmd *map;
 	struct hns3_cmd_desc desc;
+	uint16_t tmp_qs_id = 0;
+	uint16_t qs_id_l;
+	uint16_t qs_id_h;
 
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_NQ_TO_QS_LINK, false);
 
 	map = (struct hns3_nq_to_qs_link_cmd *)desc.data;
 
 	map->nq_id = rte_cpu_to_le_16(q_id);
-	map->qset_id = rte_cpu_to_le_16(qs_id | HNS3_DCB_Q_QS_LINK_VLD_MSK);
+
+	/*
+	 * Network engine with revision_id 0x21 uses 0~9 bit of qs_id to
+	 * configure qset_id. So we need to convert qs_id to the follow
+	 * format to support qset_id > 1024.
+	 * qs_id: | 15 | 14 ~ 10 |  9 ~ 0   |
+	 *            /         / \         \
+	 *           /         /   \         \
+	 * qset_id: | 15 ~ 11 |  10 |  9 ~ 0  |
+	 *          | qs_id_h | vld | qs_id_l |
+	 */
+	qs_id_l = hns3_get_field(qs_id, HNS3_DCB_QS_ID_L_MSK,
+				 HNS3_DCB_QS_ID_L_S);
+	qs_id_h = hns3_get_field(qs_id, HNS3_DCB_QS_ID_H_MSK,
+				 HNS3_DCB_QS_ID_H_S);
+	hns3_set_field(tmp_qs_id, HNS3_DCB_QS_ID_L_MSK, HNS3_DCB_QS_ID_L_S,
+		       qs_id_l);
+	hns3_set_field(tmp_qs_id, HNS3_DCB_QS_ID_H_EXT_MSK,
+		       HNS3_DCB_QS_ID_H_EXT_S, qs_id_h);
+	map->qset_id = rte_cpu_to_le_16(tmp_qs_id | HNS3_DCB_Q_QS_LINK_VLD_MSK);
 
 	return hns3_cmd_send(hw, &desc, 1);
 }
@@ -1291,7 +1354,7 @@ hns3_dcb_cfg_validate(struct hns3_adapter *hns, uint8_t *tc, bool *changed)
 		*changed = true;
 }
 
-static void
+static int
 hns3_dcb_info_cfg(struct hns3_adapter *hns)
 {
 	struct rte_eth_dcb_rx_conf *dcb_rx_conf;
@@ -1299,6 +1362,7 @@ hns3_dcb_info_cfg(struct hns3_adapter *hns)
 	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;
@@ -1338,8 +1402,12 @@ 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];
 
-	hns3_dcb_update_tc_queue_mapping(hw, hw->data->nb_rx_queues,
-					 hw->data->nb_tx_queues);
+	ret = hns3_dcb_update_tc_queue_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);
+
+	return ret;
 }
 
 static int
@@ -1378,9 +1446,8 @@ hns3_dcb_info_update(struct hns3_adapter *hns, uint8_t num_tc)
 		hw->dcb_info.num_tc = 1;
 	}
 	hw->hw_tc_map = bit_map;
-	hns3_dcb_info_cfg(hns);
 
-	return 0;
+	return hns3_dcb_info_cfg(hns);
 }
 
 static int
@@ -1505,6 +1572,7 @@ hns3_dcb_init(struct hns3_hw *hw)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct hns3_pf *pf = &hns->pf;
+	uint16_t default_tqp_num;
 	int ret;
 
 	PMD_INIT_FUNC_TRACE();
@@ -1525,11 +1593,24 @@ hns3_dcb_init(struct hns3_hw *hw)
 
 		ret = hns3_dcb_info_init(hw);
 		if (ret) {
-			hns3_err(hw, "dcb info init failed: %d", ret);
+			hns3_err(hw, "dcb info init failed, ret = %d.", ret);
+			return ret;
+		}
+
+		/*
+		 * The number of queues configured by default cannot exceed
+		 * the maximum number of queues for a single TC.
+		 */
+		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);
+		if (ret) {
+			hns3_err(hw,
+				 "update tc queue mapping failed, ret = %d.",
+				 ret);
 			return ret;
 		}
-		hns3_dcb_update_tc_queue_mapping(hw, hw->tqps_num,
-						 hw->tqps_num);
 	}
 
 	/*
@@ -1541,7 +1622,7 @@ hns3_dcb_init(struct hns3_hw *hw)
 	 */
 	ret = hns3_dcb_init_hw(hw);
 	if (ret) {
-		hns3_err(hw, "dcb init hardware failed: %d", ret);
+		hns3_err(hw, "dcb init hardware failed, ret = %d.", ret);
 		return ret;
 	}
 
@@ -1556,10 +1637,15 @@ hns3_update_queue_map_configure(struct hns3_adapter *hns)
 	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	int ret;
 
-	hns3_dcb_update_tc_queue_mapping(hw, nb_rx_q, nb_tx_q);
+	ret = hns3_dcb_update_tc_queue_mapping(hw, nb_rx_q, nb_tx_q);
+	if (ret) {
+		hns3_err(hw, "failed to update tc queue mapping, ret = %d.",
+			 ret);
+		return ret;
+	}
 	ret = hns3_q_to_qs_map(hw);
 	if (ret)
-		hns3_err(hw, "failed to map nq to qs! ret = %d", ret);
+		hns3_err(hw, "failed to map nq to qs, ret = %d.", ret);
 
 	return ret;
 }
diff --git a/drivers/net/hns3/hns3_dcb.h b/drivers/net/hns3/hns3_dcb.h
index 557d88b..05c9786 100644
--- a/drivers/net/hns3/hns3_dcb.h
+++ b/drivers/net/hns3/hns3_dcb.h
@@ -52,6 +52,12 @@ struct hns3_qs_to_pri_link_cmd {
 	uint16_t rsvd;
 	uint8_t priority;
 #define HNS3_DCB_QS_PRI_LINK_VLD_MSK	BIT(0)
+#define HNS3_DCB_QS_ID_L_MSK		GENMASK(9, 0)
+#define HNS3_DCB_QS_ID_L_S		0
+#define HNS3_DCB_QS_ID_H_MSK		GENMASK(14, 10)
+#define HNS3_DCB_QS_ID_H_S		10
+#define HNS3_DCB_QS_ID_H_EXT_S		11
+#define HNS3_DCB_QS_ID_H_EXT_MSK	GENMASK(15, 11)
 	uint8_t link_vld;
 	uint8_t rsvd1[18];
 };
@@ -89,11 +95,12 @@ struct hns3_pg_shapping_cmd {
 	uint32_t rsvd1[4];
 };
 
-#define HNS3_BP_GRP_NUM		32
+#define HNS3_BP_GRP_NUM			32
 #define HNS3_BP_SUB_GRP_ID_S		0
 #define HNS3_BP_SUB_GRP_ID_M		GENMASK(4, 0)
 #define HNS3_BP_GRP_ID_S		5
 #define HNS3_BP_GRP_ID_M		GENMASK(9, 5)
+
 struct hns3_bp_to_qs_map_cmd {
 	uint8_t tc_id;
 	uint8_t rsvd[2];
@@ -165,15 +172,13 @@ int hns3_dcb_init_hw(struct hns3_hw *hw);
 
 int hns3_dcb_info_init(struct hns3_hw *hw);
 
-int
-hns3_fc_enable(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf);
-
-int
-hns3_dcb_pfc_enable(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf);
+int hns3_fc_enable(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf);
 
-void hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q);
+int hns3_dcb_pfc_enable(struct rte_eth_dev *dev,
+			struct rte_eth_pfc_conf *pfc_conf);
 
-void hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue);
+int hns3_queue_to_tc_mapping(struct hns3_hw *hw, uint16_t nb_rx_q,
+			     uint16_t nb_tx_q);
 
 int hns3_dcb_cfg_update(struct hns3_adapter *hns);
 
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index c45b1b3..3162852 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2660,6 +2660,49 @@ hns3_query_function_status(struct hns3_hw *hw)
 }
 
 static int
+hns3_get_pf_max_tqp_num(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+
+	if (pf->tqp_config_mode == HNS3_FLEX_MAX_TQP_NUM_MODE) {
+		/*
+		 * The total_tqps_num obtained from firmware is maximum tqp
+		 * numbers of this port, which should be used for pf and vfs.
+		 * There is no need for pf to have so many tqp numbers in
+		 * most cases. RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF,
+		 * coming from config file, is assigned to maximum queue number
+		 * for the pf of this port by user. So users can modify the
+		 * maximum queue number of pf according to their own application
+		 * scenarios, which is more flexible to use. In addition, many
+		 * memories can be saved due to allocating queue statistics
+		 * room according to the actual number of queues required. The
+		 * maximum queue number of pf fpr network engine with
+		 * revision_id greater than 0x30 is assigned by config file.
+		 */
+		if (RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF <= 0) {
+			hns3_err(hw, "RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF(%d) "
+				 "must be greater than 0.",
+				 RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF);
+			return -EINVAL;
+		}
+
+		hw->tqps_num = RTE_MIN(RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF,
+				       hw->total_tqps_num);
+	} else {
+		/*
+		 * Due to the limitation on the number of pf interrupts
+		 * available, the maximum queue number assigned to pf on
+		 * the network engine with revision_id 0x21 is 64.
+		 */
+		hw->tqps_num = RTE_MIN(hw->total_tqps_num,
+				       HNS3_MAX_TQP_NUM_HIP08_PF);
+	}
+
+	return 0;
+}
+
+static int
 hns3_query_pf_resource(struct hns3_hw *hw)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
@@ -2676,9 +2719,13 @@ hns3_query_pf_resource(struct hns3_hw *hw)
 	}
 
 	req = (struct hns3_pf_res_cmd *)desc.data;
-	hw->total_tqps_num = rte_le_to_cpu_16(req->tqp_num);
+	hw->total_tqps_num = rte_le_to_cpu_16(req->tqp_num) +
+			     rte_le_to_cpu_16(req->ext_tqp_num);
+	ret = hns3_get_pf_max_tqp_num(hw);
+	if (ret)
+		return ret;
+
 	pf->pkt_buf_size = rte_le_to_cpu_16(req->buf_size) << HNS3_BUF_UNIT_S;
-	hw->tqps_num = RTE_MIN(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
 	pf->func_num = rte_le_to_cpu_16(req->pf_own_fun_number);
 
 	if (req->tx_buf_size)
@@ -2902,7 +2949,9 @@ hns3_query_dev_specifications(struct hns3_hw *hw)
 static int
 hns3_get_capability(struct hns3_hw *hw)
 {
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct rte_pci_device *pci_dev;
+	struct hns3_pf *pf = &hns->pf;
 	struct rte_eth_dev *eth_dev;
 	uint16_t device_id;
 	uint8_t revision;
@@ -2936,6 +2985,7 @@ hns3_get_capability(struct hns3_hw *hw)
 		hw->tso_mode = HNS3_TSO_SW_CAL_PSEUDO_H_CSUM;
 		hw->vlan_mode = HNS3_SW_SHIFT_AND_DISCARD_MODE;
 		hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN;
+		pf->tqp_config_mode = HNS3_FIXED_MAX_TQP_NUM_MODE;
 		return 0;
 	}
 
@@ -2953,6 +3003,7 @@ hns3_get_capability(struct hns3_hw *hw)
 	hw->tso_mode = HNS3_TSO_HW_CAL_PSEUDO_H_CSUM;
 	hw->vlan_mode = HNS3_HW_SHIFT_AND_DISCARD_MODE;
 	hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN;
+	pf->tqp_config_mode = HNS3_FLEX_MAX_TQP_NUM_MODE;
 
 	return 0;
 }
@@ -3048,7 +3099,7 @@ hns3_get_configuration(struct hns3_hw *hw)
 
 	ret = hns3_get_board_configuration(hw);
 	if (ret)
-		PMD_INIT_LOG(ERR, "Failed to get board configuration: %d", ret);
+		PMD_INIT_LOG(ERR, "failed to get board configuration: %d", ret);
 
 	return ret;
 }
@@ -3081,29 +3132,18 @@ hns3_map_tqps_to_func(struct hns3_hw *hw, uint16_t func_id, uint16_t tqp_pid,
 static int
 hns3_map_tqp(struct hns3_hw *hw)
 {
-	uint16_t tqps_num = hw->total_tqps_num;
-	uint16_t func_id;
-	uint16_t tqp_id;
-	bool is_pf;
-	int num;
 	int ret;
 	int i;
 
 	/*
-	 * In current version VF is not supported when PF is driven by DPDK
-	 * driver, so we allocate tqps to PF as much as possible.
+	 * In current version, VF is not supported when PF is driven by DPDK
+	 * driver, so we assign total tqps_num tqps allocated to this port
+	 * to PF.
 	 */
-	tqp_id = 0;
-	num = DIV_ROUND_UP(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
-	for (func_id = HNS3_PF_FUNC_ID; func_id < num; func_id++) {
-		is_pf = func_id == HNS3_PF_FUNC_ID ? true : false;
-		for (i = 0;
-		     i < HNS3_MAX_TQP_NUM_PER_FUNC && tqp_id < tqps_num; i++) {
-			ret = hns3_map_tqps_to_func(hw, func_id, tqp_id++, i,
-						    is_pf);
-			if (ret)
-				return ret;
-		}
+	for (i = 0; i < hw->total_tqps_num; i++) {
+		ret = hns3_map_tqps_to_func(hw, HNS3_PF_FUNC_ID, i, i, true);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
@@ -4558,17 +4598,21 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
 		goto err_get_config;
 	}
 
+	ret = hns3_tqp_stats_init(hw);
+	if (ret)
+		goto err_get_config;
+
 	ret = hns3_init_hardware(hns);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to init hardware: %d", ret);
-		goto err_get_config;
+		goto err_init_hw;
 	}
 
 	/* Initialize flow director filter list & hash */
 	ret = hns3_fdir_filter_init(hns);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to alloc hashmap for fdir: %d", ret);
-		goto err_hw_init;
+		goto err_fdir;
 	}
 
 	hns3_set_default_rss_args(hw);
@@ -4577,16 +4621,17 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
 	if (ret) {
 		PMD_INIT_LOG(ERR, "fail to enable hw error interrupts: %d",
 			     ret);
-		goto err_fdir;
+		goto err_enable_intr;
 	}
 
 	return 0;
 
-err_fdir:
+err_enable_intr:
 	hns3_fdir_filter_uninit(hns);
-err_hw_init:
+err_fdir:
 	hns3_uninit_umv_space(hw);
-
+err_init_hw:
+	hns3_tqp_stats_uninit(hw);
 err_get_config:
 	hns3_pf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
@@ -4618,6 +4663,7 @@ hns3_uninit_pf(struct rte_eth_dev *eth_dev)
 	hns3_promisc_uninit(hw);
 	hns3_fdir_filter_uninit(hns);
 	hns3_uninit_umv_space(hw);
+	hns3_tqp_stats_uninit(hw);
 	hns3_pf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
 	hns3_intr_unregister(&pci_dev->intr_handle, hns3_interrupt_handler,
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 3c5ccc7..22c6a15 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -134,9 +134,9 @@ enum hns3_fc_status {
 };
 
 struct hns3_tc_queue_info {
-	uint8_t	tqp_offset;     /* TQP offset from base TQP */
-	uint8_t	tqp_count;      /* Total TQPs */
-	uint8_t	tc;             /* TC index */
+	uint16_t tqp_offset;    /* TQP offset from base TQP */
+	uint16_t tqp_count;     /* Total TQPs */
+	uint8_t tc;             /* TC index */
 	bool enable;            /* If this TC is enable or not */
 };
 
@@ -661,11 +661,35 @@ struct hns3_ptype_table {
 	uint32_t ol4table[HNS3_OL4TBL_NUM];
 };
 
+#define HNS3_FIXED_MAX_TQP_NUM_MODE		0
+#define HNS3_FLEX_MAX_TQP_NUM_MODE		1
+
 struct hns3_pf {
 	struct hns3_adapter *adapter;
 	bool is_main_pf;
 	uint16_t func_num; /* num functions of this pf, include pf and vfs */
 
+	/*
+	 * tqp_config mode
+	 * tqp_config_mode value range:
+	 *	HNS3_FIXED_MAX_TQP_NUM_MODE,
+	 *	HNS3_FLEX_MAX_TQP_NUM_MODE
+	 *
+	 * - HNS3_FIXED_MAX_TQP_NUM_MODE
+	 *   There is a limitation on the number of pf interrupts available for
+	 *   on some versions of network engines. In this case, the maximum
+	 *   queue number of pf can not be greater than the interrupt number,
+	 *   such as pf of network engine with revision_id 0x21. So the maximum
+	 *   number of queues must be fixed.
+	 *
+	 * - HNS3_FLEX_MAX_TQP_NUM_MODE
+	 *   In this mode, the maximum queue number of pf has not any constraint
+	 *   and comes from the macro RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF
+	 *   in the config file. Users can modify the macro according to their
+	 *   own application scenarios, which is more flexible to use.
+	 */
+	uint8_t tqp_config_mode;
+
 	uint32_t pkt_buf_size; /* Total pf buf size for tx/rx */
 	uint32_t tx_buf_size; /* Tx buffer size for each TC */
 	uint32_t dv_buf_size; /* Dv buffer size for each TC */
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 4c73441..0b949e9 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1191,20 +1191,21 @@ hns3vf_get_capability(struct hns3_hw *hw)
 static int
 hns3vf_check_tqp_info(struct hns3_hw *hw)
 {
-	uint16_t tqps_num;
+	if (hw->tqps_num == 0) {
+		PMD_INIT_LOG(ERR, "Get invalid tqps_num(0) from PF.");
+		return -EINVAL;
+	}
 
-	tqps_num = hw->tqps_num;
-	if (tqps_num > HNS3_MAX_TQP_NUM_PER_FUNC || tqps_num == 0) {
-		PMD_INIT_LOG(ERR, "Get invalid tqps_num(%u) from PF. valid "
-				  "range: 1~%d",
-			     tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
+	if (hw->rss_size_max == 0) {
+		PMD_INIT_LOG(ERR, "Get invalid rss_size_max(0) from PF.");
 		return -EINVAL;
 	}
 
-	hw->alloc_rss_size = RTE_MIN(hw->rss_size_max, hw->tqps_num);
+	hw->tqps_num = RTE_MIN(hw->rss_size_max, hw->tqps_num);
 
 	return 0;
 }
+
 static int
 hns3vf_get_port_base_vlan_filter_state(struct hns3_hw *hw)
 {
@@ -1295,6 +1296,7 @@ hns3vf_get_tc_info(struct hns3_hw *hw)
 {
 	uint8_t resp_msg;
 	int ret;
+	int i;
 
 	ret = hns3_send_mbx_msg(hw, HNS3_MBX_GET_TCINFO, 0, NULL, 0,
 				true, &resp_msg, sizeof(resp_msg));
@@ -1306,6 +1308,11 @@ hns3vf_get_tc_info(struct hns3_hw *hw)
 
 	hw->hw_tc_map = resp_msg;
 
+	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
+		if (hw->hw_tc_map & BIT(i))
+			hw->num_tc++;
+	}
+
 	return 0;
 }
 
@@ -1366,17 +1373,10 @@ hns3vf_get_configuration(struct hns3_hw *hw)
 }
 
 static int
-hns3vf_set_tc_info(struct hns3_adapter *hns)
+hns3vf_set_tc_queue_mapping(struct hns3_adapter *hns, uint16_t nb_rx_q,
+			    uint16_t nb_tx_q)
 {
 	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;
-	uint8_t i;
-
-	hw->num_tc = 0;
-	for (i = 0; i < HNS3_MAX_TC_NUM; i++)
-		if (hw->hw_tc_map & BIT(i))
-			hw->num_tc++;
 
 	if (nb_rx_q < hw->num_tc) {
 		hns3_err(hw, "number of Rx queues(%d) is less than tcs(%d).",
@@ -1390,10 +1390,7 @@ hns3vf_set_tc_info(struct hns3_adapter *hns)
 		return -EINVAL;
 	}
 
-	hns3_set_rss_size(hw, nb_rx_q);
-	hns3_tc_queue_mapping_cfg(hw, nb_tx_q);
-
-	return 0;
+	return hns3_queue_to_tc_mapping(hw, nb_rx_q, nb_tx_q);
 }
 
 static void
@@ -1783,20 +1780,33 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)
 		goto err_get_config;
 	}
 
+	ret = hns3_tqp_stats_init(hw);
+	if (ret)
+		goto err_get_config;
+
+	ret = hns3vf_set_tc_queue_mapping(hns, hw->tqps_num, hw->tqps_num);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "failed to set tc info, ret = %d.", ret);
+		goto err_set_tc_queue;
+	}
+
 	ret = hns3vf_clear_vport_list(hw);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to clear tbl list: %d", ret);
-		goto err_get_config;
+		goto err_set_tc_queue;
 	}
 
 	ret = hns3vf_init_hardware(hns);
 	if (ret)
-		goto err_get_config;
+		goto err_set_tc_queue;
 
 	hns3_set_default_rss_args(hw);
 
 	return 0;
 
+err_set_tc_queue:
+	hns3_tqp_stats_uninit(hw);
+
 err_get_config:
 	hns3vf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
@@ -1825,6 +1835,7 @@ hns3vf_uninit_vf(struct rte_eth_dev *eth_dev)
 	(void)hns3_config_gro(hw, false);
 	(void)hns3vf_set_alive(hw, false);
 	(void)hns3vf_set_promisc_mode(hw, false, false, false);
+	hns3_tqp_stats_uninit(hw);
 	hns3vf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
 	hns3_intr_unregister(&pci_dev->intr_handle, hns3vf_interrupt_handler,
@@ -2004,9 +2015,11 @@ 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 = hns3vf_set_tc_info(hns);
+	ret = hns3vf_set_tc_queue_mapping(hns, nb_rx_q, nb_tx_q);
 	if (ret)
 		return ret;
 
diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c
index e6a065b..79e3028 100644
--- a/drivers/net/hns3/hns3_fdir.c
+++ b/drivers/net/hns3/hns3_fdir.c
@@ -46,6 +46,8 @@
 #define HNS3_FD_AD_QUEUE_REGION_SIZE_M	GENMASK(20, 17)
 #define HNS3_FD_AD_COUNTER_HIGH_BIT	7
 #define HNS3_FD_AD_COUNTER_HIGH_BIT_B	26
+#define HNS3_FD_AD_QUEUE_ID_HIGH_BIT	10
+#define HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B	21
 
 enum HNS3_PORT_TYPE {
 	HOST_PORT,
@@ -437,6 +439,9 @@ static int hns3_fd_ad_config(struct hns3_hw *hw, int loc,
 	/* set extend bit if counter_id is in [128 ~ 255] */
 	if (action->counter_id & BIT(HNS3_FD_AD_COUNTER_HIGH_BIT))
 		hns3_set_bit(ad_data, HNS3_FD_AD_COUNTER_HIGH_BIT_B, 1);
+	/* set extend bit if queue id > 1024 */
+	if (action->queue_id & BIT(HNS3_FD_AD_QUEUE_ID_HIGH_BIT))
+		hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B, 1);
 	ad_data <<= HNS3_FD_AD_DATA_S;
 	hns3_set_bit(ad_data, HNS3_FD_AD_DROP_B, action->drop_packet);
 	if (action->nb_queues == 1)
diff --git a/drivers/net/hns3/hns3_regs.c b/drivers/net/hns3/hns3_regs.c
index 63c8602..a76f42c 100644
--- a/drivers/net/hns3/hns3_regs.c
+++ b/drivers/net/hns3/hns3_regs.c
@@ -295,7 +295,7 @@ hns3_direct_access_regs(struct hns3_hw *hw, uint32_t *data)
 	reg_um = sizeof(ring_reg_addrs) / sizeof(uint32_t);
 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
 	for (j = 0; j < hw->tqps_num; j++) {
-		reg_offset = HNS3_TQP_REG_OFFSET + HNS3_TQP_REG_SIZE * j;
+		reg_offset = hns3_get_tqp_reg_offset(j);
 		for (i = 0; i < reg_um; i++)
 			*data++ = hns3_read_dev(hw,
 						ring_reg_addrs[i] + reg_offset);
diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h
index 5cf924e..d83c3b3 100644
--- a/drivers/net/hns3/hns3_regs.h
+++ b/drivers/net/hns3/hns3_regs.h
@@ -89,6 +89,9 @@
 #define HNS3_TQP_REG_OFFSET			0x80000
 #define HNS3_TQP_REG_SIZE			0x200
 
+#define HNS3_TQP_EXT_REG_OFFSET			0x100
+#define HNS3_MIN_EXTEND_QUEUE_ID		1024
+
 /* bar registers for tqp interrupt */
 #define HNS3_TQP_INTR_CTRL_REG			0x20000
 #define HNS3_TQP_INTR_GL0_REG			0x20100
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 930aa28..e3f0db4 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -405,7 +405,7 @@ hns3_tqp_enable(struct hns3_hw *hw, uint16_t queue_id, bool enable)
 	req = (struct hns3_cfg_com_tqp_queue_cmd *)desc.data;
 
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_COM_TQP_QUEUE, false);
-	req->tqp_id = rte_cpu_to_le_16(queue_id & HNS3_RING_ID_MASK);
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
 	req->stream_id = 0;
 	hns3_set_bit(req->enable, HNS3_TQP_ENABLE_B, enable ? 1 : 0);
 
@@ -426,7 +426,7 @@ hns3_send_reset_tqp_cmd(struct hns3_hw *hw, uint16_t queue_id, bool enable)
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE, false);
 
 	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
-	req->tqp_id = rte_cpu_to_le_16(queue_id & HNS3_RING_ID_MASK);
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
 	hns3_set_bit(req->reset_req, HNS3_TQP_RESET_B, enable ? 1 : 0);
 
 	ret = hns3_cmd_send(hw, &desc, 1);
@@ -446,7 +446,7 @@ hns3_get_reset_status(struct hns3_hw *hw, uint16_t queue_id)
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE, true);
 
 	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
-	req->tqp_id = rte_cpu_to_le_16(queue_id & HNS3_RING_ID_MASK);
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
 
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret) {
@@ -1341,6 +1341,22 @@ hns3_rx_queue_conf_check(struct hns3_hw *hw, const struct rte_eth_rxconf *conf,
 	return 0;
 }
 
+uint32_t
+hns3_get_tqp_reg_offset(uint16_t queue_id)
+{
+	uint32_t reg_offset;
+
+	/* Need an extend offset to config queue > 1024 */
+	if (queue_id < HNS3_MIN_EXTEND_QUEUE_ID)
+		reg_offset = HNS3_TQP_REG_OFFSET + queue_id * HNS3_TQP_REG_SIZE;
+	else
+		reg_offset = HNS3_TQP_REG_OFFSET + HNS3_TQP_EXT_REG_OFFSET +
+			     (queue_id - HNS3_MIN_EXTEND_QUEUE_ID) *
+			     HNS3_TQP_REG_SIZE;
+
+	return reg_offset;
+}
+
 int
 hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		    unsigned int socket_id, const struct rte_eth_rxconf *conf,
@@ -1422,6 +1438,8 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	rxq->configured = true;
 	rxq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
 				idx * HNS3_TQP_REG_SIZE);
+	rxq->io_base = (void *)((char *)hw->io_base +
+					hns3_get_tqp_reg_offset(idx));
 	rxq->io_head_reg = (volatile void *)((char *)rxq->io_base +
 			   HNS3_RING_RX_HEAD_REG);
 	rxq->rx_buf_len = rx_buf_size;
@@ -2183,8 +2201,8 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		txq->pvid_sw_shift_en = false;
 	txq->max_non_tso_bd_num = hw->max_non_tso_bd_num;
 	txq->configured = true;
-	txq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
-				idx * HNS3_TQP_REG_SIZE);
+	txq->io_base = (void *)((char *)hw->io_base +
+						hns3_get_tqp_reg_offset(idx));
 	txq->io_tail_reg = (volatile void *)((char *)txq->io_base +
 					     HNS3_RING_TX_TAIL_REG);
 	txq->min_tx_pkt_len = hw->min_tx_pkt_len;
diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index d7d70f6..cdfe115 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -661,4 +661,6 @@ void hns3_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 		       struct rte_eth_rxq_info *qinfo);
 void hns3_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 		       struct rte_eth_txq_info *qinfo);
+uint32_t hns3_get_tqp_reg_offset(uint16_t idx);
+
 #endif /* _HNS3_RXTX_H_ */
diff --git a/drivers/net/hns3/hns3_stats.c b/drivers/net/hns3/hns3_stats.c
index e8846b9..8c3c7cc 100644
--- a/drivers/net/hns3/hns3_stats.c
+++ b/drivers/net/hns3/hns3_stats.c
@@ -330,6 +330,8 @@ static const struct hns3_xstats_name_offset hns3_tx_queue_strings[] = {
 #define HNS3_FIX_NUM_STATS (HNS3_NUM_MAC_STATS + HNS3_NUM_ERROR_INT_XSTATS + \
 			    HNS3_NUM_RESET_XSTATS)
 
+static void hns3_tqp_stats_clear(struct hns3_hw *hw);
+
 /*
  * Query all the MAC statistics data of Network ICL command ,opcode id: 0x0034.
  * This command is used before send 'query_mac_stat command', the descriptor
@@ -456,8 +458,7 @@ hns3_update_tqp_stats(struct hns3_hw *hw)
 		hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_RX_STATUS,
 					  true);
 
-		desc.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						HNS3_QUEUE_ID_MASK);
+		desc.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to query RX No.%d queue stat: %d",
@@ -471,8 +472,7 @@ hns3_update_tqp_stats(struct hns3_hw *hw)
 		hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_TX_STATUS,
 					  true);
 
-		desc.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						HNS3_QUEUE_ID_MASK);
+		desc.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to query TX No.%d queue stat: %d",
@@ -553,7 +553,6 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 {
 	struct hns3_adapter *hns = eth_dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	struct hns3_tqp_stats *stats = &hw->tqp_stats;
 	struct hns3_cmd_desc desc_reset;
 	struct hns3_rx_queue *rxq;
 	struct hns3_tx_queue *txq;
@@ -561,14 +560,13 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 	int ret;
 
 	/*
-	 * If this is a reset xstats is NULL, and we have cleared the
-	 * registers by reading them.
+	 * Note: Reading hardware statistics of rx/tx queue packet number
+	 * will clear them.
 	 */
 	for (i = 0; i < hw->tqps_num; i++) {
 		hns3_cmd_setup_basic_desc(&desc_reset, HNS3_OPC_QUERY_RX_STATUS,
 					  true);
-		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						      HNS3_QUEUE_ID_MASK);
+		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc_reset, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to reset RX No.%d queue stat: %d",
@@ -578,8 +576,7 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 
 		hns3_cmd_setup_basic_desc(&desc_reset, HNS3_OPC_QUERY_TX_STATUS,
 					  true);
-		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						      HNS3_QUEUE_ID_MASK);
+		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc_reset, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to reset TX No.%d queue stat: %d",
@@ -614,7 +611,7 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 		}
 	}
 
-	memset(stats, 0, sizeof(struct hns3_tqp_stats));
+	hns3_tqp_stats_clear(hw);
 
 	return 0;
 }
@@ -668,8 +665,7 @@ hns3_get_queue_stats(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	/* Get rx queue stats */
 	for (j = 0; j < dev->data->nb_rx_queues; j++) {
 		for (i = 0; i < HNS3_NUM_RX_QUEUE_STATS; i++) {
-			reg_offset = HNS3_TQP_REG_OFFSET +
-					HNS3_TQP_REG_SIZE * j;
+			reg_offset = hns3_get_tqp_reg_offset(j);
 			xstats[*count].value = hns3_read_dev(hw,
 				reg_offset + hns3_rx_queue_strings[i].offset);
 			xstats[*count].id = *count;
@@ -680,8 +676,7 @@ hns3_get_queue_stats(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	/* Get tx queue stats */
 	for (j = 0; j < dev->data->nb_tx_queues; j++) {
 		for (i = 0; i < HNS3_NUM_TX_QUEUE_STATS; i++) {
-			reg_offset = HNS3_TQP_REG_OFFSET +
-					HNS3_TQP_REG_SIZE * j;
+			reg_offset = hns3_get_tqp_reg_offset(j);
 			xstats[*count].value = hns3_read_dev(hw,
 				reg_offset + hns3_tx_queue_strings[i].offset);
 			xstats[*count].id = *count;
@@ -1071,3 +1066,49 @@ hns3_dev_xstats_reset(struct rte_eth_dev *dev)
 
 	return 0;
 }
+
+int
+hns3_tqp_stats_init(struct hns3_hw *hw)
+{
+	struct hns3_tqp_stats *tqp_stats = &hw->tqp_stats;
+
+	tqp_stats->rcb_rx_ring_pktnum = rte_zmalloc("hns3_rx_ring_pkt_num",
+					 sizeof(uint64_t) * hw->tqps_num, 0);
+	if (tqp_stats->rcb_rx_ring_pktnum == NULL) {
+		hns3_err(hw, "failed to allocate rx_ring pkt_num.");
+		return -ENOMEM;
+	}
+
+	tqp_stats->rcb_tx_ring_pktnum = rte_zmalloc("hns3_tx_ring_pkt_num",
+					 sizeof(uint64_t) * hw->tqps_num, 0);
+	if (tqp_stats->rcb_tx_ring_pktnum == NULL) {
+		hns3_err(hw, "failed to allocate tx_ring pkt_num.");
+		rte_free(tqp_stats->rcb_rx_ring_pktnum);
+		tqp_stats->rcb_rx_ring_pktnum = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void
+hns3_tqp_stats_uninit(struct hns3_hw *hw)
+{
+	struct hns3_tqp_stats *tqp_stats = &hw->tqp_stats;
+
+	rte_free(tqp_stats->rcb_rx_ring_pktnum);
+	tqp_stats->rcb_rx_ring_pktnum = NULL;
+	rte_free(tqp_stats->rcb_tx_ring_pktnum);
+	tqp_stats->rcb_tx_ring_pktnum = NULL;
+}
+
+static void
+hns3_tqp_stats_clear(struct hns3_hw *hw)
+{
+	struct hns3_tqp_stats *stats = &hw->tqp_stats;
+
+	stats->rcb_rx_ring_pktnum_rcd = 0;
+	stats->rcb_tx_ring_pktnum_rcd = 0;
+	memset(stats->rcb_rx_ring_pktnum, 0, sizeof(uint64_t) * hw->tqps_num);
+	memset(stats->rcb_tx_ring_pktnum, 0, sizeof(uint64_t) * hw->tqps_num);
+}
diff --git a/drivers/net/hns3/hns3_stats.h b/drivers/net/hns3/hns3_stats.h
index 07570cb..9fcd5f9 100644
--- a/drivers/net/hns3/hns3_stats.h
+++ b/drivers/net/hns3/hns3_stats.h
@@ -14,8 +14,8 @@
 struct hns3_tqp_stats {
 	uint64_t rcb_tx_ring_pktnum_rcd; /* Total num of transmitted packets */
 	uint64_t rcb_rx_ring_pktnum_rcd; /* Total num of received packets */
-	uint64_t rcb_tx_ring_pktnum[HNS3_MAX_TQP_NUM_PER_FUNC];
-	uint64_t rcb_rx_ring_pktnum[HNS3_MAX_TQP_NUM_PER_FUNC];
+	uint64_t *rcb_rx_ring_pktnum;
+	uint64_t *rcb_tx_ring_pktnum;
 };
 
 /* mac stats, Statistics counters collected by the MAC, opcode id: 0x0032 */
@@ -149,5 +149,7 @@ int hns3_dev_xstats_get_names_by_id(struct rte_eth_dev *dev,
 				    uint32_t size);
 int hns3_stats_reset(struct rte_eth_dev *dev);
 void hns3_error_int_stats_add(struct hns3_adapter *hns, const char *err);
+int hns3_tqp_stats_init(struct hns3_hw *hw);
+void hns3_tqp_stats_uninit(struct hns3_hw *hw);
 
 #endif /* _HNS3_STATS_H_ */
-- 
2.9.5


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

* [dpdk-dev] [PATCH 3/9] net/hns3: fix error type when validating RSS flow action
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 2/9] net/hns3: maximize the queue number Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 4/9] net/hns3: set suitable type when initial flow error struct Wei Hu (Xavier)
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: "Wei Hu (Xavier)" <xavier.huwei@huawei.com>

Because the macro named RTE_FLOW_ERROR_TYPE_ACTION_CONF indicates a action
configuration and the macro named RTE_FLOW_ERROR_TYPE_ACTION indicates a
specific action, the driver needs to return RTE_FLOW_ERROR_ACTION_CONF type
and notify the user when a RSS configuration is invalid with actions list
in the internal function named hns3_parse_rss_filter called by the
'.validate' ops implementation function named hns3_flow_validate.

Besides, this patch removes some unncessary judgment lines in
hns3_parse_rss_filter.

Fixes: c37ca66f2b27 ("net/hns3: support RSS")
Cc: stable@dpdk.org

Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_flow.c | 35 +++++++++--------------------------
 1 file changed, 9 insertions(+), 26 deletions(-)

diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index f8e5f05..a6676d6 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -1356,7 +1356,6 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev,
 	const struct rte_flow_action_rss *rss;
 	const struct rte_flow_action *act;
 	uint32_t act_index = 0;
-	uint64_t flow_types;
 	uint16_t n;
 
 	NEXT_ITEM_OF_ACTION(act, actions, act_index);
@@ -1364,7 +1363,7 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev,
 
 	if (rss == NULL) {
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act, "no valid queues");
 	}
 
@@ -1372,48 +1371,32 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev,
 		if (rss->queue[n] < dev->data->nb_rx_queues)
 			continue;
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act,
 					  "queue id > max number of queues");
 	}
 
-	/* Parse flow types of RSS */
 	if (!(rss->types & HNS3_ETH_RSS_SUPPORT) && rss->types)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act,
 					  "Flow types is unsupported by "
 					  "hns3's RSS");
-
-	flow_types = rss->types & HNS3_ETH_RSS_SUPPORT;
-	if (flow_types != rss->types)
-		hns3_warn(hw, "RSS flow types(%" PRIx64 ") include unsupported "
-			  "flow types", rss->types);
-
-	/* Parse RSS related parameters from RSS configuration */
-	switch (rss->func) {
-	case RTE_ETH_HASH_FUNCTION_DEFAULT:
-	case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
-	case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
-	case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
-		break;
-	default:
+	if (rss->func >= RTE_ETH_HASH_FUNCTION_MAX)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
-					  "input RSS hash functions are not supported");
-	}
-
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
+					  "RSS hash func are not supported");
 	if (rss->level)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "a nonzero RSS encapsulation level is not supported");
 	if (rss->key_len && rss->key_len != RTE_DIM(rss_conf->key))
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "RSS hash key must be exactly 40 bytes");
 	if (rss->queue_num > RTE_DIM(rss_conf->queue))
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "too many queues for RSS context");
 
 	if (rss->types & (ETH_RSS_L4_DST_ONLY | ETH_RSS_L4_SRC_ONLY) &&
-- 
2.9.5


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

* [dpdk-dev] [PATCH 4/9] net/hns3: set suitable type when initial flow error struct
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                   ` (2 preceding siblings ...)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 3/9] net/hns3: fix error type when validating RSS flow action Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 5/9] net/hns3: offload calculating the shapping para to firmware Wei Hu (Xavier)
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: "Wei Hu (Xavier)" <xavier.huwei@huawei.com>

The API of rte_flow_error_set is used to pass detail error information to
caller, this patch sets suitable type when calling rte_flow_error_set API.

Fixes: fcba820d9b9e ("net/hns3: support flow director")
Fixes: c37ca66f2b27 ("net/hns3: support RSS")
Cc: stable@dpdk.org

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_flow.c | 54 ++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index a6676d6..4fb129e 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -168,9 +168,9 @@ hns3_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,
 	if (cnt) {
 		if (!cnt->shared || cnt->shared != shared)
 			return rte_flow_error_set(error, ENOTSUP,
-						  RTE_FLOW_ERROR_TYPE_ACTION,
-						  cnt,
-						  "Counter id is used,shared flag not match");
+				RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+				cnt,
+				"Counter id is used, shared flag not match");
 		cnt->ref_cnt++;
 		return 0;
 	}
@@ -178,7 +178,7 @@ hns3_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,
 	cnt = rte_zmalloc("hns3 counter", sizeof(*cnt), 0);
 	if (cnt == NULL)
 		return rte_flow_error_set(error, ENOMEM,
-					  RTE_FLOW_ERROR_TYPE_ACTION, cnt,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, cnt,
 					  "Alloc mem for counter failed");
 	cnt->id = id;
 	cnt->shared = shared;
@@ -206,13 +206,13 @@ hns3_counter_query(struct rte_eth_dev *dev, struct rte_flow *flow,
 	cnt = hns3_counter_lookup(dev, flow->counter_id);
 	if (cnt == NULL)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 					  "Can't find counter id");
 
 	ret = hns3_get_count(&hns->hw, flow->counter_id, &value);
 	if (ret) {
 		rte_flow_error_set(error, -ret,
-				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "Read counter fail.");
 		return ret;
 	}
@@ -374,9 +374,9 @@ hns3_handle_actions(struct rte_eth_dev *dev,
 			    (const struct rte_flow_action_mark *)actions->conf;
 			if (mark->id >= HNS3_MAX_FILTER_ID)
 				return rte_flow_error_set(error, EINVAL,
-						     RTE_FLOW_ERROR_TYPE_ACTION,
-						     actions,
-						     "Invalid Mark ID");
+						RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+						actions,
+						"Invalid Mark ID");
 			rule->fd_id = mark->id;
 			rule->flags |= HNS3_RULE_FLAG_FDID;
 			break;
@@ -390,9 +390,9 @@ hns3_handle_actions(struct rte_eth_dev *dev,
 			counter_num = pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1];
 			if (act_count->id >= counter_num)
 				return rte_flow_error_set(error, EINVAL,
-						     RTE_FLOW_ERROR_TYPE_ACTION,
-						     actions,
-						     "Invalid counter id");
+						RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+						actions,
+						"Invalid counter id");
 			rule->act_cnt = *act_count;
 			rule->flags |= HNS3_RULE_FLAG_COUNTER;
 			break;
@@ -556,7 +556,7 @@ hns3_parse_ipv4(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		    ipv4_mask->hdr.time_to_live ||
 		    ipv4_mask->hdr.hdr_checksum) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst ip,tos,proto in IPV4");
 		}
@@ -621,7 +621,7 @@ hns3_parse_ipv6(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		if (ipv6_mask->hdr.vtc_flow ||
 		    ipv6_mask->hdr.payload_len || ipv6_mask->hdr.hop_limits) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst ip,proto in IPV6");
 		}
@@ -681,7 +681,7 @@ hns3_parse_tcp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		    tcp_mask->hdr.rx_win ||
 		    tcp_mask->hdr.cksum || tcp_mask->hdr.tcp_urp) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in TCP");
 		}
@@ -728,7 +728,7 @@ hns3_parse_udp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		udp_mask = item->mask;
 		if (udp_mask->hdr.dgram_len || udp_mask->hdr.dgram_cksum) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in UDP");
 		}
@@ -775,7 +775,7 @@ hns3_parse_sctp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		sctp_mask = item->mask;
 		if (sctp_mask->hdr.cksum)
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in SCTP");
 
@@ -920,14 +920,14 @@ hns3_parse_vxlan(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (vxlan_mask->flags)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Flags is not supported in VxLAN");
 
 	/* VNI must be totally masked or not. */
 	if (memcmp(vxlan_mask->vni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(vxlan_mask->vni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "VNI must be totally masked or not in VxLAN");
 	if (vxlan_mask->vni[0]) {
 		hns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);
@@ -971,14 +971,14 @@ hns3_parse_nvgre(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (nvgre_mask->protocol || nvgre_mask->c_k_s_rsvd0_ver)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Ver/protocal is not supported in NVGRE");
 
 	/* TNI must be totally masked or not. */
 	if (memcmp(nvgre_mask->tni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(nvgre_mask->tni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "TNI must be totally masked or not in NVGRE");
 
 	if (nvgre_mask->tni[0]) {
@@ -1025,13 +1025,13 @@ hns3_parse_geneve(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (geneve_mask->ver_opt_len_o_c_rsvd0 || geneve_mask->protocol)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Ver/protocal is not supported in GENEVE");
 	/* VNI must be totally masked or not. */
 	if (memcmp(geneve_mask->vni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(geneve_mask->vni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "VNI must be totally masked or not in GENEVE");
 	if (geneve_mask->vni[0]) {
 		hns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);
@@ -1062,7 +1062,7 @@ hns3_parse_tunnel(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_HANDLE,
+					  RTE_FLOW_ERROR_TYPE_ITEM,
 					  NULL, "Unsupported tunnel type!");
 	}
 	if (ret)
@@ -1116,7 +1116,7 @@ hns3_parse_normal(const struct rte_flow_item *item,
 		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_HANDLE,
+					  RTE_FLOW_ERROR_TYPE_ITEM,
 					  NULL, "Unsupported normal type!");
 	}
 
@@ -1132,7 +1132,7 @@ hns3_validate_item(const struct rte_flow_item *item,
 
 	if (item->last)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_LAST, item,
 					  "Not supported last point for range");
 
 	for (i = 0; i < step_mngr.count; i++) {
@@ -1218,7 +1218,7 @@ hns3_parse_fdir_filter(struct rte_eth_dev *dev,
 
 	if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 					  "fdir_conf.mode isn't perfect");
 
 	step_mngr.items = first_items;
-- 
2.9.5


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

* [dpdk-dev] [PATCH 5/9] net/hns3: offload calculating the shapping para to firmware
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                   ` (3 preceding siblings ...)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 4/9] net/hns3: set suitable type when initial flow error struct Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 6/9] net/hns3: set max scheduling rate based on actual board Wei Hu (Xavier)
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Huisong Li <lihuisong@huawei.com>

In order to have more flexible selection of shapping algorithm based on
different versions of hns3 network engine, moves the algorithm of
calculating shapping parameter to firmware to execute. If bit
HNS3_TM_RATE_VLD_B of flag field of struct named hns3_pri_shapping_cmd,
hns3_pg_shapping_cmd or hns3_port_shapping_cmd is set to 1, firmware of
network engine, which device revision_id is greater than and equal to 0x30,
will recalculate the shapping parameters according to the xxx_rate field
of struct hns3_xxx_shapping_cmd and the opcode of scheduling level, and
configure to hardware.

But driver still needs to calculate shapping parameters and configure
firmware, so as to be compatible with the network engine with revision_id
eqauls 0x21. And the rate and the flag will be ignored based on the network
engine with revision_id equals 0x21.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_dcb.c | 55 +++++++++++++++++++++++++++++++++++----------
 drivers/net/hns3/hns3_dcb.h | 39 +++++++++++++++++++++++++-------
 2 files changed, 74 insertions(+), 20 deletions(-)

diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index fecedff..857e79e 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -365,12 +365,22 @@ hns3_dcb_port_shaper_cfg(struct hns3_hw *hw)
 
 	shap_cfg_cmd->port_shapping_para = rte_cpu_to_le_32(shapping_para);
 
+	/*
+	 * Configure the port_rate and set bit HNS3_TM_RATE_VLD_B of flag
+	 * field in hns3_port_shapping_cmd to require firmware to recalculate
+	 * shapping parameters. And whether the parameters are recalculated
+	 * depends on the firmware version. But driver still needs to
+	 * calculate it and configure to firmware for better compatibility.
+	 */
+	shap_cfg_cmd->port_rate = rte_cpu_to_le_32(hw->mac.link_speed);
+	hns3_set_bit(shap_cfg_cmd->flag, HNS3_TM_RATE_VLD_B, 1);
+
 	return hns3_cmd_send(hw, &desc, 1);
 }
 
 static int
 hns3_dcb_pg_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
-			 uint8_t pg_id, uint32_t shapping_para)
+			 uint8_t pg_id, uint32_t shapping_para, uint32_t rate)
 {
 	struct hns3_pg_shapping_cmd *shap_cfg_cmd;
 	enum hns3_opcode_type opcode;
@@ -386,6 +396,16 @@ hns3_dcb_pg_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
 
 	shap_cfg_cmd->pg_shapping_para = rte_cpu_to_le_32(shapping_para);
 
+	/*
+	 * Configure the pg_rate and set bit HNS3_TM_RATE_VLD_B of flag field in
+	 * hns3_pg_shapping_cmd to require firmware to recalculate shapping
+	 * parameters. And whether parameters are recalculated depends on
+	 * the firmware version. But driver still needs to calculate it and
+	 * configure to firmware for better compatibility.
+	 */
+	shap_cfg_cmd->pg_rate = rte_cpu_to_le_32(rate);
+	hns3_set_bit(shap_cfg_cmd->flag, HNS3_TM_RATE_VLD_B, 1);
+
 	return hns3_cmd_send(hw, &desc, 1);
 }
 
@@ -397,6 +417,7 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 	struct hns3_pf *pf = &hns->pf;
 	uint32_t ir_u, ir_b, ir_s;
 	uint32_t shaper_para;
+	uint32_t rate;
 	uint8_t i;
 	int ret;
 
@@ -406,10 +427,10 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 
 	/* Pg to pri */
 	for (i = 0; i < hw->dcb_info.num_pg; i++) {
+		rate = hw->dcb_info.pg_info[i].bw_limit;
+
 		/* Calc shaper para */
-		ret = hns3_shaper_para_calc(hw,
-					    hw->dcb_info.pg_info[i].bw_limit,
-					    HNS3_SHAPER_LVL_PG,
+		ret = hns3_shaper_para_calc(hw, rate, HNS3_SHAPER_LVL_PG,
 					    &shaper_parameter);
 		if (ret) {
 			hns3_err(hw, "calculate shaper parameter failed: %d",
@@ -422,7 +443,7 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pg_shapping_cfg(hw, HNS3_DCB_SHAP_C_BUCKET, i,
-					       shaper_para);
+					       shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config PG CIR shaper parameter failed: %d",
@@ -438,7 +459,7 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pg_shapping_cfg(hw, HNS3_DCB_SHAP_P_BUCKET, i,
-					       shaper_para);
+					       shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config PG PIR shaper parameter failed: %d",
@@ -486,7 +507,7 @@ hns3_dcb_pri_schd_mode_cfg(struct hns3_hw *hw, uint8_t pri_id)
 
 static int
 hns3_dcb_pri_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
-			  uint8_t pri_id, uint32_t shapping_para)
+			  uint8_t pri_id, uint32_t shapping_para, uint32_t rate)
 {
 	struct hns3_pri_shapping_cmd *shap_cfg_cmd;
 	enum hns3_opcode_type opcode;
@@ -503,6 +524,16 @@ hns3_dcb_pri_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
 
 	shap_cfg_cmd->pri_shapping_para = rte_cpu_to_le_32(shapping_para);
 
+	/*
+	 * Configure the pri_rate and set bit HNS3_TM_RATE_VLD_B of flag
+	 * field in hns3_pri_shapping_cmd to require firmware to recalculate
+	 * shapping parameters. And whether the parameters are recalculated
+	 * depends on the firmware version. But driver still needs to
+	 * calculate it and configure to firmware for better compatibility.
+	 */
+	shap_cfg_cmd->pri_rate = rte_cpu_to_le_32(rate);
+	hns3_set_bit(shap_cfg_cmd->flag, HNS3_TM_RATE_VLD_B, 1);
+
 	return hns3_cmd_send(hw, &desc, 1);
 }
 
@@ -512,12 +543,12 @@ hns3_dcb_pri_tc_base_shaper_cfg(struct hns3_hw *hw)
 	struct hns3_shaper_parameter shaper_parameter;
 	uint32_t ir_u, ir_b, ir_s;
 	uint32_t shaper_para;
+	uint32_t rate;
 	int ret, i;
 
 	for (i = 0; i < hw->dcb_info.num_tc; i++) {
-		ret = hns3_shaper_para_calc(hw,
-					    hw->dcb_info.tc_info[i].bw_limit,
-					    HNS3_SHAPER_LVL_PRI,
+		rate = hw->dcb_info.tc_info[i].bw_limit;
+		ret = hns3_shaper_para_calc(hw, rate, HNS3_SHAPER_LVL_PRI,
 					    &shaper_parameter);
 		if (ret) {
 			hns3_err(hw, "calculate shaper parameter failed: %d",
@@ -530,7 +561,7 @@ hns3_dcb_pri_tc_base_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pri_shapping_cfg(hw, HNS3_DCB_SHAP_C_BUCKET, i,
-						shaper_para);
+						shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config priority CIR shaper parameter failed: %d",
@@ -546,7 +577,7 @@ hns3_dcb_pri_tc_base_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pri_shapping_cfg(hw, HNS3_DCB_SHAP_P_BUCKET, i,
-						shaper_para);
+						shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config priority PIR shaper parameter failed: %d",
diff --git a/drivers/net/hns3/hns3_dcb.h b/drivers/net/hns3/hns3_dcb.h
index 05c9786..39ff332 100644
--- a/drivers/net/hns3/hns3_dcb.h
+++ b/drivers/net/hns3/hns3_dcb.h
@@ -16,7 +16,7 @@
 
 /* SP or DWRR */
 #define HNS3_DCB_TX_SCHD_DWRR_MSK	BIT(0)
-#define HNS3_DCB_TX_SCHD_SP_MSK		(0xFE)
+#define HNS3_DCB_TX_SCHD_SP_MSK		0xFE
 
 enum hns3_shap_bucket {
 	HNS3_DCB_SHAP_C_BUCKET = 0,
@@ -81,18 +81,46 @@ struct hns3_nq_to_qs_link_cmd {
 #define HNS3_DCB_SHAP_BS_S_MSK  GENMASK(25, 21)
 #define HNS3_DCB_SHAP_BS_S_LSH	21
 
+/*
+ * For more flexible selection of shapping algorithm in different network
+ * engine, the algorithm calculating shapping parameter is moved to firmware to
+ * execute. Bit HNS3_TM_RATE_VLD_B of flag field in hns3_pri_shapping_cmd,
+ * hns3_pg_shapping_cmd or hns3_port_shapping_cmd is set to 1 to require
+ * firmware to recalculate shapping parameters. However, whether the parameters
+ * are recalculated depends on the firmware version. If firmware doesn't support
+ * the calculation of shapping parameters, such as on network engine with
+ * revision id 0x21, the value driver calculated will be used to configure to
+ * hardware. On the contrary, firmware ignores configuration of driver
+ * and recalculates the parameter.
+ */
+#define HNS3_TM_RATE_VLD_B	0
+
 struct hns3_pri_shapping_cmd {
 	uint8_t pri_id;
 	uint8_t rsvd[3];
 	uint32_t pri_shapping_para;
-	uint32_t rsvd1[4];
+	uint8_t flag;
+	uint8_t rsvd1[3];
+	uint32_t pri_rate;  /* Unit Mbps */
+	uint8_t rsvd2[8];
 };
 
 struct hns3_pg_shapping_cmd {
 	uint8_t pg_id;
 	uint8_t rsvd[3];
 	uint32_t pg_shapping_para;
-	uint32_t rsvd1[4];
+	uint8_t flag;
+	uint8_t rsvd1[3];
+	uint32_t pg_rate; /* Unit Mbps */
+	uint8_t rsvd2[8];
+};
+
+struct hns3_port_shapping_cmd {
+	uint32_t port_shapping_para;
+	uint8_t flag;
+	uint8_t rsvd[3];
+	uint32_t port_rate;   /* Unit Mbps */
+	uint8_t rsvd1[12];
 };
 
 #define HNS3_BP_GRP_NUM			32
@@ -115,11 +143,6 @@ struct hns3_pfc_en_cmd {
 	uint8_t rsvd[22];
 };
 
-struct hns3_port_shapping_cmd {
-	uint32_t port_shapping_para;
-	uint32_t rsvd[5];
-};
-
 struct hns3_cfg_pause_param_cmd {
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
 	uint8_t pause_trans_gap;
-- 
2.9.5


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

* [dpdk-dev] [PATCH 6/9] net/hns3: set max scheduling rate based on actual board
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                   ` (4 preceding siblings ...)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 5/9] net/hns3: offload calculating the shapping para to firmware Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 7/9] net/hns3: support start and stop Tx or Rx queue Wei Hu (Xavier)
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Huisong Li <lihuisong@huawei.com>

Currently, max scheduling rates configuration of pg, pri and port are set
to 100000Mbps, which is the maximum bandwidth of hns3 network engine with
revision_id equals 0x21. However, max scheduling rate configuration should
be set to hardware based on the actual hardware board environment.

The max_tm_rate in struct hns3_hw, meaning the rate, is obtained from
firmware. So we should use the variable to configure the max scheduling
rate.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_dcb.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index 857e79e..27ae014 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -62,9 +62,9 @@ hns3_shaper_para_calc(struct hns3_hw *hw, uint32_t ir, uint8_t shaper_level,
 		return -EINVAL;
 	}
 
-	if (ir > HNS3_ETHER_MAX_RATE) {
-		hns3_err(hw, "rate(%d) exceeds the rate driver supported "
-			 "HNS3_ETHER_MAX_RATE(%d)", ir, HNS3_ETHER_MAX_RATE);
+	if (ir > hw->max_tm_rate) {
+		hns3_err(hw, "rate(%d) exceeds the max rate(%d) driver "
+			 "supported.", ir, hw->max_tm_rate);
 		return -EINVAL;
 	}
 
@@ -100,7 +100,7 @@ hns3_shaper_para_calc(struct hns3_hw *hw, uint32_t ir, uint8_t shaper_level,
 		 * ir_calc gets minimum value when tick is the maximum value.
 		 * At the same time, value of ir_u_calc can only be increased up
 		 * to eight after the while loop if the value of ir is equal
-		 * to HNS3_ETHER_MAX_RATE.
+		 * to hw->max_tm_rate.
 		 */
 		uint32_t numerator;
 		do {
@@ -736,7 +736,7 @@ hns3_dcb_info_init(struct hns3_hw *hw)
 		hw->dcb_info.pg_dwrr[i] = i ? 0 : BW_MAX_PERCENT;
 		hw->dcb_info.pg_info[i].pg_id = i;
 		hw->dcb_info.pg_info[i].pg_sch_mode = HNS3_SCH_MODE_DWRR;
-		hw->dcb_info.pg_info[i].bw_limit = HNS3_ETHER_MAX_RATE;
+		hw->dcb_info.pg_info[i].bw_limit = hw->max_tm_rate;
 
 		if (i != 0)
 			continue;
@@ -1405,7 +1405,7 @@ hns3_dcb_info_cfg(struct hns3_adapter *hns)
 	hw->dcb_info.pg_dwrr[0] = BW_MAX_PERCENT;
 	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 = HNS3_ETHER_MAX_RATE;
+	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;
 
 	/* Each tc has same bw for valid tc by default */
-- 
2.9.5


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

* [dpdk-dev] [PATCH 7/9] net/hns3: support start and stop Tx or Rx queue
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                   ` (5 preceding siblings ...)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 6/9] net/hns3: set max scheduling rate based on actual board Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 8/9] net/hns3: check return value when reading PCI config space Wei Hu (Xavier)
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Chengchang Tang <tangchengchang@huawei.com>

The new generation hns3 network engine supports independent enabling and
disabling of a single Tx/Rx queue. So, it can support the queue start and
stop feature. In addition, when different numbers of Tx and Rx queues need
to be enabled in some applications, hns3 pmd does not need to create fake
queues to enable these scenarios.

This patch Add queue start and stop feature for the new generation hns3
networking engine. Cancel the creation of fake queue on the new generation
network engine. And the previously improperly named queue related function
was renamed to improve readability.

Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_cmd.h       |   4 +-
 drivers/net/hns3/hns3_ethdev.c    |  98 ++++--
 drivers/net/hns3/hns3_ethdev_vf.c |  93 ++++--
 drivers/net/hns3/hns3_regs.c      |   2 +
 drivers/net/hns3/hns3_regs.h      |   2 +
 drivers/net/hns3/hns3_rxtx.c      | 647 +++++++++++++++++++++++++++++++-------
 drivers/net/hns3/hns3_rxtx.h      |  16 +-
 8 files changed, 691 insertions(+), 173 deletions(-)

diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c
index f7cfa00..589547c 100644
--- a/drivers/net/hns3/hns3_cmd.c
+++ b/drivers/net/hns3/hns3_cmd.c
@@ -443,7 +443,7 @@ static void hns3_parse_capability(struct hns3_hw *hw,
 	if (hns3_get_bit(caps, HNS3_CAPS_PHY_IMP_B))
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_COPPER_B, 1);
 	if (hns3_get_bit(caps, HNS3_CAPS_TQP_TXRX_INDEP_B))
-		hns3_set_bit(hw->capability, HNS3_CAPS_TQP_TXRX_INDEP_B, 1);
+		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_INDEP_TXRX_B, 1);
 	if (hns3_get_bit(caps, HNS3_CAPS_STASH_B))
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_STASH_B, 1);
 }
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index ecca75c..bbd0034 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -159,6 +159,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_QUERY_RX_STATUS        = 0x0B13,
 	HNS3_OPC_CFG_COM_TQP_QUEUE      = 0x0B20,
 	HNS3_OPC_RESET_TQP_QUEUE        = 0x0B22,
+	HNS3_OPC_RESET_TQP_QUEUE_INDEP  = 0x0B23,
 
 	/* TSO command */
 	HNS3_OPC_TSO_GENERIC_CONFIG     = 0x0C01,
@@ -810,7 +811,8 @@ struct hns3_reset_tqp_queue_cmd {
 	uint16_t tqp_id;
 	uint8_t reset_req;
 	uint8_t ready_to_reset;
-	uint8_t rsv[20];
+	uint8_t queue_direction;
+	uint8_t rsv[19];
 };
 
 #define HNS3_CFG_RESET_MAC_B		3
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 3162852..158bc11 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2293,20 +2293,25 @@ hns3_dev_configure(struct rte_eth_dev *dev)
 	bool gro_en;
 	int ret;
 
+	hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
+
 	/*
-	 * Hardware does not support individually enable/disable/reset the Tx or
-	 * Rx queue in hns3 network engine. Driver must enable/disable/reset Tx
-	 * and Rx queues at the same time. When the numbers of Tx queues
-	 * allocated by upper applications are not equal to the numbers of Rx
-	 * queues, driver needs to setup fake Tx or Rx queues to adjust numbers
-	 * of Tx/Rx queues. otherwise, network engine can not work as usual. But
-	 * these fake queues are imperceptible, and can not be used by upper
-	 * applications.
+	 * Some versions of hardware network engine does not support
+	 * individually enable/disable/reset the Tx or Rx queue. These devices
+	 * must enable/disable/reset Tx and Rx queues at the same time. When the
+	 * numbers of Tx queues allocated by upper applications are not equal to
+	 * the numbers of Rx queues, driver needs to setup fake Tx or Rx queues
+	 * to adjust numbers of Tx/Rx queues. otherwise, network engine can not
+	 * work as usual. But these fake queues are imperceptible, and can not
+	 * be used by upper applications.
 	 */
-	ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
-	if (ret) {
-		hns3_err(hw, "Failed to set rx/tx fake queues: %d", ret);
-		return ret;
+	if (!hns3_dev_indep_txrx_supported(hw)) {
+		ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
+		if (ret) {
+			hns3_err(hw, "fail to set Rx/Tx fake queues, ret = %d.",
+				 ret);
+			return ret;
+		}
 	}
 
 	hw->adapter_state = HNS3_NIC_CONFIGURING;
@@ -2504,6 +2509,10 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_TX_OFFLOAD_MBUF_FAST_FREE |
 				 hns3_txvlan_cap_get(hw));
 
+	if (hns3_dev_indep_txrx_supported(hw))
+		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+
 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = HNS3_MAX_RING_DESC,
 		.nb_min = HNS3_MIN_RING_DESC,
@@ -4684,23 +4693,22 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue)
 	if (ret)
 		return ret;
 
-	/* Enable queues */
-	ret = hns3_start_queues(hns, reset_queue);
+	ret = hns3_init_queues(hns, reset_queue);
 	if (ret) {
-		PMD_INIT_LOG(ERR, "Failed to start queues: %d", ret);
+		PMD_INIT_LOG(ERR, "failed to init queues, ret = %d.", ret);
 		return ret;
 	}
 
-	/* Enable MAC */
 	ret = hns3_cfg_mac_mode(hw, true);
 	if (ret) {
-		PMD_INIT_LOG(ERR, "Failed to enable MAC: %d", ret);
+		PMD_INIT_LOG(ERR, "failed to enable MAC, ret = %d", ret);
 		goto err_config_mac_mode;
 	}
 	return 0;
 
 err_config_mac_mode:
-	hns3_stop_queues(hns, true);
+	hns3_dev_release_mbufs(hns);
+	hns3_reset_all_tqps(hns);
 	return ret;
 }
 
@@ -4831,6 +4839,32 @@ hns3_dev_start(struct rte_eth_dev *dev)
 		return ret;
 	}
 
+	/*
+	 * There are three register used to control the status of a TQP
+	 * (contains a pair of Tx queue and Rx queue) in the new version network
+	 * engine. One is used to control the enabling of Tx queue, the other is
+	 * used to control the enabling of Rx queue, and the last is the master
+	 * switch used to control the enabling of the tqp. The Tx register and
+	 * TQP register must be enabled at the same time to enable a Tx queue.
+	 * The same applies to the Rx queue. For the older network engine, this
+	 * function only refresh the enabled flag, and it is used to update the
+	 * status of queue in the dpdk framework.
+	 */
+	ret = hns3_start_all_txqs(dev);
+	if (ret) {
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
+	ret = hns3_start_all_rxqs(dev);
+	if (ret) {
+		hns3_stop_all_txqs(dev);
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
 	hw->adapter_state = HNS3_NIC_STARTED;
 	rte_spinlock_unlock(&hw->lock);
 
@@ -4843,11 +4877,12 @@ hns3_dev_start(struct rte_eth_dev *dev)
 
 	/* Enable interrupt of all rx queues before enabling queues */
 	hns3_dev_all_rx_queue_intr_enable(hw, true);
+
 	/*
-	 * When finished the initialization, enable queues to receive/transmit
-	 * packets.
+	 * After finished the initialization, enable tqps to receive/transmit
+	 * packets and refresh all queue status.
 	 */
-	hns3_enable_all_queues(hw, true);
+	hns3_start_tqps(hw);
 
 	hns3_info(hw, "hns3 dev start successful!");
 	return 0;
@@ -4857,7 +4892,6 @@ static int
 hns3_do_stop(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	bool reset_queue;
 	int ret;
 
 	ret = hns3_cfg_mac_mode(hw, false);
@@ -4867,11 +4901,15 @@ hns3_do_stop(struct hns3_adapter *hns)
 
 	if (rte_atomic16_read(&hw->reset.disable_cmd) == 0) {
 		hns3_configure_all_mac_addr(hns, true);
-		reset_queue = true;
-	} else
-		reset_queue = false;
+		ret = hns3_reset_all_tqps(hns);
+		if (ret) {
+			hns3_err(hw, "failed to reset all queues ret = %d.",
+				 ret);
+			return ret;
+		}
+	}
 	hw->mac.default_addr_setted = false;
-	return hns3_stop_queues(hns, reset_queue);
+	return 0;
 }
 
 static void
@@ -4928,6 +4966,7 @@ hns3_dev_stop(struct rte_eth_dev *dev)
 
 	rte_spinlock_lock(&hw->lock);
 	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
+		hns3_stop_tqps(hw);
 		hns3_do_stop(hns);
 		hns3_unmap_rx_interrupt(dev);
 		hns3_dev_release_mbufs(hns);
@@ -5165,7 +5204,7 @@ hns3_reinit_dev(struct hns3_adapter *hns)
 		return ret;
 	}
 
-	ret = hns3_reset_all_queues(hns);
+	ret = hns3_reset_all_tqps(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to reset all queues: %d", ret);
 		return ret;
@@ -5443,6 +5482,7 @@ hns3_stop_service(struct hns3_adapter *hns)
 	rte_spinlock_lock(&hw->lock);
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED ||
 	    hw->adapter_state == HNS3_NIC_STOPPING) {
+		hns3_enable_all_queues(hw, false);
 		hns3_do_stop(hns);
 		hw->reset.mbuf_deferred_free = true;
 	} else
@@ -5626,6 +5666,10 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.tx_queue_setup         = hns3_tx_queue_setup,
 	.rx_queue_release       = hns3_dev_rx_queue_release,
 	.tx_queue_release       = hns3_dev_tx_queue_release,
+	.rx_queue_start         = hns3_dev_rx_queue_start,
+	.rx_queue_stop          = hns3_dev_rx_queue_stop,
+	.tx_queue_start         = hns3_dev_tx_queue_start,
+	.tx_queue_stop          = hns3_dev_tx_queue_stop,
 	.rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
 	.rxq_info_get           = hns3_rxq_info_get,
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 0b949e9..849f6cc 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -757,20 +757,25 @@ hns3vf_dev_configure(struct rte_eth_dev *dev)
 	bool gro_en;
 	int ret;
 
+	hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
+
 	/*
-	 * Hardware does not support individually enable/disable/reset the Tx or
-	 * Rx queue in hns3 network engine. Driver must enable/disable/reset Tx
-	 * and Rx queues at the same time. When the numbers of Tx queues
-	 * allocated by upper applications are not equal to the numbers of Rx
-	 * queues, driver needs to setup fake Tx or Rx queues to adjust numbers
-	 * of Tx/Rx queues. otherwise, network engine can not work as usual. But
-	 * these fake queues are imperceptible, and can not be used by upper
-	 * applications.
+	 * Some versions of hardware network engine does not support
+	 * individually enable/disable/reset the Tx or Rx queue. These devices
+	 * must enable/disable/reset Tx and Rx queues at the same time. When the
+	 * numbers of Tx queues allocated by upper applications are not equal to
+	 * the numbers of Rx queues, driver needs to setup fake Tx or Rx queues
+	 * to adjust numbers of Tx/Rx queues. otherwise, network engine can not
+	 * work as usual. But these fake queues are imperceptible, and can not
+	 * be used by upper applications.
 	 */
-	ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
-	if (ret) {
-		hns3_err(hw, "Failed to set rx/tx fake queues: %d", ret);
-		return ret;
+	if (!hns3_dev_indep_txrx_supported(hw)) {
+		ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
+		if (ret) {
+			hns3_err(hw, "fail to set Rx/Tx fake queues, ret = %d.",
+				 ret);
+			return ret;
+		}
 	}
 
 	hw->adapter_state = HNS3_NIC_CONFIGURING;
@@ -956,6 +961,10 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_TX_OFFLOAD_MBUF_FAST_FREE |
 				 hns3_txvlan_cap_get(hw));
 
+	if (hns3_dev_indep_txrx_supported(hw))
+		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+
 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = HNS3_MAX_RING_DESC,
 		.nb_min = HNS3_MIN_RING_DESC,
@@ -1849,16 +1858,20 @@ static int
 hns3vf_do_stop(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	bool reset_queue;
+	int ret;
 
 	hw->mac.link_status = ETH_LINK_DOWN;
 
 	if (rte_atomic16_read(&hw->reset.disable_cmd) == 0) {
 		hns3vf_configure_mac_addr(hns, true);
-		reset_queue = true;
-	} else
-		reset_queue = false;
-	return hns3_stop_queues(hns, reset_queue);
+		ret = hns3_reset_all_tqps(hns);
+		if (ret) {
+			hns3_err(hw, "failed to reset all queues ret = %d",
+				 ret);
+			return ret;
+		}
+	}
+	return 0;
 }
 
 static void
@@ -1914,6 +1927,7 @@ hns3vf_dev_stop(struct rte_eth_dev *dev)
 
 	rte_spinlock_lock(&hw->lock);
 	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
+		hns3_stop_tqps(hw);
 		hns3vf_do_stop(hns);
 		hns3vf_unmap_rx_interrupt(dev);
 		hns3_dev_release_mbufs(hns);
@@ -2023,9 +2037,9 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 	if (ret)
 		return ret;
 
-	ret = hns3_start_queues(hns, reset_queue);
+	ret = hns3_init_queues(hns, reset_queue);
 	if (ret)
-		hns3_err(hw, "Failed to start queues: %d", ret);
+		hns3_err(hw, "failed to init queues, ret = %d.", ret);
 
 	return ret;
 }
@@ -2155,6 +2169,33 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
 		rte_spinlock_unlock(&hw->lock);
 		return ret;
 	}
+
+	/*
+	 * There are three register used to control the status of a TQP
+	 * (contains a pair of Tx queue and Rx queue) in the new version network
+	 * engine. One is used to control the enabling of Tx queue, the other is
+	 * used to control the enabling of Rx queue, and the last is the master
+	 * switch used to control the enabling of the tqp. The Tx register and
+	 * TQP register must be enabled at the same time to enable a Tx queue.
+	 * The same applies to the Rx queue. For the older network enginem, this
+	 * function only refresh the enabled flag, and it is used to update the
+	 * status of queue in the dpdk framework.
+	 */
+	ret = hns3_start_all_txqs(dev);
+	if (ret) {
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
+	ret = hns3_start_all_rxqs(dev);
+	if (ret) {
+		hns3_stop_all_txqs(dev);
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
 	hw->adapter_state = HNS3_NIC_STARTED;
 	rte_spinlock_unlock(&hw->lock);
 
@@ -2167,11 +2208,12 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
 
 	/* Enable interrupt of all rx queues before enabling queues */
 	hns3_dev_all_rx_queue_intr_enable(hw, true);
+
 	/*
-	 * When finished the initialization, enable queues to receive/transmit
-	 * packets.
+	 * After finished the initialization, start all tqps to receive/transmit
+	 * packets and refresh all queue status.
 	 */
-	hns3_enable_all_queues(hw, true);
+	hns3_start_tqps(hw);
 
 	return ret;
 }
@@ -2313,6 +2355,7 @@ hns3vf_stop_service(struct hns3_adapter *hns)
 	rte_spinlock_lock(&hw->lock);
 	if (hw->adapter_state == HNS3_NIC_STARTED ||
 	    hw->adapter_state == HNS3_NIC_STOPPING) {
+		hns3_enable_all_queues(hw, false);
 		hns3vf_do_stop(hns);
 		hw->reset.mbuf_deferred_free = true;
 	} else
@@ -2555,7 +2598,7 @@ hns3vf_reinit_dev(struct hns3_adapter *hns)
 		rte_intr_enable(&pci_dev->intr_handle);
 	}
 
-	ret = hns3_reset_all_queues(hns);
+	ret = hns3_reset_all_tqps(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to reset all queues: %d", ret);
 		return ret;
@@ -2593,6 +2636,10 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.tx_queue_setup     = hns3_tx_queue_setup,
 	.rx_queue_release   = hns3_dev_rx_queue_release,
 	.tx_queue_release   = hns3_dev_tx_queue_release,
+	.rx_queue_start     = hns3_dev_rx_queue_start,
+	.rx_queue_stop      = hns3_dev_rx_queue_stop,
+	.tx_queue_start     = hns3_dev_tx_queue_start,
+	.tx_queue_stop      = hns3_dev_tx_queue_stop,
 	.rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
 	.rxq_info_get       = hns3_rxq_info_get,
diff --git a/drivers/net/hns3/hns3_regs.c b/drivers/net/hns3/hns3_regs.c
index a76f42c..1b7dd72 100644
--- a/drivers/net/hns3/hns3_regs.c
+++ b/drivers/net/hns3/hns3_regs.c
@@ -62,6 +62,7 @@ static const uint32_t ring_reg_addrs[] = {HNS3_RING_RX_BASEADDR_L_REG,
 					  HNS3_RING_RX_BASEADDR_H_REG,
 					  HNS3_RING_RX_BD_NUM_REG,
 					  HNS3_RING_RX_BD_LEN_REG,
+					  HNS3_RING_RX_EN_REG,
 					  HNS3_RING_RX_MERGE_EN_REG,
 					  HNS3_RING_RX_TAIL_REG,
 					  HNS3_RING_RX_HEAD_REG,
@@ -73,6 +74,7 @@ static const uint32_t ring_reg_addrs[] = {HNS3_RING_RX_BASEADDR_L_REG,
 					  HNS3_RING_TX_BASEADDR_L_REG,
 					  HNS3_RING_TX_BASEADDR_H_REG,
 					  HNS3_RING_TX_BD_NUM_REG,
+					  HNS3_RING_TX_EN_REG,
 					  HNS3_RING_TX_PRIORITY_REG,
 					  HNS3_RING_TX_TC_REG,
 					  HNS3_RING_TX_MERGE_EN_REG,
diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h
index d83c3b3..81a0af5 100644
--- a/drivers/net/hns3/hns3_regs.h
+++ b/drivers/net/hns3/hns3_regs.h
@@ -83,6 +83,8 @@
 #define HNS3_RING_TX_BD_ERR_REG			0x00074
 
 #define HNS3_RING_EN_REG			0x00090
+#define HNS3_RING_RX_EN_REG			0x00098
+#define HNS3_RING_TX_EN_REG			0x000d4
 
 #define HNS3_RING_EN_B				0
 
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index e3f0db4..60f110c 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -74,7 +74,7 @@ hns3_tx_queue_release_mbufs(struct hns3_tx_queue *txq)
 {
 	uint16_t i;
 
-	/* Note: Fake rx queue will not enter here */
+	/* Note: Fake tx queue will not enter here */
 	if (txq->sw_ring) {
 		for (i = 0; i < txq->nb_tx_desc; i++) {
 			if (txq->sw_ring[i].mbuf) {
@@ -371,27 +371,159 @@ hns3_enable_all_queues(struct hns3_hw *hw, bool en)
 	struct hns3_rx_queue *rxq;
 	struct hns3_tx_queue *txq;
 	uint32_t rcb_reg;
+	void *tqp_base;
 	int i;
 
 	for (i = 0; i < hw->cfg_max_queues; i++) {
-		if (i < nb_rx_q)
-			rxq = hw->data->rx_queues[i];
-		else
-			rxq = hw->fkq_data.rx_queues[i - nb_rx_q];
-		if (i < nb_tx_q)
-			txq = hw->data->tx_queues[i];
-		else
-			txq = hw->fkq_data.tx_queues[i - nb_tx_q];
-		if (rxq == NULL || txq == NULL ||
-		    (en && (rxq->rx_deferred_start || txq->tx_deferred_start)))
-			continue;
+		if (hns3_dev_indep_txrx_supported(hw)) {
+			rxq = i < nb_rx_q ? hw->data->rx_queues[i] : NULL;
+			txq = i < nb_tx_q ? hw->data->tx_queues[i] : NULL;
+			/*
+			 * After initialization, rxq and txq won't be NULL at
+			 * the same time.
+			 */
+			if (rxq != NULL)
+				tqp_base = rxq->io_base;
+			else if (txq != NULL)
+				tqp_base = txq->io_base;
+			else
+				return;
+		} else {
+			rxq = i < nb_rx_q ? hw->data->rx_queues[i] :
+			      hw->fkq_data.rx_queues[i - nb_rx_q];
 
-		rcb_reg = hns3_read_dev(rxq, HNS3_RING_EN_REG);
+			tqp_base = rxq->io_base;
+		}
+		/*
+		 * This is the master switch that used to control the enabling
+		 * of a pair of Tx and Rx queues. Both the Rx and Tx point to
+		 * the same register
+		 */
+		rcb_reg = hns3_read_reg(tqp_base, HNS3_RING_EN_REG);
 		if (en)
 			rcb_reg |= BIT(HNS3_RING_EN_B);
 		else
 			rcb_reg &= ~BIT(HNS3_RING_EN_B);
-		hns3_write_dev(rxq, HNS3_RING_EN_REG, rcb_reg);
+		hns3_write_reg(tqp_base, HNS3_RING_EN_REG, rcb_reg);
+	}
+}
+
+static void
+hns3_enable_txq(struct hns3_tx_queue *txq, bool en)
+{
+	struct hns3_hw *hw = &txq->hns->hw;
+	uint32_t reg;
+
+	if (hns3_dev_indep_txrx_supported(hw)) {
+		reg = hns3_read_dev(txq, HNS3_RING_TX_EN_REG);
+		if (en)
+			reg |= BIT(HNS3_RING_EN_B);
+		else
+			reg &= ~BIT(HNS3_RING_EN_B);
+		hns3_write_dev(txq, HNS3_RING_TX_EN_REG, reg);
+	}
+	txq->enabled = en;
+}
+
+static void
+hns3_enable_rxq(struct hns3_rx_queue *rxq, bool en)
+{
+	struct hns3_hw *hw = &rxq->hns->hw;
+	uint32_t reg;
+
+	if (hns3_dev_indep_txrx_supported(hw)) {
+		reg = hns3_read_dev(rxq, HNS3_RING_RX_EN_REG);
+		if (en)
+			reg |= BIT(HNS3_RING_EN_B);
+		else
+			reg &= ~BIT(HNS3_RING_EN_B);
+		hns3_write_dev(rxq, HNS3_RING_RX_EN_REG, reg);
+	}
+	rxq->enabled = en;
+}
+
+int
+hns3_start_all_txqs(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq;
+	uint16_t i, j;
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		txq = hw->data->tx_queues[i];
+		if (!txq) {
+			hns3_err(hw, "Tx queue %u not available or setup.", i);
+			goto start_txqs_fail;
+		}
+		/*
+		 * Tx queue is enabled by default. Therefore, the Tx queues
+		 * needs to be disabled when deferred_start is set. There is
+		 * another master switch used to control the enabling of a pair
+		 * of Tx and Rx queues. And the master switch is disabled by
+		 * default.
+		 */
+		if (txq->tx_deferred_start)
+			hns3_enable_txq(txq, false);
+		else
+			hns3_enable_txq(txq, true);
+	}
+	return 0;
+
+start_txqs_fail:
+	for (j = 0; j < i; j++) {
+		txq = hw->data->tx_queues[j];
+		hns3_enable_txq(txq, false);
+	}
+	return -EINVAL;
+}
+
+int
+hns3_start_all_rxqs(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_rx_queue *rxq;
+	uint16_t i, j;
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		rxq = hw->data->rx_queues[i];
+		if (!rxq) {
+			hns3_err(hw, "Rx queue %u not available or setup.", i);
+			goto start_rxqs_fail;
+		}
+		/*
+		 * Rx queue is enabled by default. Therefore, the Rx queues
+		 * needs to be disabled when deferred_start is set. There is
+		 * another master switch used to control the enabling of a pair
+		 * of Tx and Rx queues. And the master switch is disabled by
+		 * default.
+		 */
+		if (rxq->rx_deferred_start)
+			hns3_enable_rxq(rxq, false);
+		else
+			hns3_enable_rxq(rxq, true);
+	}
+	return 0;
+
+start_rxqs_fail:
+	for (j = 0; j < i; j++) {
+		rxq = hw->data->rx_queues[j];
+		hns3_enable_rxq(rxq, false);
+	}
+	return -EINVAL;
+}
+
+void
+hns3_stop_all_txqs(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq;
+	uint16_t i;
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		txq = hw->data->tx_queues[i];
+		if (!txq)
+			continue;
+		hns3_enable_txq(txq, false);
 	}
 }
 
@@ -428,16 +560,17 @@ hns3_send_reset_tqp_cmd(struct hns3_hw *hw, uint16_t queue_id, bool enable)
 	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
 	req->tqp_id = rte_cpu_to_le_16(queue_id);
 	hns3_set_bit(req->reset_req, HNS3_TQP_RESET_B, enable ? 1 : 0);
-
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret)
-		hns3_err(hw, "Send tqp reset cmd error, ret = %d", ret);
+		hns3_err(hw, "send tqp reset cmd error, queue_id = %u, "
+			     "ret = %d", queue_id, ret);
 
 	return ret;
 }
 
 static int
-hns3_get_reset_status(struct hns3_hw *hw, uint16_t queue_id)
+hns3_get_tqp_reset_status(struct hns3_hw *hw, uint16_t queue_id,
+			  uint8_t *reset_status)
 {
 	struct hns3_reset_tqp_queue_cmd *req;
 	struct hns3_cmd_desc desc;
@@ -450,19 +583,20 @@ hns3_get_reset_status(struct hns3_hw *hw, uint16_t queue_id)
 
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret) {
-		hns3_err(hw, "Get reset status error, ret =%d", ret);
+		hns3_err(hw, "get tqp reset status error, queue_id = %u, "
+			     "ret = %d.", queue_id, ret);
 		return ret;
 	}
-
-	return hns3_get_bit(req->ready_to_reset, HNS3_TQP_RESET_B);
+	*reset_status = hns3_get_bit(req->ready_to_reset, HNS3_TQP_RESET_B);
+	return ret;
 }
 
 static int
-hns3_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
+hns3pf_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 {
 #define HNS3_TQP_RESET_TRY_MS	200
+	uint8_t reset_status;
 	uint64_t end;
-	int reset_status;
 	int ret;
 
 	ret = hns3_tqp_enable(hw, queue_id, false);
@@ -479,21 +613,23 @@ hns3_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 		hns3_err(hw, "Send reset tqp cmd fail, ret = %d", ret);
 		return ret;
 	}
-	ret = -ETIMEDOUT;
 	end = get_timeofday_ms() + HNS3_TQP_RESET_TRY_MS;
 	do {
 		/* Wait for tqp hw reset */
 		rte_delay_ms(HNS3_POLL_RESPONE_MS);
-		reset_status = hns3_get_reset_status(hw, queue_id);
-		if (reset_status) {
-			ret = 0;
+		ret = hns3_get_tqp_reset_status(hw, queue_id, &reset_status);
+		if (ret)
+			goto tqp_reset_fail;
+
+		if (reset_status)
 			break;
-		}
 	} while (get_timeofday_ms() < end);
 
-	if (ret) {
-		hns3_err(hw, "Reset TQP fail, ret = %d", ret);
-		return ret;
+	if (!reset_status) {
+		ret = -ETIMEDOUT;
+		hns3_err(hw, "reset tqp timeout, queue_id = %u, ret = %d",
+			     queue_id, ret);
+		goto tqp_reset_fail;
 	}
 
 	ret = hns3_send_reset_tqp_cmd(hw, queue_id, false);
@@ -501,6 +637,10 @@ hns3_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 		hns3_err(hw, "Deassert the soft reset fail, ret = %d", ret);
 
 	return ret;
+
+tqp_reset_fail:
+	hns3_send_reset_tqp_cmd(hw, queue_id, false);
+	return ret;
 }
 
 static int
@@ -516,28 +656,33 @@ hns3vf_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 
 	memcpy(msg_data, &queue_id, sizeof(uint16_t));
 
-	return hns3_send_mbx_msg(hw, HNS3_MBX_QUEUE_RESET, 0, msg_data,
+	ret = hns3_send_mbx_msg(hw, HNS3_MBX_QUEUE_RESET, 0, msg_data,
 				 sizeof(msg_data), true, NULL, 0);
+	if (ret)
+		hns3_err(hw, "fail to reset tqp, queue_id = %u, ret = %d.",
+			 queue_id, ret);
+	return ret;
 }
 
 static int
-hns3_reset_queue(struct hns3_adapter *hns, uint16_t queue_id)
+hns3_reset_tqp(struct hns3_adapter *hns, uint16_t queue_id)
 {
 	struct hns3_hw *hw = &hns->hw;
+
 	if (hns->is_vf)
 		return hns3vf_reset_tqp(hw, queue_id);
 	else
-		return hns3_reset_tqp(hw, queue_id);
+		return hns3pf_reset_tqp(hw, queue_id);
 }
 
 int
-hns3_reset_all_queues(struct hns3_adapter *hns)
+hns3_reset_all_tqps(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	int ret, i;
 
 	for (i = 0; i < hw->cfg_max_queues; i++) {
-		ret = hns3_reset_queue(hns, i);
+		ret = hns3_reset_tqp(hns, i);
 		if (ret) {
 			hns3_err(hw, "Failed to reset No.%d queue: %d", i, ret);
 			return ret;
@@ -546,6 +691,121 @@ hns3_reset_all_queues(struct hns3_adapter *hns)
 	return 0;
 }
 
+static int
+hns3_send_reset_queue_cmd(struct hns3_hw *hw, uint16_t queue_id,
+			  enum hns3_ring_type queue_type, bool enable)
+{
+	struct hns3_reset_tqp_queue_cmd *req;
+	struct hns3_cmd_desc desc;
+	int queue_direction;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE_INDEP, false);
+
+	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
+	queue_direction = queue_type == HNS3_RING_TYPE_TX ? 0 : 1;
+	req->queue_direction = rte_cpu_to_le_16(queue_direction);
+	hns3_set_bit(req->reset_req, HNS3_TQP_RESET_B, enable ? 1 : 0);
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "send queue reset cmd error, queue_id = %u, "
+			 "queue_type = %s, ret = %d.", queue_id,
+			 queue_type == HNS3_RING_TYPE_TX ? "Tx" : "Rx", ret);
+	return ret;
+}
+
+static int
+hns3_get_queue_reset_status(struct hns3_hw *hw, uint16_t queue_id,
+			    enum hns3_ring_type queue_type,
+			    uint8_t *reset_status)
+{
+	struct hns3_reset_tqp_queue_cmd *req;
+	struct hns3_cmd_desc desc;
+	int queue_direction;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE_INDEP, true);
+
+	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
+	queue_direction = queue_type == HNS3_RING_TYPE_TX ? 0 : 1;
+	req->queue_direction = rte_cpu_to_le_16(queue_direction);
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "get queue reset status error, queue_id = %u "
+			 "queue_type = %s, ret = %d.", queue_id,
+			 queue_type == HNS3_RING_TYPE_TX ? "Tx" : "Rx", ret);
+		return ret;
+	}
+
+	*reset_status = hns3_get_bit(req->ready_to_reset, HNS3_TQP_RESET_B);
+	return  ret;
+}
+
+static int
+hns3_reset_queue(struct hns3_hw *hw, uint16_t queue_id,
+		 enum hns3_ring_type queue_type)
+{
+#define HNS3_QUEUE_RESET_TRY_MS	200
+	struct hns3_tx_queue *txq;
+	struct hns3_rx_queue *rxq;
+	uint32_t reset_wait_times;
+	uint32_t max_wait_times;
+	uint8_t reset_status;
+	int ret;
+
+	if (queue_type == HNS3_RING_TYPE_TX) {
+		txq = hw->data->tx_queues[queue_id];
+		hns3_enable_txq(txq, false);
+	} else {
+		rxq = hw->data->rx_queues[queue_id];
+		hns3_enable_rxq(rxq, false);
+	}
+
+	ret = hns3_send_reset_queue_cmd(hw, queue_id, queue_type, true);
+	if (ret) {
+		hns3_err(hw, "send reset queue cmd fail, ret = %d.", ret);
+		return ret;
+	}
+
+	reset_wait_times = 0;
+	max_wait_times = HNS3_QUEUE_RESET_TRY_MS / HNS3_POLL_RESPONE_MS;
+	while (reset_wait_times < max_wait_times) {
+		/* Wait for queue hw reset */
+		rte_delay_ms(HNS3_POLL_RESPONE_MS);
+		ret = hns3_get_queue_reset_status(hw, queue_id,
+						queue_type, &reset_status);
+		if (ret)
+			goto queue_reset_fail;
+
+		if (reset_status)
+			break;
+		reset_wait_times++;
+	}
+
+	if (!reset_status) {
+		hns3_err(hw, "reset queue timeout, queue_id = %u, "
+			     "queue_type = %s", queue_id,
+			     queue_type == HNS3_RING_TYPE_TX ? "Tx" : "Rx");
+		ret = -ETIMEDOUT;
+		goto queue_reset_fail;
+	}
+
+	ret = hns3_send_reset_queue_cmd(hw, queue_id, queue_type, false);
+	if (ret)
+		hns3_err(hw, "deassert queue reset fail, ret = %d.", ret);
+
+	return ret;
+
+queue_reset_fail:
+	hns3_send_reset_queue_cmd(hw, queue_id, queue_type, false);
+	return ret;
+}
+
+
 void
 hns3_set_queue_intr_gl(struct hns3_hw *hw, uint16_t queue_id,
 		       uint8_t gl_idx, uint16_t gl_value)
@@ -658,7 +918,7 @@ hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 }
 
 static int
-hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
+hns3_init_rxq(struct hns3_adapter *hns, uint16_t idx)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rx_queue *rxq;
@@ -669,7 +929,7 @@ hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 	rxq = (struct hns3_rx_queue *)hw->data->rx_queues[idx];
 	ret = hns3_alloc_rx_queue_mbufs(hw, rxq);
 	if (ret) {
-		hns3_err(hw, "Failed to alloc mbuf for No.%d rx queue: %d",
+		hns3_err(hw, "fail to alloc mbuf for Rx queue %u, ret = %d.",
 			 idx, ret);
 		return ret;
 	}
@@ -687,7 +947,7 @@ hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 }
 
 static void
-hns3_fake_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
+hns3_init_fake_rxq(struct hns3_adapter *hns, uint16_t idx)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rx_queue *rxq;
@@ -701,9 +961,8 @@ hns3_fake_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 }
 
 static void
-hns3_init_tx_queue(struct hns3_tx_queue *queue)
+hns3_init_txq(struct hns3_tx_queue *txq)
 {
-	struct hns3_tx_queue *txq = queue;
 	struct hns3_desc *desc;
 	int i;
 
@@ -721,26 +980,6 @@ hns3_init_tx_queue(struct hns3_tx_queue *queue)
 }
 
 static void
-hns3_dev_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
-{
-	struct hns3_hw *hw = &hns->hw;
-	struct hns3_tx_queue *txq;
-
-	txq = (struct hns3_tx_queue *)hw->data->tx_queues[idx];
-	hns3_init_tx_queue(txq);
-}
-
-static void
-hns3_fake_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
-{
-	struct hns3_hw *hw = &hns->hw;
-	struct hns3_tx_queue *txq;
-
-	txq = (struct hns3_tx_queue *)hw->fkq_data.tx_queues[idx];
-	hns3_init_tx_queue(txq);
-}
-
-static void
 hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
@@ -766,38 +1005,41 @@ hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 }
 
 static int
-hns3_start_rx_queues(struct hns3_adapter *hns)
+hns3_init_rx_queues(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rx_queue *rxq;
-	int i, j;
+	uint16_t i, j;
 	int ret;
 
 	/* Initialize RSS for queues */
 	ret = hns3_config_rss(hns);
 	if (ret) {
-		hns3_err(hw, "Failed to configure rss %d", ret);
+		hns3_err(hw, "failed to configure rss, ret = %d.", ret);
 		return ret;
 	}
 
 	for (i = 0; i < hw->data->nb_rx_queues; i++) {
 		rxq = (struct hns3_rx_queue *)hw->data->rx_queues[i];
-		if (rxq == NULL || rxq->rx_deferred_start)
+		if (!rxq) {
+			hns3_err(hw, "Rx queue %u not available or setup.", i);
+			goto out;
+		}
+
+		if (rxq->rx_deferred_start)
 			continue;
-		ret = hns3_dev_rx_queue_start(hns, i);
+
+		ret = hns3_init_rxq(hns, i);
 		if (ret) {
-			hns3_err(hw, "Failed to start No.%d rx queue: %d", i,
+			hns3_err(hw, "failed to init Rx queue %u, ret = %d.", i,
 				 ret);
 			goto out;
 		}
 	}
 
-	for (i = 0; i < hw->fkq_data.nb_fake_rx_queues; i++) {
-		rxq = (struct hns3_rx_queue *)hw->fkq_data.rx_queues[i];
-		if (rxq == NULL || rxq->rx_deferred_start)
-			continue;
-		hns3_fake_rx_queue_start(hns, i);
-	}
+	for (i = 0; i < hw->fkq_data.nb_fake_rx_queues; i++)
+		hns3_init_fake_rxq(hns, i);
+
 	return 0;
 
 out:
@@ -809,74 +1051,104 @@ hns3_start_rx_queues(struct hns3_adapter *hns)
 	return ret;
 }
 
-static void
-hns3_start_tx_queues(struct hns3_adapter *hns)
+static int
+hns3_init_tx_queues(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_tx_queue *txq;
-	int i;
+	uint16_t i;
 
 	for (i = 0; i < hw->data->nb_tx_queues; i++) {
 		txq = (struct hns3_tx_queue *)hw->data->tx_queues[i];
-		if (txq == NULL || txq->tx_deferred_start)
+		if (!txq) {
+			hns3_err(hw, "Tx queue %u not available or setup.", i);
+			return -EINVAL;
+		}
+
+		if (txq->tx_deferred_start)
 			continue;
-		hns3_dev_tx_queue_start(hns, i);
+		hns3_init_txq(txq);
 	}
 
 	for (i = 0; i < hw->fkq_data.nb_fake_tx_queues; i++) {
 		txq = (struct hns3_tx_queue *)hw->fkq_data.tx_queues[i];
-		if (txq == NULL || txq->tx_deferred_start)
-			continue;
-		hns3_fake_tx_queue_start(hns, i);
+		hns3_init_txq(txq);
 	}
-
 	hns3_init_tx_ring_tc(hns);
+
+	return 0;
 }
 
 /*
- * Start all queues.
- * Note: just init and setup queues, and don't enable queue rx&tx.
+ * Init all queues.
+ * Note: just init and setup queues, and don't enable tqps.
  */
 int
-hns3_start_queues(struct hns3_adapter *hns, bool reset_queue)
+hns3_init_queues(struct hns3_adapter *hns, bool reset_queue)
 {
 	struct hns3_hw *hw = &hns->hw;
 	int ret;
 
 	if (reset_queue) {
-		ret = hns3_reset_all_queues(hns);
+		ret = hns3_reset_all_tqps(hns);
 		if (ret) {
-			hns3_err(hw, "Failed to reset all queues %d", ret);
+			hns3_err(hw, "failed to reset all queues, ret = %d.",
+				 ret);
 			return ret;
 		}
 	}
 
-	ret = hns3_start_rx_queues(hns);
+	ret = hns3_init_rx_queues(hns);
 	if (ret) {
-		hns3_err(hw, "Failed to start rx queues: %d", ret);
+		hns3_err(hw, "failed to init rx queues, ret = %d.", ret);
 		return ret;
 	}
 
-	hns3_start_tx_queues(hns);
+	ret = hns3_init_tx_queues(hns);
+	if (ret) {
+		hns3_dev_release_mbufs(hns);
+		hns3_err(hw, "failed to init tx queues, ret = %d.", ret);
+	}
 
-	return 0;
+	return ret;
 }
 
-int
-hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue)
+void
+hns3_start_tqps(struct hns3_hw *hw)
 {
-	struct hns3_hw *hw = &hns->hw;
-	int ret;
+	struct hns3_tx_queue *txq;
+	struct hns3_rx_queue *rxq;
+	uint16_t i;
 
-	hns3_enable_all_queues(hw, false);
-	if (reset_queue) {
-		ret = hns3_reset_all_queues(hns);
-		if (ret) {
-			hns3_err(hw, "Failed to reset all queues %d", ret);
-			return ret;
-		}
+	hns3_enable_all_queues(hw, true);
+
+	for (i = 0; i < hw->data->nb_tx_queues; i++) {
+		txq = hw->data->tx_queues[i];
+		if (txq->enabled)
+			hw->data->tx_queue_state[i] =
+				RTE_ETH_QUEUE_STATE_STARTED;
 	}
-	return 0;
+
+	for (i = 0; i < hw->data->nb_rx_queues; i++) {
+		rxq = hw->data->rx_queues[i];
+		if (rxq->enabled)
+			hw->data->rx_queue_state[i] =
+				RTE_ETH_QUEUE_STATE_STARTED;
+	}
+}
+
+void
+hns3_stop_tqps(struct hns3_hw *hw)
+{
+	uint16_t i;
+
+	hns3_enable_all_queues(hw, false);
+
+	for (i = 0; i < hw->data->nb_tx_queues; i++)
+		hw->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	for (i = 0; i < hw->data->nb_rx_queues; i++)
+		hw->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
 }
 
 /*
@@ -1202,13 +1474,12 @@ hns3_set_fake_rx_or_tx_queues(struct rte_eth_dev *dev, uint16_t nb_rx_q,
 	int ret;
 
 	/* Setup new number of fake RX/TX queues and reconfigure device. */
-	hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
 	rx_need_add_nb_q = hw->cfg_max_queues - nb_rx_q;
 	tx_need_add_nb_q = hw->cfg_max_queues - nb_tx_q;
 	ret = hns3_fake_rx_queue_config(hw, rx_need_add_nb_q);
 	if (ret) {
 		hns3_err(hw, "Fail to configure fake rx queues: %d", ret);
-		goto cfg_fake_rx_q_fail;
+		return ret;
 	}
 
 	ret = hns3_fake_tx_queue_config(hw, tx_need_add_nb_q);
@@ -1241,8 +1512,6 @@ hns3_set_fake_rx_or_tx_queues(struct rte_eth_dev *dev, uint16_t nb_rx_q,
 	(void)hns3_fake_tx_queue_config(hw, 0);
 cfg_fake_tx_q_fail:
 	(void)hns3_fake_rx_queue_config(hw, 0);
-cfg_fake_rx_q_fail:
-	hw->cfg_max_queues = 0;
 
 	return ret;
 }
@@ -1258,7 +1527,7 @@ hns3_dev_release_mbufs(struct hns3_adapter *hns)
 	if (dev_data->rx_queues)
 		for (i = 0; i < dev_data->nb_rx_queues; i++) {
 			rxq = dev_data->rx_queues[i];
-			if (rxq == NULL || rxq->rx_deferred_start)
+			if (rxq == NULL)
 				continue;
 			hns3_rx_queue_release_mbufs(rxq);
 		}
@@ -1266,7 +1535,7 @@ hns3_dev_release_mbufs(struct hns3_adapter *hns)
 	if (dev_data->tx_queues)
 		for (i = 0; i < dev_data->nb_tx_queues; i++) {
 			txq = dev_data->tx_queues[i];
-			if (txq == NULL || txq->tx_deferred_start)
+			if (txq == NULL)
 				continue;
 			hns3_tx_queue_release_mbufs(txq);
 		}
@@ -1315,10 +1584,49 @@ hns3_rx_buf_len_calc(struct rte_mempool *mp, uint16_t *rx_buf_len)
 }
 
 static int
+hns3_rxq_conf_runtime_check(struct hns3_hw *hw, uint16_t buf_size,
+				uint16_t nb_desc)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	struct rte_eth_rxmode *rxmode = &hw->data->dev_conf.rxmode;
+	eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
+	uint16_t min_vec_bds;
+
+	/*
+	 * HNS3 hardware network engine set scattered as default. If the driver
+	 * is not work in scattered mode and the pkts greater than buf_size
+	 * but smaller than max_rx_pkt_len will be distributed to multiple BDs.
+	 * Driver cannot handle this situation.
+	 */
+	if (!hw->data->scattered_rx && rxmode->max_rx_pkt_len > buf_size) {
+		hns3_err(hw, "max_rx_pkt_len is not allowed to be set greater "
+			     "than rx_buf_len if scattered is off.");
+		return -EINVAL;
+	}
+
+	if (pkt_burst == hns3_recv_pkts_vec) {
+		min_vec_bds = HNS3_DEFAULT_RXQ_REARM_THRESH +
+			      HNS3_DEFAULT_RX_BURST;
+		if (nb_desc < min_vec_bds ||
+		    nb_desc % HNS3_DEFAULT_RXQ_REARM_THRESH) {
+			hns3_err(hw, "if Rx burst mode is vector, "
+				 "number of descriptor is required to be "
+				 "bigger than min vector bds:%u, and could be "
+				 "divided by rxq rearm thresh:%u.",
+				 min_vec_bds, HNS3_DEFAULT_RXQ_REARM_THRESH);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int
 hns3_rx_queue_conf_check(struct hns3_hw *hw, const struct rte_eth_rxconf *conf,
 			 struct rte_mempool *mp, uint16_t nb_desc,
 			 uint16_t *buf_size)
 {
+	int ret;
+
 	if (nb_desc > HNS3_MAX_RING_DESC || nb_desc < HNS3_MIN_RING_DESC ||
 	    nb_desc % HNS3_ALIGN_RING_DESC) {
 		hns3_err(hw, "Number (%u) of rx descriptors is invalid",
@@ -1338,6 +1646,14 @@ hns3_rx_queue_conf_check(struct hns3_hw *hw, const struct rte_eth_rxconf *conf,
 		return -EINVAL;
 	}
 
+	if (hw->data->dev_started) {
+		ret = hns3_rxq_conf_runtime_check(hw, *buf_size, nb_desc);
+		if (ret) {
+			hns3_err(hw, "Rx queue runtime setup fail.");
+			return ret;
+		}
+	}
+
 	return 0;
 }
 
@@ -1370,11 +1686,6 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	int rx_entry_len;
 	int ret;
 
-	if (dev->data->dev_started) {
-		hns3_err(hw, "rx_queue_setup after dev_start no supported");
-		return -EINVAL;
-	}
-
 	ret = hns3_rx_queue_conf_check(hw, conf, mp, nb_desc, &rx_buf_size);
 	if (ret)
 		return ret;
@@ -1402,7 +1713,12 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	rxq->mb_pool = mp;
 	rxq->rx_free_thresh = (conf->rx_free_thresh > 0) ?
 		conf->rx_free_thresh : HNS3_DEFAULT_RX_FREE_THRESH;
+
 	rxq->rx_deferred_start = conf->rx_deferred_start;
+	if (rxq->rx_deferred_start && !hns3_dev_indep_txrx_supported(hw)) {
+		hns3_warn(hw, "deferred start is not supported.");
+		rxq->rx_deferred_start = false;
+	}
 
 	rx_entry_len = (rxq->nb_rx_desc + HNS3_DEFAULT_RX_BURST) *
 			sizeof(struct hns3_entry);
@@ -2132,11 +2448,6 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	int tx_entry_len;
 	int ret;
 
-	if (dev->data->dev_started) {
-		hns3_err(hw, "tx_queue_setup after dev_start no supported");
-		return -EINVAL;
-	}
-
 	ret = hns3_tx_queue_conf_check(hw, conf, nb_desc,
 				       &tx_rs_thresh, &tx_free_thresh, idx);
 	if (ret)
@@ -2160,6 +2471,11 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	}
 
 	txq->tx_deferred_start = conf->tx_deferred_start;
+	if (txq->tx_deferred_start && !hns3_dev_indep_txrx_supported(hw)) {
+		hns3_warn(hw, "deferred start is not supported.");
+		txq->tx_deferred_start = false;
+	}
+
 	tx_entry_len = sizeof(struct hns3_entry) * txq->nb_tx_desc;
 	txq->sw_ring = rte_zmalloc_socket("hns3 TX sw ring", tx_entry_len,
 					  RTE_CACHE_LINE_SIZE, socket_id);
@@ -3377,3 +3693,98 @@ hns3_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	qinfo->conf.tx_free_thresh = txq->tx_free_thresh;
 	qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
 }
+
+int
+hns3_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_rx_queue *rxq = dev->data->rx_queues[rx_queue_id];
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	int ret;
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	ret = hns3_reset_queue(hw, rx_queue_id, HNS3_RING_TYPE_RX);
+	if (ret) {
+		hns3_err(hw, "fail to reset Rx queue %u, ret = %d.",
+			 rx_queue_id, ret);
+		return ret;
+	}
+
+	ret = hns3_init_rxq(hns, rx_queue_id);
+	if (ret) {
+		hns3_err(hw, "fail to init Rx queue %u, ret = %d.",
+			 rx_queue_id, ret);
+		return ret;
+	}
+
+	hns3_enable_rxq(rxq, true);
+	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+
+	return ret;
+}
+
+int
+hns3_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_rx_queue *rxq = dev->data->rx_queues[rx_queue_id];
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	hns3_enable_rxq(rxq, false);
+	hns3_rx_queue_release_mbufs(rxq);
+	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	return 0;
+}
+
+int
+hns3_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq = dev->data->tx_queues[tx_queue_id];
+	int ret;
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	ret = hns3_reset_queue(hw, tx_queue_id, HNS3_RING_TYPE_TX);
+	if (ret) {
+		hns3_err(hw, "fail to reset Tx queue %u, ret = %d.",
+			 tx_queue_id, ret);
+		return ret;
+	}
+
+	hns3_init_txq(txq);
+	hns3_enable_txq(txq, true);
+	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+
+	return ret;
+}
+
+int
+hns3_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq = dev->data->tx_queues[tx_queue_id];
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	hns3_enable_txq(txq, false);
+	hns3_tx_queue_release_mbufs(txq);
+	/*
+	 * All the mbufs in sw_ring are released and all the pointers in sw_ring
+	 * are set to NULL. If this queue is still called by upper layer,
+	 * residual SW status of this txq may cause these pointers in sw_ring
+	 * which have been set to NULL to be released again. To avoid it,
+	 * reinit the txq.
+	 */
+	hns3_init_txq(txq);
+	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	return 0;
+}
diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index cdfe115..abc7c54 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -307,6 +307,7 @@ struct hns3_rx_queue {
 	 * point, the pvid_sw_discard_en will be false.
 	 */
 	bool pvid_sw_discard_en;
+	bool enabled;           /* indicate if Rx queue has been enabled */
 
 	uint64_t l2_errors;
 	uint64_t pkt_len_errors;
@@ -405,6 +406,7 @@ struct hns3_tx_queue {
 	 * this point.
 	 */
 	bool pvid_sw_shift_en;
+	bool enabled;           /* indicate if Tx queue has been enabled */
 
 	/*
 	 * The following items are used for the abnormal errors statistics in
@@ -602,13 +604,14 @@ hns3_rx_calc_ptype(struct hns3_rx_queue *rxq, const uint32_t l234_info,
 void hns3_dev_rx_queue_release(void *queue);
 void hns3_dev_tx_queue_release(void *queue);
 void hns3_free_all_queues(struct rte_eth_dev *dev);
-int hns3_reset_all_queues(struct hns3_adapter *hns);
+int hns3_reset_all_tqps(struct hns3_adapter *hns);
 void hns3_dev_all_rx_queue_intr_enable(struct hns3_hw *hw, bool en);
 int hns3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
 int hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 void hns3_enable_all_queues(struct hns3_hw *hw, bool en);
-int hns3_start_queues(struct hns3_adapter *hns, bool reset_queue);
-int hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue);
+int hns3_init_queues(struct hns3_adapter *hns, bool reset_queue);
+void hns3_start_tqps(struct hns3_hw *hw);
+void hns3_stop_tqps(struct hns3_hw *hw);
 int hns3_rxq_iterate(struct rte_eth_dev *dev,
 		 int (*callback)(struct hns3_rx_queue *, void *), void *arg);
 void hns3_dev_release_mbufs(struct hns3_adapter *hns);
@@ -617,6 +620,10 @@ int hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 			struct rte_mempool *mp);
 int hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 			unsigned int socket, const struct rte_eth_txconf *conf);
+int hns3_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id);
+int hns3_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id);
+int hns3_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id);
+int hns3_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id);
 uint16_t hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 			uint16_t nb_pkts);
 uint16_t hns3_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
@@ -662,5 +669,8 @@ void hns3_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 void hns3_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 		       struct rte_eth_txq_info *qinfo);
 uint32_t hns3_get_tqp_reg_offset(uint16_t idx);
+int hns3_start_all_txqs(struct rte_eth_dev *dev);
+int hns3_start_all_rxqs(struct rte_eth_dev *dev);
+void hns3_stop_all_txqs(struct rte_eth_dev *dev);
 
 #endif /* _HNS3_RXTX_H_ */
-- 
2.9.5


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

* [dpdk-dev] [PATCH 8/9] net/hns3: check return value when reading PCI config space
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                   ` (6 preceding siblings ...)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 7/9] net/hns3: support start and stop Tx or Rx queue Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 9/9] net/hns3: remove redundant return value assignments Wei Hu (Xavier)
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Hongbo Zheng <zhenghongbo3@huawei.com>

This patch add return value check when calling rte_pci_read_config
function.

Fixes: cea37e513329 ("net/hns3: fix FLR reset")
Cc: stable@dpdk.org

Signed-off-by: Hongbo Zheng <zhenghongbo3@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_ethdev_vf.c | 62 ++++++++++++++++++++++++++++++++-------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 849f6cc..a6cc11d 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -64,12 +64,18 @@ static int hns3vf_add_mc_mac_addr(struct hns3_hw *hw,
 static int hns3vf_remove_mc_mac_addr(struct hns3_hw *hw,
 				     struct rte_ether_addr *mac_addr);
 /* set PCI bus mastering */
-static void
+static int
 hns3vf_set_bus_master(const struct rte_pci_device *device, bool op)
 {
 	uint16_t reg;
+	int ret;
 
-	rte_pci_read_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	ret = rte_pci_read_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+			     PCI_COMMAND);
+		return ret;
+	}
 
 	if (op)
 		/* set the master bit */
@@ -77,7 +83,7 @@ hns3vf_set_bus_master(const struct rte_pci_device *device, bool op)
 	else
 		reg &= ~(PCI_COMMAND_MASTER);
 
-	rte_pci_write_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	return rte_pci_write_config(device, &reg, sizeof(reg), PCI_COMMAND);
 }
 
 /**
@@ -94,16 +100,34 @@ hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap)
 	uint8_t pos;
 	uint8_t id;
 	int ttl;
+	int ret;
+
+	ret = rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", PCI_STATUS);
+		return 0;
+	}
 
-	rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS);
 	if (!(status & PCI_STATUS_CAP_LIST))
 		return 0;
 
 	ttl = MAX_PCIE_CAPABILITY;
-	rte_pci_read_config(device, &pos, sizeof(pos), PCI_CAPABILITY_LIST);
+	ret = rte_pci_read_config(device, &pos, sizeof(pos),
+				  PCI_CAPABILITY_LIST);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+			     PCI_CAPABILITY_LIST);
+		return 0;
+	}
+
 	while (ttl-- && pos >= PCI_STD_HEADER_SIZEOF) {
-		rte_pci_read_config(device, &id, sizeof(id),
-				    (pos + PCI_CAP_LIST_ID));
+		ret = rte_pci_read_config(device, &id, sizeof(id),
+					  (pos + PCI_CAP_LIST_ID));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_CAP_LIST_ID));
+			break;
+		}
 
 		if (id == 0xFF)
 			break;
@@ -111,8 +135,13 @@ hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap)
 		if (id == cap)
 			return (int)pos;
 
-		rte_pci_read_config(device, &pos, sizeof(pos),
-				    (pos + PCI_CAP_LIST_NEXT));
+		ret = rte_pci_read_config(device, &pos, sizeof(pos),
+					  (pos + PCI_CAP_LIST_NEXT));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_CAP_LIST_NEXT));
+			break;
+		}
 	}
 	return 0;
 }
@@ -122,11 +151,18 @@ hns3vf_enable_msix(const struct rte_pci_device *device, bool op)
 {
 	uint16_t control;
 	int pos;
+	int ret;
 
 	pos = hns3vf_find_pci_capability(device, PCI_CAP_ID_MSIX);
 	if (pos) {
-		rte_pci_read_config(device, &control, sizeof(control),
+		ret = rte_pci_read_config(device, &control, sizeof(control),
 				    (pos + PCI_MSIX_FLAGS));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_MSIX_FLAGS));
+			return -ENXIO;
+		}
+
 		if (op)
 			control |= PCI_MSIX_FLAGS_ENABLE;
 		else
@@ -2574,7 +2610,11 @@ hns3vf_reinit_dev(struct hns3_adapter *hns)
 
 	if (hw->reset.level == HNS3_VF_FULL_RESET) {
 		rte_intr_disable(&pci_dev->intr_handle);
-		hns3vf_set_bus_master(pci_dev, true);
+		ret = hns3vf_set_bus_master(pci_dev, true);
+		if (ret) {
+			hns3_err(hw, "failed to set pci bus, ret = %d", ret);
+			return ret;
+		}
 	}
 
 	/* Firmware command initialize */
-- 
2.9.5


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

* [dpdk-dev] [PATCH 9/9] net/hns3: remove redundant return value assignments
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                   ` (7 preceding siblings ...)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 8/9] net/hns3: check return value when reading PCI config space Wei Hu (Xavier)
@ 2020-09-29 11:09 ` Wei Hu (Xavier)
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 11:09 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Hongbo Zheng <zhenghongbo3@huawei.com>

When an error occurs in the reset process, -EIO is returned.
The assignment of ret here is redundant, so deleted it.

Signed-off-by: Hongbo Zheng <zhenghongbo3@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_intr.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c
index dfd7371..2565688 100644
--- a/drivers/net/hns3/hns3_intr.c
+++ b/drivers/net/hns3/hns3_intr.c
@@ -1888,7 +1888,6 @@ hns3_reset_process(struct hns3_adapter *hns, enum hns3_reset_level new_level)
 		if (hw->reset.wait_data->result == HNS3_WAIT_REQUEST)
 			rte_eal_alarm_cancel(hns3_wait_callback,
 					     hw->reset.wait_data);
-		ret = -EBUSY;
 		goto err;
 	}
 
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver
  2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                   ` (8 preceding siblings ...)
  2020-09-29 11:09 ` [dpdk-dev] [PATCH 9/9] net/hns3: remove redundant return value assignments Wei Hu (Xavier)
@ 2020-09-29 12:01 ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
                     ` (9 more replies)
  9 siblings, 10 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

This series are updates and fixes for hns3 PMD driver.

Chengchang Tang (1):
  net/hns3: support start and stop Tx or Rx queue

Hongbo Zheng (2):
  net/hns3: check return value when reading PCI config space
  net/hns3: remove redundant return value assignments

Huisong Li (3):
  net/hns3: expand the number of queues for one TC up to 512
  net/hns3: offload calculating the shapping para to firmware
  net/hns3: set max scheduling rate based on actual board

Wei Hu (Xavier) (3):
  net/hns3: maximize the queue number
  net/hns3: fix error type when validating RSS flow action
  net/hns3: set suitable type when initial flow error struct

 config/rte_config.h               |   3 +
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_cmd.h       |  28 +-
 drivers/net/hns3/hns3_dcb.c       | 205 +++++++++---
 drivers/net/hns3/hns3_dcb.h       |  60 +++-
 drivers/net/hns3/hns3_ethdev.c    | 214 +++++++++---
 drivers/net/hns3/hns3_ethdev.h    |  32 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 214 ++++++++----
 drivers/net/hns3/hns3_fdir.c      |   6 +-
 drivers/net/hns3/hns3_flow.c      |  97 +++---
 drivers/net/hns3/hns3_intr.c      |   1 -
 drivers/net/hns3/hns3_regs.c      |   4 +-
 drivers/net/hns3/hns3_regs.h      |   5 +
 drivers/net/hns3/hns3_rss.c       |  34 +-
 drivers/net/hns3/hns3_rss.h       |   5 +-
 drivers/net/hns3/hns3_rxtx.c      | 675 +++++++++++++++++++++++++++++++-------
 drivers/net/hns3/hns3_rxtx.h      |  18 +-
 drivers/net/hns3/hns3_stats.c     |  73 ++++-
 drivers/net/hns3/hns3_stats.h     |   6 +-
 19 files changed, 1281 insertions(+), 401 deletions(-)

-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 1/9] net/hns3: expand the number of queues for one TC up to 512
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 2/9] net/hns3: maximize the queue number Wei Hu (Xavier)
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Huisong Li <lihuisong@huawei.com>

The maximum number of queues for one TC hns3 PF PMD driver supported is 64
based on hns3 network engine with revision_id equals 0x21, while it is
expanded up to 512 on hns3 network engine with revision_id equals 0x30.

So the following points need to be modified to maintain better
compatibility.
1) Using a extended rss_size_max field as the maximum queue number of one
   TC PF driver supported.
2) The data type of the RSS redirection table needs to be changed from
   uint8_t to uint16_t.
3) rss_tc_mode modification
   The bitwidth of tc_offset, meaning the rx queue index, has to expand
   from 10 bit to 11 bits. The tc_size, meaning the exponent with base 2
   of queues supported on TC, needs to expand from 3 bits to 4 bits.
4) RSS indirection table modification
   Currently, a field with 7 bits width is used to record the queue index
   for RSS indirection table. It means that PF needs to expand the queue
   index field to 9 bits. As the RSS indirection table config command
   reserved 4 bytes to configure the RSS queue index, a extern field can be
   added. So an entries of RSS indirection table queue index has two fields
   to set: rss_result_l and rss_result_h, while rss_result_l records the
   lower 8 bits and rss_result_h records the higher 1 bit.

In addition, 2~4 modifications is also compatible with hns3 VF PMD driver.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_cmd.h    | 17 ++++++++++++-----
 drivers/net/hns3/hns3_ethdev.c | 16 ++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |  2 ++
 drivers/net/hns3/hns3_fdir.c   |  1 -
 drivers/net/hns3/hns3_flow.c   |  8 +++-----
 drivers/net/hns3/hns3_rss.c    | 34 +++++++++++++++++++++++++---------
 drivers/net/hns3/hns3_rss.h    |  5 +++--
 7 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 0b531d9..dd50484 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -441,6 +441,8 @@ struct hns3_umv_spc_alc_cmd {
 #define HNS3_CFG_SPEED_ABILITY_M	GENMASK(7, 0)
 #define HNS3_CFG_UMV_TBL_SPACE_S	16
 #define HNS3_CFG_UMV_TBL_SPACE_M	GENMASK(31, 16)
+#define HNS3_CFG_EXT_RSS_SIZE_S		0
+#define HNS3_CFG_EXT_RSS_SIZE_M		GENMASK(3, 0)
 
 #define HNS3_ACCEPT_TAG1_B		0
 #define HNS3_ACCEPT_UNTAG1_B		1
@@ -567,20 +569,25 @@ struct hns3_rss_input_tuple_cmd {
 	uint8_t rsv[16];
 };
 
-#define HNS3_RSS_CFG_TBL_SIZE	16
+#define HNS3_RSS_CFG_TBL_SIZE		16
+#define HNS3_RSS_CFG_TBL_SIZE_H		4
+#define HNS3_RSS_CFG_TBL_BW_H		2
+#define HNS3_RSS_CFG_TBL_BW_L		8
 
 /* Configure the indirection table, opcode:0x0D07 */
 struct hns3_rss_indirection_table_cmd {
 	uint16_t start_table_index;  /* Bit3~0 must be 0x0. */
 	uint16_t rss_set_bitmap;
-	uint8_t rsv[4];
-	uint8_t rss_result[HNS3_RSS_CFG_TBL_SIZE];
+	uint8_t rss_result_h[HNS3_RSS_CFG_TBL_SIZE_H];
+	uint8_t rss_result_l[HNS3_RSS_CFG_TBL_SIZE];
 };
 
 #define HNS3_RSS_TC_OFFSET_S		0
-#define HNS3_RSS_TC_OFFSET_M		(0x3ff << HNS3_RSS_TC_OFFSET_S)
+#define HNS3_RSS_TC_OFFSET_M		GENMASK(10, 0)
+#define HNS3_RSS_TC_SIZE_MSB_S		11
+#define HNS3_RSS_TC_SIZE_MSB_OFFSET	3
 #define HNS3_RSS_TC_SIZE_S		12
-#define HNS3_RSS_TC_SIZE_M		(0x7 << HNS3_RSS_TC_SIZE_S)
+#define HNS3_RSS_TC_SIZE_M		GENMASK(14, 12)
 #define HNS3_RSS_TC_VALID_B		15
 
 /* Configure the tc_size and tc_offset, opcode:0x0D08 */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 99bcc7a..c45b1b3 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2709,6 +2709,7 @@ hns3_parse_cfg(struct hns3_cfg *cfg, struct hns3_cmd_desc *desc)
 {
 	struct hns3_cfg_param_cmd *req;
 	uint64_t mac_addr_tmp_high;
+	uint8_t ext_rss_size_max;
 	uint64_t mac_addr_tmp;
 	uint32_t i;
 
@@ -2761,6 +2762,21 @@ hns3_parse_cfg(struct hns3_cfg *cfg, struct hns3_cmd_desc *desc)
 					HNS3_CFG_UMV_TBL_SPACE_S);
 	if (!cfg->umv_space)
 		cfg->umv_space = HNS3_DEFAULT_UMV_SPACE_PER_PF;
+
+	ext_rss_size_max = hns3_get_field(rte_le_to_cpu_32(req->param[2]),
+					       HNS3_CFG_EXT_RSS_SIZE_M,
+					       HNS3_CFG_EXT_RSS_SIZE_S);
+
+	/*
+	 * Field ext_rss_size_max obtained from firmware will be more flexible
+	 * for future changes and expansions, which is an exponent of 2, instead
+	 * of reading out directly. If this field is not zero, hns3 PF PMD
+	 * driver uses it as rss_size_max under one TC. Device, whose revision
+	 * id is greater than or equal to PCI_REVISION_ID_HIP09_A, obtains the
+	 * maximum number of queues supported under a TC through this field.
+	 */
+	if (ext_rss_size_max)
+		cfg->rss_size_max = 1U << ext_rss_size_max;
 }
 
 /* hns3_get_board_cfg: query the static parameter from NCL_config file in flash
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index c2d0a75..3c5ccc7 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -64,6 +64,8 @@
 #define HNS3_HIP08_MIN_TX_PKT_LEN	33
 #define HNS3_HIP09_MIN_TX_PKT_LEN	9
 
+#define HNS3_BITS_PER_BYTE	8
+
 #define HNS3_4_TCS			4
 #define HNS3_8_TCS			8
 
diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c
index 65ab19d..e6a065b 100644
--- a/drivers/net/hns3/hns3_fdir.c
+++ b/drivers/net/hns3/hns3_fdir.c
@@ -125,7 +125,6 @@ static const struct key_info tuple_key_info[] = {
 	{INNER_SCTP_TAG, 32},
 };
 
-#define HNS3_BITS_PER_BYTE	8
 #define MAX_KEY_LENGTH		400
 #define MAX_200B_KEY_LENGTH	200
 #define MAX_META_DATA_LENGTH	16
diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index 2cdfb68..f8e5f05 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -1531,15 +1531,14 @@ hns3_update_indir_table(struct rte_eth_dev *dev,
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	uint8_t indir_tbl[HNS3_RSS_IND_TBL_SIZE];
+	uint16_t indir_tbl[HNS3_RSS_IND_TBL_SIZE];
 	uint16_t j, allow_rss_queues;
-	uint8_t queue_id;
 	uint32_t i;
 
 	allow_rss_queues = RTE_MIN(dev->data->nb_rx_queues, hw->rss_size_max);
 	/* Fill in redirection table */
 	memcpy(indir_tbl, hw->rss_info.rss_indirection_tbl,
-	       HNS3_RSS_IND_TBL_SIZE);
+	       sizeof(hw->rss_info.rss_indirection_tbl));
 	for (i = 0, j = 0; i < HNS3_RSS_IND_TBL_SIZE; i++, j++) {
 		j %= num;
 		if (conf->queue[j] >= allow_rss_queues) {
@@ -1549,8 +1548,7 @@ hns3_update_indir_table(struct rte_eth_dev *dev,
 				 allow_rss_queues);
 			return -EINVAL;
 		}
-		queue_id = conf->queue[j];
-		indir_tbl[i] = queue_id;
+		indir_tbl[i] = conf->queue[j];
 	}
 
 	return hns3_set_rss_indir_table(hw, indir_tbl, HNS3_RSS_IND_TBL_SIZE);
diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c
index 5b51512..a8b8143 100644
--- a/drivers/net/hns3/hns3_rss.c
+++ b/drivers/net/hns3/hns3_rss.c
@@ -266,11 +266,15 @@ hns3_set_rss_input_tuple(struct hns3_hw *hw)
  * Used to configure the indirection table of rss.
  */
 int
-hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
+hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size)
 {
 	struct hns3_rss_indirection_table_cmd *req;
 	struct hns3_cmd_desc desc;
-	int ret, i, j, num;
+	uint8_t qid_msb_off;
+	uint8_t qid_msb_val;
+	uint16_t q_id;
+	uint16_t i, j;
+	int ret;
 
 	req = (struct hns3_rss_indirection_table_cmd *)desc.data;
 
@@ -281,9 +285,17 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
 				rte_cpu_to_le_16(i * HNS3_RSS_CFG_TBL_SIZE);
 		req->rss_set_bitmap = rte_cpu_to_le_16(HNS3_RSS_SET_BITMAP_MSK);
 		for (j = 0; j < HNS3_RSS_CFG_TBL_SIZE; j++) {
-			num = i * HNS3_RSS_CFG_TBL_SIZE + j;
-			req->rss_result[j] = indir[num];
+			q_id = indir[i * HNS3_RSS_CFG_TBL_SIZE + j];
+			req->rss_result_l[j] = q_id & 0xff;
+
+			qid_msb_off =
+				j * HNS3_RSS_CFG_TBL_BW_H / HNS3_BITS_PER_BYTE;
+			qid_msb_val = (q_id >> HNS3_RSS_CFG_TBL_BW_L & 0x1)
+					<< (j * HNS3_RSS_CFG_TBL_BW_H %
+					HNS3_BITS_PER_BYTE);
+			req->rss_result_h[qid_msb_off] |= qid_msb_val;
 		}
+
 		ret = hns3_cmd_send(hw, &desc, 1);
 		if (ret) {
 			hns3_err(hw,
@@ -294,7 +306,8 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
 	}
 
 	/* Update redirection table of hw */
-	memcpy(hw->rss_info.rss_indirection_tbl, indir,	HNS3_RSS_IND_TBL_SIZE);
+	memcpy(hw->rss_info.rss_indirection_tbl, indir,
+	       sizeof(hw->rss_info.rss_indirection_tbl));
 
 	return 0;
 }
@@ -302,10 +315,11 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
 int
 hns3_rss_reset_indir_table(struct hns3_hw *hw)
 {
-	uint8_t *lut;
+	uint16_t *lut;
 	int ret;
 
-	lut = rte_zmalloc("hns3_rss_lut", HNS3_RSS_IND_TBL_SIZE, 0);
+	lut = rte_zmalloc("hns3_rss_lut",
+			  HNS3_RSS_IND_TBL_SIZE * sizeof(uint16_t), 0);
 	if (lut == NULL) {
 		hns3_err(hw, "No hns3_rss_lut memory can be allocated");
 		return -ENOMEM;
@@ -487,7 +501,7 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
 	uint16_t i, indir_size = HNS3_RSS_IND_TBL_SIZE; /* Table size is 512 */
-	uint8_t indirection_tbl[HNS3_RSS_IND_TBL_SIZE];
+	uint16_t indirection_tbl[HNS3_RSS_IND_TBL_SIZE];
 	uint16_t idx, shift, allow_rss_queues;
 	int ret;
 
@@ -499,7 +513,7 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
 	}
 	rte_spinlock_lock(&hw->lock);
 	memcpy(indirection_tbl, rss_cfg->rss_indirection_tbl,
-		HNS3_RSS_IND_TBL_SIZE);
+	       sizeof(rss_cfg->rss_indirection_tbl));
 	allow_rss_queues = RTE_MIN(dev->data->nb_rx_queues, hw->rss_size_max);
 	for (i = 0; i < reta_size; i++) {
 		idx = i / RTE_RETA_GROUP_SIZE;
@@ -598,6 +612,8 @@ hns3_set_rss_tc_mode(struct hns3_hw *hw)
 		hns3_set_bit(mode, HNS3_RSS_TC_VALID_B, (tc_valid[i] & 0x1));
 		hns3_set_field(mode, HNS3_RSS_TC_SIZE_M, HNS3_RSS_TC_SIZE_S,
 			       tc_size[i]);
+		if (tc_size[i] >> HNS3_RSS_TC_SIZE_MSB_OFFSET > 0)
+			hns3_set_bit(mode, HNS3_RSS_TC_SIZE_MSB_S, 1);
 		hns3_set_field(mode, HNS3_RSS_TC_OFFSET_M, HNS3_RSS_TC_OFFSET_S,
 			       tc_offset[i]);
 
diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h
index 8fa1b30..b5ac8ae 100644
--- a/drivers/net/hns3/hns3_rss.h
+++ b/drivers/net/hns3/hns3_rss.h
@@ -45,7 +45,7 @@ struct hns3_rss_conf {
 	uint8_t hash_algo; /* hash function type definited by hardware */
 	uint8_t key[HNS3_RSS_KEY_SIZE];  /* Hash key */
 	struct hns3_rss_tuple_cfg rss_tuple_sets;
-	uint8_t rss_indirection_tbl[HNS3_RSS_IND_TBL_SIZE]; /* Shadow table */
+	uint16_t rss_indirection_tbl[HNS3_RSS_IND_TBL_SIZE]; /* Shadow table */
 	uint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */
 	bool valid; /* check if RSS rule is valid */
 };
@@ -97,7 +97,8 @@ int hns3_dev_rss_reta_query(struct rte_eth_dev *dev,
 			    struct rte_eth_rss_reta_entry64 *reta_conf,
 			    uint16_t reta_size);
 void hns3_set_default_rss_args(struct hns3_hw *hw);
-int hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size);
+int hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir,
+			     uint16_t size);
 int hns3_rss_reset_indir_table(struct hns3_hw *hw);
 int hns3_config_rss(struct hns3_adapter *hns);
 void hns3_rss_uninit(struct hns3_adapter *hns);
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 2/9] net/hns3: maximize the queue number
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 3/9] net/hns3: fix error type when validating RSS flow action Wei Hu (Xavier)
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: "Wei Hu (Xavier)" <xavier.huwei@huawei.com>

The maximum number of queues for hns3 PF and VF driver is 64 based on hns3
network engine with revision_id equals 0x21. Based on hns3 network engine
with revision_id equals 0x30, the hns3 PF PMD driver can support up to 1280
queues, and hns3 VF PMD driver can support up to 128 queues.

The following points need to be modified to support maximizing queue number
and maintain better compatibility:
1) Maximizing the number of queues for hns3 PF and VF PMD driver
   In current version, VF is not supported when PF is driven by hns3 PMD
   driver. If maximum queue numbers allocated to PF PMD driver is less than
   total tqps_num allocated to this port, all remaining number of queues
   are mapped to VF function, which is unreasonable. So we fix that all
   remaining number of queues are mapped to PF function.

   Using RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF which comes from configuration
   file to limit the queue number allocated to PF device based on hns3
   network engine with revision_id greater than 0x30. And PF device still
   keep the maximum 64 queues based on hns3 network engine with revision_id
   equals 0x21.

   Remove restriction of the macro HNS3_MAX_TQP_NUM_PER_FUNC on the maximum
   number of queues in hns3 VF PMD driver and use the value allocated by
   hns3 PF kernel netdev driver.

2) According to the queue number allocated to PF device, a variable array
   for Rx and Tx queue is dynamically allocated to record the statistics of
   Rx and Tx queues during the .dev_init ops implementation function.
3) Add an extended field in hns3_pf_res_cmd to support the case that
   numbers of queue are greater than 1024.
4) Use new base address of Rx or Tx queue if QUEUE_ID of Rx or Tx queue is
   greater than 1024.
5) Remove queue id mask and use all bits of actual queue_id as the queue_id
   to configure hardware.
6) Currently, 0~9 bits of qset_id in hns3_nq_to_qs_link_cmd used to record
   actual qset id and 10 bit as VLD bit are configured to hardware. So we
   also need to use 11~15 bits when actual qset_id is greater than 1024.
7) The number of queue sets based on different network engine are
   different. We use it to calculate group number and configure to hardware
   in the backpressure configuration.
8) Adding check operations for number of Rx and Tx queue user configured
   when mapping queue to tc Rx queue numbers under a single TC must be
   less than rss_size_max supported by a single TC. Rx and Tx queue numbers
   are allocated to every TC by average. So Rx and Tx queue numbers must be
   an integer multiple of 2, or redundant queues are not available.
9) We can specify which packets enter the queue with a specific queue
   number, when creating flow table rules by rte_flow API. Currently,
   driver uses 0~9 bits to record the queue_id. So it is necessary to
   extend one bit field to record queue_id and configure to hardware, if
   the queue_id is greater than 1024.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
v1 -> v2: fix typo. replace 'fpr'  with 'for'.
---
 config/rte_config.h               |   3 +
 drivers/net/hns3/hns3_cmd.h       |   7 +-
 drivers/net/hns3/hns3_dcb.c       | 138 +++++++++++++++++++++++++++++++-------
 drivers/net/hns3/hns3_dcb.h       |  21 +++---
 drivers/net/hns3/hns3_ethdev.c    | 100 +++++++++++++++++++--------
 drivers/net/hns3/hns3_ethdev.h    |  30 ++++++++-
 drivers/net/hns3/hns3_ethdev_vf.c |  59 +++++++++-------
 drivers/net/hns3/hns3_fdir.c      |   5 ++
 drivers/net/hns3/hns3_regs.c      |   2 +-
 drivers/net/hns3/hns3_regs.h      |   3 +
 drivers/net/hns3/hns3_rxtx.c      |  28 ++++++--
 drivers/net/hns3/hns3_rxtx.h      |   2 +
 drivers/net/hns3/hns3_stats.c     |  73 +++++++++++++++-----
 drivers/net/hns3/hns3_stats.h     |   6 +-
 14 files changed, 362 insertions(+), 115 deletions(-)

diff --git a/config/rte_config.h b/config/rte_config.h
index 0bae630..03d90d7 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -117,6 +117,9 @@
 /* fm10k defines */
 #define RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE 1
 
+/* hns3 defines */
+#define RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF 256
+
 /* i40e defines */
 #define RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC 1
 #undef RTE_LIBRTE_I40E_16BYTE_RX_DESC
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index dd50484..ecca75c 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -9,7 +9,6 @@
 #define HNS3_CMDQ_RX_INVLD_B		0
 #define HNS3_CMDQ_RX_OUTVLD_B		1
 #define HNS3_CMD_DESC_ALIGNMENT		4096
-#define HNS3_QUEUE_ID_MASK		0x1ff
 #define HNS3_CMD_FLAG_NEXT		BIT(2)
 
 struct hns3_hw;
@@ -388,7 +387,8 @@ struct hns3_pf_res_cmd {
 	uint16_t pf_own_fun_number;
 	uint16_t tx_buf_size;
 	uint16_t dv_buf_size;
-	uint16_t tqp_num_ext;
+	/* number of queues that exceed 1024 */
+	uint16_t ext_tqp_num;
 	uint16_t roh_pf_intr_vector_number;
 	uint32_t rsv[1];
 };
@@ -671,7 +671,6 @@ struct hns3_config_mac_speed_dup_cmd {
 	uint8_t rsv[22];
 };
 
-#define HNS3_RING_ID_MASK		GENMASK(9, 0)
 #define HNS3_TQP_ENABLE_B		0
 
 #define HNS3_MAC_CFG_AN_EN_B		0
@@ -835,7 +834,7 @@ struct hns3_dev_specs_0_cmd {
 	uint32_t max_tm_rate;
 };
 
-#define HNS3_MAX_TQP_NUM_PER_FUNC	64
+#define HNS3_MAX_TQP_NUM_HIP08_PF	64
 #define HNS3_DEFAULT_TX_BUF		0x4000    /* 16k  bytes */
 #define HNS3_TOTAL_PKT_BUF		0x108000  /* 1.03125M bytes */
 #define HNS3_DEFAULT_DV			0xA000    /* 40k byte */
diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index c1be49e..fecedff 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -576,21 +576,31 @@ hns3_dcb_pri_shaper_cfg(struct hns3_hw *hw)
 	return ret;
 }
 
-void
+static int
 hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q)
 {
 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
 	uint16_t rx_qnum_per_tc;
+	uint16_t used_rx_queues;
 	int i;
 
 	rx_qnum_per_tc = nb_rx_q / hw->num_tc;
-	rx_qnum_per_tc = RTE_MIN(hw->rss_size_max, rx_qnum_per_tc);
-	if (hw->alloc_rss_size != rx_qnum_per_tc) {
-		hns3_info(hw, "rss size changes from %u to %u",
-			  hw->alloc_rss_size, rx_qnum_per_tc);
-		hw->alloc_rss_size = rx_qnum_per_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.",
+			 rx_qnum_per_tc, hw->rss_size_max);
+		return -EINVAL;
 	}
-	hw->used_rx_queues = hw->num_tc * hw->alloc_rss_size;
+
+	used_rx_queues = hw->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);
+		return -EINVAL;
+	}
+	hw->alloc_rss_size = rx_qnum_per_tc;
+	hw->used_rx_queues = used_rx_queues;
 
 	/*
 	 * When rss size is changed, we need to update rss redirection table
@@ -604,15 +614,29 @@ hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q)
 			rss_cfg->rss_indirection_tbl[i] =
 							i % hw->alloc_rss_size;
 	}
+
+	return 0;
 }
 
-void
-hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue)
+static int
+hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_tx_q)
 {
 	struct hns3_tc_queue_info *tc_queue;
+	uint16_t used_tx_queues;
+	uint16_t tx_qnum_per_tc;
 	uint8_t i;
 
-	hw->tx_qnum_per_tc = nb_queue / hw->num_tc;
+	tx_qnum_per_tc = nb_tx_q / hw->num_tc;
+	used_tx_queues = hw->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);
+		return -EINVAL;
+	}
+
+	hw->used_tx_queues = used_tx_queues;
+	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) {
@@ -628,22 +652,39 @@ hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue)
 			tc_queue->tc = 0;
 		}
 	}
-	hw->used_tx_queues = hw->num_tc * hw->tx_qnum_per_tc;
+
+	return 0;
 }
 
-static void
+int
+hns3_queue_to_tc_mapping(struct hns3_hw *hw, uint16_t nb_rx_q, uint16_t nb_tx_q)
+{
+	int ret;
+
+	ret = hns3_set_rss_size(hw, nb_rx_q);
+	if (ret)
+		return ret;
+
+	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)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct hns3_pf *pf = &hns->pf;
+	int ret;
 
 	hw->num_tc = hw->dcb_info.num_tc;
-	hns3_set_rss_size(hw, nb_rx_q);
-	hns3_tc_queue_mapping_cfg(hw, nb_tx_q);
+	ret = hns3_queue_to_tc_mapping(hw, nb_rx_q, nb_tx_q);
+	if (ret)
+		return ret;
 
 	if (!hns->is_vf)
 		memcpy(pf->prio_tc, hw->dcb_info.prio_tc, HNS3_MAX_USER_PRIO);
+
+	return 0;
 }
 
 int
@@ -886,13 +927,35 @@ hns3_q_to_qs_map_cfg(struct hns3_hw *hw, uint16_t q_id, uint16_t qs_id)
 {
 	struct hns3_nq_to_qs_link_cmd *map;
 	struct hns3_cmd_desc desc;
+	uint16_t tmp_qs_id = 0;
+	uint16_t qs_id_l;
+	uint16_t qs_id_h;
 
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_NQ_TO_QS_LINK, false);
 
 	map = (struct hns3_nq_to_qs_link_cmd *)desc.data;
 
 	map->nq_id = rte_cpu_to_le_16(q_id);
-	map->qset_id = rte_cpu_to_le_16(qs_id | HNS3_DCB_Q_QS_LINK_VLD_MSK);
+
+	/*
+	 * Network engine with revision_id 0x21 uses 0~9 bit of qs_id to
+	 * configure qset_id. So we need to convert qs_id to the follow
+	 * format to support qset_id > 1024.
+	 * qs_id: | 15 | 14 ~ 10 |  9 ~ 0   |
+	 *            /         / \         \
+	 *           /         /   \         \
+	 * qset_id: | 15 ~ 11 |  10 |  9 ~ 0  |
+	 *          | qs_id_h | vld | qs_id_l |
+	 */
+	qs_id_l = hns3_get_field(qs_id, HNS3_DCB_QS_ID_L_MSK,
+				 HNS3_DCB_QS_ID_L_S);
+	qs_id_h = hns3_get_field(qs_id, HNS3_DCB_QS_ID_H_MSK,
+				 HNS3_DCB_QS_ID_H_S);
+	hns3_set_field(tmp_qs_id, HNS3_DCB_QS_ID_L_MSK, HNS3_DCB_QS_ID_L_S,
+		       qs_id_l);
+	hns3_set_field(tmp_qs_id, HNS3_DCB_QS_ID_H_EXT_MSK,
+		       HNS3_DCB_QS_ID_H_EXT_S, qs_id_h);
+	map->qset_id = rte_cpu_to_le_16(tmp_qs_id | HNS3_DCB_Q_QS_LINK_VLD_MSK);
 
 	return hns3_cmd_send(hw, &desc, 1);
 }
@@ -1291,7 +1354,7 @@ hns3_dcb_cfg_validate(struct hns3_adapter *hns, uint8_t *tc, bool *changed)
 		*changed = true;
 }
 
-static void
+static int
 hns3_dcb_info_cfg(struct hns3_adapter *hns)
 {
 	struct rte_eth_dcb_rx_conf *dcb_rx_conf;
@@ -1299,6 +1362,7 @@ hns3_dcb_info_cfg(struct hns3_adapter *hns)
 	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;
@@ -1338,8 +1402,12 @@ 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];
 
-	hns3_dcb_update_tc_queue_mapping(hw, hw->data->nb_rx_queues,
-					 hw->data->nb_tx_queues);
+	ret = hns3_dcb_update_tc_queue_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);
+
+	return ret;
 }
 
 static int
@@ -1378,9 +1446,8 @@ hns3_dcb_info_update(struct hns3_adapter *hns, uint8_t num_tc)
 		hw->dcb_info.num_tc = 1;
 	}
 	hw->hw_tc_map = bit_map;
-	hns3_dcb_info_cfg(hns);
 
-	return 0;
+	return hns3_dcb_info_cfg(hns);
 }
 
 static int
@@ -1505,6 +1572,7 @@ hns3_dcb_init(struct hns3_hw *hw)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct hns3_pf *pf = &hns->pf;
+	uint16_t default_tqp_num;
 	int ret;
 
 	PMD_INIT_FUNC_TRACE();
@@ -1525,11 +1593,24 @@ hns3_dcb_init(struct hns3_hw *hw)
 
 		ret = hns3_dcb_info_init(hw);
 		if (ret) {
-			hns3_err(hw, "dcb info init failed: %d", ret);
+			hns3_err(hw, "dcb info init failed, ret = %d.", ret);
+			return ret;
+		}
+
+		/*
+		 * The number of queues configured by default cannot exceed
+		 * the maximum number of queues for a single TC.
+		 */
+		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);
+		if (ret) {
+			hns3_err(hw,
+				 "update tc queue mapping failed, ret = %d.",
+				 ret);
 			return ret;
 		}
-		hns3_dcb_update_tc_queue_mapping(hw, hw->tqps_num,
-						 hw->tqps_num);
 	}
 
 	/*
@@ -1541,7 +1622,7 @@ hns3_dcb_init(struct hns3_hw *hw)
 	 */
 	ret = hns3_dcb_init_hw(hw);
 	if (ret) {
-		hns3_err(hw, "dcb init hardware failed: %d", ret);
+		hns3_err(hw, "dcb init hardware failed, ret = %d.", ret);
 		return ret;
 	}
 
@@ -1556,10 +1637,15 @@ hns3_update_queue_map_configure(struct hns3_adapter *hns)
 	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	int ret;
 
-	hns3_dcb_update_tc_queue_mapping(hw, nb_rx_q, nb_tx_q);
+	ret = hns3_dcb_update_tc_queue_mapping(hw, nb_rx_q, nb_tx_q);
+	if (ret) {
+		hns3_err(hw, "failed to update tc queue mapping, ret = %d.",
+			 ret);
+		return ret;
+	}
 	ret = hns3_q_to_qs_map(hw);
 	if (ret)
-		hns3_err(hw, "failed to map nq to qs! ret = %d", ret);
+		hns3_err(hw, "failed to map nq to qs, ret = %d.", ret);
 
 	return ret;
 }
diff --git a/drivers/net/hns3/hns3_dcb.h b/drivers/net/hns3/hns3_dcb.h
index 557d88b..05c9786 100644
--- a/drivers/net/hns3/hns3_dcb.h
+++ b/drivers/net/hns3/hns3_dcb.h
@@ -52,6 +52,12 @@ struct hns3_qs_to_pri_link_cmd {
 	uint16_t rsvd;
 	uint8_t priority;
 #define HNS3_DCB_QS_PRI_LINK_VLD_MSK	BIT(0)
+#define HNS3_DCB_QS_ID_L_MSK		GENMASK(9, 0)
+#define HNS3_DCB_QS_ID_L_S		0
+#define HNS3_DCB_QS_ID_H_MSK		GENMASK(14, 10)
+#define HNS3_DCB_QS_ID_H_S		10
+#define HNS3_DCB_QS_ID_H_EXT_S		11
+#define HNS3_DCB_QS_ID_H_EXT_MSK	GENMASK(15, 11)
 	uint8_t link_vld;
 	uint8_t rsvd1[18];
 };
@@ -89,11 +95,12 @@ struct hns3_pg_shapping_cmd {
 	uint32_t rsvd1[4];
 };
 
-#define HNS3_BP_GRP_NUM		32
+#define HNS3_BP_GRP_NUM			32
 #define HNS3_BP_SUB_GRP_ID_S		0
 #define HNS3_BP_SUB_GRP_ID_M		GENMASK(4, 0)
 #define HNS3_BP_GRP_ID_S		5
 #define HNS3_BP_GRP_ID_M		GENMASK(9, 5)
+
 struct hns3_bp_to_qs_map_cmd {
 	uint8_t tc_id;
 	uint8_t rsvd[2];
@@ -165,15 +172,13 @@ int hns3_dcb_init_hw(struct hns3_hw *hw);
 
 int hns3_dcb_info_init(struct hns3_hw *hw);
 
-int
-hns3_fc_enable(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf);
-
-int
-hns3_dcb_pfc_enable(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf);
+int hns3_fc_enable(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf);
 
-void hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q);
+int hns3_dcb_pfc_enable(struct rte_eth_dev *dev,
+			struct rte_eth_pfc_conf *pfc_conf);
 
-void hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue);
+int hns3_queue_to_tc_mapping(struct hns3_hw *hw, uint16_t nb_rx_q,
+			     uint16_t nb_tx_q);
 
 int hns3_dcb_cfg_update(struct hns3_adapter *hns);
 
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index c45b1b3..6e0f52b 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2660,6 +2660,49 @@ hns3_query_function_status(struct hns3_hw *hw)
 }
 
 static int
+hns3_get_pf_max_tqp_num(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+
+	if (pf->tqp_config_mode == HNS3_FLEX_MAX_TQP_NUM_MODE) {
+		/*
+		 * The total_tqps_num obtained from firmware is maximum tqp
+		 * numbers of this port, which should be used for PF and VFs.
+		 * There is no need for pf to have so many tqp numbers in
+		 * most cases. RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF,
+		 * coming from config file, is assigned to maximum queue number
+		 * for the PF of this port by user. So users can modify the
+		 * maximum queue number of PF according to their own application
+		 * scenarios, which is more flexible to use. In addition, many
+		 * memories can be saved due to allocating queue statistics
+		 * room according to the actual number of queues required. The
+		 * maximum queue number of PF for network engine with
+		 * revision_id greater than 0x30 is assigned by config file.
+		 */
+		if (RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF <= 0) {
+			hns3_err(hw, "RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF(%d) "
+				 "must be greater than 0.",
+				 RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF);
+			return -EINVAL;
+		}
+
+		hw->tqps_num = RTE_MIN(RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF,
+				       hw->total_tqps_num);
+	} else {
+		/*
+		 * Due to the limitation on the number of PF interrupts
+		 * available, the maximum queue number assigned to PF on
+		 * the network engine with revision_id 0x21 is 64.
+		 */
+		hw->tqps_num = RTE_MIN(hw->total_tqps_num,
+				       HNS3_MAX_TQP_NUM_HIP08_PF);
+	}
+
+	return 0;
+}
+
+static int
 hns3_query_pf_resource(struct hns3_hw *hw)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
@@ -2676,9 +2719,13 @@ hns3_query_pf_resource(struct hns3_hw *hw)
 	}
 
 	req = (struct hns3_pf_res_cmd *)desc.data;
-	hw->total_tqps_num = rte_le_to_cpu_16(req->tqp_num);
+	hw->total_tqps_num = rte_le_to_cpu_16(req->tqp_num) +
+			     rte_le_to_cpu_16(req->ext_tqp_num);
+	ret = hns3_get_pf_max_tqp_num(hw);
+	if (ret)
+		return ret;
+
 	pf->pkt_buf_size = rte_le_to_cpu_16(req->buf_size) << HNS3_BUF_UNIT_S;
-	hw->tqps_num = RTE_MIN(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
 	pf->func_num = rte_le_to_cpu_16(req->pf_own_fun_number);
 
 	if (req->tx_buf_size)
@@ -2902,7 +2949,9 @@ hns3_query_dev_specifications(struct hns3_hw *hw)
 static int
 hns3_get_capability(struct hns3_hw *hw)
 {
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct rte_pci_device *pci_dev;
+	struct hns3_pf *pf = &hns->pf;
 	struct rte_eth_dev *eth_dev;
 	uint16_t device_id;
 	uint8_t revision;
@@ -2936,6 +2985,7 @@ hns3_get_capability(struct hns3_hw *hw)
 		hw->tso_mode = HNS3_TSO_SW_CAL_PSEUDO_H_CSUM;
 		hw->vlan_mode = HNS3_SW_SHIFT_AND_DISCARD_MODE;
 		hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN;
+		pf->tqp_config_mode = HNS3_FIXED_MAX_TQP_NUM_MODE;
 		return 0;
 	}
 
@@ -2953,6 +3003,7 @@ hns3_get_capability(struct hns3_hw *hw)
 	hw->tso_mode = HNS3_TSO_HW_CAL_PSEUDO_H_CSUM;
 	hw->vlan_mode = HNS3_HW_SHIFT_AND_DISCARD_MODE;
 	hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN;
+	pf->tqp_config_mode = HNS3_FLEX_MAX_TQP_NUM_MODE;
 
 	return 0;
 }
@@ -3048,7 +3099,7 @@ hns3_get_configuration(struct hns3_hw *hw)
 
 	ret = hns3_get_board_configuration(hw);
 	if (ret)
-		PMD_INIT_LOG(ERR, "Failed to get board configuration: %d", ret);
+		PMD_INIT_LOG(ERR, "failed to get board configuration: %d", ret);
 
 	return ret;
 }
@@ -3081,29 +3132,18 @@ hns3_map_tqps_to_func(struct hns3_hw *hw, uint16_t func_id, uint16_t tqp_pid,
 static int
 hns3_map_tqp(struct hns3_hw *hw)
 {
-	uint16_t tqps_num = hw->total_tqps_num;
-	uint16_t func_id;
-	uint16_t tqp_id;
-	bool is_pf;
-	int num;
 	int ret;
 	int i;
 
 	/*
-	 * In current version VF is not supported when PF is driven by DPDK
-	 * driver, so we allocate tqps to PF as much as possible.
+	 * In current version, VF is not supported when PF is driven by DPDK
+	 * driver, so we assign total tqps_num tqps allocated to this port
+	 * to PF.
 	 */
-	tqp_id = 0;
-	num = DIV_ROUND_UP(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
-	for (func_id = HNS3_PF_FUNC_ID; func_id < num; func_id++) {
-		is_pf = func_id == HNS3_PF_FUNC_ID ? true : false;
-		for (i = 0;
-		     i < HNS3_MAX_TQP_NUM_PER_FUNC && tqp_id < tqps_num; i++) {
-			ret = hns3_map_tqps_to_func(hw, func_id, tqp_id++, i,
-						    is_pf);
-			if (ret)
-				return ret;
-		}
+	for (i = 0; i < hw->total_tqps_num; i++) {
+		ret = hns3_map_tqps_to_func(hw, HNS3_PF_FUNC_ID, i, i, true);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
@@ -4558,17 +4598,21 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
 		goto err_get_config;
 	}
 
+	ret = hns3_tqp_stats_init(hw);
+	if (ret)
+		goto err_get_config;
+
 	ret = hns3_init_hardware(hns);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to init hardware: %d", ret);
-		goto err_get_config;
+		goto err_init_hw;
 	}
 
 	/* Initialize flow director filter list & hash */
 	ret = hns3_fdir_filter_init(hns);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to alloc hashmap for fdir: %d", ret);
-		goto err_hw_init;
+		goto err_fdir;
 	}
 
 	hns3_set_default_rss_args(hw);
@@ -4577,16 +4621,17 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
 	if (ret) {
 		PMD_INIT_LOG(ERR, "fail to enable hw error interrupts: %d",
 			     ret);
-		goto err_fdir;
+		goto err_enable_intr;
 	}
 
 	return 0;
 
-err_fdir:
+err_enable_intr:
 	hns3_fdir_filter_uninit(hns);
-err_hw_init:
+err_fdir:
 	hns3_uninit_umv_space(hw);
-
+err_init_hw:
+	hns3_tqp_stats_uninit(hw);
 err_get_config:
 	hns3_pf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
@@ -4618,6 +4663,7 @@ hns3_uninit_pf(struct rte_eth_dev *eth_dev)
 	hns3_promisc_uninit(hw);
 	hns3_fdir_filter_uninit(hns);
 	hns3_uninit_umv_space(hw);
+	hns3_tqp_stats_uninit(hw);
 	hns3_pf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
 	hns3_intr_unregister(&pci_dev->intr_handle, hns3_interrupt_handler,
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 3c5ccc7..22c6a15 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -134,9 +134,9 @@ enum hns3_fc_status {
 };
 
 struct hns3_tc_queue_info {
-	uint8_t	tqp_offset;     /* TQP offset from base TQP */
-	uint8_t	tqp_count;      /* Total TQPs */
-	uint8_t	tc;             /* TC index */
+	uint16_t tqp_offset;    /* TQP offset from base TQP */
+	uint16_t tqp_count;     /* Total TQPs */
+	uint8_t tc;             /* TC index */
 	bool enable;            /* If this TC is enable or not */
 };
 
@@ -661,11 +661,35 @@ struct hns3_ptype_table {
 	uint32_t ol4table[HNS3_OL4TBL_NUM];
 };
 
+#define HNS3_FIXED_MAX_TQP_NUM_MODE		0
+#define HNS3_FLEX_MAX_TQP_NUM_MODE		1
+
 struct hns3_pf {
 	struct hns3_adapter *adapter;
 	bool is_main_pf;
 	uint16_t func_num; /* num functions of this pf, include pf and vfs */
 
+	/*
+	 * tqp_config mode
+	 * tqp_config_mode value range:
+	 *	HNS3_FIXED_MAX_TQP_NUM_MODE,
+	 *	HNS3_FLEX_MAX_TQP_NUM_MODE
+	 *
+	 * - HNS3_FIXED_MAX_TQP_NUM_MODE
+	 *   There is a limitation on the number of pf interrupts available for
+	 *   on some versions of network engines. In this case, the maximum
+	 *   queue number of pf can not be greater than the interrupt number,
+	 *   such as pf of network engine with revision_id 0x21. So the maximum
+	 *   number of queues must be fixed.
+	 *
+	 * - HNS3_FLEX_MAX_TQP_NUM_MODE
+	 *   In this mode, the maximum queue number of pf has not any constraint
+	 *   and comes from the macro RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF
+	 *   in the config file. Users can modify the macro according to their
+	 *   own application scenarios, which is more flexible to use.
+	 */
+	uint8_t tqp_config_mode;
+
 	uint32_t pkt_buf_size; /* Total pf buf size for tx/rx */
 	uint32_t tx_buf_size; /* Tx buffer size for each TC */
 	uint32_t dv_buf_size; /* Dv buffer size for each TC */
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 4c73441..0b949e9 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1191,20 +1191,21 @@ hns3vf_get_capability(struct hns3_hw *hw)
 static int
 hns3vf_check_tqp_info(struct hns3_hw *hw)
 {
-	uint16_t tqps_num;
+	if (hw->tqps_num == 0) {
+		PMD_INIT_LOG(ERR, "Get invalid tqps_num(0) from PF.");
+		return -EINVAL;
+	}
 
-	tqps_num = hw->tqps_num;
-	if (tqps_num > HNS3_MAX_TQP_NUM_PER_FUNC || tqps_num == 0) {
-		PMD_INIT_LOG(ERR, "Get invalid tqps_num(%u) from PF. valid "
-				  "range: 1~%d",
-			     tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
+	if (hw->rss_size_max == 0) {
+		PMD_INIT_LOG(ERR, "Get invalid rss_size_max(0) from PF.");
 		return -EINVAL;
 	}
 
-	hw->alloc_rss_size = RTE_MIN(hw->rss_size_max, hw->tqps_num);
+	hw->tqps_num = RTE_MIN(hw->rss_size_max, hw->tqps_num);
 
 	return 0;
 }
+
 static int
 hns3vf_get_port_base_vlan_filter_state(struct hns3_hw *hw)
 {
@@ -1295,6 +1296,7 @@ hns3vf_get_tc_info(struct hns3_hw *hw)
 {
 	uint8_t resp_msg;
 	int ret;
+	int i;
 
 	ret = hns3_send_mbx_msg(hw, HNS3_MBX_GET_TCINFO, 0, NULL, 0,
 				true, &resp_msg, sizeof(resp_msg));
@@ -1306,6 +1308,11 @@ hns3vf_get_tc_info(struct hns3_hw *hw)
 
 	hw->hw_tc_map = resp_msg;
 
+	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
+		if (hw->hw_tc_map & BIT(i))
+			hw->num_tc++;
+	}
+
 	return 0;
 }
 
@@ -1366,17 +1373,10 @@ hns3vf_get_configuration(struct hns3_hw *hw)
 }
 
 static int
-hns3vf_set_tc_info(struct hns3_adapter *hns)
+hns3vf_set_tc_queue_mapping(struct hns3_adapter *hns, uint16_t nb_rx_q,
+			    uint16_t nb_tx_q)
 {
 	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;
-	uint8_t i;
-
-	hw->num_tc = 0;
-	for (i = 0; i < HNS3_MAX_TC_NUM; i++)
-		if (hw->hw_tc_map & BIT(i))
-			hw->num_tc++;
 
 	if (nb_rx_q < hw->num_tc) {
 		hns3_err(hw, "number of Rx queues(%d) is less than tcs(%d).",
@@ -1390,10 +1390,7 @@ hns3vf_set_tc_info(struct hns3_adapter *hns)
 		return -EINVAL;
 	}
 
-	hns3_set_rss_size(hw, nb_rx_q);
-	hns3_tc_queue_mapping_cfg(hw, nb_tx_q);
-
-	return 0;
+	return hns3_queue_to_tc_mapping(hw, nb_rx_q, nb_tx_q);
 }
 
 static void
@@ -1783,20 +1780,33 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)
 		goto err_get_config;
 	}
 
+	ret = hns3_tqp_stats_init(hw);
+	if (ret)
+		goto err_get_config;
+
+	ret = hns3vf_set_tc_queue_mapping(hns, hw->tqps_num, hw->tqps_num);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "failed to set tc info, ret = %d.", ret);
+		goto err_set_tc_queue;
+	}
+
 	ret = hns3vf_clear_vport_list(hw);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to clear tbl list: %d", ret);
-		goto err_get_config;
+		goto err_set_tc_queue;
 	}
 
 	ret = hns3vf_init_hardware(hns);
 	if (ret)
-		goto err_get_config;
+		goto err_set_tc_queue;
 
 	hns3_set_default_rss_args(hw);
 
 	return 0;
 
+err_set_tc_queue:
+	hns3_tqp_stats_uninit(hw);
+
 err_get_config:
 	hns3vf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
@@ -1825,6 +1835,7 @@ hns3vf_uninit_vf(struct rte_eth_dev *eth_dev)
 	(void)hns3_config_gro(hw, false);
 	(void)hns3vf_set_alive(hw, false);
 	(void)hns3vf_set_promisc_mode(hw, false, false, false);
+	hns3_tqp_stats_uninit(hw);
 	hns3vf_disable_irq0(hw);
 	rte_intr_disable(&pci_dev->intr_handle);
 	hns3_intr_unregister(&pci_dev->intr_handle, hns3vf_interrupt_handler,
@@ -2004,9 +2015,11 @@ 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 = hns3vf_set_tc_info(hns);
+	ret = hns3vf_set_tc_queue_mapping(hns, nb_rx_q, nb_tx_q);
 	if (ret)
 		return ret;
 
diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c
index e6a065b..79e3028 100644
--- a/drivers/net/hns3/hns3_fdir.c
+++ b/drivers/net/hns3/hns3_fdir.c
@@ -46,6 +46,8 @@
 #define HNS3_FD_AD_QUEUE_REGION_SIZE_M	GENMASK(20, 17)
 #define HNS3_FD_AD_COUNTER_HIGH_BIT	7
 #define HNS3_FD_AD_COUNTER_HIGH_BIT_B	26
+#define HNS3_FD_AD_QUEUE_ID_HIGH_BIT	10
+#define HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B	21
 
 enum HNS3_PORT_TYPE {
 	HOST_PORT,
@@ -437,6 +439,9 @@ static int hns3_fd_ad_config(struct hns3_hw *hw, int loc,
 	/* set extend bit if counter_id is in [128 ~ 255] */
 	if (action->counter_id & BIT(HNS3_FD_AD_COUNTER_HIGH_BIT))
 		hns3_set_bit(ad_data, HNS3_FD_AD_COUNTER_HIGH_BIT_B, 1);
+	/* set extend bit if queue id > 1024 */
+	if (action->queue_id & BIT(HNS3_FD_AD_QUEUE_ID_HIGH_BIT))
+		hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B, 1);
 	ad_data <<= HNS3_FD_AD_DATA_S;
 	hns3_set_bit(ad_data, HNS3_FD_AD_DROP_B, action->drop_packet);
 	if (action->nb_queues == 1)
diff --git a/drivers/net/hns3/hns3_regs.c b/drivers/net/hns3/hns3_regs.c
index 63c8602..a76f42c 100644
--- a/drivers/net/hns3/hns3_regs.c
+++ b/drivers/net/hns3/hns3_regs.c
@@ -295,7 +295,7 @@ hns3_direct_access_regs(struct hns3_hw *hw, uint32_t *data)
 	reg_um = sizeof(ring_reg_addrs) / sizeof(uint32_t);
 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
 	for (j = 0; j < hw->tqps_num; j++) {
-		reg_offset = HNS3_TQP_REG_OFFSET + HNS3_TQP_REG_SIZE * j;
+		reg_offset = hns3_get_tqp_reg_offset(j);
 		for (i = 0; i < reg_um; i++)
 			*data++ = hns3_read_dev(hw,
 						ring_reg_addrs[i] + reg_offset);
diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h
index 5cf924e..d83c3b3 100644
--- a/drivers/net/hns3/hns3_regs.h
+++ b/drivers/net/hns3/hns3_regs.h
@@ -89,6 +89,9 @@
 #define HNS3_TQP_REG_OFFSET			0x80000
 #define HNS3_TQP_REG_SIZE			0x200
 
+#define HNS3_TQP_EXT_REG_OFFSET			0x100
+#define HNS3_MIN_EXTEND_QUEUE_ID		1024
+
 /* bar registers for tqp interrupt */
 #define HNS3_TQP_INTR_CTRL_REG			0x20000
 #define HNS3_TQP_INTR_GL0_REG			0x20100
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 930aa28..e3f0db4 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -405,7 +405,7 @@ hns3_tqp_enable(struct hns3_hw *hw, uint16_t queue_id, bool enable)
 	req = (struct hns3_cfg_com_tqp_queue_cmd *)desc.data;
 
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_COM_TQP_QUEUE, false);
-	req->tqp_id = rte_cpu_to_le_16(queue_id & HNS3_RING_ID_MASK);
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
 	req->stream_id = 0;
 	hns3_set_bit(req->enable, HNS3_TQP_ENABLE_B, enable ? 1 : 0);
 
@@ -426,7 +426,7 @@ hns3_send_reset_tqp_cmd(struct hns3_hw *hw, uint16_t queue_id, bool enable)
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE, false);
 
 	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
-	req->tqp_id = rte_cpu_to_le_16(queue_id & HNS3_RING_ID_MASK);
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
 	hns3_set_bit(req->reset_req, HNS3_TQP_RESET_B, enable ? 1 : 0);
 
 	ret = hns3_cmd_send(hw, &desc, 1);
@@ -446,7 +446,7 @@ hns3_get_reset_status(struct hns3_hw *hw, uint16_t queue_id)
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE, true);
 
 	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
-	req->tqp_id = rte_cpu_to_le_16(queue_id & HNS3_RING_ID_MASK);
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
 
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret) {
@@ -1341,6 +1341,22 @@ hns3_rx_queue_conf_check(struct hns3_hw *hw, const struct rte_eth_rxconf *conf,
 	return 0;
 }
 
+uint32_t
+hns3_get_tqp_reg_offset(uint16_t queue_id)
+{
+	uint32_t reg_offset;
+
+	/* Need an extend offset to config queue > 1024 */
+	if (queue_id < HNS3_MIN_EXTEND_QUEUE_ID)
+		reg_offset = HNS3_TQP_REG_OFFSET + queue_id * HNS3_TQP_REG_SIZE;
+	else
+		reg_offset = HNS3_TQP_REG_OFFSET + HNS3_TQP_EXT_REG_OFFSET +
+			     (queue_id - HNS3_MIN_EXTEND_QUEUE_ID) *
+			     HNS3_TQP_REG_SIZE;
+
+	return reg_offset;
+}
+
 int
 hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		    unsigned int socket_id, const struct rte_eth_rxconf *conf,
@@ -1422,6 +1438,8 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	rxq->configured = true;
 	rxq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
 				idx * HNS3_TQP_REG_SIZE);
+	rxq->io_base = (void *)((char *)hw->io_base +
+					hns3_get_tqp_reg_offset(idx));
 	rxq->io_head_reg = (volatile void *)((char *)rxq->io_base +
 			   HNS3_RING_RX_HEAD_REG);
 	rxq->rx_buf_len = rx_buf_size;
@@ -2183,8 +2201,8 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		txq->pvid_sw_shift_en = false;
 	txq->max_non_tso_bd_num = hw->max_non_tso_bd_num;
 	txq->configured = true;
-	txq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
-				idx * HNS3_TQP_REG_SIZE);
+	txq->io_base = (void *)((char *)hw->io_base +
+						hns3_get_tqp_reg_offset(idx));
 	txq->io_tail_reg = (volatile void *)((char *)txq->io_base +
 					     HNS3_RING_TX_TAIL_REG);
 	txq->min_tx_pkt_len = hw->min_tx_pkt_len;
diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index d7d70f6..cdfe115 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -661,4 +661,6 @@ void hns3_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 		       struct rte_eth_rxq_info *qinfo);
 void hns3_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 		       struct rte_eth_txq_info *qinfo);
+uint32_t hns3_get_tqp_reg_offset(uint16_t idx);
+
 #endif /* _HNS3_RXTX_H_ */
diff --git a/drivers/net/hns3/hns3_stats.c b/drivers/net/hns3/hns3_stats.c
index e8846b9..8c3c7cc 100644
--- a/drivers/net/hns3/hns3_stats.c
+++ b/drivers/net/hns3/hns3_stats.c
@@ -330,6 +330,8 @@ static const struct hns3_xstats_name_offset hns3_tx_queue_strings[] = {
 #define HNS3_FIX_NUM_STATS (HNS3_NUM_MAC_STATS + HNS3_NUM_ERROR_INT_XSTATS + \
 			    HNS3_NUM_RESET_XSTATS)
 
+static void hns3_tqp_stats_clear(struct hns3_hw *hw);
+
 /*
  * Query all the MAC statistics data of Network ICL command ,opcode id: 0x0034.
  * This command is used before send 'query_mac_stat command', the descriptor
@@ -456,8 +458,7 @@ hns3_update_tqp_stats(struct hns3_hw *hw)
 		hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_RX_STATUS,
 					  true);
 
-		desc.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						HNS3_QUEUE_ID_MASK);
+		desc.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to query RX No.%d queue stat: %d",
@@ -471,8 +472,7 @@ hns3_update_tqp_stats(struct hns3_hw *hw)
 		hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_TX_STATUS,
 					  true);
 
-		desc.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						HNS3_QUEUE_ID_MASK);
+		desc.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to query TX No.%d queue stat: %d",
@@ -553,7 +553,6 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 {
 	struct hns3_adapter *hns = eth_dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	struct hns3_tqp_stats *stats = &hw->tqp_stats;
 	struct hns3_cmd_desc desc_reset;
 	struct hns3_rx_queue *rxq;
 	struct hns3_tx_queue *txq;
@@ -561,14 +560,13 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 	int ret;
 
 	/*
-	 * If this is a reset xstats is NULL, and we have cleared the
-	 * registers by reading them.
+	 * Note: Reading hardware statistics of rx/tx queue packet number
+	 * will clear them.
 	 */
 	for (i = 0; i < hw->tqps_num; i++) {
 		hns3_cmd_setup_basic_desc(&desc_reset, HNS3_OPC_QUERY_RX_STATUS,
 					  true);
-		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						      HNS3_QUEUE_ID_MASK);
+		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc_reset, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to reset RX No.%d queue stat: %d",
@@ -578,8 +576,7 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 
 		hns3_cmd_setup_basic_desc(&desc_reset, HNS3_OPC_QUERY_TX_STATUS,
 					  true);
-		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i &
-						      HNS3_QUEUE_ID_MASK);
+		desc_reset.data[0] = rte_cpu_to_le_32((uint32_t)i);
 		ret = hns3_cmd_send(hw, &desc_reset, 1);
 		if (ret) {
 			hns3_err(hw, "Failed to reset TX No.%d queue stat: %d",
@@ -614,7 +611,7 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 		}
 	}
 
-	memset(stats, 0, sizeof(struct hns3_tqp_stats));
+	hns3_tqp_stats_clear(hw);
 
 	return 0;
 }
@@ -668,8 +665,7 @@ hns3_get_queue_stats(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	/* Get rx queue stats */
 	for (j = 0; j < dev->data->nb_rx_queues; j++) {
 		for (i = 0; i < HNS3_NUM_RX_QUEUE_STATS; i++) {
-			reg_offset = HNS3_TQP_REG_OFFSET +
-					HNS3_TQP_REG_SIZE * j;
+			reg_offset = hns3_get_tqp_reg_offset(j);
 			xstats[*count].value = hns3_read_dev(hw,
 				reg_offset + hns3_rx_queue_strings[i].offset);
 			xstats[*count].id = *count;
@@ -680,8 +676,7 @@ hns3_get_queue_stats(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	/* Get tx queue stats */
 	for (j = 0; j < dev->data->nb_tx_queues; j++) {
 		for (i = 0; i < HNS3_NUM_TX_QUEUE_STATS; i++) {
-			reg_offset = HNS3_TQP_REG_OFFSET +
-					HNS3_TQP_REG_SIZE * j;
+			reg_offset = hns3_get_tqp_reg_offset(j);
 			xstats[*count].value = hns3_read_dev(hw,
 				reg_offset + hns3_tx_queue_strings[i].offset);
 			xstats[*count].id = *count;
@@ -1071,3 +1066,49 @@ hns3_dev_xstats_reset(struct rte_eth_dev *dev)
 
 	return 0;
 }
+
+int
+hns3_tqp_stats_init(struct hns3_hw *hw)
+{
+	struct hns3_tqp_stats *tqp_stats = &hw->tqp_stats;
+
+	tqp_stats->rcb_rx_ring_pktnum = rte_zmalloc("hns3_rx_ring_pkt_num",
+					 sizeof(uint64_t) * hw->tqps_num, 0);
+	if (tqp_stats->rcb_rx_ring_pktnum == NULL) {
+		hns3_err(hw, "failed to allocate rx_ring pkt_num.");
+		return -ENOMEM;
+	}
+
+	tqp_stats->rcb_tx_ring_pktnum = rte_zmalloc("hns3_tx_ring_pkt_num",
+					 sizeof(uint64_t) * hw->tqps_num, 0);
+	if (tqp_stats->rcb_tx_ring_pktnum == NULL) {
+		hns3_err(hw, "failed to allocate tx_ring pkt_num.");
+		rte_free(tqp_stats->rcb_rx_ring_pktnum);
+		tqp_stats->rcb_rx_ring_pktnum = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void
+hns3_tqp_stats_uninit(struct hns3_hw *hw)
+{
+	struct hns3_tqp_stats *tqp_stats = &hw->tqp_stats;
+
+	rte_free(tqp_stats->rcb_rx_ring_pktnum);
+	tqp_stats->rcb_rx_ring_pktnum = NULL;
+	rte_free(tqp_stats->rcb_tx_ring_pktnum);
+	tqp_stats->rcb_tx_ring_pktnum = NULL;
+}
+
+static void
+hns3_tqp_stats_clear(struct hns3_hw *hw)
+{
+	struct hns3_tqp_stats *stats = &hw->tqp_stats;
+
+	stats->rcb_rx_ring_pktnum_rcd = 0;
+	stats->rcb_tx_ring_pktnum_rcd = 0;
+	memset(stats->rcb_rx_ring_pktnum, 0, sizeof(uint64_t) * hw->tqps_num);
+	memset(stats->rcb_tx_ring_pktnum, 0, sizeof(uint64_t) * hw->tqps_num);
+}
diff --git a/drivers/net/hns3/hns3_stats.h b/drivers/net/hns3/hns3_stats.h
index 07570cb..9fcd5f9 100644
--- a/drivers/net/hns3/hns3_stats.h
+++ b/drivers/net/hns3/hns3_stats.h
@@ -14,8 +14,8 @@
 struct hns3_tqp_stats {
 	uint64_t rcb_tx_ring_pktnum_rcd; /* Total num of transmitted packets */
 	uint64_t rcb_rx_ring_pktnum_rcd; /* Total num of received packets */
-	uint64_t rcb_tx_ring_pktnum[HNS3_MAX_TQP_NUM_PER_FUNC];
-	uint64_t rcb_rx_ring_pktnum[HNS3_MAX_TQP_NUM_PER_FUNC];
+	uint64_t *rcb_rx_ring_pktnum;
+	uint64_t *rcb_tx_ring_pktnum;
 };
 
 /* mac stats, Statistics counters collected by the MAC, opcode id: 0x0032 */
@@ -149,5 +149,7 @@ int hns3_dev_xstats_get_names_by_id(struct rte_eth_dev *dev,
 				    uint32_t size);
 int hns3_stats_reset(struct rte_eth_dev *dev);
 void hns3_error_int_stats_add(struct hns3_adapter *hns, const char *err);
+int hns3_tqp_stats_init(struct hns3_hw *hw);
+void hns3_tqp_stats_uninit(struct hns3_hw *hw);
 
 #endif /* _HNS3_STATS_H_ */
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 3/9] net/hns3: fix error type when validating RSS flow action
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 2/9] net/hns3: maximize the queue number Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 4/9] net/hns3: set suitable type when initial flow error struct Wei Hu (Xavier)
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: "Wei Hu (Xavier)" <xavier.huwei@huawei.com>

Because the macro named RTE_FLOW_ERROR_TYPE_ACTION_CONF indicates a action
configuration and the macro named RTE_FLOW_ERROR_TYPE_ACTION indicates a
specific action, the driver needs to return RTE_FLOW_ERROR_ACTION_CONF type
and notify the user when a RSS configuration is invalid with actions list
in the internal function named hns3_parse_rss_filter called by the
'.validate' ops implementation function named hns3_flow_validate.

Besides, this patch removes some unnecessary judgment lines in
hns3_parse_rss_filter.

Fixes: c37ca66f2b27 ("net/hns3: support RSS")
Cc: stable@dpdk.org

Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_flow.c | 35 +++++++++--------------------------
 1 file changed, 9 insertions(+), 26 deletions(-)

diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index f8e5f05..a6676d6 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -1356,7 +1356,6 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev,
 	const struct rte_flow_action_rss *rss;
 	const struct rte_flow_action *act;
 	uint32_t act_index = 0;
-	uint64_t flow_types;
 	uint16_t n;
 
 	NEXT_ITEM_OF_ACTION(act, actions, act_index);
@@ -1364,7 +1363,7 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev,
 
 	if (rss == NULL) {
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act, "no valid queues");
 	}
 
@@ -1372,48 +1371,32 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev,
 		if (rss->queue[n] < dev->data->nb_rx_queues)
 			continue;
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act,
 					  "queue id > max number of queues");
 	}
 
-	/* Parse flow types of RSS */
 	if (!(rss->types & HNS3_ETH_RSS_SUPPORT) && rss->types)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act,
 					  "Flow types is unsupported by "
 					  "hns3's RSS");
-
-	flow_types = rss->types & HNS3_ETH_RSS_SUPPORT;
-	if (flow_types != rss->types)
-		hns3_warn(hw, "RSS flow types(%" PRIx64 ") include unsupported "
-			  "flow types", rss->types);
-
-	/* Parse RSS related parameters from RSS configuration */
-	switch (rss->func) {
-	case RTE_ETH_HASH_FUNCTION_DEFAULT:
-	case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
-	case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
-	case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
-		break;
-	default:
+	if (rss->func >= RTE_ETH_HASH_FUNCTION_MAX)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
-					  "input RSS hash functions are not supported");
-	}
-
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
+					  "RSS hash func are not supported");
 	if (rss->level)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "a nonzero RSS encapsulation level is not supported");
 	if (rss->key_len && rss->key_len != RTE_DIM(rss_conf->key))
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "RSS hash key must be exactly 40 bytes");
 	if (rss->queue_num > RTE_DIM(rss_conf->queue))
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "too many queues for RSS context");
 
 	if (rss->types & (ETH_RSS_L4_DST_ONLY | ETH_RSS_L4_SRC_ONLY) &&
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 4/9] net/hns3: set suitable type when initial flow error struct
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                     ` (2 preceding siblings ...)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 3/9] net/hns3: fix error type when validating RSS flow action Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 5/9] net/hns3: offload calculating the shapping para to firmware Wei Hu (Xavier)
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: "Wei Hu (Xavier)" <xavier.huwei@huawei.com>

The API of rte_flow_error_set is used to pass detail error information to
caller, this patch sets suitable type when calling rte_flow_error_set API.

Fixes: fcba820d9b9e ("net/hns3: support flow director")
Fixes: c37ca66f2b27 ("net/hns3: support RSS")
Cc: stable@dpdk.org

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_flow.c | 54 ++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index a6676d6..4fb129e 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -168,9 +168,9 @@ hns3_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,
 	if (cnt) {
 		if (!cnt->shared || cnt->shared != shared)
 			return rte_flow_error_set(error, ENOTSUP,
-						  RTE_FLOW_ERROR_TYPE_ACTION,
-						  cnt,
-						  "Counter id is used,shared flag not match");
+				RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+				cnt,
+				"Counter id is used, shared flag not match");
 		cnt->ref_cnt++;
 		return 0;
 	}
@@ -178,7 +178,7 @@ hns3_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,
 	cnt = rte_zmalloc("hns3 counter", sizeof(*cnt), 0);
 	if (cnt == NULL)
 		return rte_flow_error_set(error, ENOMEM,
-					  RTE_FLOW_ERROR_TYPE_ACTION, cnt,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, cnt,
 					  "Alloc mem for counter failed");
 	cnt->id = id;
 	cnt->shared = shared;
@@ -206,13 +206,13 @@ hns3_counter_query(struct rte_eth_dev *dev, struct rte_flow *flow,
 	cnt = hns3_counter_lookup(dev, flow->counter_id);
 	if (cnt == NULL)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 					  "Can't find counter id");
 
 	ret = hns3_get_count(&hns->hw, flow->counter_id, &value);
 	if (ret) {
 		rte_flow_error_set(error, -ret,
-				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "Read counter fail.");
 		return ret;
 	}
@@ -374,9 +374,9 @@ hns3_handle_actions(struct rte_eth_dev *dev,
 			    (const struct rte_flow_action_mark *)actions->conf;
 			if (mark->id >= HNS3_MAX_FILTER_ID)
 				return rte_flow_error_set(error, EINVAL,
-						     RTE_FLOW_ERROR_TYPE_ACTION,
-						     actions,
-						     "Invalid Mark ID");
+						RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+						actions,
+						"Invalid Mark ID");
 			rule->fd_id = mark->id;
 			rule->flags |= HNS3_RULE_FLAG_FDID;
 			break;
@@ -390,9 +390,9 @@ hns3_handle_actions(struct rte_eth_dev *dev,
 			counter_num = pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1];
 			if (act_count->id >= counter_num)
 				return rte_flow_error_set(error, EINVAL,
-						     RTE_FLOW_ERROR_TYPE_ACTION,
-						     actions,
-						     "Invalid counter id");
+						RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+						actions,
+						"Invalid counter id");
 			rule->act_cnt = *act_count;
 			rule->flags |= HNS3_RULE_FLAG_COUNTER;
 			break;
@@ -556,7 +556,7 @@ hns3_parse_ipv4(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		    ipv4_mask->hdr.time_to_live ||
 		    ipv4_mask->hdr.hdr_checksum) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst ip,tos,proto in IPV4");
 		}
@@ -621,7 +621,7 @@ hns3_parse_ipv6(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		if (ipv6_mask->hdr.vtc_flow ||
 		    ipv6_mask->hdr.payload_len || ipv6_mask->hdr.hop_limits) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst ip,proto in IPV6");
 		}
@@ -681,7 +681,7 @@ hns3_parse_tcp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		    tcp_mask->hdr.rx_win ||
 		    tcp_mask->hdr.cksum || tcp_mask->hdr.tcp_urp) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in TCP");
 		}
@@ -728,7 +728,7 @@ hns3_parse_udp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		udp_mask = item->mask;
 		if (udp_mask->hdr.dgram_len || udp_mask->hdr.dgram_cksum) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in UDP");
 		}
@@ -775,7 +775,7 @@ hns3_parse_sctp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		sctp_mask = item->mask;
 		if (sctp_mask->hdr.cksum)
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in SCTP");
 
@@ -920,14 +920,14 @@ hns3_parse_vxlan(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (vxlan_mask->flags)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Flags is not supported in VxLAN");
 
 	/* VNI must be totally masked or not. */
 	if (memcmp(vxlan_mask->vni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(vxlan_mask->vni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "VNI must be totally masked or not in VxLAN");
 	if (vxlan_mask->vni[0]) {
 		hns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);
@@ -971,14 +971,14 @@ hns3_parse_nvgre(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (nvgre_mask->protocol || nvgre_mask->c_k_s_rsvd0_ver)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Ver/protocal is not supported in NVGRE");
 
 	/* TNI must be totally masked or not. */
 	if (memcmp(nvgre_mask->tni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(nvgre_mask->tni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "TNI must be totally masked or not in NVGRE");
 
 	if (nvgre_mask->tni[0]) {
@@ -1025,13 +1025,13 @@ hns3_parse_geneve(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (geneve_mask->ver_opt_len_o_c_rsvd0 || geneve_mask->protocol)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Ver/protocal is not supported in GENEVE");
 	/* VNI must be totally masked or not. */
 	if (memcmp(geneve_mask->vni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(geneve_mask->vni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "VNI must be totally masked or not in GENEVE");
 	if (geneve_mask->vni[0]) {
 		hns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);
@@ -1062,7 +1062,7 @@ hns3_parse_tunnel(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_HANDLE,
+					  RTE_FLOW_ERROR_TYPE_ITEM,
 					  NULL, "Unsupported tunnel type!");
 	}
 	if (ret)
@@ -1116,7 +1116,7 @@ hns3_parse_normal(const struct rte_flow_item *item,
 		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_HANDLE,
+					  RTE_FLOW_ERROR_TYPE_ITEM,
 					  NULL, "Unsupported normal type!");
 	}
 
@@ -1132,7 +1132,7 @@ hns3_validate_item(const struct rte_flow_item *item,
 
 	if (item->last)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_LAST, item,
 					  "Not supported last point for range");
 
 	for (i = 0; i < step_mngr.count; i++) {
@@ -1218,7 +1218,7 @@ hns3_parse_fdir_filter(struct rte_eth_dev *dev,
 
 	if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 					  "fdir_conf.mode isn't perfect");
 
 	step_mngr.items = first_items;
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 5/9] net/hns3: offload calculating the shapping para to firmware
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                     ` (3 preceding siblings ...)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 4/9] net/hns3: set suitable type when initial flow error struct Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 6/9] net/hns3: set max scheduling rate based on actual board Wei Hu (Xavier)
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Huisong Li <lihuisong@huawei.com>

In order to have more flexible selection of shapping algorithm based on
different versions of hns3 network engine, moves the algorithm of
calculating shapping parameter to firmware to execute. If bit
HNS3_TM_RATE_VLD_B of flag field of struct named hns3_pri_shapping_cmd,
hns3_pg_shapping_cmd or hns3_port_shapping_cmd is set to 1, firmware of
network engine, which device revision_id is greater than and equal to 0x30,
will recalculate the shapping parameters according to the xxx_rate field
of struct hns3_xxx_shapping_cmd and the opcode of scheduling level, and
configure to hardware.

But driver still needs to calculate shapping parameters and configure
firmware, so as to be compatible with the network engine with revision_id
eqauls 0x21. And the rate and the flag will be ignored based on the network
engine with revision_id equals 0x21.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_dcb.c | 55 +++++++++++++++++++++++++++++++++++----------
 drivers/net/hns3/hns3_dcb.h | 39 +++++++++++++++++++++++++-------
 2 files changed, 74 insertions(+), 20 deletions(-)

diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index fecedff..857e79e 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -365,12 +365,22 @@ hns3_dcb_port_shaper_cfg(struct hns3_hw *hw)
 
 	shap_cfg_cmd->port_shapping_para = rte_cpu_to_le_32(shapping_para);
 
+	/*
+	 * Configure the port_rate and set bit HNS3_TM_RATE_VLD_B of flag
+	 * field in hns3_port_shapping_cmd to require firmware to recalculate
+	 * shapping parameters. And whether the parameters are recalculated
+	 * depends on the firmware version. But driver still needs to
+	 * calculate it and configure to firmware for better compatibility.
+	 */
+	shap_cfg_cmd->port_rate = rte_cpu_to_le_32(hw->mac.link_speed);
+	hns3_set_bit(shap_cfg_cmd->flag, HNS3_TM_RATE_VLD_B, 1);
+
 	return hns3_cmd_send(hw, &desc, 1);
 }
 
 static int
 hns3_dcb_pg_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
-			 uint8_t pg_id, uint32_t shapping_para)
+			 uint8_t pg_id, uint32_t shapping_para, uint32_t rate)
 {
 	struct hns3_pg_shapping_cmd *shap_cfg_cmd;
 	enum hns3_opcode_type opcode;
@@ -386,6 +396,16 @@ hns3_dcb_pg_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
 
 	shap_cfg_cmd->pg_shapping_para = rte_cpu_to_le_32(shapping_para);
 
+	/*
+	 * Configure the pg_rate and set bit HNS3_TM_RATE_VLD_B of flag field in
+	 * hns3_pg_shapping_cmd to require firmware to recalculate shapping
+	 * parameters. And whether parameters are recalculated depends on
+	 * the firmware version. But driver still needs to calculate it and
+	 * configure to firmware for better compatibility.
+	 */
+	shap_cfg_cmd->pg_rate = rte_cpu_to_le_32(rate);
+	hns3_set_bit(shap_cfg_cmd->flag, HNS3_TM_RATE_VLD_B, 1);
+
 	return hns3_cmd_send(hw, &desc, 1);
 }
 
@@ -397,6 +417,7 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 	struct hns3_pf *pf = &hns->pf;
 	uint32_t ir_u, ir_b, ir_s;
 	uint32_t shaper_para;
+	uint32_t rate;
 	uint8_t i;
 	int ret;
 
@@ -406,10 +427,10 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 
 	/* Pg to pri */
 	for (i = 0; i < hw->dcb_info.num_pg; i++) {
+		rate = hw->dcb_info.pg_info[i].bw_limit;
+
 		/* Calc shaper para */
-		ret = hns3_shaper_para_calc(hw,
-					    hw->dcb_info.pg_info[i].bw_limit,
-					    HNS3_SHAPER_LVL_PG,
+		ret = hns3_shaper_para_calc(hw, rate, HNS3_SHAPER_LVL_PG,
 					    &shaper_parameter);
 		if (ret) {
 			hns3_err(hw, "calculate shaper parameter failed: %d",
@@ -422,7 +443,7 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pg_shapping_cfg(hw, HNS3_DCB_SHAP_C_BUCKET, i,
-					       shaper_para);
+					       shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config PG CIR shaper parameter failed: %d",
@@ -438,7 +459,7 @@ hns3_dcb_pg_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pg_shapping_cfg(hw, HNS3_DCB_SHAP_P_BUCKET, i,
-					       shaper_para);
+					       shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config PG PIR shaper parameter failed: %d",
@@ -486,7 +507,7 @@ hns3_dcb_pri_schd_mode_cfg(struct hns3_hw *hw, uint8_t pri_id)
 
 static int
 hns3_dcb_pri_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
-			  uint8_t pri_id, uint32_t shapping_para)
+			  uint8_t pri_id, uint32_t shapping_para, uint32_t rate)
 {
 	struct hns3_pri_shapping_cmd *shap_cfg_cmd;
 	enum hns3_opcode_type opcode;
@@ -503,6 +524,16 @@ hns3_dcb_pri_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
 
 	shap_cfg_cmd->pri_shapping_para = rte_cpu_to_le_32(shapping_para);
 
+	/*
+	 * Configure the pri_rate and set bit HNS3_TM_RATE_VLD_B of flag
+	 * field in hns3_pri_shapping_cmd to require firmware to recalculate
+	 * shapping parameters. And whether the parameters are recalculated
+	 * depends on the firmware version. But driver still needs to
+	 * calculate it and configure to firmware for better compatibility.
+	 */
+	shap_cfg_cmd->pri_rate = rte_cpu_to_le_32(rate);
+	hns3_set_bit(shap_cfg_cmd->flag, HNS3_TM_RATE_VLD_B, 1);
+
 	return hns3_cmd_send(hw, &desc, 1);
 }
 
@@ -512,12 +543,12 @@ hns3_dcb_pri_tc_base_shaper_cfg(struct hns3_hw *hw)
 	struct hns3_shaper_parameter shaper_parameter;
 	uint32_t ir_u, ir_b, ir_s;
 	uint32_t shaper_para;
+	uint32_t rate;
 	int ret, i;
 
 	for (i = 0; i < hw->dcb_info.num_tc; i++) {
-		ret = hns3_shaper_para_calc(hw,
-					    hw->dcb_info.tc_info[i].bw_limit,
-					    HNS3_SHAPER_LVL_PRI,
+		rate = hw->dcb_info.tc_info[i].bw_limit;
+		ret = hns3_shaper_para_calc(hw, rate, HNS3_SHAPER_LVL_PRI,
 					    &shaper_parameter);
 		if (ret) {
 			hns3_err(hw, "calculate shaper parameter failed: %d",
@@ -530,7 +561,7 @@ hns3_dcb_pri_tc_base_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pri_shapping_cfg(hw, HNS3_DCB_SHAP_C_BUCKET, i,
-						shaper_para);
+						shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config priority CIR shaper parameter failed: %d",
@@ -546,7 +577,7 @@ hns3_dcb_pri_tc_base_shaper_cfg(struct hns3_hw *hw)
 							 HNS3_SHAPER_BS_S_DEF);
 
 		ret = hns3_dcb_pri_shapping_cfg(hw, HNS3_DCB_SHAP_P_BUCKET, i,
-						shaper_para);
+						shaper_para, rate);
 		if (ret) {
 			hns3_err(hw,
 				 "config priority PIR shaper parameter failed: %d",
diff --git a/drivers/net/hns3/hns3_dcb.h b/drivers/net/hns3/hns3_dcb.h
index 05c9786..39ff332 100644
--- a/drivers/net/hns3/hns3_dcb.h
+++ b/drivers/net/hns3/hns3_dcb.h
@@ -16,7 +16,7 @@
 
 /* SP or DWRR */
 #define HNS3_DCB_TX_SCHD_DWRR_MSK	BIT(0)
-#define HNS3_DCB_TX_SCHD_SP_MSK		(0xFE)
+#define HNS3_DCB_TX_SCHD_SP_MSK		0xFE
 
 enum hns3_shap_bucket {
 	HNS3_DCB_SHAP_C_BUCKET = 0,
@@ -81,18 +81,46 @@ struct hns3_nq_to_qs_link_cmd {
 #define HNS3_DCB_SHAP_BS_S_MSK  GENMASK(25, 21)
 #define HNS3_DCB_SHAP_BS_S_LSH	21
 
+/*
+ * For more flexible selection of shapping algorithm in different network
+ * engine, the algorithm calculating shapping parameter is moved to firmware to
+ * execute. Bit HNS3_TM_RATE_VLD_B of flag field in hns3_pri_shapping_cmd,
+ * hns3_pg_shapping_cmd or hns3_port_shapping_cmd is set to 1 to require
+ * firmware to recalculate shapping parameters. However, whether the parameters
+ * are recalculated depends on the firmware version. If firmware doesn't support
+ * the calculation of shapping parameters, such as on network engine with
+ * revision id 0x21, the value driver calculated will be used to configure to
+ * hardware. On the contrary, firmware ignores configuration of driver
+ * and recalculates the parameter.
+ */
+#define HNS3_TM_RATE_VLD_B	0
+
 struct hns3_pri_shapping_cmd {
 	uint8_t pri_id;
 	uint8_t rsvd[3];
 	uint32_t pri_shapping_para;
-	uint32_t rsvd1[4];
+	uint8_t flag;
+	uint8_t rsvd1[3];
+	uint32_t pri_rate;  /* Unit Mbps */
+	uint8_t rsvd2[8];
 };
 
 struct hns3_pg_shapping_cmd {
 	uint8_t pg_id;
 	uint8_t rsvd[3];
 	uint32_t pg_shapping_para;
-	uint32_t rsvd1[4];
+	uint8_t flag;
+	uint8_t rsvd1[3];
+	uint32_t pg_rate; /* Unit Mbps */
+	uint8_t rsvd2[8];
+};
+
+struct hns3_port_shapping_cmd {
+	uint32_t port_shapping_para;
+	uint8_t flag;
+	uint8_t rsvd[3];
+	uint32_t port_rate;   /* Unit Mbps */
+	uint8_t rsvd1[12];
 };
 
 #define HNS3_BP_GRP_NUM			32
@@ -115,11 +143,6 @@ struct hns3_pfc_en_cmd {
 	uint8_t rsvd[22];
 };
 
-struct hns3_port_shapping_cmd {
-	uint32_t port_shapping_para;
-	uint32_t rsvd[5];
-};
-
 struct hns3_cfg_pause_param_cmd {
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
 	uint8_t pause_trans_gap;
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 6/9] net/hns3: set max scheduling rate based on actual board
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                     ` (4 preceding siblings ...)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 5/9] net/hns3: offload calculating the shapping para to firmware Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 7/9] net/hns3: support start and stop Tx or Rx queue Wei Hu (Xavier)
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Huisong Li <lihuisong@huawei.com>

Currently, max scheduling rates configuration of pg, pri and port are set
to 100000Mbps, which is the maximum bandwidth of hns3 network engine with
revision_id equals 0x21. However, max scheduling rate configuration should
be set to hardware based on the actual hardware board environment.

The max_tm_rate in struct hns3_hw, meaning the rate, is obtained from
firmware. So we should use the variable to configure the max scheduling
rate.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_dcb.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c
index 857e79e..27ae014 100644
--- a/drivers/net/hns3/hns3_dcb.c
+++ b/drivers/net/hns3/hns3_dcb.c
@@ -62,9 +62,9 @@ hns3_shaper_para_calc(struct hns3_hw *hw, uint32_t ir, uint8_t shaper_level,
 		return -EINVAL;
 	}
 
-	if (ir > HNS3_ETHER_MAX_RATE) {
-		hns3_err(hw, "rate(%d) exceeds the rate driver supported "
-			 "HNS3_ETHER_MAX_RATE(%d)", ir, HNS3_ETHER_MAX_RATE);
+	if (ir > hw->max_tm_rate) {
+		hns3_err(hw, "rate(%d) exceeds the max rate(%d) driver "
+			 "supported.", ir, hw->max_tm_rate);
 		return -EINVAL;
 	}
 
@@ -100,7 +100,7 @@ hns3_shaper_para_calc(struct hns3_hw *hw, uint32_t ir, uint8_t shaper_level,
 		 * ir_calc gets minimum value when tick is the maximum value.
 		 * At the same time, value of ir_u_calc can only be increased up
 		 * to eight after the while loop if the value of ir is equal
-		 * to HNS3_ETHER_MAX_RATE.
+		 * to hw->max_tm_rate.
 		 */
 		uint32_t numerator;
 		do {
@@ -736,7 +736,7 @@ hns3_dcb_info_init(struct hns3_hw *hw)
 		hw->dcb_info.pg_dwrr[i] = i ? 0 : BW_MAX_PERCENT;
 		hw->dcb_info.pg_info[i].pg_id = i;
 		hw->dcb_info.pg_info[i].pg_sch_mode = HNS3_SCH_MODE_DWRR;
-		hw->dcb_info.pg_info[i].bw_limit = HNS3_ETHER_MAX_RATE;
+		hw->dcb_info.pg_info[i].bw_limit = hw->max_tm_rate;
 
 		if (i != 0)
 			continue;
@@ -1405,7 +1405,7 @@ hns3_dcb_info_cfg(struct hns3_adapter *hns)
 	hw->dcb_info.pg_dwrr[0] = BW_MAX_PERCENT;
 	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 = HNS3_ETHER_MAX_RATE;
+	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;
 
 	/* Each tc has same bw for valid tc by default */
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 7/9] net/hns3: support start and stop Tx or Rx queue
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                     ` (5 preceding siblings ...)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 6/9] net/hns3: set max scheduling rate based on actual board Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-30 22:49     ` Ferruh Yigit
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 8/9] net/hns3: check return value when reading PCI config space Wei Hu (Xavier)
                     ` (2 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Chengchang Tang <tangchengchang@huawei.com>

The new generation hns3 network engine supports independent enabling and
disabling of a single Tx/Rx queue. So, it can support the queue start and
stop feature. In addition, when different numbers of Tx and Rx queues need
to be enabled in some applications, hns3 pmd does not need to create fake
queues to enable these scenarios.

This patch Add queue start and stop feature for the new generation hns3
networking engine. Cancel the creation of fake queue on the new generation
network engine. And the previously improperly named queue related function
was renamed to improve readability.

Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_cmd.h       |   4 +-
 drivers/net/hns3/hns3_ethdev.c    |  98 ++++--
 drivers/net/hns3/hns3_ethdev_vf.c |  93 ++++--
 drivers/net/hns3/hns3_regs.c      |   2 +
 drivers/net/hns3/hns3_regs.h      |   2 +
 drivers/net/hns3/hns3_rxtx.c      | 647 +++++++++++++++++++++++++++++++-------
 drivers/net/hns3/hns3_rxtx.h      |  16 +-
 8 files changed, 691 insertions(+), 173 deletions(-)

diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c
index f7cfa00..589547c 100644
--- a/drivers/net/hns3/hns3_cmd.c
+++ b/drivers/net/hns3/hns3_cmd.c
@@ -443,7 +443,7 @@ static void hns3_parse_capability(struct hns3_hw *hw,
 	if (hns3_get_bit(caps, HNS3_CAPS_PHY_IMP_B))
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_COPPER_B, 1);
 	if (hns3_get_bit(caps, HNS3_CAPS_TQP_TXRX_INDEP_B))
-		hns3_set_bit(hw->capability, HNS3_CAPS_TQP_TXRX_INDEP_B, 1);
+		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_INDEP_TXRX_B, 1);
 	if (hns3_get_bit(caps, HNS3_CAPS_STASH_B))
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_STASH_B, 1);
 }
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index ecca75c..bbd0034 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -159,6 +159,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_QUERY_RX_STATUS        = 0x0B13,
 	HNS3_OPC_CFG_COM_TQP_QUEUE      = 0x0B20,
 	HNS3_OPC_RESET_TQP_QUEUE        = 0x0B22,
+	HNS3_OPC_RESET_TQP_QUEUE_INDEP  = 0x0B23,
 
 	/* TSO command */
 	HNS3_OPC_TSO_GENERIC_CONFIG     = 0x0C01,
@@ -810,7 +811,8 @@ struct hns3_reset_tqp_queue_cmd {
 	uint16_t tqp_id;
 	uint8_t reset_req;
 	uint8_t ready_to_reset;
-	uint8_t rsv[20];
+	uint8_t queue_direction;
+	uint8_t rsv[19];
 };
 
 #define HNS3_CFG_RESET_MAC_B		3
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 6e0f52b..d6f3cc0 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2293,20 +2293,25 @@ hns3_dev_configure(struct rte_eth_dev *dev)
 	bool gro_en;
 	int ret;
 
+	hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
+
 	/*
-	 * Hardware does not support individually enable/disable/reset the Tx or
-	 * Rx queue in hns3 network engine. Driver must enable/disable/reset Tx
-	 * and Rx queues at the same time. When the numbers of Tx queues
-	 * allocated by upper applications are not equal to the numbers of Rx
-	 * queues, driver needs to setup fake Tx or Rx queues to adjust numbers
-	 * of Tx/Rx queues. otherwise, network engine can not work as usual. But
-	 * these fake queues are imperceptible, and can not be used by upper
-	 * applications.
+	 * Some versions of hardware network engine does not support
+	 * individually enable/disable/reset the Tx or Rx queue. These devices
+	 * must enable/disable/reset Tx and Rx queues at the same time. When the
+	 * numbers of Tx queues allocated by upper applications are not equal to
+	 * the numbers of Rx queues, driver needs to setup fake Tx or Rx queues
+	 * to adjust numbers of Tx/Rx queues. otherwise, network engine can not
+	 * work as usual. But these fake queues are imperceptible, and can not
+	 * be used by upper applications.
 	 */
-	ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
-	if (ret) {
-		hns3_err(hw, "Failed to set rx/tx fake queues: %d", ret);
-		return ret;
+	if (!hns3_dev_indep_txrx_supported(hw)) {
+		ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
+		if (ret) {
+			hns3_err(hw, "fail to set Rx/Tx fake queues, ret = %d.",
+				 ret);
+			return ret;
+		}
 	}
 
 	hw->adapter_state = HNS3_NIC_CONFIGURING;
@@ -2504,6 +2509,10 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_TX_OFFLOAD_MBUF_FAST_FREE |
 				 hns3_txvlan_cap_get(hw));
 
+	if (hns3_dev_indep_txrx_supported(hw))
+		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+
 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = HNS3_MAX_RING_DESC,
 		.nb_min = HNS3_MIN_RING_DESC,
@@ -4684,23 +4693,22 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue)
 	if (ret)
 		return ret;
 
-	/* Enable queues */
-	ret = hns3_start_queues(hns, reset_queue);
+	ret = hns3_init_queues(hns, reset_queue);
 	if (ret) {
-		PMD_INIT_LOG(ERR, "Failed to start queues: %d", ret);
+		PMD_INIT_LOG(ERR, "failed to init queues, ret = %d.", ret);
 		return ret;
 	}
 
-	/* Enable MAC */
 	ret = hns3_cfg_mac_mode(hw, true);
 	if (ret) {
-		PMD_INIT_LOG(ERR, "Failed to enable MAC: %d", ret);
+		PMD_INIT_LOG(ERR, "failed to enable MAC, ret = %d", ret);
 		goto err_config_mac_mode;
 	}
 	return 0;
 
 err_config_mac_mode:
-	hns3_stop_queues(hns, true);
+	hns3_dev_release_mbufs(hns);
+	hns3_reset_all_tqps(hns);
 	return ret;
 }
 
@@ -4831,6 +4839,32 @@ hns3_dev_start(struct rte_eth_dev *dev)
 		return ret;
 	}
 
+	/*
+	 * There are three register used to control the status of a TQP
+	 * (contains a pair of Tx queue and Rx queue) in the new version network
+	 * engine. One is used to control the enabling of Tx queue, the other is
+	 * used to control the enabling of Rx queue, and the last is the master
+	 * switch used to control the enabling of the tqp. The Tx register and
+	 * TQP register must be enabled at the same time to enable a Tx queue.
+	 * The same applies to the Rx queue. For the older network engine, this
+	 * function only refresh the enabled flag, and it is used to update the
+	 * status of queue in the dpdk framework.
+	 */
+	ret = hns3_start_all_txqs(dev);
+	if (ret) {
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
+	ret = hns3_start_all_rxqs(dev);
+	if (ret) {
+		hns3_stop_all_txqs(dev);
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
 	hw->adapter_state = HNS3_NIC_STARTED;
 	rte_spinlock_unlock(&hw->lock);
 
@@ -4843,11 +4877,12 @@ hns3_dev_start(struct rte_eth_dev *dev)
 
 	/* Enable interrupt of all rx queues before enabling queues */
 	hns3_dev_all_rx_queue_intr_enable(hw, true);
+
 	/*
-	 * When finished the initialization, enable queues to receive/transmit
-	 * packets.
+	 * After finished the initialization, enable tqps to receive/transmit
+	 * packets and refresh all queue status.
 	 */
-	hns3_enable_all_queues(hw, true);
+	hns3_start_tqps(hw);
 
 	hns3_info(hw, "hns3 dev start successful!");
 	return 0;
@@ -4857,7 +4892,6 @@ static int
 hns3_do_stop(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	bool reset_queue;
 	int ret;
 
 	ret = hns3_cfg_mac_mode(hw, false);
@@ -4867,11 +4901,15 @@ hns3_do_stop(struct hns3_adapter *hns)
 
 	if (rte_atomic16_read(&hw->reset.disable_cmd) == 0) {
 		hns3_configure_all_mac_addr(hns, true);
-		reset_queue = true;
-	} else
-		reset_queue = false;
+		ret = hns3_reset_all_tqps(hns);
+		if (ret) {
+			hns3_err(hw, "failed to reset all queues ret = %d.",
+				 ret);
+			return ret;
+		}
+	}
 	hw->mac.default_addr_setted = false;
-	return hns3_stop_queues(hns, reset_queue);
+	return 0;
 }
 
 static void
@@ -4928,6 +4966,7 @@ hns3_dev_stop(struct rte_eth_dev *dev)
 
 	rte_spinlock_lock(&hw->lock);
 	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
+		hns3_stop_tqps(hw);
 		hns3_do_stop(hns);
 		hns3_unmap_rx_interrupt(dev);
 		hns3_dev_release_mbufs(hns);
@@ -5165,7 +5204,7 @@ hns3_reinit_dev(struct hns3_adapter *hns)
 		return ret;
 	}
 
-	ret = hns3_reset_all_queues(hns);
+	ret = hns3_reset_all_tqps(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to reset all queues: %d", ret);
 		return ret;
@@ -5443,6 +5482,7 @@ hns3_stop_service(struct hns3_adapter *hns)
 	rte_spinlock_lock(&hw->lock);
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED ||
 	    hw->adapter_state == HNS3_NIC_STOPPING) {
+		hns3_enable_all_queues(hw, false);
 		hns3_do_stop(hns);
 		hw->reset.mbuf_deferred_free = true;
 	} else
@@ -5626,6 +5666,10 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.tx_queue_setup         = hns3_tx_queue_setup,
 	.rx_queue_release       = hns3_dev_rx_queue_release,
 	.tx_queue_release       = hns3_dev_tx_queue_release,
+	.rx_queue_start         = hns3_dev_rx_queue_start,
+	.rx_queue_stop          = hns3_dev_rx_queue_stop,
+	.tx_queue_start         = hns3_dev_tx_queue_start,
+	.tx_queue_stop          = hns3_dev_tx_queue_stop,
 	.rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
 	.rxq_info_get           = hns3_rxq_info_get,
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 0b949e9..849f6cc 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -757,20 +757,25 @@ hns3vf_dev_configure(struct rte_eth_dev *dev)
 	bool gro_en;
 	int ret;
 
+	hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
+
 	/*
-	 * Hardware does not support individually enable/disable/reset the Tx or
-	 * Rx queue in hns3 network engine. Driver must enable/disable/reset Tx
-	 * and Rx queues at the same time. When the numbers of Tx queues
-	 * allocated by upper applications are not equal to the numbers of Rx
-	 * queues, driver needs to setup fake Tx or Rx queues to adjust numbers
-	 * of Tx/Rx queues. otherwise, network engine can not work as usual. But
-	 * these fake queues are imperceptible, and can not be used by upper
-	 * applications.
+	 * Some versions of hardware network engine does not support
+	 * individually enable/disable/reset the Tx or Rx queue. These devices
+	 * must enable/disable/reset Tx and Rx queues at the same time. When the
+	 * numbers of Tx queues allocated by upper applications are not equal to
+	 * the numbers of Rx queues, driver needs to setup fake Tx or Rx queues
+	 * to adjust numbers of Tx/Rx queues. otherwise, network engine can not
+	 * work as usual. But these fake queues are imperceptible, and can not
+	 * be used by upper applications.
 	 */
-	ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
-	if (ret) {
-		hns3_err(hw, "Failed to set rx/tx fake queues: %d", ret);
-		return ret;
+	if (!hns3_dev_indep_txrx_supported(hw)) {
+		ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
+		if (ret) {
+			hns3_err(hw, "fail to set Rx/Tx fake queues, ret = %d.",
+				 ret);
+			return ret;
+		}
 	}
 
 	hw->adapter_state = HNS3_NIC_CONFIGURING;
@@ -956,6 +961,10 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_TX_OFFLOAD_MBUF_FAST_FREE |
 				 hns3_txvlan_cap_get(hw));
 
+	if (hns3_dev_indep_txrx_supported(hw))
+		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+
 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = HNS3_MAX_RING_DESC,
 		.nb_min = HNS3_MIN_RING_DESC,
@@ -1849,16 +1858,20 @@ static int
 hns3vf_do_stop(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	bool reset_queue;
+	int ret;
 
 	hw->mac.link_status = ETH_LINK_DOWN;
 
 	if (rte_atomic16_read(&hw->reset.disable_cmd) == 0) {
 		hns3vf_configure_mac_addr(hns, true);
-		reset_queue = true;
-	} else
-		reset_queue = false;
-	return hns3_stop_queues(hns, reset_queue);
+		ret = hns3_reset_all_tqps(hns);
+		if (ret) {
+			hns3_err(hw, "failed to reset all queues ret = %d",
+				 ret);
+			return ret;
+		}
+	}
+	return 0;
 }
 
 static void
@@ -1914,6 +1927,7 @@ hns3vf_dev_stop(struct rte_eth_dev *dev)
 
 	rte_spinlock_lock(&hw->lock);
 	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
+		hns3_stop_tqps(hw);
 		hns3vf_do_stop(hns);
 		hns3vf_unmap_rx_interrupt(dev);
 		hns3_dev_release_mbufs(hns);
@@ -2023,9 +2037,9 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 	if (ret)
 		return ret;
 
-	ret = hns3_start_queues(hns, reset_queue);
+	ret = hns3_init_queues(hns, reset_queue);
 	if (ret)
-		hns3_err(hw, "Failed to start queues: %d", ret);
+		hns3_err(hw, "failed to init queues, ret = %d.", ret);
 
 	return ret;
 }
@@ -2155,6 +2169,33 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
 		rte_spinlock_unlock(&hw->lock);
 		return ret;
 	}
+
+	/*
+	 * There are three register used to control the status of a TQP
+	 * (contains a pair of Tx queue and Rx queue) in the new version network
+	 * engine. One is used to control the enabling of Tx queue, the other is
+	 * used to control the enabling of Rx queue, and the last is the master
+	 * switch used to control the enabling of the tqp. The Tx register and
+	 * TQP register must be enabled at the same time to enable a Tx queue.
+	 * The same applies to the Rx queue. For the older network enginem, this
+	 * function only refresh the enabled flag, and it is used to update the
+	 * status of queue in the dpdk framework.
+	 */
+	ret = hns3_start_all_txqs(dev);
+	if (ret) {
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
+	ret = hns3_start_all_rxqs(dev);
+	if (ret) {
+		hns3_stop_all_txqs(dev);
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
 	hw->adapter_state = HNS3_NIC_STARTED;
 	rte_spinlock_unlock(&hw->lock);
 
@@ -2167,11 +2208,12 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
 
 	/* Enable interrupt of all rx queues before enabling queues */
 	hns3_dev_all_rx_queue_intr_enable(hw, true);
+
 	/*
-	 * When finished the initialization, enable queues to receive/transmit
-	 * packets.
+	 * After finished the initialization, start all tqps to receive/transmit
+	 * packets and refresh all queue status.
 	 */
-	hns3_enable_all_queues(hw, true);
+	hns3_start_tqps(hw);
 
 	return ret;
 }
@@ -2313,6 +2355,7 @@ hns3vf_stop_service(struct hns3_adapter *hns)
 	rte_spinlock_lock(&hw->lock);
 	if (hw->adapter_state == HNS3_NIC_STARTED ||
 	    hw->adapter_state == HNS3_NIC_STOPPING) {
+		hns3_enable_all_queues(hw, false);
 		hns3vf_do_stop(hns);
 		hw->reset.mbuf_deferred_free = true;
 	} else
@@ -2555,7 +2598,7 @@ hns3vf_reinit_dev(struct hns3_adapter *hns)
 		rte_intr_enable(&pci_dev->intr_handle);
 	}
 
-	ret = hns3_reset_all_queues(hns);
+	ret = hns3_reset_all_tqps(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to reset all queues: %d", ret);
 		return ret;
@@ -2593,6 +2636,10 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.tx_queue_setup     = hns3_tx_queue_setup,
 	.rx_queue_release   = hns3_dev_rx_queue_release,
 	.tx_queue_release   = hns3_dev_tx_queue_release,
+	.rx_queue_start     = hns3_dev_rx_queue_start,
+	.rx_queue_stop      = hns3_dev_rx_queue_stop,
+	.tx_queue_start     = hns3_dev_tx_queue_start,
+	.tx_queue_stop      = hns3_dev_tx_queue_stop,
 	.rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
 	.rxq_info_get       = hns3_rxq_info_get,
diff --git a/drivers/net/hns3/hns3_regs.c b/drivers/net/hns3/hns3_regs.c
index a76f42c..1b7dd72 100644
--- a/drivers/net/hns3/hns3_regs.c
+++ b/drivers/net/hns3/hns3_regs.c
@@ -62,6 +62,7 @@ static const uint32_t ring_reg_addrs[] = {HNS3_RING_RX_BASEADDR_L_REG,
 					  HNS3_RING_RX_BASEADDR_H_REG,
 					  HNS3_RING_RX_BD_NUM_REG,
 					  HNS3_RING_RX_BD_LEN_REG,
+					  HNS3_RING_RX_EN_REG,
 					  HNS3_RING_RX_MERGE_EN_REG,
 					  HNS3_RING_RX_TAIL_REG,
 					  HNS3_RING_RX_HEAD_REG,
@@ -73,6 +74,7 @@ static const uint32_t ring_reg_addrs[] = {HNS3_RING_RX_BASEADDR_L_REG,
 					  HNS3_RING_TX_BASEADDR_L_REG,
 					  HNS3_RING_TX_BASEADDR_H_REG,
 					  HNS3_RING_TX_BD_NUM_REG,
+					  HNS3_RING_TX_EN_REG,
 					  HNS3_RING_TX_PRIORITY_REG,
 					  HNS3_RING_TX_TC_REG,
 					  HNS3_RING_TX_MERGE_EN_REG,
diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h
index d83c3b3..81a0af5 100644
--- a/drivers/net/hns3/hns3_regs.h
+++ b/drivers/net/hns3/hns3_regs.h
@@ -83,6 +83,8 @@
 #define HNS3_RING_TX_BD_ERR_REG			0x00074
 
 #define HNS3_RING_EN_REG			0x00090
+#define HNS3_RING_RX_EN_REG			0x00098
+#define HNS3_RING_TX_EN_REG			0x000d4
 
 #define HNS3_RING_EN_B				0
 
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index e3f0db4..60f110c 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -74,7 +74,7 @@ hns3_tx_queue_release_mbufs(struct hns3_tx_queue *txq)
 {
 	uint16_t i;
 
-	/* Note: Fake rx queue will not enter here */
+	/* Note: Fake tx queue will not enter here */
 	if (txq->sw_ring) {
 		for (i = 0; i < txq->nb_tx_desc; i++) {
 			if (txq->sw_ring[i].mbuf) {
@@ -371,27 +371,159 @@ hns3_enable_all_queues(struct hns3_hw *hw, bool en)
 	struct hns3_rx_queue *rxq;
 	struct hns3_tx_queue *txq;
 	uint32_t rcb_reg;
+	void *tqp_base;
 	int i;
 
 	for (i = 0; i < hw->cfg_max_queues; i++) {
-		if (i < nb_rx_q)
-			rxq = hw->data->rx_queues[i];
-		else
-			rxq = hw->fkq_data.rx_queues[i - nb_rx_q];
-		if (i < nb_tx_q)
-			txq = hw->data->tx_queues[i];
-		else
-			txq = hw->fkq_data.tx_queues[i - nb_tx_q];
-		if (rxq == NULL || txq == NULL ||
-		    (en && (rxq->rx_deferred_start || txq->tx_deferred_start)))
-			continue;
+		if (hns3_dev_indep_txrx_supported(hw)) {
+			rxq = i < nb_rx_q ? hw->data->rx_queues[i] : NULL;
+			txq = i < nb_tx_q ? hw->data->tx_queues[i] : NULL;
+			/*
+			 * After initialization, rxq and txq won't be NULL at
+			 * the same time.
+			 */
+			if (rxq != NULL)
+				tqp_base = rxq->io_base;
+			else if (txq != NULL)
+				tqp_base = txq->io_base;
+			else
+				return;
+		} else {
+			rxq = i < nb_rx_q ? hw->data->rx_queues[i] :
+			      hw->fkq_data.rx_queues[i - nb_rx_q];
 
-		rcb_reg = hns3_read_dev(rxq, HNS3_RING_EN_REG);
+			tqp_base = rxq->io_base;
+		}
+		/*
+		 * This is the master switch that used to control the enabling
+		 * of a pair of Tx and Rx queues. Both the Rx and Tx point to
+		 * the same register
+		 */
+		rcb_reg = hns3_read_reg(tqp_base, HNS3_RING_EN_REG);
 		if (en)
 			rcb_reg |= BIT(HNS3_RING_EN_B);
 		else
 			rcb_reg &= ~BIT(HNS3_RING_EN_B);
-		hns3_write_dev(rxq, HNS3_RING_EN_REG, rcb_reg);
+		hns3_write_reg(tqp_base, HNS3_RING_EN_REG, rcb_reg);
+	}
+}
+
+static void
+hns3_enable_txq(struct hns3_tx_queue *txq, bool en)
+{
+	struct hns3_hw *hw = &txq->hns->hw;
+	uint32_t reg;
+
+	if (hns3_dev_indep_txrx_supported(hw)) {
+		reg = hns3_read_dev(txq, HNS3_RING_TX_EN_REG);
+		if (en)
+			reg |= BIT(HNS3_RING_EN_B);
+		else
+			reg &= ~BIT(HNS3_RING_EN_B);
+		hns3_write_dev(txq, HNS3_RING_TX_EN_REG, reg);
+	}
+	txq->enabled = en;
+}
+
+static void
+hns3_enable_rxq(struct hns3_rx_queue *rxq, bool en)
+{
+	struct hns3_hw *hw = &rxq->hns->hw;
+	uint32_t reg;
+
+	if (hns3_dev_indep_txrx_supported(hw)) {
+		reg = hns3_read_dev(rxq, HNS3_RING_RX_EN_REG);
+		if (en)
+			reg |= BIT(HNS3_RING_EN_B);
+		else
+			reg &= ~BIT(HNS3_RING_EN_B);
+		hns3_write_dev(rxq, HNS3_RING_RX_EN_REG, reg);
+	}
+	rxq->enabled = en;
+}
+
+int
+hns3_start_all_txqs(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq;
+	uint16_t i, j;
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		txq = hw->data->tx_queues[i];
+		if (!txq) {
+			hns3_err(hw, "Tx queue %u not available or setup.", i);
+			goto start_txqs_fail;
+		}
+		/*
+		 * Tx queue is enabled by default. Therefore, the Tx queues
+		 * needs to be disabled when deferred_start is set. There is
+		 * another master switch used to control the enabling of a pair
+		 * of Tx and Rx queues. And the master switch is disabled by
+		 * default.
+		 */
+		if (txq->tx_deferred_start)
+			hns3_enable_txq(txq, false);
+		else
+			hns3_enable_txq(txq, true);
+	}
+	return 0;
+
+start_txqs_fail:
+	for (j = 0; j < i; j++) {
+		txq = hw->data->tx_queues[j];
+		hns3_enable_txq(txq, false);
+	}
+	return -EINVAL;
+}
+
+int
+hns3_start_all_rxqs(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_rx_queue *rxq;
+	uint16_t i, j;
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		rxq = hw->data->rx_queues[i];
+		if (!rxq) {
+			hns3_err(hw, "Rx queue %u not available or setup.", i);
+			goto start_rxqs_fail;
+		}
+		/*
+		 * Rx queue is enabled by default. Therefore, the Rx queues
+		 * needs to be disabled when deferred_start is set. There is
+		 * another master switch used to control the enabling of a pair
+		 * of Tx and Rx queues. And the master switch is disabled by
+		 * default.
+		 */
+		if (rxq->rx_deferred_start)
+			hns3_enable_rxq(rxq, false);
+		else
+			hns3_enable_rxq(rxq, true);
+	}
+	return 0;
+
+start_rxqs_fail:
+	for (j = 0; j < i; j++) {
+		rxq = hw->data->rx_queues[j];
+		hns3_enable_rxq(rxq, false);
+	}
+	return -EINVAL;
+}
+
+void
+hns3_stop_all_txqs(struct rte_eth_dev *dev)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq;
+	uint16_t i;
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		txq = hw->data->tx_queues[i];
+		if (!txq)
+			continue;
+		hns3_enable_txq(txq, false);
 	}
 }
 
@@ -428,16 +560,17 @@ hns3_send_reset_tqp_cmd(struct hns3_hw *hw, uint16_t queue_id, bool enable)
 	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
 	req->tqp_id = rte_cpu_to_le_16(queue_id);
 	hns3_set_bit(req->reset_req, HNS3_TQP_RESET_B, enable ? 1 : 0);
-
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret)
-		hns3_err(hw, "Send tqp reset cmd error, ret = %d", ret);
+		hns3_err(hw, "send tqp reset cmd error, queue_id = %u, "
+			     "ret = %d", queue_id, ret);
 
 	return ret;
 }
 
 static int
-hns3_get_reset_status(struct hns3_hw *hw, uint16_t queue_id)
+hns3_get_tqp_reset_status(struct hns3_hw *hw, uint16_t queue_id,
+			  uint8_t *reset_status)
 {
 	struct hns3_reset_tqp_queue_cmd *req;
 	struct hns3_cmd_desc desc;
@@ -450,19 +583,20 @@ hns3_get_reset_status(struct hns3_hw *hw, uint16_t queue_id)
 
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret) {
-		hns3_err(hw, "Get reset status error, ret =%d", ret);
+		hns3_err(hw, "get tqp reset status error, queue_id = %u, "
+			     "ret = %d.", queue_id, ret);
 		return ret;
 	}
-
-	return hns3_get_bit(req->ready_to_reset, HNS3_TQP_RESET_B);
+	*reset_status = hns3_get_bit(req->ready_to_reset, HNS3_TQP_RESET_B);
+	return ret;
 }
 
 static int
-hns3_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
+hns3pf_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 {
 #define HNS3_TQP_RESET_TRY_MS	200
+	uint8_t reset_status;
 	uint64_t end;
-	int reset_status;
 	int ret;
 
 	ret = hns3_tqp_enable(hw, queue_id, false);
@@ -479,21 +613,23 @@ hns3_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 		hns3_err(hw, "Send reset tqp cmd fail, ret = %d", ret);
 		return ret;
 	}
-	ret = -ETIMEDOUT;
 	end = get_timeofday_ms() + HNS3_TQP_RESET_TRY_MS;
 	do {
 		/* Wait for tqp hw reset */
 		rte_delay_ms(HNS3_POLL_RESPONE_MS);
-		reset_status = hns3_get_reset_status(hw, queue_id);
-		if (reset_status) {
-			ret = 0;
+		ret = hns3_get_tqp_reset_status(hw, queue_id, &reset_status);
+		if (ret)
+			goto tqp_reset_fail;
+
+		if (reset_status)
 			break;
-		}
 	} while (get_timeofday_ms() < end);
 
-	if (ret) {
-		hns3_err(hw, "Reset TQP fail, ret = %d", ret);
-		return ret;
+	if (!reset_status) {
+		ret = -ETIMEDOUT;
+		hns3_err(hw, "reset tqp timeout, queue_id = %u, ret = %d",
+			     queue_id, ret);
+		goto tqp_reset_fail;
 	}
 
 	ret = hns3_send_reset_tqp_cmd(hw, queue_id, false);
@@ -501,6 +637,10 @@ hns3_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 		hns3_err(hw, "Deassert the soft reset fail, ret = %d", ret);
 
 	return ret;
+
+tqp_reset_fail:
+	hns3_send_reset_tqp_cmd(hw, queue_id, false);
+	return ret;
 }
 
 static int
@@ -516,28 +656,33 @@ hns3vf_reset_tqp(struct hns3_hw *hw, uint16_t queue_id)
 
 	memcpy(msg_data, &queue_id, sizeof(uint16_t));
 
-	return hns3_send_mbx_msg(hw, HNS3_MBX_QUEUE_RESET, 0, msg_data,
+	ret = hns3_send_mbx_msg(hw, HNS3_MBX_QUEUE_RESET, 0, msg_data,
 				 sizeof(msg_data), true, NULL, 0);
+	if (ret)
+		hns3_err(hw, "fail to reset tqp, queue_id = %u, ret = %d.",
+			 queue_id, ret);
+	return ret;
 }
 
 static int
-hns3_reset_queue(struct hns3_adapter *hns, uint16_t queue_id)
+hns3_reset_tqp(struct hns3_adapter *hns, uint16_t queue_id)
 {
 	struct hns3_hw *hw = &hns->hw;
+
 	if (hns->is_vf)
 		return hns3vf_reset_tqp(hw, queue_id);
 	else
-		return hns3_reset_tqp(hw, queue_id);
+		return hns3pf_reset_tqp(hw, queue_id);
 }
 
 int
-hns3_reset_all_queues(struct hns3_adapter *hns)
+hns3_reset_all_tqps(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	int ret, i;
 
 	for (i = 0; i < hw->cfg_max_queues; i++) {
-		ret = hns3_reset_queue(hns, i);
+		ret = hns3_reset_tqp(hns, i);
 		if (ret) {
 			hns3_err(hw, "Failed to reset No.%d queue: %d", i, ret);
 			return ret;
@@ -546,6 +691,121 @@ hns3_reset_all_queues(struct hns3_adapter *hns)
 	return 0;
 }
 
+static int
+hns3_send_reset_queue_cmd(struct hns3_hw *hw, uint16_t queue_id,
+			  enum hns3_ring_type queue_type, bool enable)
+{
+	struct hns3_reset_tqp_queue_cmd *req;
+	struct hns3_cmd_desc desc;
+	int queue_direction;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE_INDEP, false);
+
+	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
+	queue_direction = queue_type == HNS3_RING_TYPE_TX ? 0 : 1;
+	req->queue_direction = rte_cpu_to_le_16(queue_direction);
+	hns3_set_bit(req->reset_req, HNS3_TQP_RESET_B, enable ? 1 : 0);
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "send queue reset cmd error, queue_id = %u, "
+			 "queue_type = %s, ret = %d.", queue_id,
+			 queue_type == HNS3_RING_TYPE_TX ? "Tx" : "Rx", ret);
+	return ret;
+}
+
+static int
+hns3_get_queue_reset_status(struct hns3_hw *hw, uint16_t queue_id,
+			    enum hns3_ring_type queue_type,
+			    uint8_t *reset_status)
+{
+	struct hns3_reset_tqp_queue_cmd *req;
+	struct hns3_cmd_desc desc;
+	int queue_direction;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RESET_TQP_QUEUE_INDEP, true);
+
+	req = (struct hns3_reset_tqp_queue_cmd *)desc.data;
+	req->tqp_id = rte_cpu_to_le_16(queue_id);
+	queue_direction = queue_type == HNS3_RING_TYPE_TX ? 0 : 1;
+	req->queue_direction = rte_cpu_to_le_16(queue_direction);
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "get queue reset status error, queue_id = %u "
+			 "queue_type = %s, ret = %d.", queue_id,
+			 queue_type == HNS3_RING_TYPE_TX ? "Tx" : "Rx", ret);
+		return ret;
+	}
+
+	*reset_status = hns3_get_bit(req->ready_to_reset, HNS3_TQP_RESET_B);
+	return  ret;
+}
+
+static int
+hns3_reset_queue(struct hns3_hw *hw, uint16_t queue_id,
+		 enum hns3_ring_type queue_type)
+{
+#define HNS3_QUEUE_RESET_TRY_MS	200
+	struct hns3_tx_queue *txq;
+	struct hns3_rx_queue *rxq;
+	uint32_t reset_wait_times;
+	uint32_t max_wait_times;
+	uint8_t reset_status;
+	int ret;
+
+	if (queue_type == HNS3_RING_TYPE_TX) {
+		txq = hw->data->tx_queues[queue_id];
+		hns3_enable_txq(txq, false);
+	} else {
+		rxq = hw->data->rx_queues[queue_id];
+		hns3_enable_rxq(rxq, false);
+	}
+
+	ret = hns3_send_reset_queue_cmd(hw, queue_id, queue_type, true);
+	if (ret) {
+		hns3_err(hw, "send reset queue cmd fail, ret = %d.", ret);
+		return ret;
+	}
+
+	reset_wait_times = 0;
+	max_wait_times = HNS3_QUEUE_RESET_TRY_MS / HNS3_POLL_RESPONE_MS;
+	while (reset_wait_times < max_wait_times) {
+		/* Wait for queue hw reset */
+		rte_delay_ms(HNS3_POLL_RESPONE_MS);
+		ret = hns3_get_queue_reset_status(hw, queue_id,
+						queue_type, &reset_status);
+		if (ret)
+			goto queue_reset_fail;
+
+		if (reset_status)
+			break;
+		reset_wait_times++;
+	}
+
+	if (!reset_status) {
+		hns3_err(hw, "reset queue timeout, queue_id = %u, "
+			     "queue_type = %s", queue_id,
+			     queue_type == HNS3_RING_TYPE_TX ? "Tx" : "Rx");
+		ret = -ETIMEDOUT;
+		goto queue_reset_fail;
+	}
+
+	ret = hns3_send_reset_queue_cmd(hw, queue_id, queue_type, false);
+	if (ret)
+		hns3_err(hw, "deassert queue reset fail, ret = %d.", ret);
+
+	return ret;
+
+queue_reset_fail:
+	hns3_send_reset_queue_cmd(hw, queue_id, queue_type, false);
+	return ret;
+}
+
+
 void
 hns3_set_queue_intr_gl(struct hns3_hw *hw, uint16_t queue_id,
 		       uint8_t gl_idx, uint16_t gl_value)
@@ -658,7 +918,7 @@ hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 }
 
 static int
-hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
+hns3_init_rxq(struct hns3_adapter *hns, uint16_t idx)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rx_queue *rxq;
@@ -669,7 +929,7 @@ hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 	rxq = (struct hns3_rx_queue *)hw->data->rx_queues[idx];
 	ret = hns3_alloc_rx_queue_mbufs(hw, rxq);
 	if (ret) {
-		hns3_err(hw, "Failed to alloc mbuf for No.%d rx queue: %d",
+		hns3_err(hw, "fail to alloc mbuf for Rx queue %u, ret = %d.",
 			 idx, ret);
 		return ret;
 	}
@@ -687,7 +947,7 @@ hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 }
 
 static void
-hns3_fake_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
+hns3_init_fake_rxq(struct hns3_adapter *hns, uint16_t idx)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rx_queue *rxq;
@@ -701,9 +961,8 @@ hns3_fake_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 }
 
 static void
-hns3_init_tx_queue(struct hns3_tx_queue *queue)
+hns3_init_txq(struct hns3_tx_queue *txq)
 {
-	struct hns3_tx_queue *txq = queue;
 	struct hns3_desc *desc;
 	int i;
 
@@ -721,26 +980,6 @@ hns3_init_tx_queue(struct hns3_tx_queue *queue)
 }
 
 static void
-hns3_dev_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
-{
-	struct hns3_hw *hw = &hns->hw;
-	struct hns3_tx_queue *txq;
-
-	txq = (struct hns3_tx_queue *)hw->data->tx_queues[idx];
-	hns3_init_tx_queue(txq);
-}
-
-static void
-hns3_fake_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
-{
-	struct hns3_hw *hw = &hns->hw;
-	struct hns3_tx_queue *txq;
-
-	txq = (struct hns3_tx_queue *)hw->fkq_data.tx_queues[idx];
-	hns3_init_tx_queue(txq);
-}
-
-static void
 hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
@@ -766,38 +1005,41 @@ hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 }
 
 static int
-hns3_start_rx_queues(struct hns3_adapter *hns)
+hns3_init_rx_queues(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rx_queue *rxq;
-	int i, j;
+	uint16_t i, j;
 	int ret;
 
 	/* Initialize RSS for queues */
 	ret = hns3_config_rss(hns);
 	if (ret) {
-		hns3_err(hw, "Failed to configure rss %d", ret);
+		hns3_err(hw, "failed to configure rss, ret = %d.", ret);
 		return ret;
 	}
 
 	for (i = 0; i < hw->data->nb_rx_queues; i++) {
 		rxq = (struct hns3_rx_queue *)hw->data->rx_queues[i];
-		if (rxq == NULL || rxq->rx_deferred_start)
+		if (!rxq) {
+			hns3_err(hw, "Rx queue %u not available or setup.", i);
+			goto out;
+		}
+
+		if (rxq->rx_deferred_start)
 			continue;
-		ret = hns3_dev_rx_queue_start(hns, i);
+
+		ret = hns3_init_rxq(hns, i);
 		if (ret) {
-			hns3_err(hw, "Failed to start No.%d rx queue: %d", i,
+			hns3_err(hw, "failed to init Rx queue %u, ret = %d.", i,
 				 ret);
 			goto out;
 		}
 	}
 
-	for (i = 0; i < hw->fkq_data.nb_fake_rx_queues; i++) {
-		rxq = (struct hns3_rx_queue *)hw->fkq_data.rx_queues[i];
-		if (rxq == NULL || rxq->rx_deferred_start)
-			continue;
-		hns3_fake_rx_queue_start(hns, i);
-	}
+	for (i = 0; i < hw->fkq_data.nb_fake_rx_queues; i++)
+		hns3_init_fake_rxq(hns, i);
+
 	return 0;
 
 out:
@@ -809,74 +1051,104 @@ hns3_start_rx_queues(struct hns3_adapter *hns)
 	return ret;
 }
 
-static void
-hns3_start_tx_queues(struct hns3_adapter *hns)
+static int
+hns3_init_tx_queues(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_tx_queue *txq;
-	int i;
+	uint16_t i;
 
 	for (i = 0; i < hw->data->nb_tx_queues; i++) {
 		txq = (struct hns3_tx_queue *)hw->data->tx_queues[i];
-		if (txq == NULL || txq->tx_deferred_start)
+		if (!txq) {
+			hns3_err(hw, "Tx queue %u not available or setup.", i);
+			return -EINVAL;
+		}
+
+		if (txq->tx_deferred_start)
 			continue;
-		hns3_dev_tx_queue_start(hns, i);
+		hns3_init_txq(txq);
 	}
 
 	for (i = 0; i < hw->fkq_data.nb_fake_tx_queues; i++) {
 		txq = (struct hns3_tx_queue *)hw->fkq_data.tx_queues[i];
-		if (txq == NULL || txq->tx_deferred_start)
-			continue;
-		hns3_fake_tx_queue_start(hns, i);
+		hns3_init_txq(txq);
 	}
-
 	hns3_init_tx_ring_tc(hns);
+
+	return 0;
 }
 
 /*
- * Start all queues.
- * Note: just init and setup queues, and don't enable queue rx&tx.
+ * Init all queues.
+ * Note: just init and setup queues, and don't enable tqps.
  */
 int
-hns3_start_queues(struct hns3_adapter *hns, bool reset_queue)
+hns3_init_queues(struct hns3_adapter *hns, bool reset_queue)
 {
 	struct hns3_hw *hw = &hns->hw;
 	int ret;
 
 	if (reset_queue) {
-		ret = hns3_reset_all_queues(hns);
+		ret = hns3_reset_all_tqps(hns);
 		if (ret) {
-			hns3_err(hw, "Failed to reset all queues %d", ret);
+			hns3_err(hw, "failed to reset all queues, ret = %d.",
+				 ret);
 			return ret;
 		}
 	}
 
-	ret = hns3_start_rx_queues(hns);
+	ret = hns3_init_rx_queues(hns);
 	if (ret) {
-		hns3_err(hw, "Failed to start rx queues: %d", ret);
+		hns3_err(hw, "failed to init rx queues, ret = %d.", ret);
 		return ret;
 	}
 
-	hns3_start_tx_queues(hns);
+	ret = hns3_init_tx_queues(hns);
+	if (ret) {
+		hns3_dev_release_mbufs(hns);
+		hns3_err(hw, "failed to init tx queues, ret = %d.", ret);
+	}
 
-	return 0;
+	return ret;
 }
 
-int
-hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue)
+void
+hns3_start_tqps(struct hns3_hw *hw)
 {
-	struct hns3_hw *hw = &hns->hw;
-	int ret;
+	struct hns3_tx_queue *txq;
+	struct hns3_rx_queue *rxq;
+	uint16_t i;
 
-	hns3_enable_all_queues(hw, false);
-	if (reset_queue) {
-		ret = hns3_reset_all_queues(hns);
-		if (ret) {
-			hns3_err(hw, "Failed to reset all queues %d", ret);
-			return ret;
-		}
+	hns3_enable_all_queues(hw, true);
+
+	for (i = 0; i < hw->data->nb_tx_queues; i++) {
+		txq = hw->data->tx_queues[i];
+		if (txq->enabled)
+			hw->data->tx_queue_state[i] =
+				RTE_ETH_QUEUE_STATE_STARTED;
 	}
-	return 0;
+
+	for (i = 0; i < hw->data->nb_rx_queues; i++) {
+		rxq = hw->data->rx_queues[i];
+		if (rxq->enabled)
+			hw->data->rx_queue_state[i] =
+				RTE_ETH_QUEUE_STATE_STARTED;
+	}
+}
+
+void
+hns3_stop_tqps(struct hns3_hw *hw)
+{
+	uint16_t i;
+
+	hns3_enable_all_queues(hw, false);
+
+	for (i = 0; i < hw->data->nb_tx_queues; i++)
+		hw->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	for (i = 0; i < hw->data->nb_rx_queues; i++)
+		hw->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
 }
 
 /*
@@ -1202,13 +1474,12 @@ hns3_set_fake_rx_or_tx_queues(struct rte_eth_dev *dev, uint16_t nb_rx_q,
 	int ret;
 
 	/* Setup new number of fake RX/TX queues and reconfigure device. */
-	hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
 	rx_need_add_nb_q = hw->cfg_max_queues - nb_rx_q;
 	tx_need_add_nb_q = hw->cfg_max_queues - nb_tx_q;
 	ret = hns3_fake_rx_queue_config(hw, rx_need_add_nb_q);
 	if (ret) {
 		hns3_err(hw, "Fail to configure fake rx queues: %d", ret);
-		goto cfg_fake_rx_q_fail;
+		return ret;
 	}
 
 	ret = hns3_fake_tx_queue_config(hw, tx_need_add_nb_q);
@@ -1241,8 +1512,6 @@ hns3_set_fake_rx_or_tx_queues(struct rte_eth_dev *dev, uint16_t nb_rx_q,
 	(void)hns3_fake_tx_queue_config(hw, 0);
 cfg_fake_tx_q_fail:
 	(void)hns3_fake_rx_queue_config(hw, 0);
-cfg_fake_rx_q_fail:
-	hw->cfg_max_queues = 0;
 
 	return ret;
 }
@@ -1258,7 +1527,7 @@ hns3_dev_release_mbufs(struct hns3_adapter *hns)
 	if (dev_data->rx_queues)
 		for (i = 0; i < dev_data->nb_rx_queues; i++) {
 			rxq = dev_data->rx_queues[i];
-			if (rxq == NULL || rxq->rx_deferred_start)
+			if (rxq == NULL)
 				continue;
 			hns3_rx_queue_release_mbufs(rxq);
 		}
@@ -1266,7 +1535,7 @@ hns3_dev_release_mbufs(struct hns3_adapter *hns)
 	if (dev_data->tx_queues)
 		for (i = 0; i < dev_data->nb_tx_queues; i++) {
 			txq = dev_data->tx_queues[i];
-			if (txq == NULL || txq->tx_deferred_start)
+			if (txq == NULL)
 				continue;
 			hns3_tx_queue_release_mbufs(txq);
 		}
@@ -1315,10 +1584,49 @@ hns3_rx_buf_len_calc(struct rte_mempool *mp, uint16_t *rx_buf_len)
 }
 
 static int
+hns3_rxq_conf_runtime_check(struct hns3_hw *hw, uint16_t buf_size,
+				uint16_t nb_desc)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	struct rte_eth_rxmode *rxmode = &hw->data->dev_conf.rxmode;
+	eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
+	uint16_t min_vec_bds;
+
+	/*
+	 * HNS3 hardware network engine set scattered as default. If the driver
+	 * is not work in scattered mode and the pkts greater than buf_size
+	 * but smaller than max_rx_pkt_len will be distributed to multiple BDs.
+	 * Driver cannot handle this situation.
+	 */
+	if (!hw->data->scattered_rx && rxmode->max_rx_pkt_len > buf_size) {
+		hns3_err(hw, "max_rx_pkt_len is not allowed to be set greater "
+			     "than rx_buf_len if scattered is off.");
+		return -EINVAL;
+	}
+
+	if (pkt_burst == hns3_recv_pkts_vec) {
+		min_vec_bds = HNS3_DEFAULT_RXQ_REARM_THRESH +
+			      HNS3_DEFAULT_RX_BURST;
+		if (nb_desc < min_vec_bds ||
+		    nb_desc % HNS3_DEFAULT_RXQ_REARM_THRESH) {
+			hns3_err(hw, "if Rx burst mode is vector, "
+				 "number of descriptor is required to be "
+				 "bigger than min vector bds:%u, and could be "
+				 "divided by rxq rearm thresh:%u.",
+				 min_vec_bds, HNS3_DEFAULT_RXQ_REARM_THRESH);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int
 hns3_rx_queue_conf_check(struct hns3_hw *hw, const struct rte_eth_rxconf *conf,
 			 struct rte_mempool *mp, uint16_t nb_desc,
 			 uint16_t *buf_size)
 {
+	int ret;
+
 	if (nb_desc > HNS3_MAX_RING_DESC || nb_desc < HNS3_MIN_RING_DESC ||
 	    nb_desc % HNS3_ALIGN_RING_DESC) {
 		hns3_err(hw, "Number (%u) of rx descriptors is invalid",
@@ -1338,6 +1646,14 @@ hns3_rx_queue_conf_check(struct hns3_hw *hw, const struct rte_eth_rxconf *conf,
 		return -EINVAL;
 	}
 
+	if (hw->data->dev_started) {
+		ret = hns3_rxq_conf_runtime_check(hw, *buf_size, nb_desc);
+		if (ret) {
+			hns3_err(hw, "Rx queue runtime setup fail.");
+			return ret;
+		}
+	}
+
 	return 0;
 }
 
@@ -1370,11 +1686,6 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	int rx_entry_len;
 	int ret;
 
-	if (dev->data->dev_started) {
-		hns3_err(hw, "rx_queue_setup after dev_start no supported");
-		return -EINVAL;
-	}
-
 	ret = hns3_rx_queue_conf_check(hw, conf, mp, nb_desc, &rx_buf_size);
 	if (ret)
 		return ret;
@@ -1402,7 +1713,12 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	rxq->mb_pool = mp;
 	rxq->rx_free_thresh = (conf->rx_free_thresh > 0) ?
 		conf->rx_free_thresh : HNS3_DEFAULT_RX_FREE_THRESH;
+
 	rxq->rx_deferred_start = conf->rx_deferred_start;
+	if (rxq->rx_deferred_start && !hns3_dev_indep_txrx_supported(hw)) {
+		hns3_warn(hw, "deferred start is not supported.");
+		rxq->rx_deferred_start = false;
+	}
 
 	rx_entry_len = (rxq->nb_rx_desc + HNS3_DEFAULT_RX_BURST) *
 			sizeof(struct hns3_entry);
@@ -2132,11 +2448,6 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	int tx_entry_len;
 	int ret;
 
-	if (dev->data->dev_started) {
-		hns3_err(hw, "tx_queue_setup after dev_start no supported");
-		return -EINVAL;
-	}
-
 	ret = hns3_tx_queue_conf_check(hw, conf, nb_desc,
 				       &tx_rs_thresh, &tx_free_thresh, idx);
 	if (ret)
@@ -2160,6 +2471,11 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	}
 
 	txq->tx_deferred_start = conf->tx_deferred_start;
+	if (txq->tx_deferred_start && !hns3_dev_indep_txrx_supported(hw)) {
+		hns3_warn(hw, "deferred start is not supported.");
+		txq->tx_deferred_start = false;
+	}
+
 	tx_entry_len = sizeof(struct hns3_entry) * txq->nb_tx_desc;
 	txq->sw_ring = rte_zmalloc_socket("hns3 TX sw ring", tx_entry_len,
 					  RTE_CACHE_LINE_SIZE, socket_id);
@@ -3377,3 +3693,98 @@ hns3_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	qinfo->conf.tx_free_thresh = txq->tx_free_thresh;
 	qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
 }
+
+int
+hns3_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_rx_queue *rxq = dev->data->rx_queues[rx_queue_id];
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	int ret;
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	ret = hns3_reset_queue(hw, rx_queue_id, HNS3_RING_TYPE_RX);
+	if (ret) {
+		hns3_err(hw, "fail to reset Rx queue %u, ret = %d.",
+			 rx_queue_id, ret);
+		return ret;
+	}
+
+	ret = hns3_init_rxq(hns, rx_queue_id);
+	if (ret) {
+		hns3_err(hw, "fail to init Rx queue %u, ret = %d.",
+			 rx_queue_id, ret);
+		return ret;
+	}
+
+	hns3_enable_rxq(rxq, true);
+	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+
+	return ret;
+}
+
+int
+hns3_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_rx_queue *rxq = dev->data->rx_queues[rx_queue_id];
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	hns3_enable_rxq(rxq, false);
+	hns3_rx_queue_release_mbufs(rxq);
+	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	return 0;
+}
+
+int
+hns3_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq = dev->data->tx_queues[tx_queue_id];
+	int ret;
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	ret = hns3_reset_queue(hw, tx_queue_id, HNS3_RING_TYPE_TX);
+	if (ret) {
+		hns3_err(hw, "fail to reset Tx queue %u, ret = %d.",
+			 tx_queue_id, ret);
+		return ret;
+	}
+
+	hns3_init_txq(txq);
+	hns3_enable_txq(txq, true);
+	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+
+	return ret;
+}
+
+int
+hns3_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_tx_queue *txq = dev->data->tx_queues[tx_queue_id];
+
+	if (!hns3_dev_indep_txrx_supported(hw))
+		return -ENOTSUP;
+
+	hns3_enable_txq(txq, false);
+	hns3_tx_queue_release_mbufs(txq);
+	/*
+	 * All the mbufs in sw_ring are released and all the pointers in sw_ring
+	 * are set to NULL. If this queue is still called by upper layer,
+	 * residual SW status of this txq may cause these pointers in sw_ring
+	 * which have been set to NULL to be released again. To avoid it,
+	 * reinit the txq.
+	 */
+	hns3_init_txq(txq);
+	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+	return 0;
+}
diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index cdfe115..abc7c54 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -307,6 +307,7 @@ struct hns3_rx_queue {
 	 * point, the pvid_sw_discard_en will be false.
 	 */
 	bool pvid_sw_discard_en;
+	bool enabled;           /* indicate if Rx queue has been enabled */
 
 	uint64_t l2_errors;
 	uint64_t pkt_len_errors;
@@ -405,6 +406,7 @@ struct hns3_tx_queue {
 	 * this point.
 	 */
 	bool pvid_sw_shift_en;
+	bool enabled;           /* indicate if Tx queue has been enabled */
 
 	/*
 	 * The following items are used for the abnormal errors statistics in
@@ -602,13 +604,14 @@ hns3_rx_calc_ptype(struct hns3_rx_queue *rxq, const uint32_t l234_info,
 void hns3_dev_rx_queue_release(void *queue);
 void hns3_dev_tx_queue_release(void *queue);
 void hns3_free_all_queues(struct rte_eth_dev *dev);
-int hns3_reset_all_queues(struct hns3_adapter *hns);
+int hns3_reset_all_tqps(struct hns3_adapter *hns);
 void hns3_dev_all_rx_queue_intr_enable(struct hns3_hw *hw, bool en);
 int hns3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
 int hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 void hns3_enable_all_queues(struct hns3_hw *hw, bool en);
-int hns3_start_queues(struct hns3_adapter *hns, bool reset_queue);
-int hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue);
+int hns3_init_queues(struct hns3_adapter *hns, bool reset_queue);
+void hns3_start_tqps(struct hns3_hw *hw);
+void hns3_stop_tqps(struct hns3_hw *hw);
 int hns3_rxq_iterate(struct rte_eth_dev *dev,
 		 int (*callback)(struct hns3_rx_queue *, void *), void *arg);
 void hns3_dev_release_mbufs(struct hns3_adapter *hns);
@@ -617,6 +620,10 @@ int hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 			struct rte_mempool *mp);
 int hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 			unsigned int socket, const struct rte_eth_txconf *conf);
+int hns3_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id);
+int hns3_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id);
+int hns3_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id);
+int hns3_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id);
 uint16_t hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 			uint16_t nb_pkts);
 uint16_t hns3_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
@@ -662,5 +669,8 @@ void hns3_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 void hns3_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 		       struct rte_eth_txq_info *qinfo);
 uint32_t hns3_get_tqp_reg_offset(uint16_t idx);
+int hns3_start_all_txqs(struct rte_eth_dev *dev);
+int hns3_start_all_rxqs(struct rte_eth_dev *dev);
+void hns3_stop_all_txqs(struct rte_eth_dev *dev);
 
 #endif /* _HNS3_RXTX_H_ */
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 8/9] net/hns3: check return value when reading PCI config space
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                     ` (6 preceding siblings ...)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 7/9] net/hns3: support start and stop Tx or Rx queue Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 9/9] net/hns3: remove redundant return value assignments Wei Hu (Xavier)
  2020-09-30 22:59   ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Ferruh Yigit
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Hongbo Zheng <zhenghongbo3@huawei.com>

This patch add return value check when calling rte_pci_read_config
function.

Fixes: cea37e513329 ("net/hns3: fix FLR reset")
Cc: stable@dpdk.org

Signed-off-by: Hongbo Zheng <zhenghongbo3@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_ethdev_vf.c | 62 ++++++++++++++++++++++++++++++++-------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 849f6cc..a6cc11d 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -64,12 +64,18 @@ static int hns3vf_add_mc_mac_addr(struct hns3_hw *hw,
 static int hns3vf_remove_mc_mac_addr(struct hns3_hw *hw,
 				     struct rte_ether_addr *mac_addr);
 /* set PCI bus mastering */
-static void
+static int
 hns3vf_set_bus_master(const struct rte_pci_device *device, bool op)
 {
 	uint16_t reg;
+	int ret;
 
-	rte_pci_read_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	ret = rte_pci_read_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+			     PCI_COMMAND);
+		return ret;
+	}
 
 	if (op)
 		/* set the master bit */
@@ -77,7 +83,7 @@ hns3vf_set_bus_master(const struct rte_pci_device *device, bool op)
 	else
 		reg &= ~(PCI_COMMAND_MASTER);
 
-	rte_pci_write_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	return rte_pci_write_config(device, &reg, sizeof(reg), PCI_COMMAND);
 }
 
 /**
@@ -94,16 +100,34 @@ hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap)
 	uint8_t pos;
 	uint8_t id;
 	int ttl;
+	int ret;
+
+	ret = rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", PCI_STATUS);
+		return 0;
+	}
 
-	rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS);
 	if (!(status & PCI_STATUS_CAP_LIST))
 		return 0;
 
 	ttl = MAX_PCIE_CAPABILITY;
-	rte_pci_read_config(device, &pos, sizeof(pos), PCI_CAPABILITY_LIST);
+	ret = rte_pci_read_config(device, &pos, sizeof(pos),
+				  PCI_CAPABILITY_LIST);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+			     PCI_CAPABILITY_LIST);
+		return 0;
+	}
+
 	while (ttl-- && pos >= PCI_STD_HEADER_SIZEOF) {
-		rte_pci_read_config(device, &id, sizeof(id),
-				    (pos + PCI_CAP_LIST_ID));
+		ret = rte_pci_read_config(device, &id, sizeof(id),
+					  (pos + PCI_CAP_LIST_ID));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_CAP_LIST_ID));
+			break;
+		}
 
 		if (id == 0xFF)
 			break;
@@ -111,8 +135,13 @@ hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap)
 		if (id == cap)
 			return (int)pos;
 
-		rte_pci_read_config(device, &pos, sizeof(pos),
-				    (pos + PCI_CAP_LIST_NEXT));
+		ret = rte_pci_read_config(device, &pos, sizeof(pos),
+					  (pos + PCI_CAP_LIST_NEXT));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_CAP_LIST_NEXT));
+			break;
+		}
 	}
 	return 0;
 }
@@ -122,11 +151,18 @@ hns3vf_enable_msix(const struct rte_pci_device *device, bool op)
 {
 	uint16_t control;
 	int pos;
+	int ret;
 
 	pos = hns3vf_find_pci_capability(device, PCI_CAP_ID_MSIX);
 	if (pos) {
-		rte_pci_read_config(device, &control, sizeof(control),
+		ret = rte_pci_read_config(device, &control, sizeof(control),
 				    (pos + PCI_MSIX_FLAGS));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_MSIX_FLAGS));
+			return -ENXIO;
+		}
+
 		if (op)
 			control |= PCI_MSIX_FLAGS_ENABLE;
 		else
@@ -2574,7 +2610,11 @@ hns3vf_reinit_dev(struct hns3_adapter *hns)
 
 	if (hw->reset.level == HNS3_VF_FULL_RESET) {
 		rte_intr_disable(&pci_dev->intr_handle);
-		hns3vf_set_bus_master(pci_dev, true);
+		ret = hns3vf_set_bus_master(pci_dev, true);
+		if (ret) {
+			hns3_err(hw, "failed to set pci bus, ret = %d", ret);
+			return ret;
+		}
 	}
 
 	/* Firmware command initialize */
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 9/9] net/hns3: remove redundant return value assignments
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                     ` (7 preceding siblings ...)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 8/9] net/hns3: check return value when reading PCI config space Wei Hu (Xavier)
@ 2020-09-29 12:01   ` Wei Hu (Xavier)
  2020-09-30 22:59   ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Ferruh Yigit
  9 siblings, 0 replies; 23+ messages in thread
From: Wei Hu (Xavier) @ 2020-09-29 12:01 UTC (permalink / raw)
  To: dev; +Cc: xavier.huwei

From: Hongbo Zheng <zhenghongbo3@huawei.com>

When an error occurs in the reset process, -EIO is returned.
The assignment of ret here is redundant, so deleted it.

Signed-off-by: Hongbo Zheng <zhenghongbo3@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
 drivers/net/hns3/hns3_intr.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c
index dfd7371..2565688 100644
--- a/drivers/net/hns3/hns3_intr.c
+++ b/drivers/net/hns3/hns3_intr.c
@@ -1888,7 +1888,6 @@ hns3_reset_process(struct hns3_adapter *hns, enum hns3_reset_level new_level)
 		if (hw->reset.wait_data->result == HNS3_WAIT_REQUEST)
 			rte_eal_alarm_cancel(hns3_wait_callback,
 					     hw->reset.wait_data);
-		ret = -EBUSY;
 		goto err;
 	}
 
-- 
2.9.5


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

* Re: [dpdk-dev] [PATCH v2 7/9] net/hns3: support start and stop Tx or Rx queue
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 7/9] net/hns3: support start and stop Tx or Rx queue Wei Hu (Xavier)
@ 2020-09-30 22:49     ` Ferruh Yigit
  2020-09-30 22:54       ` Ferruh Yigit
  0 siblings, 1 reply; 23+ messages in thread
From: Ferruh Yigit @ 2020-09-30 22:49 UTC (permalink / raw)
  To: Wei Hu (Xavier), dev; +Cc: xavier.huwei

On 9/29/2020 1:01 PM, Wei Hu (Xavier) wrote:
> From: Chengchang Tang <tangchengchang@huawei.com>
> 
> The new generation hns3 network engine supports independent enabling and
> disabling of a single Tx/Rx queue. So, it can support the queue start and
> stop feature. In addition, when different numbers of Tx and Rx queues need
> to be enabled in some applications, hns3 pmd does not need to create fake
> queues to enable these scenarios.
> 
> This patch Add queue start and stop feature for the new generation hns3
> networking engine. Cancel the creation of fake queue on the new generation
> network engine. And the previously improperly named queue related function
> was renamed to improve readability.
> 
> Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
> Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>

<...>

> @@ -5626,6 +5666,10 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
>   	.tx_queue_setup         = hns3_tx_queue_setup,
>   	.rx_queue_release       = hns3_dev_rx_queue_release,
>   	.tx_queue_release       = hns3_dev_tx_queue_release,
> +	.rx_queue_start         = hns3_dev_rx_queue_start,
> +	.rx_queue_stop          = hns3_dev_rx_queue_stop,
> +	.tx_queue_start         = hns3_dev_tx_queue_start,
> +	.tx_queue_stop          = hns3_dev_tx_queue_stop,
>   	.rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
>   	.rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
>   	.rxq_info_get           = hns3_rxq_info_get,


Can you please update feature files ('hns3.ini' & 'hns3_vf.ini') to announce 
"Queue start/stop" feature?



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

* Re: [dpdk-dev] [PATCH v2 7/9] net/hns3: support start and stop Tx or Rx queue
  2020-09-30 22:49     ` Ferruh Yigit
@ 2020-09-30 22:54       ` Ferruh Yigit
  0 siblings, 0 replies; 23+ messages in thread
From: Ferruh Yigit @ 2020-09-30 22:54 UTC (permalink / raw)
  To: Wei Hu (Xavier), dev; +Cc: xavier.huwei

On 9/30/2020 11:49 PM, Ferruh Yigit wrote:
> On 9/29/2020 1:01 PM, Wei Hu (Xavier) wrote:
>> From: Chengchang Tang <tangchengchang@huawei.com>
>>
>> The new generation hns3 network engine supports independent enabling and
>> disabling of a single Tx/Rx queue. So, it can support the queue start and
>> stop feature. In addition, when different numbers of Tx and Rx queues need
>> to be enabled in some applications, hns3 pmd does not need to create fake
>> queues to enable these scenarios.
>>
>> This patch Add queue start and stop feature for the new generation hns3
>> networking engine. Cancel the creation of fake queue on the new generation
>> network engine. And the previously improperly named queue related function
>> was renamed to improve readability.
>>
>> Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
>> Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
> 
> <...>
> 
>> @@ -5626,6 +5666,10 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
>>       .tx_queue_setup         = hns3_tx_queue_setup,
>>       .rx_queue_release       = hns3_dev_rx_queue_release,
>>       .tx_queue_release       = hns3_dev_tx_queue_release,
>> +    .rx_queue_start         = hns3_dev_rx_queue_start,
>> +    .rx_queue_stop          = hns3_dev_rx_queue_stop,
>> +    .tx_queue_start         = hns3_dev_tx_queue_start,
>> +    .tx_queue_stop          = hns3_dev_tx_queue_stop,
>>       .rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
>>       .rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
>>       .rxq_info_get           = hns3_rxq_info_get,
> 
> 
> Can you please update feature files ('hns3.ini' & 'hns3_vf.ini') to announce 
> "Queue start/stop" feature?
> 

This looks like only comment, I will add them while merging, please double check 
after merge.


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

* Re: [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver
  2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
                     ` (8 preceding siblings ...)
  2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 9/9] net/hns3: remove redundant return value assignments Wei Hu (Xavier)
@ 2020-09-30 22:59   ` Ferruh Yigit
  9 siblings, 0 replies; 23+ messages in thread
From: Ferruh Yigit @ 2020-09-30 22:59 UTC (permalink / raw)
  To: Wei Hu (Xavier), dev; +Cc: xavier.huwei

On 9/29/2020 1:01 PM, Wei Hu (Xavier) wrote:
> This series are updates and fixes for hns3 PMD driver.
> 
> Chengchang Tang (1):
>    net/hns3: support start and stop Tx or Rx queue
> 
> Hongbo Zheng (2):
>    net/hns3: check return value when reading PCI config space
>    net/hns3: remove redundant return value assignments
> 
> Huisong Li (3):
>    net/hns3: expand the number of queues for one TC up to 512
>    net/hns3: offload calculating the shapping para to firmware
>    net/hns3: set max scheduling rate based on actual board
> 
> Wei Hu (Xavier) (3):
>    net/hns3: maximize the queue number
>    net/hns3: fix error type when validating RSS flow action
>    net/hns3: set suitable type when initial flow error struct
> 

Series applied to dpdk-next-net/main, thanks.

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

end of thread, other threads:[~2020-09-30 22:59 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-29 11:09 [dpdk-dev] [PATCH 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 2/9] net/hns3: maximize the queue number Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 3/9] net/hns3: fix error type when validating RSS flow action Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 4/9] net/hns3: set suitable type when initial flow error struct Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 5/9] net/hns3: offload calculating the shapping para to firmware Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 6/9] net/hns3: set max scheduling rate based on actual board Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 7/9] net/hns3: support start and stop Tx or Rx queue Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 8/9] net/hns3: check return value when reading PCI config space Wei Hu (Xavier)
2020-09-29 11:09 ` [dpdk-dev] [PATCH 9/9] net/hns3: remove redundant return value assignments Wei Hu (Xavier)
2020-09-29 12:01 ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: expand the number of queues for one TC up to 512 Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 2/9] net/hns3: maximize the queue number Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 3/9] net/hns3: fix error type when validating RSS flow action Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 4/9] net/hns3: set suitable type when initial flow error struct Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 5/9] net/hns3: offload calculating the shapping para to firmware Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 6/9] net/hns3: set max scheduling rate based on actual board Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 7/9] net/hns3: support start and stop Tx or Rx queue Wei Hu (Xavier)
2020-09-30 22:49     ` Ferruh Yigit
2020-09-30 22:54       ` Ferruh Yigit
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 8/9] net/hns3: check return value when reading PCI config space Wei Hu (Xavier)
2020-09-29 12:01   ` [dpdk-dev] [PATCH v2 9/9] net/hns3: remove redundant return value assignments Wei Hu (Xavier)
2020-09-30 22:59   ` [dpdk-dev] [PATCH v2 0/9] updates and fixes for hns3 PMD driver Ferruh Yigit

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