This series add three feature according to the 21.05 roadmap as well as fix some bugs.
Chengchang Tang (4): net/hns3: support module EEPROM dump net/hns3: add more registers to dump net/hns3: fix maximum frame size update after buffer alloc net/hns3: fix imprecise statistics
Chengwen Feng (2): net/hns3: implement cleanup for Tx done net/hns3: support RXD advanced layout
Hongbo Zheng (1): net/hns3: add process for MAC interrupt
Huisong Li (4): net/hns3: encapsulate a port shaping interface net/hns3: support PF on electrical net device net/hns3: remove unused parameter from func declaration net/hns3: fix memory leakage for mbuf
Min Hu (Connor) (2): net/hns3: add Rx and Tx bytes stats net/hns3: add imissed packet stats
doc/guides/nics/features/hns3.ini | 1 + doc/guides/nics/features/hns3_vf.ini | 1 + doc/guides/rel_notes/release_21_05.rst | 5 + drivers/net/hns3/hns3_cmd.c | 8 +- drivers/net/hns3/hns3_cmd.h | 81 +++++++ drivers/net/hns3/hns3_dcb.c | 22 +- drivers/net/hns3/hns3_dcb.h | 2 +- drivers/net/hns3/hns3_ethdev.c | 419 +++++++++++++++++++++++++++++---- drivers/net/hns3/hns3_ethdev.h | 22 ++ drivers/net/hns3/hns3_ethdev_vf.c | 46 ++-- drivers/net/hns3/hns3_intr.c | 20 ++ drivers/net/hns3/hns3_intr.h | 4 + drivers/net/hns3/hns3_regs.c | 171 +++++++++++++- drivers/net/hns3/hns3_regs.h | 1 + drivers/net/hns3/hns3_rxtx.c | 283 ++++++++++++++++++++++ drivers/net/hns3/hns3_rxtx.h | 12 + drivers/net/hns3/hns3_rxtx_vec_neon.h | 15 ++ drivers/net/hns3/hns3_rxtx_vec_sve.c | 11 + drivers/net/hns3/hns3_stats.c | 293 +++++++++++++---------- drivers/net/hns3/hns3_stats.h | 12 +- 20 files changed, 1231 insertions(+), 198 deletions(-)
From: Chengchang Tang tangchengchang@huawei.com
This patch add support for dumping module EEPROM.
Signed-off-by: Chengchang Tang tangchengchang@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- doc/guides/rel_notes/release_21_05.rst | 4 + drivers/net/hns3/hns3_cmd.h | 16 ++++ drivers/net/hns3/hns3_ethdev.c | 159 +++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+)
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst index 2d7ceda..eb0508b 100644 --- a/doc/guides/rel_notes/release_21_05.rst +++ b/doc/guides/rel_notes/release_21_05.rst @@ -60,6 +60,10 @@ New Features * Added command to display Rx queue used descriptor count. ``show port (port_id) rxq (queue_id) desc used count``
+* **Updated Hisilicon hns3 driver.** + + * Added support for module EEPROM dumping. +
Removed Items ------------- diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index 5010278..07e7d48 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -211,6 +211,8 @@ enum hns3_opcode_type { HNS3_OPC_FIRMWARE_COMPAT_CFG = 0x701A,
/* SFP command */ + HNS3_OPC_GET_SFP_EEPROM = 0x7100, + HNS3_OPC_GET_SFP_EXIST = 0x7101, HNS3_OPC_SFP_GET_SPEED = 0x7104,
/* Interrupts commands */ @@ -714,6 +716,20 @@ struct hns3_config_auto_neg_cmd { #define HNS3_MAC_FEC_BASER 1 #define HNS3_MAC_FEC_RS 2
+#define HNS3_SFP_INFO_BD0_LEN 20UL +#define HNS3_SFP_INFO_BDX_LEN 24UL + +struct hns3_sfp_info_bd0_cmd { + uint16_t offset; + uint16_t read_len; + uint8_t data[HNS3_SFP_INFO_BD0_LEN]; +}; + +struct hns3_sfp_type { + uint8_t type; + uint8_t ext_type; +}; + struct hns3_sfp_speed_cmd { uint32_t sfp_speed; uint8_t query_type; /* 0: sfp speed, 1: active fec */ diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index dbd48de..e02a7ec 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -6172,6 +6172,163 @@ hns3_query_dev_fec_info(struct hns3_hw *hw) return ret; }
+static bool +hns3_optical_module_existed(struct hns3_hw *hw) +{ + struct hns3_cmd_desc desc; + bool existed; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_GET_SFP_EXIST, true); + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) { + hns3_err(hw, + "fail to get optical module exist state, ret = %d.\n", + ret); + return false; + } + existed = !!desc.data[0]; + + return existed; +} + +static int +hns3_get_module_eeprom_data(struct hns3_hw *hw, uint32_t offset, + uint32_t len, uint8_t *data) +{ +#define HNS3_SFP_INFO_CMD_NUM 6 +#define HNS3_SFP_INFO_MAX_LEN \ + (HNS3_SFP_INFO_BD0_LEN + \ + (HNS3_SFP_INFO_CMD_NUM - 1) * HNS3_SFP_INFO_BDX_LEN) + struct hns3_cmd_desc desc[HNS3_SFP_INFO_CMD_NUM]; + struct hns3_sfp_info_bd0_cmd *sfp_info_bd0; + uint16_t read_len; + uint16_t copy_len; + int ret; + int i; + + for (i = 0; i < HNS3_SFP_INFO_CMD_NUM; i++) { + hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_GET_SFP_EEPROM, + true); + if (i < HNS3_SFP_INFO_CMD_NUM - 1) + desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT); + } + + sfp_info_bd0 = (struct hns3_sfp_info_bd0_cmd *)desc[0].data; + sfp_info_bd0->offset = rte_cpu_to_le_16((uint16_t)offset); + read_len = RTE_MIN(len, HNS3_SFP_INFO_MAX_LEN); + sfp_info_bd0->read_len = rte_cpu_to_le_16((uint16_t)read_len); + + ret = hns3_cmd_send(hw, desc, HNS3_SFP_INFO_CMD_NUM); + if (ret) { + hns3_err(hw, "fail to get module EEPROM info, ret = %d.\n", + ret); + return ret; + } + + /* The data format in BD0 is different with the others. */ + copy_len = RTE_MIN(len, HNS3_SFP_INFO_BD0_LEN); + memcpy(data, sfp_info_bd0->data, copy_len); + read_len = copy_len; + + for (i = 1; i < HNS3_SFP_INFO_CMD_NUM; i++) { + if (read_len >= len) + break; + + copy_len = RTE_MIN(len - read_len, HNS3_SFP_INFO_BDX_LEN); + memcpy(data + read_len, desc[i].data, copy_len); + read_len += copy_len; + } + + return (int)read_len; +} + +static int +hns3_get_module_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *info) +{ + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns); + uint32_t offset = info->offset; + uint32_t len = info->length; + uint8_t *data = info->data; + uint32_t read_len = 0; + + if (hw->mac.media_type != HNS3_MEDIA_TYPE_FIBER) + return -ENOTSUP; + + if (!hns3_optical_module_existed(hw)) { + hns3_err(hw, "fail to read module EEPROM: no module is connected.\n"); + return -EIO; + } + + while (read_len < len) { + int ret; + ret = hns3_get_module_eeprom_data(hw, offset + read_len, + len - read_len, + data + read_len); + if (ret < 0) + return -EIO; + read_len += ret; + } + + return 0; +} + +static int +hns3_get_module_info(struct rte_eth_dev *dev, + struct rte_eth_dev_module_info *modinfo) +{ +#define HNS3_SFF8024_ID_SFP 0x03 +#define HNS3_SFF8024_ID_QSFP_8438 0x0c +#define HNS3_SFF8024_ID_QSFP_8436_8636 0x0d +#define HNS3_SFF8024_ID_QSFP28_8636 0x11 +#define HNS3_SFF_8636_V1_3 0x03 + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns); + struct rte_dev_eeprom_info info; + struct hns3_sfp_type sfp_type; + int ret; + + memset(&sfp_type, 0, sizeof(sfp_type)); + memset(&info, 0, sizeof(info)); + info.data = (uint8_t *)&sfp_type; + info.length = sizeof(sfp_type); + ret = hns3_get_module_eeprom(dev, &info); + if (ret) + return ret; + + switch (sfp_type.type) { + case HNS3_SFF8024_ID_SFP: + modinfo->type = RTE_ETH_MODULE_SFF_8472; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + break; + case HNS3_SFF8024_ID_QSFP_8438: + modinfo->type = RTE_ETH_MODULE_SFF_8436; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN; + break; + case HNS3_SFF8024_ID_QSFP_8436_8636: + if (sfp_type.ext_type < HNS3_SFF_8636_V1_3) { + modinfo->type = RTE_ETH_MODULE_SFF_8436; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN; + } else { + modinfo->type = RTE_ETH_MODULE_SFF_8636; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN; + } + break; + case HNS3_SFF8024_ID_QSFP28_8636: + modinfo->type = RTE_ETH_MODULE_SFF_8636; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN; + break; + default: + hns3_err(hw, "unknown module, type = %u, extra_type = %u.\n", + sfp_type.type, sfp_type.ext_type); + return -EINVAL; + } + + return 0; +} + static const struct eth_dev_ops hns3_eth_dev_ops = { .dev_configure = hns3_dev_configure, .dev_start = hns3_dev_start, @@ -6223,6 +6380,8 @@ static const struct eth_dev_ops hns3_eth_dev_ops = { .vlan_offload_set = hns3_vlan_offload_set, .vlan_pvid_set = hns3_vlan_pvid_set, .get_reg = hns3_get_regs, + .get_module_info = hns3_get_module_info, + .get_module_eeprom = hns3_get_module_eeprom, .get_dcb_info = hns3_get_dcb_info, .dev_supported_ptypes_get = hns3_dev_supported_ptypes_get, .fec_get_capability = hns3_fec_get_capability,
From: Chengchang Tang tangchengchang@huawei.com
This patch makes more registers dumped in the dump_reg API to help loacte the fault.
Signed-off-by: Chengchang Tang tangchengchang@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_cmd.h | 13 ++++ drivers/net/hns3/hns3_regs.c | 171 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 180 insertions(+), 4 deletions(-)
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index 07e7d48..6a58166 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -95,6 +95,19 @@ enum hns3_opcode_type { HNS3_OPC_QUERY_REG_NUM = 0x0040, HNS3_OPC_QUERY_32_BIT_REG = 0x0041, HNS3_OPC_QUERY_64_BIT_REG = 0x0042, + HNS3_OPC_DFX_BD_NUM = 0x0043, + HNS3_OPC_DFX_BIOS_COMMON_REG = 0x0044, + HNS3_OPC_DFX_SSU_REG_0 = 0x0045, + HNS3_OPC_DFX_SSU_REG_1 = 0x0046, + HNS3_OPC_DFX_IGU_EGU_REG = 0x0047, + HNS3_OPC_DFX_RPU_REG_0 = 0x0048, + HNS3_OPC_DFX_RPU_REG_1 = 0x0049, + HNS3_OPC_DFX_NCSI_REG = 0x004A, + HNS3_OPC_DFX_RTC_REG = 0x004B, + HNS3_OPC_DFX_PPP_REG = 0x004C, + HNS3_OPC_DFX_RCB_REG = 0x004D, + HNS3_OPC_DFX_TQP_REG = 0x004E, + HNS3_OPC_DFX_SSU_REG_2 = 0x004F,
HNS3_OPC_QUERY_DEV_SPECS = 0x0050,
diff --git a/drivers/net/hns3/hns3_regs.c b/drivers/net/hns3/hns3_regs.c index 84f3157..4022bb9 100644 --- a/drivers/net/hns3/hns3_regs.c +++ b/drivers/net/hns3/hns3_regs.c @@ -15,6 +15,8 @@ #define REG_NUM_PER_LINE 4 #define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(uint32_t))
+static int hns3_get_dfx_reg_line(struct hns3_hw *hw, uint32_t *length); + static const uint32_t cmdq_reg_addrs[] = {HNS3_CMDQ_TX_ADDR_L_REG, HNS3_CMDQ_TX_ADDR_H_REG, HNS3_CMDQ_TX_DEPTH_REG, @@ -77,6 +79,21 @@ static const uint32_t tqp_intr_reg_addrs[] = {HNS3_TQP_INTR_CTRL_REG, HNS3_TQP_INTR_GL2_REG, HNS3_TQP_INTR_RL_REG};
+static const uint32_t hns3_dfx_reg_opcode_list[] = { + HNS3_OPC_DFX_BIOS_COMMON_REG, + HNS3_OPC_DFX_SSU_REG_0, + HNS3_OPC_DFX_SSU_REG_1, + HNS3_OPC_DFX_IGU_EGU_REG, + HNS3_OPC_DFX_RPU_REG_0, + HNS3_OPC_DFX_RPU_REG_1, + HNS3_OPC_DFX_NCSI_REG, + HNS3_OPC_DFX_RTC_REG, + HNS3_OPC_DFX_PPP_REG, + HNS3_OPC_DFX_RCB_REG, + HNS3_OPC_DFX_TQP_REG, + HNS3_OPC_DFX_SSU_REG_2 +}; + static int hns3_get_regs_num(struct hns3_hw *hw, uint32_t *regs_num_32_bit, uint32_t *regs_num_64_bit) @@ -123,14 +140,21 @@ hns3_get_regs_length(struct hns3_hw *hw, uint32_t *length) if (!hns->is_vf) { ret = hns3_get_regs_num(hw, ®s_num_32_bit, ®s_num_64_bit); if (ret) { - hns3_err(hw, "Get register number failed, ret = %d.", - ret); - return -ENOTSUP; + hns3_err(hw, "fail to get the number of registers, " + "ret = %d.", ret); + return ret; } dfx_reg_lines = regs_num_32_bit * sizeof(uint32_t) / REG_LEN_PER_LINE + 1; dfx_reg_lines += regs_num_64_bit * sizeof(uint64_t) / REG_LEN_PER_LINE + 1; + + ret = hns3_get_dfx_reg_line(hw, &dfx_reg_lines); + if (ret) { + hns3_err(hw, "fail to get the number of dfx registers, " + "ret = %d.", ret); + return ret; + } len += dfx_reg_lines * REG_NUM_PER_LINE; }
@@ -310,6 +334,144 @@ hns3_direct_access_regs(struct hns3_hw *hw, uint32_t *data) return data - origin_data_ptr; }
+static int +hns3_get_dfx_reg_bd_num(struct hns3_hw *hw, uint32_t *bd_num_list, + uint32_t list_size) +{ +#define HNS3_GET_DFX_REG_BD_NUM_SIZE 4 + struct hns3_cmd_desc desc[HNS3_GET_DFX_REG_BD_NUM_SIZE]; + uint32_t index, desc_index; + uint32_t bd_num; + uint32_t i; + int ret; + + for (i = 0; i < HNS3_GET_DFX_REG_BD_NUM_SIZE - 1; i++) { + hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_DFX_BD_NUM, true); + desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT); + } + /* The last BD does not need a next flag */ + hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_DFX_BD_NUM, true); + + ret = hns3_cmd_send(hw, desc, HNS3_GET_DFX_REG_BD_NUM_SIZE); + if (ret) { + hns3_err(hw, "fail to get dfx bd num, ret = %d.\n", ret); + return ret; + } + + /* The first data in the first BD is a reserved field */ + for (i = 1; i <= list_size; i++) { + desc_index = i / HNS3_CMD_DESC_DATA_NUM; + index = i % HNS3_CMD_DESC_DATA_NUM; + bd_num = rte_le_to_cpu_32(desc[desc_index].data[index]); + bd_num_list[i - 1] = bd_num; + } + + return 0; +} + +static int +hns3_dfx_reg_cmd_send(struct hns3_hw *hw, struct hns3_cmd_desc *desc, + int bd_num, uint32_t opcode) +{ + int ret; + int i; + + for (i = 0; i < bd_num - 1; i++) { + hns3_cmd_setup_basic_desc(&desc[i], opcode, true); + desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT); + } + /* The last BD does not need a next flag */ + hns3_cmd_setup_basic_desc(&desc[i], opcode, true); + + ret = hns3_cmd_send(hw, desc, bd_num); + if (ret) { + hns3_err(hw, "fail to query dfx registers, opcode = 0x%04X, " + "ret = %d.\n", opcode, ret); + } + + return ret; +} + +static int +hns3_dfx_reg_fetch_data(struct hns3_cmd_desc *desc, int bd_num, uint32_t *reg) +{ + int desc_index; + int reg_num; + int index; + int i; + + reg_num = bd_num * HNS3_CMD_DESC_DATA_NUM; + for (i = 0; i < reg_num; i++) { + desc_index = i / HNS3_CMD_DESC_DATA_NUM; + index = i % HNS3_CMD_DESC_DATA_NUM; + *reg++ = desc[desc_index].data[index]; + } + reg_num += hns3_insert_reg_separator(reg_num, reg); + + return reg_num; +} + +static int +hns3_get_dfx_reg_line(struct hns3_hw *hw, uint32_t *lines) +{ + int opcode_num = RTE_DIM(hns3_dfx_reg_opcode_list); + uint32_t bd_num_list[opcode_num]; + uint32_t bd_num, data_len; + int ret; + int i; + + ret = hns3_get_dfx_reg_bd_num(hw, bd_num_list, opcode_num); + if (ret) + return ret; + + for (i = 0; i < opcode_num; i++) { + bd_num = bd_num_list[i]; + data_len = bd_num * HNS3_CMD_DESC_DATA_NUM * sizeof(uint32_t); + *lines += data_len / REG_LEN_PER_LINE + 1; + } + + return 0; +} + +static int +hns3_get_dfx_regs(struct hns3_hw *hw, void **data) +{ + int opcode_num = RTE_DIM(hns3_dfx_reg_opcode_list); + uint32_t max_bd_num, bd_num, opcode; + uint32_t bd_num_list[opcode_num]; + struct hns3_cmd_desc *cmd_descs; + uint32_t *reg_val = (uint32_t *)*data; + int ret; + int i; + + ret = hns3_get_dfx_reg_bd_num(hw, bd_num_list, opcode_num); + if (ret) + return ret; + + max_bd_num = 0; + for (i = 0; i < opcode_num; i++) + max_bd_num = RTE_MAX(bd_num_list[i], max_bd_num); + + cmd_descs = rte_zmalloc(NULL, sizeof(*cmd_descs) * max_bd_num, 0); + if (cmd_descs == NULL) + return -ENOMEM; + + for (i = 0; i < opcode_num; i++) { + opcode = hns3_dfx_reg_opcode_list[i]; + bd_num = bd_num_list[i]; + if (bd_num == 0) + continue; + ret = hns3_dfx_reg_cmd_send(hw, cmd_descs, bd_num, opcode); + if (ret) + break; + reg_val += hns3_dfx_reg_fetch_data(cmd_descs, bd_num, reg_val); + } + rte_free(cmd_descs); + *data = (void *)reg_val; + + return ret; +} + int hns3_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs) { @@ -371,5 +533,6 @@ hns3_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs) data += regs_num_64_bit * HNS3_64_BIT_REG_SIZE; data += hns3_insert_reg_separator(regs_num_64_bit * HNS3_64_BIT_REG_SIZE, data); - return ret; + + return hns3_get_dfx_regs(hw, (void **)&data); }
From: Chengwen Feng fengchengwen@huawei.com
This patch add support tx_done_cleanup ops, which could support for the API rte_eth_tx_done_cleanup to free consumed mbufs on Tx ring.
Signed-off-by: Chengwen Feng fengchengwen@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- doc/guides/nics/features/hns3.ini | 1 + doc/guides/nics/features/hns3_vf.ini | 1 + doc/guides/rel_notes/release_21_05.rst | 2 +- drivers/net/hns3/hns3_ethdev.c | 1 + drivers/net/hns3/hns3_ethdev_vf.c | 1 + drivers/net/hns3/hns3_rxtx.c | 59 ++++++++++++++++++++++++++++++++++ drivers/net/hns3/hns3_rxtx.h | 1 + 7 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/doc/guides/nics/features/hns3.ini b/doc/guides/nics/features/hns3.ini index ef432af..8e82d68 100644 --- a/doc/guides/nics/features/hns3.ini +++ b/doc/guides/nics/features/hns3.ini @@ -10,6 +10,7 @@ Queue start/stop = Y Runtime Rx queue setup = Y Runtime Tx queue setup = Y Burst mode info = Y +Free Tx mbuf on demand = Y MTU update = Y Jumbo frame = Y Scattered Rx = Y diff --git a/doc/guides/nics/features/hns3_vf.ini b/doc/guides/nics/features/hns3_vf.ini index 99a0bf0..c796cd5 100644 --- a/doc/guides/nics/features/hns3_vf.ini +++ b/doc/guides/nics/features/hns3_vf.ini @@ -10,6 +10,7 @@ Queue start/stop = Y Runtime Rx queue setup = Y Runtime Tx queue setup = Y Burst mode info = Y +Free Tx mbuf on demand = Y MTU update = Y Jumbo frame = Y Scattered Rx = Y diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst index eb0508b..13e3633 100644 --- a/doc/guides/rel_notes/release_21_05.rst +++ b/doc/guides/rel_notes/release_21_05.rst @@ -63,7 +63,7 @@ New Features * **Updated Hisilicon hns3 driver.**
* Added support for module EEPROM dumping. - + * Added support for freeing Tx mbuf on demand.
Removed Items ------------- diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index e02a7ec..91d720a 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -6388,6 +6388,7 @@ static const struct eth_dev_ops hns3_eth_dev_ops = { .fec_get = hns3_fec_get, .fec_set = hns3_fec_set, .tm_ops_get = hns3_tm_ops_get, + .tx_done_cleanup = hns3_tx_done_cleanup, };
static const struct hns3_reset_ops hns3_reset_ops = { diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index 3f9f328..1b8c029 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -2763,6 +2763,7 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = { .vlan_offload_set = hns3vf_vlan_offload_set, .get_reg = hns3_get_regs, .dev_supported_ptypes_get = hns3_dev_supported_ptypes_get, + .tx_done_cleanup = hns3_tx_done_cleanup, };
static const struct hns3_reset_ops hns3vf_reset_ops = { diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c index 222cf8a..5e79177 100644 --- a/drivers/net/hns3/hns3_rxtx.c +++ b/drivers/net/hns3/hns3_rxtx.c @@ -3913,6 +3913,65 @@ hns3_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) return 0; }
+static int +hns3_tx_done_cleanup_full(struct hns3_tx_queue *txq, uint32_t free_cnt) +{ + uint16_t next_to_clean = txq->next_to_clean; + uint16_t next_to_use = txq->next_to_use; + uint16_t tx_bd_ready = txq->tx_bd_ready; + struct hns3_entry *tx_pkt = &txq->sw_ring[next_to_clean]; + struct hns3_desc *desc = &txq->tx_ring[next_to_clean]; + uint32_t idx; + + if (free_cnt == 0 || free_cnt > txq->nb_tx_desc) + free_cnt = txq->nb_tx_desc; + + for (idx = 0; idx < free_cnt; idx++) { + if (next_to_clean == next_to_use) + break; + + if (desc->tx.tp_fe_sc_vld_ra_ri & + rte_cpu_to_le_16(BIT(HNS3_TXD_VLD_B))) + break; + + if (tx_pkt->mbuf != NULL) { + rte_pktmbuf_free_seg(tx_pkt->mbuf); + tx_pkt->mbuf = NULL; + } + + next_to_clean++; + tx_bd_ready++; + tx_pkt++; + desc++; + if (next_to_clean == txq->nb_tx_desc) { + tx_pkt = txq->sw_ring; + desc = txq->tx_ring; + next_to_clean = 0; + } + } + + if (idx > 0) { + txq->next_to_clean = next_to_clean; + txq->tx_bd_ready = tx_bd_ready; + } + + return (int)idx; +} + +int +hns3_tx_done_cleanup(void *txq, uint32_t free_cnt) +{ + struct hns3_tx_queue *q = (struct hns3_tx_queue *)txq; + struct rte_eth_dev *dev = &rte_eth_devices[q->port_id]; + + if (dev->tx_pkt_burst == hns3_xmit_pkts) + return hns3_tx_done_cleanup_full(q, free_cnt); + else if (dev->tx_pkt_burst == hns3_dummy_rxtx_burst) + return 0; + else + return -ENOTSUP; +} + uint32_t hns3_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) { diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h index 8f5ae5c..7118bd4 100644 --- a/drivers/net/hns3/hns3_rxtx.h +++ b/drivers/net/hns3/hns3_rxtx.h @@ -706,5 +706,6 @@ 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); void hns3_restore_tqp_enable_state(struct hns3_hw *hw); +int hns3_tx_done_cleanup(void *txq, uint32_t free_cnt);
#endif /* _HNS3_RXTX_H_ */
From: "Min Hu (Connor)" humin29@huawei.com
In current HNS3 PMD, Rx/Tx bytes from packet stats are not implemented.
This patch implemented Rx/Tx bytes using soft counters. Rx/Tx bytes stats will be enabled if the macro RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS is defined.
Signed-off-by: Min Hu (Connor) humin29@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_rxtx.c | 24 ++++++++++++++++++++++++ drivers/net/hns3/hns3_rxtx_vec_neon.h | 15 +++++++++++++++ drivers/net/hns3/hns3_rxtx_vec_sve.c | 11 +++++++++++ drivers/net/hns3/hns3_stats.c | 22 ++++++++++++++++++---- 4 files changed, 68 insertions(+), 4 deletions(-)
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c index 5e79177..a8bd2cc 100644 --- a/drivers/net/hns3/hns3_rxtx.c +++ b/drivers/net/hns3/hns3_rxtx.c @@ -2181,6 +2181,10 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) cksum_err); hns3_rxd_to_vlan_tci(rxq, rxm, l234_info, &rxd);
+#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + rxq->basic_stats.bytes += rxm->pkt_len; +#endif rx_pkts[nb_rx++] = rxm; continue; pkt_err: @@ -2401,6 +2405,10 @@ hns3_recv_scattered_pkts(void *rx_queue, cksum_err); hns3_rxd_to_vlan_tci(rxq, first_seg, l234_info, &rxd);
+#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + rxq->basic_stats.bytes += first_seg->pkt_len; +#endif rx_pkts[nb_rx++] = first_seg; first_seg = NULL; continue; @@ -3516,6 +3524,13 @@ hns3_tx_fill_hw_ring(struct hns3_tx_queue *txq, for (i = 0; i < mainpart; i += PER_LOOP_NUM) { hns3_tx_backup_4mbuf(tx_entry + i, pkts + i); hns3_tx_setup_4bd(txdp + i, pkts + i); + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + uint32_t j; + for (j = 0; j < PER_LOOP_NUM; j++) + txq->basic_stats.bytes += pkts[i + j]->pkt_len; +#endif } if (unlikely(leftover > 0)) { for (i = 0; i < leftover; i++) { @@ -3523,6 +3538,11 @@ hns3_tx_fill_hw_ring(struct hns3_tx_queue *txq, pkts + mainpart + i); hns3_tx_setup_1bd(txdp + mainpart + i, pkts + mainpart + i); + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + txq->basic_stats.bytes += pkts[mainpart + i]->pkt_len; +#endif } } } @@ -3661,6 +3681,10 @@ hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) desc->tx.tp_fe_sc_vld_ra_ri |= rte_cpu_to_le_16(BIT(HNS3_TXD_FE_B));
+#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + txq->basic_stats.bytes += tx_pkt->pkt_len; +#endif nb_hold += i; txq->next_to_use = tx_next_use; txq->tx_bd_ready -= i; diff --git a/drivers/net/hns3/hns3_rxtx_vec_neon.h b/drivers/net/hns3/hns3_rxtx_vec_neon.h index a693b4b..54d358d 100644 --- a/drivers/net/hns3/hns3_rxtx_vec_neon.h +++ b/drivers/net/hns3/hns3_rxtx_vec_neon.h @@ -61,6 +61,11 @@ hns3_xmit_fixed_burst_vec(void *__restrict tx_queue, for (i = 0; i < n; i++, tx_pkts++, tx_desc++) { hns3_vec_tx(tx_desc, *tx_pkts); tx_entry[i].mbuf = *tx_pkts; + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + txq->basic_stats.bytes += (*tx_pkts)->pkt_len; +#endif }
nb_commit -= n; @@ -72,6 +77,11 @@ hns3_xmit_fixed_burst_vec(void *__restrict tx_queue, for (i = 0; i < nb_commit; i++, tx_pkts++, tx_desc++) { hns3_vec_tx(tx_desc, *tx_pkts); tx_entry[i].mbuf = *tx_pkts; + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + txq->basic_stats.bytes += (*tx_pkts)->pkt_len; +#endif }
next_to_use += nb_commit; @@ -116,6 +126,11 @@ hns3_desc_parse_field(struct hns3_rx_queue *rxq, if (likely(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) hns3_rx_set_cksum_flag(pkt, pkt->packet_type, cksum_err); + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + rxq->basic_stats.bytes += pkt->pkt_len; +#endif }
return retcode; diff --git a/drivers/net/hns3/hns3_rxtx_vec_sve.c b/drivers/net/hns3/hns3_rxtx_vec_sve.c index b02bae7..8b9172a 100644 --- a/drivers/net/hns3/hns3_rxtx_vec_sve.c +++ b/drivers/net/hns3/hns3_rxtx_vec_sve.c @@ -58,6 +58,11 @@ hns3_desc_parse_field_sve(struct hns3_rx_queue *rxq, if (likely(key->bd_base_info[i] & BIT(HNS3_RXD_L3L4P_B))) hns3_rx_set_cksum_flag(rx_pkts[i], rx_pkts[i]->packet_type, cksum_err); + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + rxq->basic_stats.bytes += rx_pkts[i]->pkt_len; +#endif }
return retcode; @@ -408,6 +413,12 @@ hns3_tx_fill_hw_ring_sve(struct hns3_tx_queue *txq, svst1_scatter_u64offset_u64(pg, (uint64_t *)&txdp->tx.paylen, offsets, svdup_n_u64(valid_bit));
+#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Increment bytes counter */ + uint32_t idx; + for (idx = 0; idx < svcntd(); idx++) + txq->basic_stats.bytes += pkts[idx]->pkt_len; +#endif /* update index for next loop */ i += svcntd(); pkts += svcntd(); diff --git a/drivers/net/hns3/hns3_stats.c b/drivers/net/hns3/hns3_stats.c index e0e40ca..7796585 100644 --- a/drivers/net/hns3/hns3_stats.c +++ b/drivers/net/hns3/hns3_stats.c @@ -358,6 +358,7 @@ static const struct hns3_xstats_name_offset hns3_tx_queue_strings[] = { HNS3_NUM_RESET_XSTATS)
static void hns3_tqp_stats_clear(struct hns3_hw *hw); +static void hns3_tqp_basic_stats_clear(struct rte_eth_dev *dev);
/* * Query all the MAC statistics data of Network ICL command ,opcode id: 0x0034. @@ -543,16 +544,30 @@ hns3_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats) return ret; }
- /* Get the error stats of received packets */ + /* Get the error stats and bytes of received packets */ for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { rxq = eth_dev->data->rx_queues[i]; if (rxq) { cnt = rxq->err_stats.l2_errors + rxq->err_stats.pkt_len_errors; rte_stats->ierrors += cnt; + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + rte_stats->ibytes += rxq->basic_stats.bytes; +#endif } }
+#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + /* Get the bytes of received packets */ + struct hns3_tx_queue *txq; + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { + txq = eth_dev->data->tx_queues[i]; + if (txq) + rte_stats->obytes += txq->basic_stats.bytes; + } +#endif + rte_stats->oerrors = 0; /* * If HW statistics are reset by stats_reset, but a lot of residual @@ -623,6 +638,7 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev) * their source. */ hns3_tqp_stats_clear(hw); + hns3_tqp_basic_stats_clear(eth_dev);
return 0; } @@ -807,7 +823,6 @@ hns3_rxq_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, rxq_stats->packets = stats->rcb_rx_ring_pktnum[i] > rxq_stats->errors ? stats->rcb_rx_ring_pktnum[i] - rxq_stats->errors : 0; - rxq_stats->bytes = 0; for (j = 0; j < HNS3_NUM_RXQ_BASIC_STATS; j++) { val = (char *)rxq_stats + hns3_rxq_basic_stats_strings[j].offset; @@ -836,7 +851,7 @@ hns3_txq_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
txq_stats = &txq->basic_stats; txq_stats->packets = stats->rcb_tx_ring_pktnum[i]; - txq_stats->bytes = 0; + for (j = 0; j < HNS3_NUM_TXQ_BASIC_STATS; j++) { val = (char *)txq_stats + hns3_txq_basic_stats_strings[j].offset; @@ -1328,7 +1343,6 @@ hns3_dev_xstats_reset(struct rte_eth_dev *dev) if (ret) return ret;
- hns3_tqp_basic_stats_clear(dev); hns3_tqp_dfx_stats_clear(dev);
/* Clear reset stats */
From: "Min Hu (Connor)" humin29@huawei.com
This patch implement Rx imissed stats by querying cmdq.
Signed-off-by: Min Hu (Connor) humin29@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_cmd.h | 7 +++ drivers/net/hns3/hns3_ethdev.c | 7 +++ drivers/net/hns3/hns3_ethdev.h | 1 + drivers/net/hns3/hns3_stats.c | 106 ++++++++++++++++++++++++++++++++++++++++- drivers/net/hns3/hns3_stats.h | 8 ++++ 5 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index 6a58166..e329089 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -905,6 +905,13 @@ struct hns3_dev_specs_0_cmd { uint32_t max_tm_rate; };
+struct hns3_query_rpu_cmd { + uint32_t tc_queue_num; + uint32_t rsv1[2]; + uint32_t rpu_rx_pkt_drop_cnt; + uint32_t rsv2[2]; +}; + #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 */ diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 91d720a..34cd038 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -4742,6 +4742,13 @@ hns3_init_pf(struct rte_eth_dev *eth_dev) goto err_cmd_init; }
+ /* Hardware statistics of imissed registers cleared. */ + ret = hns3_update_imissed_stats(hw, true); + if (ret) { + hns3_err(hw, "clear imissed stats failed, ret = %d", ret); + return ret; + } + hns3_config_all_msix_error(hw, true);
ret = rte_intr_callback_register(&pci_dev->intr_handle, diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index 3a592c0..5299dd8 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -434,6 +434,7 @@ struct hns3_hw { struct hns3_tqp_stats tqp_stats; /* Include Mac stats | Rx stats | Tx stats */ struct hns3_mac_stats mac_stats; + struct hns3_rx_missed_stats imissed_stats; uint32_t fw_version;
uint16_t num_msi; diff --git a/drivers/net/hns3/hns3_stats.c b/drivers/net/hns3/hns3_stats.c index 7796585..365a3eb 100644 --- a/drivers/net/hns3/hns3_stats.c +++ b/drivers/net/hns3/hns3_stats.c @@ -324,6 +324,12 @@ static const struct hns3_xstats_name_offset hns3_tx_queue_strings[] = { {"TX_QUEUE_FBD", HNS3_RING_TX_FBDNUM_REG} };
+/* The statistic of imissed packet */ +static const struct hns3_xstats_name_offset hns3_imissed_stats_strings[] = { + {"RPU_DROP_CNT", + HNS3_IMISSED_STATS_FIELD_OFFSET(rpu_rx_drop_cnt)}, +}; + #define HNS3_NUM_MAC_STATS (sizeof(hns3_mac_strings) / \ sizeof(hns3_mac_strings[0]))
@@ -354,8 +360,11 @@ static const struct hns3_xstats_name_offset hns3_tx_queue_strings[] = { #define HNS3_NUM_TXQ_BASIC_STATS (sizeof(hns3_txq_basic_stats_strings) / \ sizeof(hns3_txq_basic_stats_strings[0]))
+#define HNS3_NUM_IMISSED_XSTATS (sizeof(hns3_imissed_stats_strings) / \ + sizeof(hns3_imissed_stats_strings[0])) + #define HNS3_FIX_NUM_STATS (HNS3_NUM_MAC_STATS + HNS3_NUM_ERROR_INT_XSTATS + \ - HNS3_NUM_RESET_XSTATS) + HNS3_NUM_RESET_XSTATS + HNS3_NUM_IMISSED_XSTATS)
static void hns3_tqp_stats_clear(struct hns3_hw *hw); static void hns3_tqp_basic_stats_clear(struct rte_eth_dev *dev); @@ -515,6 +524,52 @@ hns3_update_tqp_stats(struct hns3_hw *hw) return 0; }
+static int +hns3_update_rpu_drop_stats(struct hns3_hw *hw) +{ + struct hns3_rx_missed_stats *stats = &hw->imissed_stats; + struct hns3_query_rpu_cmd *req; + struct hns3_cmd_desc desc; + uint64_t cnt; + uint32_t tc_num; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_DFX_RPU_REG_0, true); + req = (struct hns3_query_rpu_cmd *)desc.data; + + /* + * tc_num is 0, means rpu stats of all TC channels will be + * get from firmware + */ + tc_num = 0; + req->tc_queue_num = rte_cpu_to_le_32(tc_num); + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) { + hns3_err(hw, "failed to query RPU stats: %d", ret); + return ret; + } + + cnt = rte_le_to_cpu_32(req->rpu_rx_pkt_drop_cnt); + stats->rpu_rx_drop_cnt += cnt; + + return 0; +} + +int +hns3_update_imissed_stats(struct hns3_hw *hw, bool is_clear) +{ + int ret; + + ret = hns3_update_rpu_drop_stats(hw); + if (ret) + return ret; + + if (is_clear) + memset(&hw->imissed_stats, 0, sizeof(hw->imissed_stats)); + + return 0; +} + /* * Query tqp tx queue statistics ,opcode id: 0x0B03. * Query tqp rx queue statistics ,opcode id: 0x0B13. @@ -531,6 +586,7 @@ hns3_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats) { struct hns3_adapter *hns = eth_dev->data->dev_private; struct hns3_hw *hw = &hns->hw; + struct hns3_rx_missed_stats *imissed_stats = &hw->imissed_stats; struct hns3_tqp_stats *stats = &hw->tqp_stats; struct hns3_rx_queue *rxq; uint64_t cnt; @@ -544,6 +600,18 @@ hns3_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats) return ret; }
+ if (!hns->is_vf) { + /* Update imissed stats */ + ret = hns3_update_imissed_stats(hw, false); + if (ret) { + hns3_err(hw, "update imissed stats failed, ret = %d", + ret); + return ret; + } + + rte_stats->imissed = imissed_stats->rpu_rx_drop_cnt; + } + /* Get the error stats and bytes of received packets */ for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { rxq = eth_dev->data->rx_queues[i]; @@ -620,6 +688,19 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev) } }
+ if (!hns->is_vf) { + /* + * Note: Reading hardware statistics of imissed registers will + * clear them. + */ + ret = hns3_update_imissed_stats(hw, true); + if (ret) { + hns3_err(hw, "clear imissed stats failed, ret = %d", + ret); + return ret; + } + } + /* * Clear soft stats of rx error packet which will be dropped * in driver. @@ -932,6 +1013,7 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, struct hns3_adapter *hns = dev->data->dev_private; struct hns3_pf *pf = &hns->pf; struct hns3_hw *hw = &hns->hw; + struct hns3_rx_missed_stats *imissed_stats = &hw->imissed_stats; struct hns3_mac_stats *mac_stats = &hw->mac_stats; struct hns3_reset_stats *reset_stats = &hw->reset.stats; struct hns3_rx_bd_errors_stats *rx_err_stats; @@ -970,6 +1052,21 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, count++; }
+ ret = hns3_update_imissed_stats(hw, false); + if (ret) { + hns3_err(hw, "update imissed stats failed, ret = %d", + ret); + return ret; + } + + for (i = 0; i < HNS3_NUM_IMISSED_XSTATS; i++) { + addr = (char *)imissed_stats + + hns3_imissed_stats_strings[i].offset; + xstats[count].value = *(uint64_t *)addr; + xstats[count].id = count; + count++; + } + for (i = 0; i < HNS3_NUM_ERROR_INT_XSTATS; i++) { addr = (char *)&pf->abn_int_stats + hns3_error_int_stats_strings[i].offset; @@ -1112,6 +1209,13 @@ hns3_dev_xstats_get_names(struct rte_eth_dev *dev, count++; }
+ for (i = 0; i < HNS3_NUM_IMISSED_XSTATS; i++) { + snprintf(xstats_names[count].name, + sizeof(xstats_names[count].name), + "%s", hns3_imissed_stats_strings[i].name); + count++; + } + for (i = 0; i < HNS3_NUM_ERROR_INT_XSTATS; i++) { snprintf(xstats_names[count].name, sizeof(xstats_names[count].name), diff --git a/drivers/net/hns3/hns3_stats.h b/drivers/net/hns3/hns3_stats.h index d213be5..01b4f36 100644 --- a/drivers/net/hns3/hns3_stats.h +++ b/drivers/net/hns3/hns3_stats.h @@ -110,6 +110,10 @@ struct hns3_mac_stats { uint64_t mac_rx_ctrl_pkt_num; };
+struct hns3_rx_missed_stats { + uint64_t rpu_rx_drop_cnt; +}; + /* store statistics names and its offset in stats structure */ struct hns3_xstats_name_offset { char name[RTE_ETH_XSTATS_NAME_SIZE]; @@ -141,6 +145,9 @@ struct hns3_reset_stats; #define HNS3_TXQ_BASIC_STATS_FIELD_OFFSET(f) \ (offsetof(struct hns3_tx_basic_stats, f))
+#define HNS3_IMISSED_STATS_FIELD_OFFSET(f) \ + (offsetof(struct hns3_rx_missed_stats, f)) + int hns3_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); int hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned int n); @@ -160,5 +167,6 @@ 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); +int hns3_update_imissed_stats(struct hns3_hw *hw, bool is_clear);
#endif /* _HNS3_STATS_H_ */
From: Huisong Li lihuisong@huawei.com
When rate of port changes, the rate limit of the port needs to be updated. So it is necessary to encapsulate an interface that configures the rate limit based on the rate.
Signed-off-by: Huisong Li lihuisong@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_dcb.c | 22 +++++++++++++++++----- drivers/net/hns3/hns3_dcb.h | 2 +- drivers/net/hns3/hns3_ethdev.c | 10 +++------- 3 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/drivers/net/hns3/hns3_dcb.c b/drivers/net/hns3/hns3_dcb.c index 7fc6ac9..ebfc240 100644 --- a/drivers/net/hns3/hns3_dcb.c +++ b/drivers/net/hns3/hns3_dcb.c @@ -330,8 +330,8 @@ hns3_dcb_get_shapping_para(uint8_t ir_b, uint8_t ir_u, uint8_t ir_s, return shapping_para; }
-int -hns3_dcb_port_shaper_cfg(struct hns3_hw *hw) +static int +hns3_dcb_port_shaper_cfg(struct hns3_hw *hw, uint32_t speed) { struct hns3_port_shapping_cmd *shap_cfg_cmd; struct hns3_shaper_parameter shaper_parameter; @@ -340,7 +340,7 @@ hns3_dcb_port_shaper_cfg(struct hns3_hw *hw) struct hns3_cmd_desc desc; int ret;
- ret = hns3_shaper_para_calc(hw, hw->mac.link_speed, + ret = hns3_shaper_para_calc(hw, speed, HNS3_SHAPER_LVL_PORT, &shaper_parameter); if (ret) { hns3_err(hw, "calculate shaper parameter failed: %d", ret); @@ -366,12 +366,24 @@ hns3_dcb_port_shaper_cfg(struct hns3_hw *hw) * 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); + shap_cfg_cmd->port_rate = rte_cpu_to_le_32(speed); hns3_set_bit(shap_cfg_cmd->flag, HNS3_TM_RATE_VLD_B, 1);
return hns3_cmd_send(hw, &desc, 1); }
+int +hns3_port_shaper_update(struct hns3_hw *hw, uint32_t speed) +{ + int ret; + + ret = hns3_dcb_port_shaper_cfg(hw, speed); + if (ret) + hns3_err(hw, "configure port shappering failed: ret = %d", ret); + + return ret; +} + static int hns3_dcb_pg_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket, uint8_t pg_id, uint32_t shapping_para, uint32_t rate) @@ -961,7 +973,7 @@ hns3_dcb_shaper_cfg(struct hns3_hw *hw) { int ret;
- ret = hns3_dcb_port_shaper_cfg(hw); + ret = hns3_dcb_port_shaper_cfg(hw, hw->mac.link_speed); if (ret) { hns3_err(hw, "config port shaper failed: %d", ret); return ret; diff --git a/drivers/net/hns3/hns3_dcb.h b/drivers/net/hns3/hns3_dcb.h index 8248434..0d25d3b 100644 --- a/drivers/net/hns3/hns3_dcb.h +++ b/drivers/net/hns3/hns3_dcb.h @@ -208,7 +208,7 @@ 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); -int hns3_dcb_port_shaper_cfg(struct hns3_hw *hw); +int hns3_port_shaper_update(struct hns3_hw *hw, uint32_t speed); int hns3_pg_shaper_rate_cfg(struct hns3_hw *hw, uint8_t pg_id, uint32_t rate); int hns3_pri_shaper_rate_cfg(struct hns3_hw *hw, uint8_t tc_no, uint32_t rate); uint8_t hns3_txq_mapped_tc_get(struct hns3_hw *hw, uint16_t txq_no); diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 34cd038..4320695 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -4384,7 +4384,6 @@ static int hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t duplex) { struct hns3_mac *mac = &hw->mac; - uint32_t cur_speed = mac->link_speed; int ret;
duplex = hns3_check_speed_dup(duplex, speed); @@ -4395,14 +4394,11 @@ hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t duplex) if (ret) return ret;
- mac->link_speed = speed; - ret = hns3_dcb_port_shaper_cfg(hw); - if (ret) { - hns3_err(hw, "failed to configure port shaper, ret = %d.", ret); - mac->link_speed = cur_speed; + ret = hns3_port_shaper_update(hw, speed); + if (ret) return ret; - }
+ mac->link_speed = speed; mac->link_duplex = duplex;
return 0;
From: Huisong Li lihuisong@huawei.com
The normal operation of electrical interface devices depends on the initialization and configuration of the PHY chip. The task of driving the PHY chip is implemented in some firmware versions. If firmware supports the phy driver, it will report a capability flag to driver in probing process. The driver determines whether to support electrical device based on the capability bit. If supported, the driver set a flag indicating that the firmware takes over the PHY, and then the firmware intializes the PHY.
This patch supports the query of link status and link info, and existing basic features for electrical device.
Signed-off-by: Huisong Li lihuisong@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- doc/guides/rel_notes/release_21_05.rst | 1 + drivers/net/hns3/hns3_cmd.h | 37 +++++++++++ drivers/net/hns3/hns3_ethdev.c | 115 +++++++++++++++++++++++++++++++-- drivers/net/hns3/hns3_ethdev.h | 5 ++ 4 files changed, 152 insertions(+), 6 deletions(-)
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst index 13e3633..07a61aa 100644 --- a/doc/guides/rel_notes/release_21_05.rst +++ b/doc/guides/rel_notes/release_21_05.rst @@ -64,6 +64,7 @@ New Features
* Added support for module EEPROM dumping. * Added support for freeing Tx mbuf on demand. + * Added support for electrical port in Kunpeng930.
Removed Items ------------- diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index e329089..c0cd72d 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -222,6 +222,8 @@ enum hns3_opcode_type {
/* Firmware stats command */ HNS3_OPC_FIRMWARE_COMPAT_CFG = 0x701A, + /* Firmware control phy command */ + HNS3_OPC_PHY_PARAM_CFG = 0x7025,
/* SFP command */ HNS3_OPC_GET_SFP_EEPROM = 0x7100, @@ -659,11 +661,46 @@ enum hns3_promisc_type {
#define HNS3_LINK_EVENT_REPORT_EN_B 0 #define HNS3_NCSI_ERROR_REPORT_EN_B 1 +#define HNS3_FIRMWARE_PHY_DRIVER_EN_B 2 struct hns3_firmware_compat_cmd { uint32_t compat; uint8_t rsv[20]; };
+/* Bitmap flags in supported, advertising and lp_advertising */ +#define HNS3_PHY_LINK_SPEED_10M_HD_BIT BIT(0) +#define HNS3_PHY_LINK_SPEED_10M_BIT BIT(1) +#define HNS3_PHY_LINK_SPEED_100M_HD_BIT BIT(2) +#define HNS3_PHY_LINK_SPEED_100M_BIT BIT(3) +#define HNS3_PHY_LINK_MODE_AUTONEG_BIT BIT(6) +#define HNS3_PHY_LINK_MODE_PAUSE_BIT BIT(13) +#define HNS3_PHY_LINK_MODE_ASYM_PAUSE_BIT BIT(14) + +#define HNS3_PHY_PARAM_CFG_BD_NUM 2 +struct hns3_phy_params_bd0_cmd { + uint32_t speed; +#define HNS3_PHY_DUPLEX_CFG_B 0 + uint8_t duplex; +#define HNS3_PHY_AUTONEG_CFG_B 0 + uint8_t autoneg; + uint8_t eth_tp_mdix; + uint8_t eth_tp_mdix_ctrl; + uint8_t port; + uint8_t transceiver; + uint8_t phy_address; + uint8_t rsv; + uint32_t supported; + uint32_t advertising; + uint32_t lp_advertising; +}; + +struct hns3_phy_params_bd1_cmd { + uint8_t master_slave_cfg; + uint8_t master_slave_state; + uint8_t rsv1[2]; + uint32_t rsv2[5]; +}; + #define HNS3_MAC_TX_EN_B 6 #define HNS3_MAC_RX_EN_B 7 #define HNS3_MAC_PAD_TX_B 11 diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 4320695..a97dee4 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -3090,6 +3090,37 @@ hns3_get_capability(struct hns3_hw *hw) }
static int +hns3_check_media_type(struct hns3_hw *hw, uint8_t media_type) +{ + int ret; + + switch (media_type) { + case HNS3_MEDIA_TYPE_COPPER: + if (!hns3_dev_copper_supported(hw)) { + PMD_INIT_LOG(ERR, + "Media type is copper, not supported."); + ret = -EOPNOTSUPP; + } else { + ret = 0; + } + break; + case HNS3_MEDIA_TYPE_FIBER: + ret = 0; + break; + case HNS3_MEDIA_TYPE_BACKPLANE: + PMD_INIT_LOG(ERR, "Media type is Backplane, not supported."); + ret = -EOPNOTSUPP; + break; + default: + PMD_INIT_LOG(ERR, "Unknown media type = %u!", media_type); + ret = -EINVAL; + break; + } + + return ret; +} + +static int hns3_get_board_configuration(struct hns3_hw *hw) { struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); @@ -3103,11 +3134,9 @@ hns3_get_board_configuration(struct hns3_hw *hw) return ret; }
- if (cfg.media_type == HNS3_MEDIA_TYPE_COPPER && - !hns3_dev_copper_supported(hw)) { - PMD_INIT_LOG(ERR, "media type is copper, not supported."); - return -EOPNOTSUPP; - } + ret = hns3_check_media_type(hw, cfg.media_type); + if (ret) + return ret;
hw->mac.media_type = cfg.media_type; hw->rss_size_max = cfg.rss_size_max; @@ -3952,6 +3981,8 @@ hns3_firmware_compat_config(struct hns3_hw *hw, bool is_init) if (is_init) { hns3_set_bit(compat, HNS3_LINK_EVENT_REPORT_EN_B, 1); hns3_set_bit(compat, HNS3_NCSI_ERROR_REPORT_EN_B, 0); + if (hw->mac.media_type == HNS3_MEDIA_TYPE_COPPER) + hns3_set_bit(compat, HNS3_FIRMWARE_PHY_DRIVER_EN_B, 1); }
req->compat = rte_cpu_to_le_32(compat); @@ -4429,6 +4460,78 @@ hns3_update_fiber_link_info(struct hns3_hw *hw) return hns3_cfg_mac_speed_dup(hw, speed, ETH_LINK_FULL_DUPLEX); }
+static void +hns3_parse_phy_params(struct hns3_cmd_desc *desc, struct hns3_mac *mac) +{ + struct hns3_phy_params_bd0_cmd *req; + + req = (struct hns3_phy_params_bd0_cmd *)desc[0].data; + mac->link_speed = rte_le_to_cpu_32(req->speed); + mac->link_duplex = hns3_get_bit(req->duplex, + HNS3_PHY_DUPLEX_CFG_B); + mac->link_autoneg = hns3_get_bit(req->autoneg, + HNS3_PHY_AUTONEG_CFG_B); + mac->supported_capa = rte_le_to_cpu_32(req->supported); + mac->advertising = rte_le_to_cpu_32(req->advertising); + mac->lp_advertising = rte_le_to_cpu_32(req->lp_advertising); + mac->support_autoneg = !!(mac->supported_capa & + HNS3_PHY_LINK_MODE_AUTONEG_BIT); +} + +static int +hns3_get_phy_params(struct hns3_hw *hw, struct hns3_mac *mac) +{ + struct hns3_cmd_desc desc[HNS3_PHY_PARAM_CFG_BD_NUM]; + uint16_t i; + int ret; + + for (i = 0; i < HNS3_PHY_PARAM_CFG_BD_NUM - 1; i++) { + hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_PHY_PARAM_CFG, + true); + desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT); + } + hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_PHY_PARAM_CFG, true); + + ret = hns3_cmd_send(hw, desc, HNS3_PHY_PARAM_CFG_BD_NUM); + if (ret) { + hns3_err(hw, "get phy parameters failed, ret = %d.", ret); + return ret; + } + + hns3_parse_phy_params(desc, mac); + + return 0; +} + +static int +hns3_update_phy_link_info(struct hns3_hw *hw) +{ + struct hns3_mac *mac = &hw->mac; + struct hns3_mac mac_info; + int ret; + + memset(&mac_info, 0, sizeof(struct hns3_mac)); + ret = hns3_get_phy_params(hw, &mac_info); + if (ret) + return ret; + + if (mac_info.link_speed != mac->link_speed) { + ret = hns3_port_shaper_update(hw, mac_info.link_speed); + if (ret) + return ret; + } + + mac->link_speed = mac_info.link_speed; + mac->link_duplex = mac_info.link_duplex; + mac->link_autoneg = mac_info.link_autoneg; + mac->supported_capa = mac_info.supported_capa; + mac->advertising = mac_info.advertising; + mac->lp_advertising = mac_info.lp_advertising; + mac->support_autoneg = mac_info.support_autoneg; + + return 0; +} + static int hns3_update_link_info(struct rte_eth_dev *eth_dev) { @@ -4437,7 +4540,7 @@ hns3_update_link_info(struct rte_eth_dev *eth_dev) int ret = 0;
if (hw->mac.media_type == HNS3_MEDIA_TYPE_COPPER) - return 0; + ret = hns3_update_phy_link_info(hw); else if (hw->mac.media_type == HNS3_MEDIA_TYPE_FIBER) ret = hns3_update_fiber_link_info(hw);
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index 5299dd8..c495802 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -180,6 +180,11 @@ struct hns3_mac { uint8_t link_autoneg : 1; /* ETH_LINK_[AUTONEG/FIXED] */ uint8_t link_status : 1; /* ETH_LINK_[DOWN/UP] */ uint32_t link_speed; /* ETH_SPEED_NUM_ */ + uint32_t supported_capa; /* supported capability for current media */ + uint32_t advertising; /* advertised capability in the local part */ + /* advertised capability in the link partner */ + uint32_t lp_advertising; + uint8_t support_autoneg; };
struct hns3_fake_queue_data {
From: Chengwen Feng fengchengwen@huawei.com
Currently, the driver get packet type by parse the L3_ID/L4_ID/OL3_ID/OL4_ID from Rx descriptor and then lookup multiple tables, it's time consuming.
Now Kunpeng930 support advanced RXD layout, which: 1. Combine OL3_ID/OL4_ID to 8bit PTYPE filed, so the driver get packet type by lookup only one table. Note: L3_ID/L4_ID become reserved fileds. 2. The 1588 timestamp located at Rx descriptor instead of query from firmware. 3. The L3E/L4E/OL3E/OL4E will be zero when L3L4P is zero, so driver could optimize the good checksum calculations (when L3E/L4E is zero then mark PKT_RX_IP_CKSUM_GOOD/PKT_RX_L4_CKSUM_GOOD).
Considering compatibility, the firmware will report capability of RXD advanced layout, the driver will identify and enable it by default.
This patch only provides basic function: identify and enable the RXD advanced layout, and lookup ptype table if supported.
Signed-off-by: Chengwen Feng fengchengwen@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_cmd.c | 8 +- drivers/net/hns3/hns3_cmd.h | 5 + drivers/net/hns3/hns3_ethdev.c | 2 + drivers/net/hns3/hns3_ethdev.h | 16 +++ drivers/net/hns3/hns3_ethdev_vf.c | 2 + drivers/net/hns3/hns3_regs.h | 1 + drivers/net/hns3/hns3_rxtx.c | 200 ++++++++++++++++++++++++++++++++++++++ drivers/net/hns3/hns3_rxtx.h | 11 +++ 8 files changed, 243 insertions(+), 2 deletions(-)
diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c index 32cd56b..8b9f075 100644 --- a/drivers/net/hns3/hns3_cmd.c +++ b/drivers/net/hns3/hns3_cmd.c @@ -409,8 +409,9 @@ hns3_cmd_send(struct hns3_hw *hw, struct hns3_cmd_desc *desc, int num) return retval; }
-static void hns3_parse_capability(struct hns3_hw *hw, - struct hns3_query_version_cmd *cmd) +static void +hns3_parse_capability(struct hns3_hw *hw, + struct hns3_query_version_cmd *cmd) { uint32_t caps = rte_le_to_cpu_32(cmd->caps[0]);
@@ -429,6 +430,9 @@ static void hns3_parse_capability(struct hns3_hw *hw, 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); + if (hns3_get_bit(caps, HNS3_CAPS_RXD_ADV_LAYOUT_B)) + hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, + 1); }
static uint32_t diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index c0cd72d..9808112 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -312,6 +312,11 @@ enum HNS3_CAPS_BITS { HNS3_CAPS_TQP_TXRX_INDEP_B, HNS3_CAPS_HW_PAD_B, HNS3_CAPS_STASH_B, + HNS3_CAPS_UDP_TUNNEL_CSUM_B, + HNS3_CAPS_RAS_IMP_B, + HNS3_CAPS_FEC_B, + HNS3_CAPS_PAUSE_B, + HNS3_CAPS_RXD_ADV_LAYOUT_B, };
enum HNS3_API_CAP_BITS { diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index a97dee4..b3fd331 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -4970,6 +4970,8 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue) return ret; }
+ hns3_enable_rxd_adv_layout(hw); + ret = hns3_init_queues(hns, reset_queue); if (ret) { PMD_INIT_LOG(ERR, "failed to init queues, ret = %d.", ret); diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index c495802..932600d 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -667,8 +667,13 @@ struct hns3_mp_param { #define HNS3_OL2TBL_NUM 4 #define HNS3_OL3TBL_NUM 16 #define HNS3_OL4TBL_NUM 16 +#define HNS3_PTYPE_NUM 256
struct hns3_ptype_table { + /* + * The next fields used to calc packet-type by the + * L3_ID/L4_ID/OL3_ID/OL4_ID from the Rx descriptor. + */ uint32_t l2l3table[HNS3_L2TBL_NUM][HNS3_L3TBL_NUM]; uint32_t l4table[HNS3_L4TBL_NUM]; uint32_t inner_l2table[HNS3_L2TBL_NUM]; @@ -677,6 +682,13 @@ struct hns3_ptype_table { uint32_t ol2table[HNS3_OL2TBL_NUM]; uint32_t ol3table[HNS3_OL3TBL_NUM]; uint32_t ol4table[HNS3_OL4TBL_NUM]; + + /* + * The next field used to calc packet-type by the PTYPE from the Rx + * descriptor, it functions only when firmware report the capability of + * HNS3_CAPS_RXD_ADV_LAYOUT_B and driver enabled it. + */ + uint32_t ptype[HNS3_PTYPE_NUM] __rte_cache_min_aligned; };
#define HNS3_FIXED_MAX_TQP_NUM_MODE 0 @@ -771,6 +783,7 @@ struct hns3_adapter { #define HNS3_DEV_SUPPORT_TX_PUSH_B 0x5 #define HNS3_DEV_SUPPORT_INDEP_TXRX_B 0x6 #define HNS3_DEV_SUPPORT_STASH_B 0x7 +#define HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B 0x9
#define hns3_dev_dcb_supported(hw) \ hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_DCB_B) @@ -801,6 +814,9 @@ struct hns3_adapter { #define hns3_dev_stash_supported(hw) \ hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_STASH_B)
+#define hns3_dev_rxd_adv_layout_supported(hw) \ + hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B) + #define HNS3_DEV_PRIVATE_TO_HW(adapter) \ (&((struct hns3_adapter *)adapter)->hw) #define HNS3_DEV_PRIVATE_TO_PF(adapter) \ diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index 1b8c029..e7f6974 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -2125,6 +2125,8 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue) if (ret) return ret;
+ hns3_enable_rxd_adv_layout(hw); + ret = hns3_init_queues(hns, reset_queue); if (ret) hns3_err(hw, "failed to init queues, ret = %d.", ret); diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h index 39fc5d1..0540554 100644 --- a/drivers/net/hns3/hns3_regs.h +++ b/drivers/net/hns3/hns3_regs.h @@ -36,6 +36,7 @@ #define HNS3_GLOBAL_RESET_REG 0x20A00 #define HNS3_FUN_RST_ING 0x20C00 #define HNS3_GRO_EN_REG 0x28000 +#define HNS3_RXD_ADV_LAYOUT_EN_REG 0x28008
/* Vector0 register bits for reset */ #define HNS3_VECTOR0_FUNCRESET_INT_B 0 diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c index a8bd2cc..e65a419 100644 --- a/drivers/net/hns3/hns3_rxtx.c +++ b/drivers/net/hns3/hns3_rxtx.c @@ -1802,6 +1802,7 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc, HNS3_PORT_BASE_VLAN_ENABLE; else rxq->pvid_sw_discard_en = false; + rxq->ptype_en = hns3_dev_rxd_adv_layout_supported(hw) ? true : false; rxq->configured = true; rxq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET + idx * HNS3_TQP_REG_SIZE); @@ -1987,6 +1988,193 @@ hns3_init_tunnel_ptype_tbl(struct hns3_ptype_table *tbl) tbl->ol4table[2] = RTE_PTYPE_TUNNEL_NVGRE; }
+static void +hns3_init_adv_layout_ptype(struct hns3_ptype_table *tbl) +{ + uint32_t *ptype = tbl->ptype; + + /* Non-tunnel L2 */ + ptype[1] = RTE_PTYPE_L2_ETHER_ARP; + ptype[3] = RTE_PTYPE_L2_ETHER_LLDP; + ptype[8] = RTE_PTYPE_L2_ETHER_TIMESYNC; + + /* Non-tunnel IPv4 */ + ptype[17] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_FRAG; + ptype[18] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_NONFRAG; + ptype[19] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_UDP; + ptype[20] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_TCP; + /* The next ptype is GRE over IPv4 */ + ptype[21] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN; + ptype[22] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_SCTP; + ptype[23] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_IGMP; + ptype[24] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_ICMP; + /* The next ptype is PTP over IPv4 + UDP */ + ptype[25] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_L4_UDP; + + /* IPv4 --> GRE/Teredo/VXLAN */ + ptype[29] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT; + /* IPv4 --> GRE/Teredo/VXLAN --> MAC */ + ptype[30] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER; + + /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */ + ptype[31] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_FRAG; + ptype[32] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_NONFRAG; + ptype[33] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_UDP; + ptype[34] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_TCP; + ptype[35] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_SCTP; + /* The next ptype's inner L4 is IGMP */ + ptype[36] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN; + ptype[37] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_ICMP; + + /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */ + ptype[39] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_FRAG; + ptype[40] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_NONFRAG; + ptype[41] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_UDP; + ptype[42] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_TCP; + ptype[43] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_SCTP; + /* The next ptype's inner L4 is IGMP */ + ptype[44] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN; + ptype[45] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_ICMP; + + /* Non-tunnel IPv6 */ + ptype[111] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_FRAG; + ptype[112] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_NONFRAG; + ptype[113] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_UDP; + ptype[114] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_TCP; + /* The next ptype is GRE over IPv6 */ + ptype[115] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN; + ptype[116] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_SCTP; + ptype[117] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_IGMP; + ptype[118] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_ICMP; + /* Special for PTP over IPv6 + UDP */ + ptype[119] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_L4_UDP; + + /* IPv6 --> GRE/Teredo/VXLAN */ + ptype[123] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT; + /* IPv6 --> GRE/Teredo/VXLAN --> MAC */ + ptype[124] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER; + + /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */ + ptype[125] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_FRAG; + ptype[126] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_NONFRAG; + ptype[127] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_UDP; + ptype[128] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_TCP; + ptype[129] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_SCTP; + /* The next ptype's inner L4 is IGMP */ + ptype[130] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN; + ptype[131] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_ICMP; + + /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */ + ptype[133] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_FRAG; + ptype[134] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_NONFRAG; + ptype[135] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_UDP; + ptype[136] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_TCP; + ptype[137] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_SCTP; + /* The next ptype's inner L4 is IGMP */ + ptype[138] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN; + ptype[139] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | + RTE_PTYPE_INNER_L4_ICMP; +} + void hns3_init_rx_ptype_tble(struct rte_eth_dev *dev) { @@ -1997,6 +2185,7 @@ hns3_init_rx_ptype_tble(struct rte_eth_dev *dev)
hns3_init_non_tunnel_ptype_tbl(tbl); hns3_init_tunnel_ptype_tbl(tbl); + hns3_init_adv_layout_ptype(tbl); }
static inline void @@ -4020,3 +4209,14 @@ hns3_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) else return fbd_num - driver_hold_bd_num; } + +void +hns3_enable_rxd_adv_layout(struct hns3_hw *hw) +{ + /* + * If the hardware support rxd advanced layout, then driver enable it + * default. + */ + if (hns3_dev_rxd_adv_layout_supported(hw)) + hns3_write_dev(hw, HNS3_RXD_ADV_LAYOUT_EN_REG, 1); +} diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h index 7118bd4..9adeb24 100644 --- a/drivers/net/hns3/hns3_rxtx.h +++ b/drivers/net/hns3/hns3_rxtx.h @@ -88,6 +88,8 @@ #define HNS3_RXD_OL3ID_M (0xf << HNS3_RXD_OL3ID_S) #define HNS3_RXD_OL4ID_S 8 #define HNS3_RXD_OL4ID_M (0xf << HNS3_RXD_OL4ID_S) +#define HNS3_RXD_PTYPE_S 4 +#define HNS3_RXD_PTYPE_M (0xff << HNS3_RXD_PTYPE_S) #define HNS3_RXD_FBHI_S 12 #define HNS3_RXD_FBHI_M (0x3 << HNS3_RXD_FBHI_S) #define HNS3_RXD_FBLI_S 14 @@ -328,6 +330,7 @@ struct hns3_rx_queue { * point, the pvid_sw_discard_en will be false. */ bool pvid_sw_discard_en; + bool ptype_en; /* indicate if the ptype field enabled */ bool enabled; /* indicate if Rx queue has been enabled */
struct hns3_rx_basic_stats basic_stats; @@ -609,6 +612,13 @@ hns3_rx_calc_ptype(struct hns3_rx_queue *rxq, const uint32_t l234_info, const struct hns3_ptype_table * const ptype_tbl = rxq->ptype_tbl; uint32_t l2id, l3id, l4id; uint32_t ol3id, ol4id, ol2id; + uint32_t ptype; + + if (rxq->ptype_en) { + ptype = hns3_get_field(ol_info, HNS3_RXD_PTYPE_M, + HNS3_RXD_PTYPE_S); + return ptype_tbl->ptype[ptype]; + }
ol4id = hns3_get_field(ol_info, HNS3_RXD_OL4ID_M, HNS3_RXD_OL4ID_S); ol3id = hns3_get_field(ol_info, HNS3_RXD_OL3ID_M, HNS3_RXD_OL3ID_S); @@ -707,5 +717,6 @@ int hns3_start_all_rxqs(struct rte_eth_dev *dev); void hns3_stop_all_txqs(struct rte_eth_dev *dev); void hns3_restore_tqp_enable_state(struct hns3_hw *hw); int hns3_tx_done_cleanup(void *txq, uint32_t free_cnt); +void hns3_enable_rxd_adv_layout(struct hns3_hw *hw);
#endif /* _HNS3_RXTX_H_ */
From: Chengchang Tang tangchengchang@huawei.com
After MTU changed, the buffer used to store packets in HW should be reallocated. And buffer size is allocated based on the maximum frame size in the PF struct. However, the value of maximum frame size is not updated in time when MTU is changed. This would lead to a packet loss for not enough buffer.
This patch update the maximum frame size before reallocating the HW buffer. And a rollback operation is added to avoid the side effects of buffer reallocation failures.
Signed-off-by: Chengchang Tang tangchengchang@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_ethdev.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index b3fd331..21c3c59 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -2460,17 +2460,33 @@ hns3_set_mac_mtu(struct hns3_hw *hw, uint16_t new_mps) static int hns3_config_mtu(struct hns3_hw *hw, uint16_t mps) { + struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); + uint16_t original_mps = hns->pf.mps; + int err; int ret;
ret = hns3_set_mac_mtu(hw, mps); if (ret) { - hns3_err(hw, "Failed to set mtu, ret = %d", ret); + hns3_err(hw, "failed to set mtu, ret = %d", ret); return ret; }
+ hns->pf.mps = mps; ret = hns3_buffer_alloc(hw); - if (ret) - hns3_err(hw, "Failed to allocate buffer, ret = %d", ret); + if (ret) { + hns3_err(hw, "failed to allocate buffer, ret = %d", ret); + goto rollback; + } + + return 0; + +rollback: + err = hns3_set_mac_mtu(hw, original_mps); + if (err) { + hns3_err(hw, "fail to rollback MTU, err = %d", err); + return ret; + } + hns->pf.mps = original_mps;
return ret; } @@ -2505,7 +2521,7 @@ hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) dev->data->port_id, mtu, ret); return ret; } - hns->pf.mps = (uint16_t)frame_size; + if (is_jumbo_frame) dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
From: Huisong Li lihuisong@huawei.com
All input parameters in the "hns3_dev_xstats_get_by_id" API are used, so the rte_unused flag of some variables should be deleted.
Fixes: 3213d584b698 ("net/hns3: fix xstats with id and names") Cc: stable@dpdk.org
Signed-off-by: Huisong Li lihuisong@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_stats.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/hns3/hns3_stats.h b/drivers/net/hns3/hns3_stats.h index 01b4f36..70a9c5b 100644 --- a/drivers/net/hns3/hns3_stats.h +++ b/drivers/net/hns3/hns3_stats.h @@ -156,8 +156,8 @@ int hns3_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned int size); int hns3_dev_xstats_get_by_id(struct rte_eth_dev *dev, - __rte_unused const uint64_t *ids, - __rte_unused uint64_t *values, + const uint64_t *ids, + uint64_t *values, uint32_t size); int hns3_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names,
From: Huisong Li lihuisong@huawei.com
The mbufs of rx queue will be allocated in "hns3_do_start" function. But these mbufs are not released when "hns3_dev_start" executes failed.
Fixes: c4ae39b2cfc5 ("net/hns3: fix Rx interrupt after reset") Cc: stable@dpdk.org
Signed-off-by: Huisong Li lihuisong@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_ethdev.c | 45 ++++++++++++++++++++++++--------------- drivers/net/hns3/hns3_ethdev_vf.c | 43 ++++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 34 deletions(-)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 21c3c59..8300fea 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -102,6 +102,7 @@ static int hns3_remove_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr); static int hns3_restore_fec(struct hns3_hw *hw); static int hns3_query_dev_fec_info(struct hns3_hw *hw); +static int hns3_do_stop(struct hns3_adapter *hns);
void hns3_ether_format_addr(char *buf, uint16_t size, const struct rte_ether_addr *ether_addr) @@ -5133,11 +5134,8 @@ hns3_dev_start(struct rte_eth_dev *dev) return ret; } ret = hns3_map_rx_interrupt(dev); - if (ret) { - hw->adapter_state = HNS3_NIC_CONFIGURED; - rte_spinlock_unlock(&hw->lock); - return ret; - } + if (ret) + goto map_rx_inter_err;
/* * There are three register used to control the status of a TQP @@ -5151,19 +5149,12 @@ hns3_dev_start(struct rte_eth_dev *dev) * 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; - } + if (ret) + goto map_rx_inter_err;
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; - } + if (ret) + goto start_all_rxqs_fail;
hw->adapter_state = HNS3_NIC_STARTED; rte_spinlock_unlock(&hw->lock); @@ -5187,7 +5178,17 @@ hns3_dev_start(struct rte_eth_dev *dev) hns3_tm_dev_start_proc(hw);
hns3_info(hw, "hns3 dev start successful!"); + return 0; + +start_all_rxqs_fail: + hns3_stop_all_txqs(dev); +map_rx_inter_err: + (void)hns3_do_stop(hns); + hw->adapter_state = HNS3_NIC_CONFIGURED; + rte_spinlock_unlock(&hw->lock); + + return ret; }
static int @@ -5196,6 +5197,17 @@ hns3_do_stop(struct hns3_adapter *hns) struct hns3_hw *hw = &hns->hw; int ret;
+ /* + * The "hns3_do_stop" function will also be called by .stop_service to + * prepare reset. At the time of global or IMP reset, the command cannot + * be sent to stop the tx/rx queues. The mbuf in Tx/Rx queues may be + * accessed during the reset process. So the mbuf can not be released + * during reset and is required to be released after the reset is + * completed. + */ + if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0) + hns3_dev_release_mbufs(hns); + ret = hns3_cfg_mac_mode(hw, false); if (ret) return ret; @@ -5273,7 +5285,6 @@ hns3_dev_stop(struct rte_eth_dev *dev) hns3_stop_tqps(hw); hns3_do_stop(hns); hns3_unmap_rx_interrupt(dev); - hns3_dev_release_mbufs(hns); hw->adapter_state = HNS3_NIC_CONFIGURED; } hns3_rx_scattered_reset(dev); diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index e7f6974..fd20c52 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -1941,6 +1941,17 @@ hns3vf_do_stop(struct hns3_adapter *hns)
hw->mac.link_status = ETH_LINK_DOWN;
+ /* + * The "hns3vf_do_stop" function will also be called by .stop_service to + * prepare reset. At the time of global or IMP reset, the command cannot + * be sent to stop the tx/rx queues. The mbuf in Tx/Rx queues may be + * accessed during the reset process. So the mbuf can not be released + * during reset and is required to be released after the reset is + * completed. + */ + if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0) + hns3_dev_release_mbufs(hns); + if (__atomic_load_n(&hw->reset.disable_cmd, __ATOMIC_RELAXED) == 0) { hns3vf_configure_mac_addr(hns, true); ret = hns3_reset_all_tqps(hns); @@ -2010,7 +2021,6 @@ hns3vf_dev_stop(struct rte_eth_dev *dev) hns3_stop_tqps(hw); hns3vf_do_stop(hns); hns3vf_unmap_rx_interrupt(dev); - hns3_dev_release_mbufs(hns); hw->adapter_state = HNS3_NIC_CONFIGURED; } hns3_rx_scattered_reset(dev); @@ -2253,11 +2263,8 @@ hns3vf_dev_start(struct rte_eth_dev *dev) return ret; } ret = hns3vf_map_rx_interrupt(dev); - if (ret) { - hw->adapter_state = HNS3_NIC_CONFIGURED; - rte_spinlock_unlock(&hw->lock); - return ret; - } + if (ret) + goto map_rx_inter_err;
/* * There are three register used to control the status of a TQP @@ -2271,19 +2278,12 @@ hns3vf_dev_start(struct rte_eth_dev *dev) * 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; - } + if (ret) + goto map_rx_inter_err;
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; - } + if (ret) + goto start_all_rxqs_fail;
hw->adapter_state = HNS3_NIC_STARTED; rte_spinlock_unlock(&hw->lock); @@ -2305,6 +2305,15 @@ hns3vf_dev_start(struct rte_eth_dev *dev) hns3_start_tqps(hw);
return ret; + +start_all_rxqs_fail: + hns3_stop_all_txqs(dev); +map_rx_inter_err: + (void)hns3vf_do_stop(hns); + hw->adapter_state = HNS3_NIC_CONFIGURED; + rte_spinlock_unlock(&hw->lock); + + return ret; }
static bool
From: Hongbo Zheng zhenghongbo3@huawei.com
Enable the interrupt report of MAC when MAC state changes and log the hardware MAC state value.
Signed-off-by: Hongbo Zheng zhenghongbo3@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_cmd.h | 3 +++ drivers/net/hns3/hns3_ethdev.c | 56 ++++++++++++++++++++++++++++++++++++------ drivers/net/hns3/hns3_intr.c | 20 +++++++++++++++ drivers/net/hns3/hns3_intr.h | 4 +++ 4 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index 9808112..4778f49 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -116,6 +116,9 @@ enum hns3_opcode_type { HNS3_OPC_QUERY_LINK_STATUS = 0x0307, HNS3_OPC_CONFIG_MAX_FRM_SIZE = 0x0308, HNS3_OPC_CONFIG_SPEED_DUP = 0x0309, + HNS3_OPC_QUERY_MAC_TNL_INT = 0x0310, + HNS3_OPC_MAC_TNL_INT_EN = 0x0311, + HNS3_OPC_CLEAR_MAC_TNL_INT = 0x0312, HNS3_OPC_CONFIG_FEC_MODE = 0x031A,
/* PFC/Pause commands */ diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 8300fea..932ac64 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -217,9 +217,6 @@ hns3_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval) goto out; }
- if (clearval && (vector0_int_stats || cmdq_src_val || hw_err_src_reg)) - hns3_warn(hw, "vector0_int_stats:0x%x cmdq_src_val:0x%x hw_err_src_reg:0x%x", - vector0_int_stats, cmdq_src_val, hw_err_src_reg); val = vector0_int_stats; ret = HNS3_VECTOR0_EVENT_OTHER; out: @@ -258,6 +255,33 @@ hns3_clear_all_event_cause(struct hns3_hw *hw) }
static void +hns3_handle_mac_tnl(struct hns3_hw *hw) +{ + struct hns3_cmd_desc desc; + uint32_t status; + int ret; + + /* query and clear mac tnl interruptions */ + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_MAC_TNL_INT, true); + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) { + hns3_err(hw, "failed to query mac tnl int, ret = %d.", ret); + return; + } + + status = rte_le_to_cpu_32(desc.data[0]); + if (status) { + hns3_warn(hw, "mac tnl int occurs, status = 0x%x.", status); + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CLEAR_MAC_TNL_INT, false); + desc.data[0] = rte_cpu_to_le_32(HNS3_MAC_TNL_INT_CLR); + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) + hns3_err(hw, "failed to clear mac tnl int, ret = %d.", + ret); + } +} + +static void hns3_interrupt_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; @@ -265,24 +289,36 @@ hns3_interrupt_handler(void *param) struct hns3_hw *hw = &hns->hw; enum hns3_evt_cause event_cause; uint32_t clearval = 0; + uint32_t vector0_int; + uint32_t ras_int; + uint32_t cmdq_int;
/* Disable interrupt */ hns3_pf_disable_irq0(hw);
event_cause = hns3_check_event_cause(hns, &clearval); + vector0_int = hns3_read_dev(hw, HNS3_VECTOR0_OTHER_INT_STS_REG); + ras_int = hns3_read_dev(hw, HNS3_RAS_PF_OTHER_INT_STS_REG); + cmdq_int = hns3_read_dev(hw, HNS3_VECTOR0_CMDQ_SRC_REG); /* vector 0 interrupt is shared with reset and mailbox source events. */ if (event_cause == HNS3_VECTOR0_EVENT_ERR) { - hns3_warn(hw, "Received err interrupt"); + hns3_warn(hw, "received interrupt: vector0_int_stat:0x%x " + "ras_int_stat:0x%x cmdq_int_stat:0x%x", + vector0_int, ras_int, cmdq_int); hns3_handle_msix_error(hns, &hw->reset.request); hns3_handle_ras_error(hns, &hw->reset.request); + hns3_handle_mac_tnl(hw); hns3_schedule_reset(hns); } else if (event_cause == HNS3_VECTOR0_EVENT_RST) { - hns3_warn(hw, "Received reset interrupt"); + hns3_warn(hw, "received reset interrupt"); hns3_schedule_reset(hns); - } else if (event_cause == HNS3_VECTOR0_EVENT_MBX) + } else if (event_cause == HNS3_VECTOR0_EVENT_MBX) { hns3_dev_handle_mbx_msg(hw); - else - hns3_err(hw, "Received unknown event"); + } else { + hns3_warn(hw, "received unknown event: vector0_int_stat:0x%x " + "ras_int_stat:0x%x cmdq_int_stat:0x%x", + vector0_int, ras_int, cmdq_int); + }
hns3_clear_event_cause(hw, event_cause, clearval); /* Enable interrupt if it is not cause by reset */ @@ -4639,6 +4675,8 @@ hns3_update_link_status(struct hns3_hw *hw) if (state != hw->mac.link_status) { hw->mac.link_status = state; hns3_warn(hw, "Link status change to %s!", state ? "up" : "down"); + hns3_config_mac_tnl_int(hw, + state == ETH_LINK_UP ? true : false); return true; }
@@ -4957,6 +4995,7 @@ hns3_uninit_pf(struct rte_eth_dev *eth_dev) (void)hns3_firmware_compat_config(hw, false); hns3_uninit_umv_space(hw); hns3_tqp_stats_uninit(hw); + hns3_config_mac_tnl_int(hw, false); hns3_pf_disable_irq0(hw); rte_intr_disable(&pci_dev->intr_handle); hns3_intr_unregister(&pci_dev->intr_handle, hns3_interrupt_handler, @@ -5282,6 +5321,7 @@ hns3_dev_stop(struct rte_eth_dev *dev) rte_spinlock_lock(&hw->lock); if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0) { hns3_tm_dev_stop_proc(hw); + hns3_config_mac_tnl_int(hw, false); hns3_stop_tqps(hw); hns3_do_stop(hns); hns3_unmap_rx_interrupt(dev); diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c index 88ce4c6..2563504 100644 --- a/drivers/net/hns3/hns3_intr.c +++ b/drivers/net/hns3/hns3_intr.c @@ -1248,6 +1248,26 @@ enable_ssu_err_intr(struct hns3_adapter *hns, bool en) return ret; }
+void +hns3_config_mac_tnl_int(struct hns3_hw *hw, bool en) +{ + struct hns3_cmd_desc desc; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_MAC_TNL_INT_EN, false); + if (en) + desc.data[0] = rte_cpu_to_le_32(HNS3_MAC_TNL_INT_EN); + else + desc.data[0] = 0; + + desc.data[1] = rte_cpu_to_le_32(HNS3_MAC_TNL_INT_EN_MASK); + + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) + hns3_err(hw, "fail to %s mac tnl intr, ret = %d", + en ? "enable" : "disable", ret); +} + static int config_ppu_err_intrs(struct hns3_adapter *hns, uint32_t cmd, bool en) { diff --git a/drivers/net/hns3/hns3_intr.h b/drivers/net/hns3/hns3_intr.h index 19de1aa..c569a9d 100644 --- a/drivers/net/hns3/hns3_intr.h +++ b/drivers/net/hns3/hns3_intr.h @@ -22,6 +22,9 @@
#define HNS3_MAC_COMMON_ERR_INT_EN 0x107FF #define HNS3_MAC_COMMON_ERR_INT_EN_MASK 0x107FF +#define HNS3_MAC_TNL_INT_EN GENMASK(9, 0) +#define HNS3_MAC_TNL_INT_EN_MASK GENMASK(9, 0) +#define HNS3_MAC_TNL_INT_CLR GENMASK(9, 0)
#define HNS3_IMP_TCM_ECC_ERR_INT_EN 0xFFFF0000 #define HNS3_IMP_TCM_ECC_ERR_INT_EN_MASK 0xFFFF0000 @@ -99,6 +102,7 @@ struct hns3_hw_error_desc { int hns3_enable_hw_error_intr(struct hns3_adapter *hns, bool state); void hns3_handle_msix_error(struct hns3_adapter *hns, uint64_t *levels); void hns3_handle_ras_error(struct hns3_adapter *hns, uint64_t *levels); +void hns3_config_mac_tnl_int(struct hns3_hw *hw, bool en);
void hns3_intr_unregister(const struct rte_intr_handle *hdl, rte_intr_callback_fn cb_fn, void *cb_arg);
From: Chengchang Tang tangchengchang@huawei.com
Currently, the hns3 statistics may be inaccurate due to the following two problems:
1. Queue-level statistics are read from the firmware, and only one Rx or Tx can be read at a time. This results in a large time interval between reading multiple queues statistics in a stress scenario, such as 1280 queues used by a PF or 256 functions used at the same time. Especially when the 256 functions are used at the same time, the interval between every two firmware commands in a function can be huge, because the scheduling mechanism of the firmware is similar to RR.
2. The current statistics are read by type. The HW statistics are read first, and then the software statistics are read. Due to preceding reasons, HW reading may be time-consuming, which cause a synchronization problem between SW and HW statistics of the same queue.
In this patch, queue-level statistics are directly read from the bar instead of the firmware, and all the statistics of a queue include HW and SW are read at a time to reduce inconsistency.
Fixes: 8839c5e202f3 ("net/hns3: support device stats") Cc: stable@dpdk.org
Signed-off-by: Chengchang Tang tangchengchang@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com --- drivers/net/hns3/hns3_stats.c | 227 ++++++++++++++---------------------------- 1 file changed, 76 insertions(+), 151 deletions(-)
diff --git a/drivers/net/hns3/hns3_stats.c b/drivers/net/hns3/hns3_stats.c index 365a3eb..a0fd5bb 100644 --- a/drivers/net/hns3/hns3_stats.c +++ b/drivers/net/hns3/hns3_stats.c @@ -367,7 +367,6 @@ static const struct hns3_xstats_name_offset hns3_imissed_stats_strings[] = { HNS3_NUM_RESET_XSTATS + HNS3_NUM_IMISSED_XSTATS)
static void hns3_tqp_stats_clear(struct hns3_hw *hw); -static void hns3_tqp_basic_stats_clear(struct rte_eth_dev *dev);
/* * Query all the MAC statistics data of Network ICL command ,opcode id: 0x0034. @@ -481,49 +480,6 @@ hns3_query_update_mac_stats(struct rte_eth_dev *dev) return ret; }
-/* Get tqp stats from register */ -static int -hns3_update_tqp_stats(struct hns3_hw *hw) -{ - struct hns3_tqp_stats *stats = &hw->tqp_stats; - struct hns3_cmd_desc desc; - uint64_t cnt; - uint16_t i; - int ret; - - for (i = 0; i < hw->tqps_num; i++) { - hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_RX_STATUS, - true); - - 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.%u queue stat: %d", - i, ret); - return ret; - } - cnt = rte_le_to_cpu_32(desc.data[1]); - stats->rcb_rx_ring_pktnum_rcd += cnt; - stats->rcb_rx_ring_pktnum[i] += cnt; - - hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_TX_STATUS, - true); - - 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.%u queue stat: %d", - i, ret); - return ret; - } - cnt = rte_le_to_cpu_32(desc.data[1]); - stats->rcb_tx_ring_pktnum_rcd += cnt; - stats->rcb_tx_ring_pktnum[i] += cnt; - } - - return 0; -} - static int hns3_update_rpu_drop_stats(struct hns3_hw *hw) { @@ -589,17 +545,11 @@ hns3_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats) struct hns3_rx_missed_stats *imissed_stats = &hw->imissed_stats; struct hns3_tqp_stats *stats = &hw->tqp_stats; struct hns3_rx_queue *rxq; + struct hns3_tx_queue *txq; uint64_t cnt; uint16_t i; int ret;
- /* Update tqp stats by read register */ - ret = hns3_update_tqp_stats(hw); - if (ret) { - hns3_err(hw, "Update tqp stats fail : %d", ret); - return ret; - } - if (!hns->is_vf) { /* Update imissed stats */ ret = hns3_update_imissed_stats(hw, false); @@ -612,29 +562,41 @@ hns3_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats) rte_stats->imissed = imissed_stats->rpu_rx_drop_cnt; }
- /* Get the error stats and bytes of received packets */ + /* Reads all the stats of a rxq in a loop to keep them synchronized */ for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { rxq = eth_dev->data->rx_queues[i]; - if (rxq) { - cnt = rxq->err_stats.l2_errors + - rxq->err_stats.pkt_len_errors; - rte_stats->ierrors += cnt; + if (rxq == NULL) + continue; + + cnt = hns3_read_dev(rxq, HNS3_RING_RX_PKTNUM_RECORD_REG); + /* + * Read hardware and software in adjacent positions to minumize + * the timing variance. + */ + rte_stats->ierrors += rxq->err_stats.l2_errors + + rxq->err_stats.pkt_len_errors; + stats->rcb_rx_ring_pktnum_rcd += cnt; + stats->rcb_rx_ring_pktnum[i] += cnt;
#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS - rte_stats->ibytes += rxq->basic_stats.bytes; + rte_stats->ibytes += rxq->basic_stats.bytes; #endif - } }
-#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS - /* Get the bytes of received packets */ - struct hns3_tx_queue *txq; + /* Reads all the stats of a txq in a loop to keep them synchronized */ for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { txq = eth_dev->data->tx_queues[i]; - if (txq) - rte_stats->obytes += txq->basic_stats.bytes; - } + if (txq == NULL) + continue; + + cnt = hns3_read_dev(txq, HNS3_RING_TX_PKTNUM_RECORD_REG); + stats->rcb_tx_ring_pktnum_rcd += cnt; + stats->rcb_tx_ring_pktnum[i] += cnt; + +#ifdef RTE_LIBRTE_HNS3_PMD_SOFT_COUNTERS + rte_stats->obytes += txq->basic_stats.bytes; #endif + }
rte_stats->oerrors = 0; /* @@ -657,37 +619,11 @@ 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_cmd_desc desc_reset; struct hns3_rx_queue *rxq; + struct hns3_tx_queue *txq; uint16_t i; int ret;
- /* - * 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); - ret = hns3_cmd_send(hw, &desc_reset, 1); - if (ret) { - hns3_err(hw, "Failed to reset RX No.%u queue stat: %d", - i, ret); - return ret; - } - - 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); - ret = hns3_cmd_send(hw, &desc_reset, 1); - if (ret) { - hns3_err(hw, "Failed to reset TX No.%u queue stat: %d", - i, ret); - return ret; - } - } - if (!hns->is_vf) { /* * Note: Reading hardware statistics of imissed registers will @@ -701,25 +637,44 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev) } }
- /* - * Clear soft stats of rx error packet which will be dropped - * in driver. - */ for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { rxq = eth_dev->data->rx_queues[i]; - if (rxq) { - rxq->err_stats.pkt_len_errors = 0; - rxq->err_stats.l2_errors = 0; - } + if (rxq == NULL) + continue; + + rxq->err_stats.pkt_len_errors = 0; + rxq->err_stats.l2_errors = 0; + } + + /* Clear all the stats of a rxq in a loop to keep them synchronized */ + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { + rxq = eth_dev->data->rx_queues[i]; + if (rxq == NULL) + continue; + + memset(&rxq->basic_stats, 0, + sizeof(struct hns3_rx_basic_stats)); + + /* This register is read-clear */ + (void)hns3_read_dev(rxq, HNS3_RING_RX_PKTNUM_RECORD_REG); + rxq->err_stats.pkt_len_errors = 0; + rxq->err_stats.l2_errors = 0; + } + + /* Clear all the stats of a txq in a loop to keep them synchronized */ + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { + txq = eth_dev->data->tx_queues[i]; + if (txq == NULL) + continue; + + memset(&txq->basic_stats, 0, + sizeof(struct hns3_tx_basic_stats)); + + /* This register is read-clear */ + (void)hns3_read_dev(txq, HNS3_RING_TX_PKTNUM_RECORD_REG); }
- /* - * 'packets' in hns3_tx_basic_stats and hns3_rx_basic_stats come - * from hw->tqp_stats. And clearing tqp stats is like clearing - * their source. - */ hns3_tqp_stats_clear(hw); - hns3_tqp_basic_stats_clear(eth_dev);
return 0; } @@ -885,6 +840,7 @@ hns3_rxq_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, struct hns3_rx_basic_stats *rxq_stats; struct hns3_rx_queue *rxq; uint16_t i, j; + uint32_t cnt; char *val;
for (i = 0; i < dev->data->nb_rx_queues; i++) { @@ -892,9 +848,17 @@ hns3_rxq_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, if (rxq == NULL) continue;
+ cnt = hns3_read_dev(rxq, HNS3_RING_RX_PKTNUM_RECORD_REG); + /* + * Read hardware and software in adjacent positions to minimize + * the time difference. + */ rxq_stats = &rxq->basic_stats; rxq_stats->errors = rxq->err_stats.l2_errors + rxq->err_stats.pkt_len_errors; + stats->rcb_rx_ring_pktnum_rcd += cnt; + stats->rcb_rx_ring_pktnum[i] += cnt; + /* * If HW statistics are reset by stats_reset, but a lot of * residual packets exist in the hardware queue and these @@ -923,6 +887,7 @@ hns3_txq_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, struct hns3_tx_basic_stats *txq_stats; struct hns3_tx_queue *txq; uint16_t i, j; + uint32_t cnt; char *val;
for (i = 0; i < dev->data->nb_tx_queues; i++) { @@ -930,6 +895,10 @@ hns3_txq_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, if (txq == NULL) continue;
+ cnt = hns3_read_dev(txq, HNS3_RING_TX_PKTNUM_RECORD_REG); + stats->rcb_tx_ring_pktnum_rcd += cnt; + stats->rcb_tx_ring_pktnum[i] += cnt; + txq_stats = &txq->basic_stats; txq_stats->packets = stats->rcb_tx_ring_pktnum[i];
@@ -943,54 +912,12 @@ hns3_txq_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, } }
-static int +static void hns3_tqp_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, int *count) { - struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int ret; - - /* Update tqp stats by read register */ - ret = hns3_update_tqp_stats(hw); - if (ret) { - hns3_err(hw, "Update tqp stats fail, ret = %d.", ret); - return ret; - } - hns3_rxq_basic_stats_get(dev, xstats, count); hns3_txq_basic_stats_get(dev, xstats, count); - - return 0; -} - -/* - * The function is only called by hns3_dev_xstats_reset to clear - * basic stats of per-queue. TQP stats are all cleared in hns3_stats_reset - * which is called before this function. - * - * @param dev - * Pointer to Ethernet device. - */ -static void -hns3_tqp_basic_stats_clear(struct rte_eth_dev *dev) -{ - struct hns3_tx_queue *txq; - struct hns3_rx_queue *rxq; - uint16_t i; - - for (i = 0; i < dev->data->nb_rx_queues; i++) { - rxq = dev->data->rx_queues[i]; - if (rxq) - memset(&rxq->basic_stats, 0, - sizeof(struct hns3_rx_basic_stats)); - } - - for (i = 0; i < dev->data->nb_tx_queues; i++) { - txq = dev->data->tx_queues[i]; - if (txq) - memset(&txq->basic_stats, 0, - sizeof(struct hns3_tx_basic_stats)); - } }
/* @@ -1032,9 +959,7 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
count = 0;
- ret = hns3_tqp_basic_stats_get(dev, xstats, &count); - if (ret < 0) - return ret; + hns3_tqp_basic_stats_get(dev, xstats, &count);
if (!hns->is_vf) { /* Update Mac stats */