aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-07-28 21:54:45 -0400
committerLuciano Coelho <luciano.coelho@nokia.com>2010-09-28 05:15:05 -0400
commit76a029fbfb18c42f75c891842df26605ef87add0 (patch)
treeb5e27bc9faba4bfda46af1e23cef4a19a2d896b6 /drivers
parentc2c192ac6c16e2e8f5cc8cf54e02bb1d4e0e761d (diff)
wl1271: Fix scan race condition
In the scan state machine, the wl1271_mutex is unlocked first then relocked, and then the scan state variables are modified. This makes it possible for ieee80211_scan_complete to be called twice in some scenarios, as the scan completion event from the firmware may be processed while the mutex is unlocked. To fix the issue, move the ieee80211_scan_complete call last in the function. This is generally safer, but there still may be issues is functions calling the scan state machine rely on states checked before the unlocking of the global mutex. (forward ported from 2.6.32 -- this is not strictly needed anymore, because the mutex doesn't need to be unlocked anymore, but I'm applying this change anyway, so that the call to ieee80211_scan_complete is in the same place) Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Saravanan Dhanabal <ext-saravanan.dhanabal@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c2
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_scan.c3
2 files changed, 2 insertions, 3 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 45d4ce36343c..02ad6c648115 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1015,10 +1015,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1015 ieee80211_enable_dyn_ps(wl->vif); 1015 ieee80211_enable_dyn_ps(wl->vif);
1016 1016
1017 if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { 1017 if (wl->scan.state != WL1271_SCAN_STATE_IDLE) {
1018 ieee80211_scan_completed(wl->hw, true);
1019 wl->scan.state = WL1271_SCAN_STATE_IDLE; 1018 wl->scan.state = WL1271_SCAN_STATE_IDLE;
1020 kfree(wl->scan.scanned_ch); 1019 kfree(wl->scan.scanned_ch);
1021 wl->scan.scanned_ch = NULL; 1020 wl->scan.scanned_ch = NULL;
1021 ieee80211_scan_completed(wl->hw, true);
1022 } 1022 }
1023 1023
1024 wl->state = WL1271_STATE_OFF; 1024 wl->state = WL1271_STATE_OFF;
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 9c80ba9b6be0..8ceaabe26e64 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -215,12 +215,11 @@ void wl1271_scan_stm(struct wl1271 *wl)
215 break; 215 break;
216 216
217 case WL1271_SCAN_STATE_DONE: 217 case WL1271_SCAN_STATE_DONE:
218 ieee80211_scan_completed(wl->hw, false);
219
220 kfree(wl->scan.scanned_ch); 218 kfree(wl->scan.scanned_ch);
221 wl->scan.scanned_ch = NULL; 219 wl->scan.scanned_ch = NULL;
222 220
223 wl->scan.state = WL1271_SCAN_STATE_IDLE; 221 wl->scan.state = WL1271_SCAN_STATE_IDLE;
222 ieee80211_scan_completed(wl->hw, false);
224 break; 223 break;
225 224
226 default: 225 default: