[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>
This commit is contained in:
committed by
David S. Miller
parent
ea49c359f3
commit
79010420cc
@@ -1383,8 +1383,9 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
/*
|
||||
* key references are protected using RCU and this requires that
|
||||
* we are in a read-site RCU section during receive processing
|
||||
* key references and virtual interfaces are protected using RCU
|
||||
* and this requires that we are in a read-side RCU section during
|
||||
* receive processing
|
||||
*/
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -1439,8 +1440,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
|
||||
bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len);
|
||||
|
||||
read_lock(&local->sub_if_lock);
|
||||
list_for_each_entry(sdata, &local->sub_if_list, list) {
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
|
||||
|
||||
if (!netif_running(sdata->dev))
|
||||
@@ -1493,7 +1493,6 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
&rx, sta);
|
||||
} else
|
||||
dev_kfree_skb(skb);
|
||||
read_unlock(&local->sub_if_lock);
|
||||
|
||||
end:
|
||||
rcu_read_unlock();
|
||||
|
Reference in New Issue
Block a user