cfg80211: fix locking and lockdep complaints
authorJohannes Berg <johannes.berg@intel.com>
Tue, 10 Jul 2012 17:39:02 +0000 (19:39 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 12 Jul 2012 10:10:49 +0000 (12:10 +0200)
To call cfg80211_get_chan_state() we need to lock
the wdev, so we need to lock the wdev_iter mutex
in cfg80211_can_use_iftype_chan(). This needs to
use nested locking for lockdep.

Also, cfg80211_get_chan_state() doesn't actually
use the rdev, so remove that completely including
the lock assertion that isn't needed.

Reported-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/chan.c
net/wireless/core.h
net/wireless/util.c

index 434c56b..1cc4b7c 100644 (file)
@@ -103,15 +103,13 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
 }
 
 void
-cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
-                       struct wireless_dev *wdev,
+cfg80211_get_chan_state(struct wireless_dev *wdev,
                        struct ieee80211_channel **chan,
                        enum cfg80211_chan_mode *chanmode)
 {
        *chan = NULL;
        *chanmode = CHAN_MODE_UNDEFINED;
 
-       ASSERT_RDEV_LOCK(rdev);
        ASSERT_WDEV_LOCK(wdev);
 
        if (!netif_running(wdev->netdev))
index eae5a25..bac97da 100644 (file)
@@ -463,8 +463,7 @@ cfg80211_can_use_chan(struct cfg80211_registered_device *rdev,
 }
 
 void
-cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
-                       struct wireless_dev *wdev,
+cfg80211_get_chan_state(struct wireless_dev *wdev,
                        struct ieee80211_channel **chan,
                        enum cfg80211_chan_mode *chanmode);
 
index f7a0647..26f8cd3 100644 (file)
@@ -1059,7 +1059,16 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
                if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
                        continue;
 
-               cfg80211_get_chan_state(rdev, wdev_iter, &ch, &chmode);
+               /*
+                * We may be holding the "wdev" mutex, but now need to lock
+                * wdev_iter. This is OK because once we get here wdev_iter
+                * is not wdev (tested above), but we need to use the nested
+                * locking for lockdep.
+                */
+               mutex_lock_nested(&wdev_iter->mtx, 1);
+               __acquire(wdev_iter->mtx);
+               cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
+               wdev_unlock(wdev_iter);
 
                switch (chmode) {
                case CHAN_MODE_UNDEFINED: