net/failsafe: add timestamp to stats snapshot
[dpdk.git] / drivers / net / failsafe / failsafe_ops.c
index ac3257e..f460551 100644 (file)
 #include <stdint.h>
 
 #include <rte_debug.h>
+#include <rte_atomic.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
 #include <rte_flow.h>
+#include <rte_cycles.h>
 
 #include "failsafe_private.h"
 
@@ -204,9 +206,34 @@ fs_dev_configure(struct rte_eth_dev *dev)
                }
        }
        FOREACH_SUBDEV(sdev, i, dev) {
+               int rmv_interrupt = 0;
+               int lsc_interrupt = 0;
+               int lsc_enabled;
+
                if (sdev->state != DEV_PROBED)
                        continue;
+
+               rmv_interrupt = ETH(sdev)->data->dev_flags &
+                               RTE_ETH_DEV_INTR_RMV;
+               if (rmv_interrupt) {
+                       DEBUG("Enabling RMV interrupts for sub_device %d", i);
+                       dev->data->dev_conf.intr_conf.rmv = 1;
+               } else {
+                       DEBUG("sub_device %d does not support RMV event", i);
+               }
+               lsc_enabled = dev->data->dev_conf.intr_conf.lsc;
+               lsc_interrupt = lsc_enabled &&
+                               (ETH(sdev)->data->dev_flags &
+                                RTE_ETH_DEV_INTR_LSC);
+               if (lsc_interrupt) {
+                       DEBUG("Enabling LSC interrupts for sub_device %d", i);
+                       dev->data->dev_conf.intr_conf.lsc = 1;
+               } else if (lsc_enabled && !lsc_interrupt) {
+                       DEBUG("Disabling LSC interrupts for sub_device %d", i);
+                       dev->data->dev_conf.intr_conf.lsc = 0;
+               }
                DEBUG("Configuring sub-device %d", i);
+               sdev->remove = 0;
                ret = rte_eth_dev_configure(PORT_ID(sdev),
                                        dev->data->nb_rx_queues,
                                        dev->data->nb_tx_queues,
@@ -215,6 +242,26 @@ fs_dev_configure(struct rte_eth_dev *dev)
                        ERROR("Could not configure sub_device %d", i);
                        return ret;
                }
+               if (rmv_interrupt) {
+                       ret = rte_eth_dev_callback_register(PORT_ID(sdev),
+                                       RTE_ETH_EVENT_INTR_RMV,
+                                       failsafe_eth_rmv_event_callback,
+                                       sdev);
+                       if (ret)
+                               WARN("Failed to register RMV callback for sub_device %d",
+                                    SUB_ID(sdev));
+               }
+               dev->data->dev_conf.intr_conf.rmv = 0;
+               if (lsc_interrupt) {
+                       ret = rte_eth_dev_callback_register(PORT_ID(sdev),
+                                               RTE_ETH_EVENT_INTR_LSC,
+                                               failsafe_eth_lsc_event_callback,
+                                               dev);
+                       if (ret)
+                               WARN("Failed to register LSC callback for sub_device %d",
+                                    SUB_ID(sdev));
+               }
+               dev->data->dev_conf.intr_conf.lsc = lsc_enabled;
                sdev->state = DEV_ACTIVE;
        }
        if (PRIV(dev)->state < DEV_ACTIVE)
@@ -240,7 +287,7 @@ fs_dev_start(struct rte_eth_dev *dev)
        }
        if (PRIV(dev)->state < DEV_STARTED)
                PRIV(dev)->state = DEV_STARTED;
-       fs_switch_dev(dev);
+       fs_switch_dev(dev, NULL);
        return 0;
 }
 
@@ -351,10 +398,14 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,
                fs_rx_queue_release(rxq);
                dev->data->rx_queues[rx_queue_id] = NULL;
        }
-       rxq = rte_zmalloc(NULL, sizeof(*rxq),
+       rxq = rte_zmalloc(NULL,
+                         sizeof(*rxq) +
+                         sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,
                          RTE_CACHE_LINE_SIZE);
        if (rxq == NULL)
                return -ENOMEM;
+       FOREACH_SUBDEV(sdev, i, dev)
+               rte_atomic64_init(&rxq->refcnt[i]);
        rxq->qid = rx_queue_id;
        rxq->socket_id = socket_id;
        rxq->info.mp = mb_pool;
@@ -414,10 +465,14 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,
                fs_tx_queue_release(txq);
                dev->data->tx_queues[tx_queue_id] = NULL;
        }
-       txq = rte_zmalloc("ethdev TX queue", sizeof(*txq),
+       txq = rte_zmalloc("ethdev TX queue",
+                         sizeof(*txq) +
+                         sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,
                          RTE_CACHE_LINE_SIZE);
        if (txq == NULL)
                return -ENOMEM;
+       FOREACH_SUBDEV(sdev, i, dev)
+               rte_atomic64_init(&txq->refcnt[i]);
        txq->qid = tx_queue_id;
        txq->socket_id = socket_id;
        txq->info.conf = *tx_conf;
@@ -528,13 +583,30 @@ fs_link_update(struct rte_eth_dev *dev,
        return -1;
 }
 
-static void
+static int
 fs_stats_get(struct rte_eth_dev *dev,
             struct rte_eth_stats *stats)
 {
-       if (TX_SUBDEV(dev) == NULL)
-               return;
-       rte_eth_stats_get(PORT_ID(TX_SUBDEV(dev)), stats);
+       struct sub_device *sdev;
+       uint8_t i;
+       int ret;
+
+       rte_memcpy(stats, &PRIV(dev)->stats_accumulator, sizeof(*stats));
+       FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
+               struct rte_eth_stats *snapshot = &sdev->stats_snapshot.stats;
+               uint64_t *timestamp = &sdev->stats_snapshot.timestamp;
+
+               ret = rte_eth_stats_get(PORT_ID(sdev), snapshot);
+               if (ret) {
+                       ERROR("Operation rte_eth_stats_get failed for sub_device %d with error %d",
+                                 i, ret);
+                       *timestamp = 0;
+                       return ret;
+               }
+               *timestamp = rte_rdtsc();
+               failsafe_stats_increment(stats, snapshot);
+       }
+       return 0;
 }
 
 static void
@@ -543,8 +615,11 @@ fs_stats_reset(struct rte_eth_dev *dev)
        struct sub_device *sdev;
        uint8_t i;
 
-       FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)
+       FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                rte_eth_stats_reset(PORT_ID(sdev));
+               memset(&sdev->stats_snapshot, 0, sizeof(struct rte_eth_stats));
+       }
+       memset(&PRIV(dev)->stats_accumulator, 0, sizeof(struct rte_eth_stats));
 }
 
 /**