net/vmxnet3: retain counters on restart
authorNachiketa Prachanda <nprachan@brocade.com>
Thu, 15 Jun 2017 12:16:08 +0000 (08:16 -0400)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 6 Jul 2017 13:00:57 +0000 (15:00 +0200)
Most NICs like virtio, igb/ixgbe etc. don't reset counters on
dev_start and arguably this helps in monitoring the counters
across a longer time span with multiple device start/stops.
vmxnet3 behavior is opposite to that and counters are reset by
the host side implementation each time the device is restarted.

Change the driver to save the counters in its private context
before it is reset by writing CMD_ACTIVATE to REG_CMD.

Signed-off-by: Nachiketa Prachanda <nprachan@brocade.com>
Acked-by: Shrikrishna Khare <skhare@vmware.com>
drivers/net/vmxnet3/vmxnet3_ethdev.c
drivers/net/vmxnet3/vmxnet3_ethdev.h

index 292a671..1301f50 100644 (file)
@@ -85,6 +85,7 @@ static void vmxnet3_dev_allmulticast_enable(struct rte_eth_dev *dev);
 static void vmxnet3_dev_allmulticast_disable(struct rte_eth_dev *dev);
 static int vmxnet3_dev_link_update(struct rte_eth_dev *dev,
                                   int wait_to_complete);
+static void vmxnet3_hw_stats_save(struct vmxnet3_hw *hw);
 static void vmxnet3_dev_stats_get(struct rte_eth_dev *dev,
                                  struct rte_eth_stats *stats);
 static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
@@ -351,6 +352,10 @@ eth_vmxnet3_dev_init(struct rte_eth_dev *eth_dev)
        RTE_ASSERT((hw->rxdata_desc_size & ~VMXNET3_RXDATA_DESC_SIZE_MASK) ==
                   hw->rxdata_desc_size);
 
+       /* clear shadow stats */
+       memset(hw->saved_tx_stats, 0, sizeof(hw->saved_tx_stats));
+       memset(hw->saved_rx_stats, 0, sizeof(hw->saved_rx_stats));
+
        return 0;
 }
 
@@ -707,6 +712,9 @@ vmxnet3_dev_start(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
+       /* Save stats before it is reset by CMD_ACTIVATE */
+       vmxnet3_hw_stats_save(hw);
+
        ret = vmxnet3_setup_driver_shared(dev);
        if (ret != VMXNET3_SUCCESS)
                return ret;
@@ -819,48 +827,106 @@ vmxnet3_dev_close(struct rte_eth_dev *dev)
        hw->adapter_stopped = 1;
 }
 
+static void
+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 void
 vmxnet3_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
        unsigned int i;
        struct vmxnet3_hw *hw = dev->data->dev_private;
+       struct UPT1_TxStats txStats;
+       struct UPT1_RxStats rxStats;
 
        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++) {
-               struct UPT1_TxStats *txStats = &hw->tqd_start[i].stats;
+               vmxnet3_hw_tx_stats_get(hw, i, &txStats);
+
+               stats->q_opackets[i] = txStats.ucastPktsTxOK +
+                       txStats.mcastPktsTxOK +
+                       txStats.bcastPktsTxOK;
 
-               stats->q_opackets[i] = txStats->ucastPktsTxOK +
-                                       txStats->mcastPktsTxOK +
-                                       txStats->bcastPktsTxOK;
-               stats->q_obytes[i] = txStats->ucastBytesTxOK +
-                                       txStats->mcastBytesTxOK +
-                                       txStats->bcastBytesTxOK;
+               stats->q_obytes[i] = txStats.ucastBytesTxOK +
+                       txStats.mcastBytesTxOK +
+                       txStats.bcastBytesTxOK;
 
                stats->opackets += stats->q_opackets[i];
                stats->obytes += stats->q_obytes[i];
-               stats->oerrors += txStats->pktsTxError + txStats->pktsTxDiscard;
+               stats->oerrors += txStats.pktsTxError + txStats.pktsTxDiscard;
        }
 
        RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_RX_QUEUES);
        for (i = 0; i < hw->num_rx_queues; i++) {
-               struct UPT1_RxStats *rxStats = &hw->rqd_start[i].stats;
+               vmxnet3_hw_rx_stats_get(hw, i, &rxStats);
 
-               stats->q_ipackets[i] = rxStats->ucastPktsRxOK +
-                                       rxStats->mcastPktsRxOK +
-                                       rxStats->bcastPktsRxOK;
+               stats->q_ipackets[i] = rxStats.ucastPktsRxOK +
+                       rxStats.mcastPktsRxOK +
+                       rxStats.bcastPktsRxOK;
 
-               stats->q_ibytes[i] = rxStats->ucastBytesRxOK +
-                                       rxStats->mcastBytesRxOK +
-                                       rxStats->bcastBytesRxOK;
+               stats->q_ibytes[i] = rxStats.ucastBytesRxOK +
+                       rxStats.mcastBytesRxOK +
+                       rxStats.bcastBytesRxOK;
 
                stats->ipackets += stats->q_ipackets[i];
                stats->ibytes += stats->q_ibytes[i];
 
-               stats->q_errors[i] = rxStats->pktsRxError;
-               stats->ierrors += rxStats->pktsRxError;
-               stats->rx_nombuf += rxStats->pktsRxOutOfBuf;
+               stats->q_errors[i] = rxStats.pktsRxError;
+               stats->ierrors += rxStats.pktsRxError;
+               stats->rx_nombuf += rxStats.pktsRxOutOfBuf;
        }
 }
 
index 7a03262..e93e4a7 100644 (file)
@@ -122,6 +122,8 @@ struct vmxnet3_hw {
        Vmxnet3_MemRegs       *memRegs;
        uint64_t              memRegsPA;
 #define VMXNET3_VFT_TABLE_SIZE     (VMXNET3_VFT_SIZE * sizeof(uint32_t))
+       UPT1_TxStats          saved_tx_stats[VMXNET3_MAX_TX_QUEUES];
+       UPT1_RxStats          saved_rx_stats[VMXNET3_MAX_RX_QUEUES];
 };
 
 #define VMXNET3_REV_3          2               /* Vmxnet3 Rev. 3 */