diff options
author | Arik Nemtsov <arik@wizery.com> | 2011-02-12 16:24:20 -0500 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-02-22 11:06:36 -0500 |
commit | a100885d9dfd8685e0b4e442afc9041ee4c90586 (patch) | |
tree | 554a0aac55b22fa5760b9c58979a976a247f717d /drivers/net/wireless | |
parent | 92fe9b5f112c77dbb63f42f7bed885d709586106 (diff) |
wl12xx: avoid blocking while holding rcu lock on bss info change
Some blocking functions were called while holding the rcu lock for
accessing STA information. This can lead to a deadlock.
Save the required info beforehand and release the rcu without
blocking.
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index cf8b3cebe9d6..d51d55998f4e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -2222,6 +2222,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2222 | u32 sta_rate_set = 0; | 2222 | u32 sta_rate_set = 0; |
2223 | int ret; | 2223 | int ret; |
2224 | struct ieee80211_sta *sta; | 2224 | struct ieee80211_sta *sta; |
2225 | bool sta_exists = false; | ||
2226 | struct ieee80211_sta_ht_cap sta_ht_cap; | ||
2225 | 2227 | ||
2226 | if (is_ibss) { | 2228 | if (is_ibss) { |
2227 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, | 2229 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, |
@@ -2293,16 +2295,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2293 | if (sta->ht_cap.ht_supported) | 2295 | if (sta->ht_cap.ht_supported) |
2294 | sta_rate_set |= | 2296 | sta_rate_set |= |
2295 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); | 2297 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); |
2298 | sta_ht_cap = sta->ht_cap; | ||
2299 | sta_exists = true; | ||
2300 | } | ||
2301 | rcu_read_unlock(); | ||
2296 | 2302 | ||
2303 | if (sta_exists) { | ||
2297 | /* handle new association with HT and HT information change */ | 2304 | /* handle new association with HT and HT information change */ |
2298 | if ((changed & BSS_CHANGED_HT) && | 2305 | if ((changed & BSS_CHANGED_HT) && |
2299 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { | 2306 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { |
2300 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, | 2307 | ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, |
2301 | true); | 2308 | true); |
2302 | if (ret < 0) { | 2309 | if (ret < 0) { |
2303 | wl1271_warning("Set ht cap true failed %d", | 2310 | wl1271_warning("Set ht cap true failed %d", |
2304 | ret); | 2311 | ret); |
2305 | rcu_read_unlock(); | ||
2306 | goto out; | 2312 | goto out; |
2307 | } | 2313 | } |
2308 | ret = wl1271_acx_set_ht_information(wl, | 2314 | ret = wl1271_acx_set_ht_information(wl, |
@@ -2310,23 +2316,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2310 | if (ret < 0) { | 2316 | if (ret < 0) { |
2311 | wl1271_warning("Set ht information failed %d", | 2317 | wl1271_warning("Set ht information failed %d", |
2312 | ret); | 2318 | ret); |
2313 | rcu_read_unlock(); | ||
2314 | goto out; | 2319 | goto out; |
2315 | } | 2320 | } |
2316 | } | 2321 | } |
2317 | /* handle new association without HT and disassociation */ | 2322 | /* handle new association without HT and disassociation */ |
2318 | else if (changed & BSS_CHANGED_ASSOC) { | 2323 | else if (changed & BSS_CHANGED_ASSOC) { |
2319 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, | 2324 | ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, |
2320 | false); | 2325 | false); |
2321 | if (ret < 0) { | 2326 | if (ret < 0) { |
2322 | wl1271_warning("Set ht cap false failed %d", | 2327 | wl1271_warning("Set ht cap false failed %d", |
2323 | ret); | 2328 | ret); |
2324 | rcu_read_unlock(); | ||
2325 | goto out; | 2329 | goto out; |
2326 | } | 2330 | } |
2327 | } | 2331 | } |
2328 | } | 2332 | } |
2329 | rcu_read_unlock(); | ||
2330 | 2333 | ||
2331 | if ((changed & BSS_CHANGED_ASSOC)) { | 2334 | if ((changed & BSS_CHANGED_ASSOC)) { |
2332 | if (bss_conf->assoc) { | 2335 | if (bss_conf->assoc) { |