IB/ipoib: Add child to parent list only if device initialized
authorValentine Fatiev <valentinef@mellanox.com>
Sun, 30 Jun 2019 13:48:41 +0000 (16:48 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 4 Jul 2019 17:20:54 +0000 (14:20 -0300)
Despite failure in ipoib_dev_init() we continue with initialization flow
and creation of child device. It causes to the situation where this child
device is added too early to parent device list.

Change the logic, so in case of failure we properly return error from
ipoib_dev_init() and add child only in success path.

Fixes: eaeb39842508 ("IB/ipoib: Move init code to ndo_init")
Signed-off-by: Valentine Fatiev <valentinef@mellanox.com>
Reviewed-by: Feras Daoud <ferasda@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/ulp/ipoib/ipoib_main.c

index 9b5e11d3fb85c58616af0c80abae7cb2b95953c9..bb904ec511bea26c567685edab19a37fb1c1e3c9 100644 (file)
@@ -1893,12 +1893,6 @@ static void ipoib_child_init(struct net_device *ndev)
        struct ipoib_dev_priv *priv = ipoib_priv(ndev);
        struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent);
 
-       dev_hold(priv->parent);
-
-       down_write(&ppriv->vlan_rwsem);
-       list_add_tail(&priv->list, &ppriv->child_intfs);
-       up_write(&ppriv->vlan_rwsem);
-
        priv->max_ib_mtu = ppriv->max_ib_mtu;
        set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
        memcpy(priv->dev->dev_addr, ppriv->dev->dev_addr, INFINIBAND_ALEN);
@@ -1941,6 +1935,17 @@ static int ipoib_ndo_init(struct net_device *ndev)
        if (rc) {
                pr_warn("%s: failed to initialize device: %s port %d (ret = %d)\n",
                        priv->ca->name, priv->dev->name, priv->port, rc);
+               return rc;
+       }
+
+       if (priv->parent) {
+               struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent);
+
+               dev_hold(priv->parent);
+
+               down_write(&ppriv->vlan_rwsem);
+               list_add_tail(&priv->list, &ppriv->child_intfs);
+               up_write(&ppriv->vlan_rwsem);
        }
 
        return 0;
@@ -1958,6 +1963,14 @@ static void ipoib_ndo_uninit(struct net_device *dev)
         */
        WARN_ON(!list_empty(&priv->child_intfs));
 
+       if (priv->parent) {
+               struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent);
+
+               down_write(&ppriv->vlan_rwsem);
+               list_del(&priv->list);
+               up_write(&ppriv->vlan_rwsem);
+       }
+
        ipoib_neigh_hash_uninit(dev);
 
        ipoib_ib_dev_cleanup(dev);
@@ -1969,15 +1982,8 @@ static void ipoib_ndo_uninit(struct net_device *dev)
                priv->wq = NULL;
        }
 
-       if (priv->parent) {
-               struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent);
-
-               down_write(&ppriv->vlan_rwsem);
-               list_del(&priv->list);
-               up_write(&ppriv->vlan_rwsem);
-
+       if (priv->parent)
                dev_put(priv->parent);
-       }
 }
 
 static int ipoib_set_vf_link_state(struct net_device *dev, int vf, int link_state)