wl1271: Move scan complete invocation into work function
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>
Tue, 24 Aug 2010 03:28:03 +0000 (06:28 +0300)
committerLuciano Coelho <luciano.coelho@nokia.com>
Tue, 28 Sep 2010 09:30:03 +0000 (12:30 +0300)
The current scan implementation can jam, if the scan request ends up
containing no work. This can especially happen if there is a scan request
with only 11a band channels for HW that does not support 11a.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
drivers/net/wireless/wl12xx/wl1271.h
drivers/net/wireless/wl12xx/wl1271_main.c
drivers/net/wireless/wl12xx/wl1271_scan.c
drivers/net/wireless/wl12xx/wl1271_scan.h

index 763ece823c5444af8e1fc1443c84ff8549847778..272cff44ab53dfa7269e81f04e410105db3d32f7 100644 (file)
@@ -416,6 +416,7 @@ struct wl1271 {
 
        /* Are we currently scanning */
        struct wl1271_scan scan;
+       struct work_struct scan_complete_work;
 
        /* Our association ID */
        u16 aid;
index 4b8f3662101fa56e13276dc446e56bbdd493c9be..0026e775bb0d4da1aafa84c8dbc631d21fe12dfb 100644 (file)
@@ -634,6 +634,8 @@ static int wl1271_setup(struct wl1271 *wl)
 
        INIT_WORK(&wl->irq_work, wl1271_irq_work);
        INIT_WORK(&wl->tx_work, wl1271_tx_work);
+       INIT_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+
        return 0;
 }
 
@@ -962,6 +964,8 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
        struct wl1271 *wl = hw->priv;
        int i;
 
+       cancel_work_sync(&wl->scan_complete_work);
+
        mutex_lock(&wl->mutex);
        wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
 
index 8d30150f3f46764bf09c418fd91c57000d8a8ab3..9f1da82ed8d61e11141c05c6dad430b4a9e759fa 100644 (file)
 #include "wl1271_scan.h"
 #include "wl1271_acx.h"
 
+void wl1271_scan_complete_work(struct work_struct *work)
+{
+       struct wl1271 *wl =
+               container_of(work, struct wl1271, scan_complete_work);
+
+       wl1271_debug(DEBUG_SCAN, "Scanning complete");
+
+       mutex_lock(&wl->mutex);
+       wl->scan.state = WL1271_SCAN_STATE_IDLE;
+       kfree(wl->scan.scanned_ch);
+       wl->scan.scanned_ch = NULL;
+       mutex_unlock(&wl->mutex);
+
+       ieee80211_scan_completed(wl->hw, false);
+}
+
+
 static int wl1271_get_scan_channels(struct wl1271 *wl,
                                    struct cfg80211_scan_request *req,
                                    struct basic_scan_channel_params *channels,
@@ -218,11 +235,7 @@ void wl1271_scan_stm(struct wl1271 *wl)
                break;
 
        case WL1271_SCAN_STATE_DONE:
-               kfree(wl->scan.scanned_ch);
-               wl->scan.scanned_ch = NULL;
-
-               wl->scan.state = WL1271_SCAN_STATE_IDLE;
-               ieee80211_scan_completed(wl->hw, false);
+               ieee80211_queue_work(wl->hw, &wl->scan_complete_work);
                break;
 
        default:
index f1815700f5f9da97464cba2f727920fd45d8f219..1404e00dc963067cf7593691d79c431439f6a002 100644 (file)
@@ -32,6 +32,7 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
                                const u8 *ssid, size_t ssid_len,
                                const u8 *ie, size_t ie_len, u8 band);
 void wl1271_scan_stm(struct wl1271 *wl);
+void wl1271_scan_complete_work(struct work_struct *work);
 
 #define WL1271_SCAN_MAX_CHANNELS       24
 #define WL1271_SCAN_DEFAULT_TAG        1