diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-09-18 17:29:21 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:53:00 -0400 |
commit | 79010420cc3f78eab911598bfdd29c4b06a83e1f (patch) | |
tree | a9031164d7944f8aa90a455d297780b241f3d865 /net/mac80211/rx.c | |
parent | ea49c359f36d5b40bf033c45a08332cb73777aa2 (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/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2535d8d4ce90..cb44a9db0e19 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1383,8 +1383,9 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1383 | } | 1383 | } |
1384 | 1384 | ||
1385 | /* | 1385 | /* |
1386 | * key references are protected using RCU and this requires that | 1386 | * key references and virtual interfaces are protected using RCU |
1387 | * we are in a read-site RCU section during receive processing | 1387 | * and this requires that we are in a read-side RCU section during |
1388 | * receive processing | ||
1388 | */ | 1389 | */ |
1389 | rcu_read_lock(); | 1390 | rcu_read_lock(); |
1390 | 1391 | ||
@@ -1439,8 +1440,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1439 | 1440 | ||
1440 | bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len); | 1441 | bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len); |
1441 | 1442 | ||
1442 | read_lock(&local->sub_if_lock); | 1443 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
1443 | list_for_each_entry(sdata, &local->sub_if_list, list) { | ||
1444 | rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; | 1444 | rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; |
1445 | 1445 | ||
1446 | if (!netif_running(sdata->dev)) | 1446 | if (!netif_running(sdata->dev)) |
@@ -1493,7 +1493,6 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1493 | &rx, sta); | 1493 | &rx, sta); |
1494 | } else | 1494 | } else |
1495 | dev_kfree_skb(skb); | 1495 | dev_kfree_skb(skb); |
1496 | read_unlock(&local->sub_if_lock); | ||
1497 | 1496 | ||
1498 | end: | 1497 | end: |
1499 | rcu_read_unlock(); | 1498 | rcu_read_unlock(); |