aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_sta.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-18 17:29:21 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:53:00 -0400
commit79010420cc3f78eab911598bfdd29c4b06a83e1f (patch)
treea9031164d7944f8aa90a455d297780b241f3d865 /net/mac80211/ieee80211_sta.c
parentea49c359f36d5b40bf033c45a08332cb73777aa2 (diff)
[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 <johannes@sipsolutions.net> Cc: Florian Lohoff <flo@rfc822.org> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Michal Piotrowski <michal.k.k.piotrowski@gmail.com> Cc: Satyam Sharma <satyam@infradead.org> Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r--net/mac80211/ieee80211_sta.c12
1 files changed, 6 insertions, 6 deletions
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)
2676 memset(&wrqu, 0, sizeof(wrqu)); 2676 memset(&wrqu, 0, sizeof(wrqu));
2677 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); 2677 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
2678 2678
2679 read_lock(&local->sub_if_lock); 2679 rcu_read_lock();
2680 list_for_each_entry(sdata, &local->sub_if_list, list) { 2680 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2681 2681
2682 /* No need to wake the master device. */ 2682 /* No need to wake the master device. */
2683 if (sdata->dev == local->mdev) 2683 if (sdata->dev == local->mdev)
@@ -2691,7 +2691,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
2691 2691
2692 netif_wake_queue(sdata->dev); 2692 netif_wake_queue(sdata->dev);
2693 } 2693 }
2694 read_unlock(&local->sub_if_lock); 2694 rcu_read_unlock();
2695 2695
2696 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2696 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2697 if (sdata->type == IEEE80211_IF_TYPE_IBSS) { 2697 if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
@@ -2828,8 +2828,8 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
2828 2828
2829 local->sta_scanning = 1; 2829 local->sta_scanning = 1;
2830 2830
2831 read_lock(&local->sub_if_lock); 2831 rcu_read_lock();
2832 list_for_each_entry(sdata, &local->sub_if_list, list) { 2832 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2833 2833
2834 /* Don't stop the master interface, otherwise we can't transmit 2834 /* Don't stop the master interface, otherwise we can't transmit
2835 * probes! */ 2835 * probes! */
@@ -2841,7 +2841,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
2841 (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) 2841 (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
2842 ieee80211_send_nullfunc(local, sdata, 1); 2842 ieee80211_send_nullfunc(local, sdata, 1);
2843 } 2843 }
2844 read_unlock(&local->sub_if_lock); 2844 rcu_read_unlock();
2845 2845
2846 if (ssid) { 2846 if (ssid) {
2847 local->scan_ssid_len = ssid_len; 2847 local->scan_ssid_len = ssid_len;