We have to release the RTNL before calling free_netdev() so that the
device state has a chance to become NETREG_UNREGISTERED. Otherwise
when removing a child interface, we hit the BUG() that tests the
device state in free_netdev().
Reported-by: Yossi Etigin <yosefe@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
*/
if (ppriv->pkey == pkey) {
result = -ENOTUNIQ;
*/
if (ppriv->pkey == pkey) {
result = -ENOTUNIQ;
goto err;
}
list_for_each_entry(priv, &ppriv->child_intfs, list) {
if (priv->pkey == pkey) {
result = -ENOTUNIQ;
goto err;
}
list_for_each_entry(priv, &ppriv->child_intfs, list) {
if (priv->pkey == pkey) {
result = -ENOTUNIQ;
result = ipoib_set_dev_features(priv, ppriv->ca);
if (result)
result = ipoib_set_dev_features(priv, ppriv->ca);
if (result)
- goto device_init_failed;
ipoib_warn(ppriv, "failed to initialize subinterface: "
"device %s, port %d",
ppriv->ca->name, ppriv->port);
ipoib_warn(ppriv, "failed to initialize subinterface: "
"device %s, port %d",
ppriv->ca->name, ppriv->port);
- goto device_init_failed;
}
result = register_netdevice(priv->dev);
}
result = register_netdevice(priv->dev);
register_failed:
ipoib_dev_cleanup(priv->dev);
register_failed:
ipoib_dev_cleanup(priv->dev);
-device_init_failed:
- free_netdev(priv->dev);
-
err:
mutex_unlock(&ppriv->vlan_mutex);
rtnl_unlock();
err:
mutex_unlock(&ppriv->vlan_mutex);
rtnl_unlock();
+ if (priv)
+ free_netdev(priv->dev);
+
return result;
}
int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
{
struct ipoib_dev_priv *ppriv, *priv, *tpriv;
return result;
}
int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
{
struct ipoib_dev_priv *ppriv, *priv, *tpriv;
+ struct net_device *dev = NULL;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
unregister_netdevice(priv->dev);
ipoib_dev_cleanup(priv->dev);
list_del(&priv->list);
unregister_netdevice(priv->dev);
ipoib_dev_cleanup(priv->dev);
list_del(&priv->list);
- free_netdev(priv->dev);
-
- ret = 0;
break;
}
}
mutex_unlock(&ppriv->vlan_mutex);
rtnl_unlock();
break;
}
}
mutex_unlock(&ppriv->vlan_mutex);
rtnl_unlock();
+ if (dev) {
+ free_netdev(dev);
+ return 0;
+ }
+
+ return -ENODEV;