net/failsafe: add Rx queue start and stop functions
authorIan Dolzhansky <ian.dolzhansky@oktetlabs.ru>
Thu, 20 Sep 2018 13:55:51 +0000 (14:55 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 27 Sep 2018 23:41:02 +0000 (01:41 +0200)
Support Rx queue deferred start.

Signed-off-by: Ian Dolzhansky <ian.dolzhansky@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Acked-by: Gaetan Rivet <gaetan.rivet@6wind.com>
doc/guides/nics/features/failsafe.ini
doc/guides/rel_notes/release_18_11.rst
drivers/net/failsafe/failsafe_ether.c
drivers/net/failsafe/failsafe_ops.c

index 39ee579..712c0b7 100644 (file)
@@ -7,6 +7,7 @@
 Link status          = Y
 Link status event    = Y
 Rx interrupt         = Y
+Queue start/stop     = P
 MTU update           = Y
 Jumbo frame          = Y
 Promiscuous mode     = Y
index e18a8bb..485caf6 100644 (file)
@@ -72,6 +72,13 @@ New Features
   SR-IOV option in Hyper-V and Azure. This is an alternative to the previous
   vdev_netvsc, tap, and failsafe drivers combination.
 
+* **Updated failsafe driver.**
+
+  Updated the failsafe driver including the following changes:
+
+  * Support for Rx queues start and stop.
+  * Support for Rx queues deferred start.
+
 * **Added ability to switch queue deferred start flag on testpmd app.**
 
   Added a console command to testpmd app, giving ability to switch
index 5b5cb3b..305deed 100644 (file)
@@ -366,6 +366,47 @@ failsafe_dev_remove(struct rte_eth_dev *dev)
                }
 }
 
+static int
+failsafe_eth_dev_rx_queues_sync(struct rte_eth_dev *dev)
+{
+       struct rxq *rxq;
+       int ret;
+       uint16_t i;
+
+       for (i = 0; i < dev->data->nb_rx_queues; i++) {
+               rxq = dev->data->rx_queues[i];
+
+               if (rxq->info.conf.rx_deferred_start &&
+                   dev->data->rx_queue_state[i] ==
+                                               RTE_ETH_QUEUE_STATE_STARTED) {
+                       /*
+                        * The subdevice Rx queue does not launch on device
+                        * start if deferred start flag is set. It needs to be
+                        * started manually in case an appropriate failsafe Rx
+                        * queue has been started earlier.
+                        */
+                       ret = dev->dev_ops->rx_queue_start(dev, i);
+                       if (ret) {
+                               ERROR("Could not synchronize Rx queue %d", i);
+                               return ret;
+                       }
+               } else if (dev->data->rx_queue_state[i] ==
+                                               RTE_ETH_QUEUE_STATE_STOPPED) {
+                       /*
+                        * The subdevice Rx queue needs to be stopped manually
+                        * in case an appropriate failsafe Rx queue has been
+                        * stopped earlier.
+                        */
+                       ret = dev->dev_ops->rx_queue_stop(dev, i);
+                       if (ret) {
+                               ERROR("Could not synchronize Rx queue %d", i);
+                               return ret;
+                       }
+               }
+       }
+       return 0;
+}
+
 int
 failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)
 {
@@ -422,6 +463,9 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)
        if (PRIV(dev)->state < DEV_STARTED)
                return 0;
        ret = dev->dev_ops->dev_start(dev);
+       if (ret)
+               goto err_remove;
+       ret = failsafe_eth_dev_rx_queues_sync(dev);
        if (ret)
                goto err_remove;
        return 0;
index 9110521..b3bfacb 100644 (file)
@@ -168,6 +168,20 @@ fs_dev_configure(struct rte_eth_dev *dev)
        return 0;
 }
 
+static void
+fs_set_queues_state_start(struct rte_eth_dev *dev)
+{
+       struct rxq *rxq;
+       uint16_t i;
+
+       for (i = 0; i < dev->data->nb_rx_queues; i++) {
+               rxq = dev->data->rx_queues[i];
+               if (!rxq->info.conf.rx_deferred_start)
+                       dev->data->rx_queue_state[i] =
+                                               RTE_ETH_QUEUE_STATE_STARTED;
+       }
+}
+
 static int
 fs_dev_start(struct rte_eth_dev *dev)
 {
@@ -202,13 +216,24 @@ fs_dev_start(struct rte_eth_dev *dev)
                }
                sdev->state = DEV_STARTED;
        }
