+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;
+ char *val;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ rxq = dev->data->rx_queues[i];
+ if (rxq == NULL)
+ continue;
+
+ rxq_stats = &rxq->basic_stats;
+ rxq_stats->errors = rxq->err_stats.l2_errors +
+ rxq->err_stats.pkt_len_errors;
+ /*
+ * 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;
+ 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;
+ 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;
+ char *val;
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ txq = dev->data->tx_queues[i];
+ if (txq == NULL)
+ continue;
+
+ 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;
+ xstats[*count].value = *(uint64_t *)val;
+ xstats[*count].id = *count;
+ (*count)++;
+ }
+ }
+}
+
+static int
+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));
+ }
+}
+