+}
+
+static void
+hns3_rxq_dfx_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+ int *count)
+{
+ struct hns3_rx_dfx_stats *dfx_stats;
+ struct hns3_rx_queue *rxq;
+ uint16_t i, j;
+ char *val;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ rxq = (struct hns3_rx_queue *)dev->data->rx_queues[i];
+ if (rxq == NULL)
+ continue;
+
+ dfx_stats = &rxq->dfx_stats;
+ for (j = 0; j < HNS3_NUM_RXQ_DFX_XSTATS; j++) {
+ val = (char *)dfx_stats +
+ hns3_rxq_dfx_stats_strings[j].offset;
+ xstats[*count].value = *(uint64_t *)val;
+ xstats[*count].id = *count;
+ (*count)++;
+ }
+ }
+}
+
+static void
+hns3_txq_dfx_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+ int *count)
+{
+ struct hns3_tx_dfx_stats *dfx_stats;
+ struct hns3_tx_queue *txq;
+ uint16_t i, j;
+ char *val;
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ txq = (struct hns3_tx_queue *)dev->data->tx_queues[i];
+ if (txq == NULL)
+ continue;
+
+ dfx_stats = &txq->dfx_stats;
+ for (j = 0; j < HNS3_NUM_TXQ_DFX_XSTATS; j++) {
+ val = (char *)dfx_stats +
+ hns3_txq_dfx_stats_strings[j].offset;
+ xstats[*count].value = *(uint64_t *)val;
+ xstats[*count].id = *count;
+ (*count)++;
+ }
+ }
+}
+
+static void
+hns3_tqp_dfx_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+ int *count)
+{
+ hns3_rxq_dfx_stats_get(dev, xstats, count);
+ hns3_txq_dfx_stats_get(dev, xstats, count);
+}
+
+static void
+hns3_rxq_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);
+ struct hns3_tqp_stats *stats = &hw->tqp_stats;
+ 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++) {
+ rxq = dev->data->rx_queues[i];
+ 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
+ * packets are error packets, flip overflow may occurred.
+ * So return 0 in this case.
+ */
+ rxq_stats->packets =
+ stats->rcb_rx_ring_pktnum[i] > rxq_stats->errors ?
+ stats->rcb_rx_ring_pktnum[i] - rxq_stats->errors : 0;
+ for (j = 0; j < HNS3_NUM_RXQ_BASIC_STATS; j++) {
+ val = (char *)rxq_stats +
+ hns3_rxq_basic_stats_strings[j].offset;
+ xstats[*count].value = *(uint64_t *)val;
+ xstats[*count].id = *count;
+ (*count)++;
+ }
+ }
+}
+
+static void
+hns3_txq_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);
+ struct hns3_tqp_stats *stats = &hw->tqp_stats;
+ 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++) {
+ txq = dev->data->tx_queues[i];
+ 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];
+
+ for (j = 0; j < HNS3_NUM_TXQ_BASIC_STATS; j++) {
+ val = (char *)txq_stats +
+ hns3_txq_basic_stats_strings[j].offset;
+ xstats[*count].value = *(uint64_t *)val;
+ xstats[*count].id = *count;
+ (*count)++;
+ }
+ }
+}
+
+static void
+hns3_tqp_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+ int *count)
+{
+ hns3_rxq_basic_stats_get(dev, xstats, count);
+ 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++;
+ }