]> git.droids-corp.org - dpdk.git/commitdiff
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 292a671cb5567ed2da737fb948ed253b9d958a4e..1301f5041ad7153494b9b84e0d1c87f86bbc53ac 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 7a03262978bd3da52506e6ddfc13f8eb505fd1d6..e93e4a77a537c6b96d1215c6ef07f50775d3e5b9 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 */