Fail-safe PMD expects to get -ENODEV error value if sub PMD control
command fails because of device removal.

Make control callbacks return with -ENODEV when the device has
disappeared.

Signed-off-by: Matan Azrad <ma...@mellanox.com>
---
 drivers/net/mlx4/mlx4.h        |  1 +
 drivers/net/mlx4/mlx4_ethdev.c | 38 ++++++++++++++++++++++++++++++++++----
 drivers/net/mlx4/mlx4_flow.c   |  2 ++
 drivers/net/mlx4/mlx4_intr.c   |  5 ++++-
 drivers/net/mlx4/mlx4_rxq.c    |  1 +
 drivers/net/mlx4/mlx4_txq.c    |  1 +
 6 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index e0a9853..cac9654 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -149,6 +149,7 @@ int mlx4_flow_ctrl_get(struct rte_eth_dev *dev,
                       struct rte_eth_fc_conf *fc_conf);
 int mlx4_flow_ctrl_set(struct rte_eth_dev *dev,
                       struct rte_eth_fc_conf *fc_conf);
+int mlx4_removed(const struct priv *priv);
 
 /* mlx4_intr.c */
 
diff --git a/drivers/net/mlx4/mlx4_ethdev.c b/drivers/net/mlx4/mlx4_ethdev.c
index b0acd12..76914b0 100644
--- a/drivers/net/mlx4/mlx4_ethdev.c
+++ b/drivers/net/mlx4/mlx4_ethdev.c
@@ -312,6 +312,8 @@
 
        ret = mlx4_sysfs_write(priv, name, value_str, (sizeof(value_str) - 1));
        if (ret < 0) {
+               if (mlx4_removed(priv))
+                       ret = -ENODEV;
                DEBUG("cannot write %s `%s' (%lu) to sysfs: %s",
                      name, value_str, value, strerror(rte_errno));
                return ret;
@@ -340,15 +342,19 @@
 
        if (sock == -1) {
                rte_errno = errno;
-               return -rte_errno;
+               goto error;
        }
        ret = mlx4_get_ifname(priv, &ifr->ifr_name);
        if (!ret && ioctl(sock, req, ifr) == -1) {
                rte_errno = errno;
-               ret = -rte_errno;
+               close(sock);
+               goto error;
        }
        close(sock);
        return ret;
+error:
+       mlx4_removed(priv);
+       return -rte_errno;
 }
 
 /**
@@ -473,13 +479,17 @@
        if (up) {
                err = mlx4_set_flags(priv, ~IFF_UP, IFF_UP);
                if (err)
-                       return err;
+                       goto error;
        } else {
                err = mlx4_set_flags(priv, ~IFF_UP, ~IFF_UP);
                if (err)
-                       return err;
+                       goto error;
        }
        return 0;
+error:
+       if (mlx4_removed(priv))
+               return -ENODEV;
+       return err;
 }
 
 /**
@@ -947,6 +957,7 @@ enum rxmode_toggle {
 
        ifr.ifr_data = (void *)&ethpause;
        if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) {
+               mlx4_removed(priv);
                ret = rte_errno;
                WARN("ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM)"
                     " failed: %s",
@@ -1002,6 +1013,7 @@ enum rxmode_toggle {
        else
                ethpause.tx_pause = 0;
        if (mlx4_ifreq(priv, SIOCETHTOOL, &ifr)) {
+               mlx4_removed(priv);
                ret = rte_errno;
                WARN("ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
                     " failed: %s",
@@ -1013,3 +1025,21 @@ enum rxmode_toggle {
        assert(ret >= 0);
        return -ret;
 }
+/**
+ * Check if mlx4 device was removed.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ *
+ * @return
+ *   -ENODEV when device is removed and rte_errno is set, otherwise 0.
+ */
+int
+mlx4_removed(const struct priv *priv)
+{
+       struct ibv_device_attr device_attr;
+
+       if (ibv_query_device(priv->ctx, &device_attr) == EIO)
+               return -(rte_errno = ENODEV);
+       return 0;
+}
diff --git a/drivers/net/mlx4/mlx4_flow.c b/drivers/net/mlx4/mlx4_flow.c
index 8b87b29..606c888 100644
--- a/drivers/net/mlx4/mlx4_flow.c
+++ b/drivers/net/mlx4/mlx4_flow.c
@@ -1069,6 +1069,8 @@ struct mlx4_drop {
        err = errno;
        msg = "flow rule rejected by device";
 error:
+       if (mlx4_removed(priv))
+               err = ENODEV;
        return rte_flow_error_set
                (error, err, RTE_FLOW_ERROR_TYPE_HANDLE, flow, msg);
 }
diff --git a/drivers/net/mlx4/mlx4_intr.c b/drivers/net/mlx4/mlx4_intr.c
index b17d109..0ebdb28 100644
--- a/drivers/net/mlx4/mlx4_intr.c
+++ b/drivers/net/mlx4/mlx4_intr.c
@@ -359,7 +359,10 @@
                        ret = EINVAL;
        }
        if (ret) {
-               rte_errno = ret;
+               if (mlx4_removed(dev->data->dev_private))
+                       ret = ENODEV;
+               else
+                       rte_errno = ret;
                WARN("unable to disable interrupt on rx queue %d",
                     idx);
        } else {
diff --git a/drivers/net/mlx4/mlx4_rxq.c b/drivers/net/mlx4/mlx4_rxq.c
index 7fe21b6..43dad26 100644
--- a/drivers/net/mlx4/mlx4_rxq.c
+++ b/drivers/net/mlx4/mlx4_rxq.c
@@ -832,6 +832,7 @@ void mlx4_rss_detach(struct mlx4_rss *rss)
        ret = rte_errno;
        mlx4_rx_queue_release(rxq);
        rte_errno = ret;
+       mlx4_removed(priv);
        assert(rte_errno > 0);
        return -rte_errno;
 }
diff --git a/drivers/net/mlx4/mlx4_txq.c b/drivers/net/mlx4/mlx4_txq.c
index a9c5bd2..09bdfd8 100644
--- a/drivers/net/mlx4/mlx4_txq.c
+++ b/drivers/net/mlx4/mlx4_txq.c
@@ -372,6 +372,7 @@ struct txq_mp2mr_mbuf_check_data {
        ret = rte_errno;
        mlx4_tx_queue_release(txq);
        rte_errno = ret;
+       mlx4_removed(priv);
        assert(rte_errno > 0);
        return -rte_errno;
 }
-- 
1.8.3.1

Reply via email to