Fix a deadlock between child interface creation/deletion and ipoib
start/stop. The former takes vlan_mutex, and then might take RTNL via
register_netdev()/unregister_netdev(). The latter is executed with
RTNL held, and tries to take vlan_mutex, which can lead to an AB-BA
deadlock.
Fix this by having the child interface creation/deletion code take the
RTNL first so vlan_mutex always nests inside RTNL. We can use
register_netdevice() for child interfaces because we form the
interface name from the parent interface and hence don't need the '%'
expansion of register_netdev().
Reported-by: Yossi Etigin <yosefe@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
ppriv = netdev_priv(pdev);
ppriv = netdev_priv(pdev);
mutex_lock(&ppriv->vlan_mutex);
/*
mutex_lock(&ppriv->vlan_mutex);
/*
goto device_init_failed;
}
goto device_init_failed;
}
- result = register_netdev(priv->dev);
+ result = register_netdevice(priv->dev);
if (result) {
ipoib_warn(priv, "failed to initialize; error %i", result);
goto register_failed;
if (result) {
ipoib_warn(priv, "failed to initialize; error %i", result);
goto register_failed;
list_add_tail(&priv->list, &ppriv->child_intfs);
mutex_unlock(&ppriv->vlan_mutex);
list_add_tail(&priv->list, &ppriv->child_intfs);
mutex_unlock(&ppriv->vlan_mutex);
return 0;
sysfs_failed:
ipoib_delete_debug_files(priv->dev);
return 0;
sysfs_failed:
ipoib_delete_debug_files(priv->dev);
- unregister_netdev(priv->dev);
+ unregister_netdevice(priv->dev);
register_failed:
ipoib_dev_cleanup(priv->dev);
register_failed:
ipoib_dev_cleanup(priv->dev);
err:
mutex_unlock(&ppriv->vlan_mutex);
err:
mutex_unlock(&ppriv->vlan_mutex);
ppriv = netdev_priv(pdev);
ppriv = netdev_priv(pdev);
mutex_lock(&ppriv->vlan_mutex);
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
if (priv->pkey == pkey) {
mutex_lock(&ppriv->vlan_mutex);
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
if (priv->pkey == pkey) {
- unregister_netdev(priv->dev);
+ unregister_netdevice(priv->dev);
ipoib_dev_cleanup(priv->dev);
list_del(&priv->list);
free_netdev(priv->dev);
ipoib_dev_cleanup(priv->dev);
list_del(&priv->list);
free_netdev(priv->dev);
}
}
mutex_unlock(&ppriv->vlan_mutex);
}
}
mutex_unlock(&ppriv->vlan_mutex);