aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-07-21 04:52:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-21 15:13:42 -0400
commitbc05d19f4b884b1dbbce48912710ae3f972c89d2 (patch)
tree56f08ca551c38d9ef18f699874f1b1bb3bb8e4f3 /net/mac80211
parent9dca9c490146e787472bc05b264e043311a4c67b (diff)
mac80211: fix IBSS lockdep complaint
Bob reported a lockdep complaint originating in the mac80211 IBSS code due to the common work struct patch. The reason is that the IBSS and station mode code have different locking orders for the cfg80211 wdev lock and the work struct (where "locking" implies running/canceling). Fix this by simply not canceling the work in the IBSS code, it is not necessary since when the REQ_RUN bit is cleared, the work will run without effect if it runs. When the interface is set down, it is flushed anyway, so there's no concern about it running after memory has been invalidated either. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=16419 Additionally, looking into this I noticed that there's a small window while the IBSS is torn down in which the work may be rescheduled and the REQ_RUN bit be set again after leave() has cleared it when a scan finishes at exactly the same time. Avoid that by setting the ssid_len to zero before clearing REQ_RUN which signals to the scan finish code that this interface is not active. Reported-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ibss.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index d4e84b22a66d..090e344d5f90 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -943,11 +943,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
943 } 943 }
944 } 944 }
945 945
946 del_timer_sync(&sdata->u.ibss.timer);
947 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
948 cancel_work_sync(&sdata->work);
949 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
950
951 sta_info_flush(sdata->local, sdata); 946 sta_info_flush(sdata->local, sdata);
952 947
953 /* remove beacon */ 948 /* remove beacon */
@@ -964,6 +959,20 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
964 memset(sdata->u.ibss.bssid, 0, ETH_ALEN); 959 memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
965 sdata->u.ibss.ssid_len = 0; 960 sdata->u.ibss.ssid_len = 0;
966 961
962 /*
963 * ssid_len indicates active or not, so needs to be visible to
964 * everybody, especially ieee80211_ibss_notify_scan_completed,
965 * so it won't restart the timer after we remove it here.
966 */
967 mb();
968
969 del_timer_sync(&sdata->u.ibss.timer);
970 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
971 /*
972 * Since the REQ_RUN bit is clear, the work won't do
973 * anything if it runs after this.
974 */
975
967 ieee80211_recalc_idle(sdata->local); 976 ieee80211_recalc_idle(sdata->local);
968 977
969 return 0; 978 return 0;