+vmxnet3_hw_tx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
+ struct UPT1_TxStats *res)
+{
+#define VMXNET3_UPDATE_TX_STAT(h, i, f, r) \
+ ((r)->f = (h)->tqd_start[(i)].stats.f + \
+ (h)->saved_tx_stats[(i)].f)
+
+ VMXNET3_UPDATE_TX_STAT(hw, q, ucastPktsTxOK, res);
+ VMXNET3_UPDATE_TX_STAT(hw, q, mcastPktsTxOK, res);
+ VMXNET3_UPDATE_TX_STAT(hw, q, bcastPktsTxOK, res);
+ VMXNET3_UPDATE_TX_STAT(hw, q, ucastBytesTxOK, res);
+ VMXNET3_UPDATE_TX_STAT(hw, q, mcastBytesTxOK, res);
+ VMXNET3_UPDATE_TX_STAT(hw, q, bcastBytesTxOK, res);
+ VMXNET3_UPDATE_TX_STAT(hw, q, pktsTxError, res);
+ VMXNET3_UPDATE_TX_STAT(hw, q, pktsTxDiscard, res);
+
+#undef VMXNET3_UPDATE_TX_STAT
+}
+
+static void
+vmxnet3_hw_rx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
+ struct UPT1_RxStats *res)
+{
+#define VMXNET3_UPDATE_RX_STAT(h, i, f, r) \
+ ((r)->f = (h)->rqd_start[(i)].stats.f + \
+ (h)->saved_rx_stats[(i)].f)
+
+ VMXNET3_UPDATE_RX_STAT(hw, q, ucastPktsRxOK, res);
+ VMXNET3_UPDATE_RX_STAT(hw, q, mcastPktsRxOK, res);
+ VMXNET3_UPDATE_RX_STAT(hw, q, bcastPktsRxOK, res);
+ VMXNET3_UPDATE_RX_STAT(hw, q, ucastBytesRxOK, res);
+ VMXNET3_UPDATE_RX_STAT(hw, q, mcastBytesRxOK, res);
+ VMXNET3_UPDATE_RX_STAT(hw, q, bcastBytesRxOK, res);
+ VMXNET3_UPDATE_RX_STAT(hw, q, pktsRxError, res);
+ VMXNET3_UPDATE_RX_STAT(hw, q, pktsRxOutOfBuf, res);
+
+#undef VMXNET3_UPDATE_RX_STATS
+}
+
+static void
+vmxnet3_hw_stats_save(struct vmxnet3_hw *hw)
+{
+ unsigned int i;
+
+ VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
+
+ RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_TX_QUEUES);
+
+ for (i = 0; i < hw->num_tx_queues; i++)
+ vmxnet3_hw_tx_stats_get(hw, i, &hw->saved_tx_stats[i]);
+ for (i = 0; i < hw->num_rx_queues; i++)
+ vmxnet3_hw_rx_stats_get(hw, i, &hw->saved_rx_stats[i]);
+}
+
+static int
+vmxnet3_dev_xstats_get_names(struct rte_eth_dev *dev,
+ struct rte_eth_xstat_name *xstats_names,
+ unsigned int n)
+{
+ unsigned int i, t, count = 0;
+ unsigned int nstats =
+ dev->data->nb_tx_queues * RTE_DIM(vmxnet3_txq_stat_strings) +
+ dev->data->nb_rx_queues * RTE_DIM(vmxnet3_rxq_stat_strings);
+
+ if (!xstats_names || n < nstats)
+ return nstats;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ if (!dev->data->rx_queues[i])
+ continue;
+
+ for (t = 0; t < RTE_DIM(vmxnet3_rxq_stat_strings); t++) {
+ snprintf(xstats_names[count].name,
+ sizeof(xstats_names[count].name),
+ "rx_q%u_%s", i,
+ vmxnet3_rxq_stat_strings[t].name);
+ count++;
+ }
+ }
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ if (!dev->data->tx_queues[i])
+ continue;
+
+ for (t = 0; t < RTE_DIM(vmxnet3_txq_stat_strings); t++) {
+ snprintf(xstats_names[count].name,
+ sizeof(xstats_names[count].name),
+ "tx_q%u_%s", i,
+ vmxnet3_txq_stat_strings[t].name);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static int
+vmxnet3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+ unsigned int n)
+{
+ unsigned int i, t, count = 0;
+ unsigned int nstats =
+ dev->data->nb_tx_queues * RTE_DIM(vmxnet3_txq_stat_strings) +
+ dev->data->nb_rx_queues * RTE_DIM(vmxnet3_rxq_stat_strings);
+
+ if (n < nstats)
+ return nstats;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ struct vmxnet3_rx_queue *rxq = dev->data->rx_queues[i];
+
+ if (rxq == NULL)
+ continue;
+
+ for (t = 0; t < RTE_DIM(vmxnet3_rxq_stat_strings); t++) {
+ xstats[count].value = *(uint64_t *)(((char *)&rxq->stats) +
+ vmxnet3_rxq_stat_strings[t].offset);
+ xstats[count].id = count;
+ count++;
+ }
+ }
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
+
+ if (txq == NULL)
+ continue;
+
+ for (t = 0; t < RTE_DIM(vmxnet3_txq_stat_strings); t++) {
+ xstats[count].value = *(uint64_t *)(((char *)&txq->stats) +
+ vmxnet3_txq_stat_strings[t].offset);
+ xstats[count].id = count;
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static int