From: Min Hu (Connor) Date: Tue, 23 Mar 2021 11:21:04 +0000 (+0800) Subject: net/hns3: support imissed stats for PF/VF X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=0f10bd6b1fb3d1981e9d4d82bb4473c75e634980;p=dpdk.git net/hns3: support imissed stats for PF/VF This patch added function level imissed stats for PF and VF. In Kunpeng920, imissed is supported, only including RPU drop stats in PF. In kunpeng930, imissed is supported,including RPU drop stats and SSU drop stats in PF. Signed-off-by: Min Hu (Connor) --- diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index 094bf7e75e..e704d0c40b 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -111,6 +111,8 @@ enum hns3_opcode_type { HNS3_OPC_QUERY_DEV_SPECS = 0x0050, + HNS3_OPC_SSU_DROP_REG = 0x0065, + /* MAC command */ HNS3_OPC_CONFIG_MAC_MODE = 0x0301, HNS3_OPC_QUERY_LINK_STATUS = 0x0307, @@ -957,6 +959,17 @@ struct hns3_query_rpu_cmd { uint32_t rsv2[2]; }; +#define HNS3_OPC_SSU_DROP_REG_NUM 2 + +struct hns3_query_ssu_cmd { + uint8_t rxtx; + uint8_t rsv[3]; + uint32_t full_drop_cnt; + uint32_t part_drop_cnt; + uint32_t oq_drop_cnt; + uint32_t rev1[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 139e893ac6..82538d4ee9 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -3122,6 +3122,7 @@ hns3_get_capability(struct hns3_hw *hw) hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_2US; hw->tso_mode = HNS3_TSO_SW_CAL_PSEUDO_H_CSUM; hw->vlan_mode = HNS3_SW_SHIFT_AND_DISCARD_MODE; + hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE1; hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN; pf->tqp_config_mode = HNS3_FIXED_MAX_TQP_NUM_MODE; hw->rss_info.ipv6_sctp_offload_supported = false; @@ -3140,6 +3141,7 @@ hns3_get_capability(struct hns3_hw *hw) hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_1US; hw->tso_mode = HNS3_TSO_HW_CAL_PSEUDO_H_CSUM; hw->vlan_mode = HNS3_HW_SHIFT_AND_DISCARD_MODE; + hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE2; hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN; pf->tqp_config_mode = HNS3_FLEX_MAX_TQP_NUM_MODE; hw->rss_info.ipv6_sctp_offload_supported = true; diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index 314916c952..6e74ec8752 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -426,6 +426,9 @@ struct hns3_queue_intr { #define HNS3_TSO_SW_CAL_PSEUDO_H_CSUM 0 #define HNS3_TSO_HW_CAL_PSEUDO_H_CSUM 1 +#define HNS3_PKTS_DROP_STATS_MODE1 0 +#define HNS3_PKTS_DROP_STATS_MODE2 1 + struct hns3_hw { struct rte_eth_dev_data *data; void *io_base; @@ -544,6 +547,24 @@ struct hns3_hw { * port won't be copied to the function which has set promisc mode. */ uint8_t promisc_mode; + + /* + * drop_stats_mode mode. + * value range: + * HNS3_PKTS_DROP_STATS_MODE1/HNS3_PKTS_DROP_STATS_MODE2 + * + * - HNS3_PKTS_DROP_STATS_MODE1 + * This mode for kunpeng920. In this mode, port level imissed stats + * is supported. It only includes RPU drop stats. + * + * - HNS3_PKTS_DROP_STATS_MODE2 + * This mode for kunpeng930. In this mode, imissed stats and oerrors + * stats is supported. Function level imissed stats is supported. It + * includes RPU drop stats in VF, and includes both RPU drop stats + * and SSU drop stats in PF. Oerror stats is also supported in PF. + */ + uint8_t drop_stats_mode; + uint8_t max_non_tso_bd_num; /* max BD number of one non-TSO packet */ struct hns3_port_base_vlan_config port_base_vlan_cfg; diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index e1e41b88b9..7ee468fca2 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -1221,6 +1221,7 @@ hns3vf_get_capability(struct hns3_hw *hw) hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_RSV_ONE; hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_2US; hw->tso_mode = HNS3_TSO_SW_CAL_PSEUDO_H_CSUM; + hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE1; hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN; hw->rss_info.ipv6_sctp_offload_supported = false; hw->promisc_mode = HNS3_UNLIMIT_PROMISC_MODE; @@ -1238,6 +1239,7 @@ hns3vf_get_capability(struct hns3_hw *hw) hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_ALL; hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_1US; hw->tso_mode = HNS3_TSO_HW_CAL_PSEUDO_H_CSUM; + hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE2; hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN; hw->rss_info.ipv6_sctp_offload_supported = true; hw->promisc_mode = HNS3_LIMIT_PROMISC_MODE; @@ -1875,6 +1877,13 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev) if (ret) goto err_get_config; + /* 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); + goto err_set_tc_queue; + } + 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); diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h index 0540554bd4..e141fe10a0 100644 --- a/drivers/net/hns3/hns3_regs.h +++ b/drivers/net/hns3/hns3_regs.h @@ -36,6 +36,8 @@ #define HNS3_GLOBAL_RESET_REG 0x20A00 #define HNS3_FUN_RST_ING 0x20C00 #define HNS3_GRO_EN_REG 0x28000 + +#define HNS3_RPU_DROP_CNT_REG 0x28004 #define HNS3_RXD_ADV_LAYOUT_EN_REG 0x28008 /* Vector0 register bits for reset */ diff --git a/drivers/net/hns3/hns3_stats.c b/drivers/net/hns3/hns3_stats.c index 7cda36c796..e802c0b1a2 100644 --- a/drivers/net/hns3/hns3_stats.c +++ b/drivers/net/hns3/hns3_stats.c @@ -269,6 +269,8 @@ static const struct hns3_xstats_name_offset hns3_tx_queue_strings[] = { static const struct hns3_xstats_name_offset hns3_imissed_stats_strings[] = { {"RPU_DROP_CNT", HNS3_IMISSED_STATS_FIELD_OFFSET(rpu_rx_drop_cnt)}, + {"SSU_DROP_CNT", + HNS3_IMISSED_STATS_FIELD_OFFSET(ssu_rx_drop_cnt)}, }; #define HNS3_NUM_MAC_STATS (sizeof(hns3_mac_strings) / \ @@ -301,8 +303,7 @@ static const struct hns3_xstats_name_offset hns3_imissed_stats_strings[] = { #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_RESET_XSTATS + HNS3_NUM_IMISSED_XSTATS) +#define HNS3_FIX_NUM_STATS (HNS3_NUM_MAC_STATS + HNS3_NUM_RESET_XSTATS) static void hns3_tqp_stats_clear(struct hns3_hw *hw); @@ -419,7 +420,7 @@ hns3_query_update_mac_stats(struct rte_eth_dev *dev) } static int -hns3_update_rpu_drop_stats(struct hns3_hw *hw) +hns3_update_port_rpu_drop_stats(struct hns3_hw *hw) { struct hns3_rx_missed_stats *stats = &hw->imissed_stats; struct hns3_query_rpu_cmd *req; @@ -449,11 +450,90 @@ hns3_update_rpu_drop_stats(struct hns3_hw *hw) return 0; } +static void +hns3_update_function_rpu_drop_stats(struct hns3_hw *hw) +{ + struct hns3_rx_missed_stats *stats = &hw->imissed_stats; + + stats->rpu_rx_drop_cnt += hns3_read_dev(hw, HNS3_RPU_DROP_CNT_REG); +} + +static int +hns3_update_rpu_drop_stats(struct hns3_hw *hw) +{ + struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); + int ret = 0; + + if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE1 && !hns->is_vf) + ret = hns3_update_port_rpu_drop_stats(hw); + else if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE2) + hns3_update_function_rpu_drop_stats(hw); + + return ret; +} + +static int +hns3_get_ssu_drop_stats(struct hns3_hw *hw, struct hns3_cmd_desc *desc, + int bd_num, bool is_rx) +{ + struct hns3_query_ssu_cmd *req; + int ret; + int i; + + for (i = 0; i < bd_num - 1; i++) { + hns3_cmd_setup_basic_desc(&desc[i], + HNS3_OPC_SSU_DROP_REG, true); + desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT); + } + hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_SSU_DROP_REG, true); + req = (struct hns3_query_ssu_cmd *)desc[0].data; + req->rxtx = is_rx ? 0 : 1; + ret = hns3_cmd_send(hw, desc, bd_num); + + return ret; +} + +static int +hns3_update_port_rx_ssu_drop_stats(struct hns3_hw *hw) +{ + struct hns3_rx_missed_stats *stats = &hw->imissed_stats; + struct hns3_cmd_desc desc[HNS3_OPC_SSU_DROP_REG_NUM]; + struct hns3_query_ssu_cmd *req; + uint64_t cnt; + int ret; + + ret = hns3_get_ssu_drop_stats(hw, desc, HNS3_OPC_SSU_DROP_REG_NUM, + true); + if (ret) { + hns3_err(hw, "failed to get Rx SSU drop stats, ret = %d", ret); + return ret; + } + + req = (struct hns3_query_ssu_cmd *)desc[0].data; + cnt = rte_le_to_cpu_32(req->oq_drop_cnt) + + rte_le_to_cpu_32(req->full_drop_cnt) + + rte_le_to_cpu_32(req->part_drop_cnt); + + stats->ssu_rx_drop_cnt += cnt; + + return 0; +} + int hns3_update_imissed_stats(struct hns3_hw *hw, bool is_clear) { + struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); int ret; + if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE1 && hns->is_vf) + return 0; + + if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE2 && !hns->is_vf) { + ret = hns3_update_port_rx_ssu_drop_stats(hw); + if (ret) + return ret; + } + ret = hns3_update_rpu_drop_stats(hw); if (ret) return ret; @@ -488,19 +568,17 @@ hns3_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats) uint16_t i; int 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; + /* 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 + + imissed_stats->ssu_rx_drop_cnt; - /* Reads all the stats of a rxq in a loop to keep them synchronized */ + /* 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 == NULL) @@ -556,17 +634,14 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev) uint16_t i; int ret; - 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; - } + /* + * 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; } for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { @@ -630,6 +705,22 @@ hns3_mac_stats_reset(__rte_unused struct rte_eth_dev *dev) return 0; } +static int +hns3_get_imissed_stats_num(struct hns3_adapter *hns) +{ +#define NO_IMISSED_STATS_NUM 0 +#define RPU_STATS_ITEM_NUM 1 + struct hns3_hw *hw = &hns->hw; + + if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE1 && hns->is_vf) + return NO_IMISSED_STATS_NUM; + + if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE2 && !hns->is_vf) + return HNS3_NUM_IMISSED_XSTATS; + + return RPU_STATS_ITEM_NUM; +} + /* This function calculates the number of xstats based on the current config */ static int hns3_xstats_calc_num(struct rte_eth_dev *dev) @@ -647,13 +738,17 @@ hns3_xstats_calc_num(struct rte_eth_dev *dev) uint16_t nb_tx_q = dev->data->nb_tx_queues; int rx_comm_stats_num = nb_rx_q * HNS3_PF_VF_RX_COMM_STATS_NUM; int tx_comm_stats_num = nb_tx_q * HNS3_PF_VF_TX_COMM_STATS_NUM; + int stats_num; + + stats_num = rx_comm_stats_num + tx_comm_stats_num; + stats_num += hns3_get_imissed_stats_num(hns); if (hns->is_vf) - return rx_comm_stats_num + tx_comm_stats_num + - HNS3_NUM_RESET_XSTATS; + stats_num += HNS3_NUM_RESET_XSTATS; else - return rx_comm_stats_num + tx_comm_stats_num + - HNS3_FIX_NUM_STATS; + stats_num += HNS3_FIX_NUM_STATS; + + return stats_num; } static void @@ -835,6 +930,31 @@ hns3_tqp_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, hns3_txq_basic_stats_get(dev, xstats, count); } +static void +hns3_imissed_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, + int *count) +{ + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + struct hns3_rx_missed_stats *imissed_stats = &hw->imissed_stats; + int imissed_stats_num; + int cnt = *count; + char *addr; + uint16_t i; + + imissed_stats_num = hns3_get_imissed_stats_num(hns); + + for (i = 0; i < imissed_stats_num; i++) { + addr = (char *)imissed_stats + + hns3_imissed_stats_strings[i].offset; + xstats[cnt].value = *(uint64_t *)addr; + xstats[cnt].id = cnt; + cnt++; + } + + *count = cnt; +} + /* * Retrieve extended(tqp | Mac) statistics of an Ethernet device. * @param dev @@ -854,7 +974,6 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, { struct hns3_adapter *hns = dev->data->dev_private; 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; @@ -890,24 +1009,17 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, xstats[count].id = count; 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++; - } - + ret = hns3_update_imissed_stats(hw, false); + if (ret) { + hns3_err(hw, "update imissed stats failed, ret = %d", + ret); + return ret; } + hns3_imissed_stats_get(dev, xstats, &count); + /* Get the reset stat */ for (i = 0; i < HNS3_NUM_RESET_XSTATS; i++) { addr = (char *)reset_stats + hns3_reset_stats_strings[i].offset; @@ -992,6 +1104,28 @@ hns3_tqp_dfx_stats_name_get(struct rte_eth_dev *dev, } } +static void +hns3_imissed_stats_name_get(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + uint32_t *count) +{ + struct hns3_adapter *hns = dev->data->dev_private; + uint32_t cnt = *count; + int imissed_stats_num; + uint16_t i; + + imissed_stats_num = hns3_get_imissed_stats_num(hns); + + for (i = 0; i < imissed_stats_num; i++) { + snprintf(xstats_names[cnt].name, + sizeof(xstats_names[cnt].name), + "%s", hns3_imissed_stats_strings[i].name); + cnt++; + } + + *count = cnt; +} + /* * Retrieve names of extended statistics of an Ethernet device. * @@ -1040,14 +1174,10 @@ hns3_dev_xstats_get_names(struct rte_eth_dev *dev, "%s", hns3_mac_strings[i].name); 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++; - } } + + hns3_imissed_stats_name_get(dev, xstats_names, &count); + for (i = 0; i < HNS3_NUM_RESET_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 8ea69b4a93..273be4246f 100644 --- a/drivers/net/hns3/hns3_stats.h +++ b/drivers/net/hns3/hns3_stats.h @@ -112,6 +112,7 @@ struct hns3_mac_stats { struct hns3_rx_missed_stats { uint64_t rpu_rx_drop_cnt; + uint64_t ssu_rx_drop_cnt; }; /* store statistics names and its offset in stats structure */