From 79010420cc3f78eab911598bfdd29c4b06a83e1f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 18 Sep 2007 17:29:21 -0400 Subject: [PATCH] mac80211: fix virtual interface locking Florian Lohoff noticed a bug in mac80211: when bringing the master interface down while other virtual interfaces are up we call dev_close() under a spinlock which is not allowed. This patch removes the sub_if_lock used by mac80211 in favour of using an RCU list. All list manipulations are already done under rtnl so are well protected against each other, and the read-side locks we took in the RX and TX code are already in RCU read-side critical sections. Signed-off-by: Johannes Berg Cc: Florian Lohoff Cc: Herbert Xu Cc: Michal Piotrowski Cc: Satyam Sharma Signed-off-by: Michael Wu Signed-off-by: John W. Linville --- net/mac80211/ieee80211_sta.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net/mac80211/ieee80211_sta.c') diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 17455c6a5229..651aaba1add4 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -2676,8 +2676,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) memset(&wrqu, 0, sizeof(wrqu)); wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); - read_lock(&local->sub_if_lock); - list_for_each_entry(sdata, &local->sub_if_list, list) { + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { /* No need to wake the master device. */ if (sdata->dev == local->mdev) @@ -2691,7 +2691,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) netif_wake_queue(sdata->dev); } - read_unlock(&local->sub_if_lock); + rcu_read_unlock(); sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->type == IEEE80211_IF_TYPE_IBSS) { @@ -2828,8 +2828,8 @@ static int ieee80211_sta_start_scan(struct net_device *dev, local->sta_scanning = 1; - read_lock(&local->sub_if_lock); - list_for_each_entry(sdata, &local->sub_if_list, list) { + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { /* Don't stop the master interface, otherwise we can't transmit * probes! */ @@ -2841,7 +2841,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) ieee80211_send_nullfunc(local, sdata, 1); } - read_unlock(&local->sub_if_lock); + rcu_read_unlock(); if (ssid) { local->scan_ssid_len = ssid_len; -- cgit v1.2.3