]> git.droids-corp.org - dpdk.git/commitdiff
net/failsafe: fix removed device handling
authorMatan Azrad <matan@mellanox.com>
Sat, 20 Jan 2018 21:12:24 +0000 (21:12 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Sun, 21 Jan 2018 20:09:43 +0000 (21:09 +0100)
There is time between the physical removal of the device until
sub-device PMDs get a RMV interrupt. At this time DPDK PMDs and
applications still don't know about the removal and may call sub-device
control operation which should return an error.

In previous code this error is reported to the application contrary to
fail-safe principle that the app should not be aware of device removal.

Add an removal check in each relevant control command error flow and
prevent an error report to application when the sub-device is removed.

Signed-off-by: Matan Azrad <matan@mellanox.com>
Acked-by: Gaetan Rivet <gaetan.rivet@6wind.com>
drivers/net/failsafe/failsafe_flow.c
drivers/net/failsafe/failsafe_ops.c
drivers/net/failsafe/failsafe_private.h

index 153ceeed480ea3be8a0b451cb3ca1f2c7273937a..c072d1e9162d67b781c757283782a3e5e22211e2 100644 (file)
@@ -87,7 +87,7 @@ fs_flow_validate(struct rte_eth_dev *dev,
                DEBUG("Calling rte_flow_validate on sub_device %d", i);
                ret = rte_flow_validate(PORT_ID(sdev),
                                attr, patterns, actions, error);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_flow_validate failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
@@ -111,7 +111,7 @@ fs_flow_create(struct rte_eth_dev *dev,
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                flow->flows[i] = rte_flow_create(PORT_ID(sdev),
                                attr, patterns, actions, error);
-               if (flow->flows[i] == NULL) {
+               if (flow->flows[i] == NULL && fs_err(sdev, -rte_errno)) {
                        ERROR("Failed to create flow on sub_device %d",
                                i);
                        goto err;
@@ -150,7 +150,7 @@ fs_flow_destroy(struct rte_eth_dev *dev,
                        continue;
                local_ret = rte_flow_destroy(PORT_ID(sdev),
                                flow->flows[i], error);
-               if (local_ret) {
+               if ((local_ret = fs_err(sdev, local_ret))) {
                        ERROR("Failed to destroy flow on sub_device %d: %d",
                                        i, local_ret);
                        if (ret == 0)
@@ -175,7 +175,7 @@ fs_flow_flush(struct rte_eth_dev *dev,
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling rte_flow_flush on sub_device %d", i);
                ret = rte_flow_flush(PORT_ID(sdev), error);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_flow_flush failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
@@ -199,8 +199,12 @@ fs_flow_query(struct rte_eth_dev *dev,
 
        sdev = TX_SUBDEV(dev);
        if (sdev != NULL) {
-               return rte_flow_query(PORT_ID(sdev),
-                               flow->flows[SUB_ID(sdev)], type, arg, error);
+               int ret = rte_flow_query(PORT_ID(sdev),
+                                        flow->flows[SUB_ID(sdev)],
+                                        type, arg, error);
+
+               if ((ret = fs_err(sdev, ret)))
+                       return ret;
        }
        WARN("No active sub_device to query about its flow");
        return -1;
@@ -223,7 +227,7 @@ fs_flow_isolate(struct rte_eth_dev *dev,
                        WARN("flow isolation mode of sub_device %d in incoherent state.",
                                i);
                ret = rte_flow_isolate(PORT_ID(sdev), set, error);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_flow_isolate failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
index 3384c3d95deaea14bb0c65971c6f5cc9d92858d7..42aaf9107674e1c825962684f877f4631916e6da 100644 (file)
@@ -160,6 +160,8 @@ fs_dev_configure(struct rte_eth_dev *dev)
                                        dev->data->nb_tx_queues,
                                        &dev->data->dev_conf);
                if (ret) {
+                       if (!fs_err(sdev, ret))
+                               continue;
                        ERROR("Could not configure sub_device %d", i);
                        return ret;
                }
@@ -202,8 +204,11 @@ fs_dev_start(struct rte_eth_dev *dev)
                        continue;
                DEBUG("Starting sub_device %d", i);
                ret = rte_eth_dev_start(PORT_ID(sdev));
-               if (ret)
+               if (ret) {
+                       if (!fs_err(sdev, ret))
+                               continue;
                        return ret;
+               }
                sdev->state = DEV_STARTED;
        }
        if (PRIV(dev)->state < DEV_STARTED)
@@ -235,7 +240,7 @@ fs_dev_set_link_up(struct rte_eth_dev *dev)
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling rte_eth_dev_set_link_up on sub_device %d", i);
                ret = rte_eth_dev_set_link_up(PORT_ID(sdev));
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_eth_dev_set_link_up failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
@@ -254,7 +259,7 @@ fs_dev_set_link_down(struct rte_eth_dev *dev)
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling rte_eth_dev_set_link_down on sub_device %d", i);
                ret = rte_eth_dev_set_link_down(PORT_ID(sdev));
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_eth_dev_set_link_down failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
@@ -371,7 +376,7 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,
                                rx_queue_id,
                                nb_rx_desc, socket_id,
                                rx_conf, mb_pool);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("RX queue setup failed for sub_device %d", i);
                        goto free_rxq;
                }
@@ -473,7 +478,7 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,
                                tx_queue_id,
                                nb_tx_desc, socket_id,
                                tx_conf);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("TX queue setup failed for sub_device %d", i);
                        goto free_txq;
                }
@@ -552,7 +557,8 @@ fs_link_update(struct rte_eth_dev *dev,
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling link_update on sub_device %d", i);
                ret = (SUBOPS(sdev, link_update))(ETH(sdev), wait_to_complete);
-               if (ret && ret != -1) {
+               if (ret && ret != -1 && sdev->remove == 0 &&
+                   rte_eth_dev_is_removed(PORT_ID(sdev)) == 0) {
                        ERROR("Link update failed for sub_device %d with error %d",
                              i, ret);
                        return ret;
@@ -576,6 +582,7 @@ static int
 fs_stats_get(struct rte_eth_dev *dev,
             struct rte_eth_stats *stats)
 {
+       struct rte_eth_stats backup;
        struct sub_device *sdev;
        uint8_t i;
        int ret;
@@ -585,14 +592,20 @@ fs_stats_get(struct rte_eth_dev *dev,
                struct rte_eth_stats *snapshot = &sdev->stats_snapshot.stats;
                uint64_t *timestamp = &sdev->stats_snapshot.timestamp;
 
+               rte_memcpy(&backup, snapshot, sizeof(backup));
                ret = rte_eth_stats_get(PORT_ID(sdev), snapshot);
                if (ret) {
+                       if (!fs_err(sdev, ret)) {
+                               rte_memcpy(snapshot, &backup, sizeof(backup));
+                               goto inc;
+                       }
                        ERROR("Operation rte_eth_stats_get failed for sub_device %d with error %d",
                                  i, ret);
                        *timestamp = 0;
                        return ret;
                }
                *timestamp = rte_rdtsc();
+inc:
                failsafe_stats_increment(stats, snapshot);
        }
        return 0;
@@ -712,7 +725,7 @@ fs_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling rte_eth_dev_set_mtu on sub_device %d", i);
                ret = rte_eth_dev_set_mtu(PORT_ID(sdev), mtu);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_eth_dev_set_mtu failed for sub_device %d with error %d",
                              i, ret);
                        return ret;
@@ -731,7 +744,7 @@ fs_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling rte_eth_dev_vlan_filter on sub_device %d", i);
                ret = rte_eth_dev_vlan_filter(PORT_ID(sdev), vlan_id, on);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_eth_dev_vlan_filter failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
@@ -765,7 +778,7 @@ fs_flow_ctrl_set(struct rte_eth_dev *dev,
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling rte_eth_dev_flow_ctrl_set on sub_device %d", i);
                ret = rte_eth_dev_flow_ctrl_set(PORT_ID(sdev), fc_conf);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_eth_dev_flow_ctrl_set failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
@@ -802,7 +815,7 @@ fs_mac_addr_add(struct rte_eth_dev *dev,
        RTE_ASSERT(index < FAILSAFE_MAX_ETHADDR);
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), mac_addr, vmdq);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_eth_dev_mac_addr_add failed for sub_device %"
                              PRIu8 " with error %d", i, ret);
                        return ret;
@@ -844,7 +857,7 @@ fs_filter_ctrl(struct rte_eth_dev *dev,
        FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
                DEBUG("Calling rte_eth_dev_filter_ctrl on sub_device %d", i);
                ret = rte_eth_dev_filter_ctrl(PORT_ID(sdev), type, op, arg);
-               if (ret) {
+               if ((ret = fs_err(sdev, ret))) {
                        ERROR("Operation rte_eth_dev_filter_ctrl failed for sub_device %d"
                              " with error %d", i, ret);
                        return ret;
index 9fcf72e4594d132f25679318ab9ac4ee619f1c1b..491636537417c39e4a2a95108ba70348dd02a438 100644 (file)
@@ -381,4 +381,15 @@ fs_switch_dev(struct rte_eth_dev *dev,
        rte_wmb();
 }
 
+/*
+ * Adjust error value and rte_errno to the fail-safe actual error value.
+ */
+static inline int
+fs_err(struct sub_device *sdev, int err)
+{
+       /* A device removal shouldn't be reported as an error. */
+       if (sdev->remove == 1 || err == -EIO)
+               return rte_errno = 0;
+       return err;
+}
 #endif /* _RTE_ETH_FAILSAFE_PRIVATE_H_ */