IPoIB: Fix deadlock between dev_change_flags() and __ipoib_dev_flush()
[cascardo/linux.git] / drivers / infiniband / ulp / ipoib / ipoib_vlan.c
index 8292554..9fad7b5 100644 (file)
@@ -140,7 +140,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
        if (!rtnl_trylock())
                return restart_syscall();
 
-       mutex_lock(&ppriv->vlan_mutex);
+       down_write(&ppriv->vlan_rwsem);
 
        /*
         * First ensure this isn't a duplicate. We check the parent device and
@@ -163,7 +163,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
        result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
 
 out:
-       mutex_unlock(&ppriv->vlan_mutex);
+       up_write(&ppriv->vlan_rwsem);
 
        if (result)
                free_netdev(priv->dev);
@@ -185,7 +185,8 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 
        if (!rtnl_trylock())
                return restart_syscall();
-       mutex_lock(&ppriv->vlan_mutex);
+
+       down_write(&ppriv->vlan_rwsem);
        list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
                if (priv->pkey == pkey &&
                    priv->child_type == IPOIB_LEGACY_CHILD) {
@@ -195,7 +196,8 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
                        break;
                }
        }
-       mutex_unlock(&ppriv->vlan_mutex);
+       up_write(&ppriv->vlan_rwsem);
+
        rtnl_unlock();
 
        if (dev) {