-       if (PRIV(dev)->state < DEV_STARTED)
+       if (PRIV(dev)->state < DEV_STARTED) {
                PRIV(dev)->state = DEV_STARTED;
+               fs_set_queues_state_start(dev);
+       }
        fs_switch_dev(dev, NULL);
        fs_unlock(dev, 0);
        return 0;
 }
 
+static void
+fs_set_queues_state_stop(struct rte_eth_dev *dev)
+{
+       uint16_t i;
+
+       for (i = 0; i < dev->data->nb_rx_queues; i++)
+               dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+}
+
 static void
 fs_dev_stop(struct rte_eth_dev *dev)
 {
@@ -223,6 +248,7 @@ fs_dev_stop(struct rte_eth_dev *dev)
                sdev->state = DEV_STARTED - 1;
        }
        failsafe_rx_intr_uninstall(dev);
+       fs_set_queues_state_stop(dev);
        fs_unlock(dev, 0);
 }
 
@@ -292,6 +318,59 @@ fs_dev_close(struct rte_eth_dev *dev)
        fs_unlock(dev, 0);
 }
 
+static int
+fs_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
+{
+       struct sub_device *sdev;
+       uint8_t i;
+       int ret;
+       int err = 0;
+       bool failure = true;
+
+       fs_lock(dev, 0);
+       FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
+               uint16_t port_id = ETH(sdev)->data->port_id;
+
+               ret = rte_eth_dev_rx_queue_stop(port_id, rx_queue_id);
+               ret = fs_err(sdev, ret);
+               if (ret) {
+                       ERROR("Rx queue stop failed for subdevice %d", i);
+                       err = ret;
+               } else {
+                       failure = false;
+               }
+       }
+       dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+       fs_unlock(dev, 0);
+       /* Return 0 in case of at least one successful queue stop */
+       return (failure) ? err : 0;
+}
+
+static int
+fs_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
+{
+       struct sub_device *sdev;
+       uint8_t i;
+       int ret;
+
+       fs_lock(dev, 0);
+       FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
+               uint16_t port_id = ETH(sdev)->data->port_id;
+
+               ret = rte_eth_dev_rx_queue_start(port_id, rx_queue_id);
+               ret = fs_err(sdev, ret);
+               if (ret) {
+                       ERROR("Rx queue start failed for subdevice %d", i);
+                       fs_rx_queue_stop(dev, rx_queue_id);
+                       fs_unlock(dev, 0);
+                       return ret;
+               }
+       }
+       dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+       fs_unlock(dev, 0);
+       return 0;
+}
+
 static void
 fs_rx_queue_release(void *queue)
 {
@@ -342,12 +421,17 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,
        uint8_t i;
        int ret;
 
+       fs_lock(dev, 0);
        if (rx_conf->rx_deferred_start) {
-               ERROR("Rx queue deferred start is not supported");
-               return -EINVAL;
+               FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
+                       if (SUBOPS(sdev, rx_queue_start) == NULL) {
+                               ERROR("Rx queue deferred start is not "
+                                       "supported for subdevice %d", i);
+                               fs_unlock(dev, 0);
+                               return -EINVAL;
+                       }
+               }
        }
-
-       fs_lock(dev, 0);
        rxq = dev->data->rx_queues[rx_queue_id];
        if (rxq != NULL) {
                fs_rx_queue_release(rxq);
@@ -1041,6 +1125,8 @@ const struct eth_dev_ops failsafe_ops = {
        .dev_supported_ptypes_get = fs_dev_supported_ptypes_get,
        .mtu_set = fs_mtu_set,
        .vlan_filter_set = fs_vlan_filter_set,
+       .rx_queue_start = fs_rx_queue_start,
+       .rx_queue_stop = fs_rx_queue_stop,
        .rx_queue_setup = fs_rx_queue_setup,
        .tx_queue_setup = fs_tx_queue_setup,
        .rx_queue_release = fs_rx_queue_release,