diff options
author | Jouni Malinen <j@w1.fi> | 2013-11-24 20:07:05 (GMT) |
---|---|---|
committer | Jouni Malinen <j@w1.fi> | 2014-01-05 20:37:50 (GMT) |
commit | d12a51b5d2adbc5bca5df3ab459ac4fd67eeb7ef (patch) | |
tree | 86bcef302c03918e31a5e2436c5fcc40ae40a2a4 /wpa_supplicant | |
parent | b1ae396f59b1e5b31b011eb1f6bb7aa794a88f94 (diff) | |
download | hostap-d12a51b5d2adbc5bca5df3ab459ac4fd67eeb7ef.zip hostap-d12a51b5d2adbc5bca5df3ab459ac4fd67eeb7ef.tar.gz hostap-d12a51b5d2adbc5bca5df3ab459ac4fd67eeb7ef.tar.bz2 |
Use radio work for scan requests
Avoid concurrent scan requests by using the radio work queuing
mechanism.
Signed-hostap: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r-- | wpa_supplicant/events.c | 61 | ||||
-rw-r--r-- | wpa_supplicant/scan.c | 68 | ||||
-rw-r--r-- | wpa_supplicant/wpa_supplicant.c | 7 | ||||
-rw-r--r-- | wpa_supplicant/wpa_supplicant_i.h | 1 |
4 files changed, 95 insertions, 42 deletions
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index bc1b65e..b0ea7a2 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Driver event processing - * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -1181,7 +1181,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, union wpa_event_data *data, int own_request) { - struct wpa_scan_results *scan_res; + struct wpa_scan_results *scan_res = NULL; + int ret = 0; int ap = 0; #ifndef CONFIG_NO_RANDOM_POOL size_t i, num; @@ -1206,7 +1207,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpa_s->scan_req = wpa_s->last_scan_req; wpa_s->sta_scan_pending = 1; wpa_supplicant_req_scan(wpa_s, 5, 0); - return -1; + ret = -1; + goto scan_work_done; } } wpa_s->sta_scan_pending = 0; @@ -1224,7 +1226,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try " "scanning again"); wpa_supplicant_req_new_scan(wpa_s, 1, 0); - return -1; + ret = -1; + goto scan_work_done; } #ifndef CONFIG_NO_RANDOM_POOL @@ -1251,9 +1254,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, scan_res_handler = wpa_s->scan_res_handler; wpa_s->scan_res_handler = NULL; scan_res_handler(wpa_s, scan_res); - - wpa_scan_results_free(scan_res); - return -2; + ret = -2; + goto scan_work_done; } if (ap) { @@ -1262,8 +1264,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, if (wpa_s->ap_iface->scan_cb) wpa_s->ap_iface->scan_cb(wpa_s->ap_iface); #endif /* CONFIG_AP */ - wpa_scan_results_free(scan_res); - return 0; + goto scan_work_done; } wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)", @@ -1286,38 +1287,44 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, return 0; } - if (sme_proc_obss_scan(wpa_s) > 0) { - wpa_scan_results_free(scan_res); - return 0; - } + if (sme_proc_obss_scan(wpa_s) > 0) + goto scan_work_done; - if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) { - wpa_scan_results_free(scan_res); - return 0; - } + if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) + goto scan_work_done; - if (autoscan_notify_scan(wpa_s, scan_res)) { - wpa_scan_results_free(scan_res); - return 0; - } + if (autoscan_notify_scan(wpa_s, scan_res)) + goto scan_work_done; if (wpa_s->disconnected) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); - wpa_scan_results_free(scan_res); - return 0; + goto scan_work_done; } if (!wpas_driver_bss_selection(wpa_s) && - bgscan_notify_scan(wpa_s, scan_res) == 1) { - wpa_scan_results_free(scan_res); - return 0; - } + bgscan_notify_scan(wpa_s, scan_res) == 1) + goto scan_work_done; wpas_wps_update_ap_info(wpa_s, scan_res); wpa_scan_results_free(scan_res); + if (wpa_s->scan_work) { + struct wpa_radio_work *work = wpa_s->scan_work; + wpa_s->scan_work = NULL; + radio_work_done(work); + } + return wpas_select_network_from_last_scan(wpa_s, 1, own_request); + +scan_work_done: + wpa_scan_results_free(scan_res); + if (wpa_s->scan_work) { + struct wpa_radio_work *work = wpa_s->scan_work; + wpa_s->scan_work = NULL; + radio_work_done(work); + } + return ret; } diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 428a668..763fc13 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -142,34 +142,67 @@ static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, } -/** - * wpa_supplicant_trigger_scan - Request driver to start a scan - * @wpa_s: Pointer to wpa_supplicant data - * @params: Scan parameters - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, - struct wpa_driver_scan_params *params) +static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) { + struct wpa_supplicant *wpa_s = work->wpa_s; + struct wpa_driver_scan_params *params = work->ctx; int ret; + if (deinit) { + wpa_scan_free_params(params); + return; + } + wpa_supplicant_notify_scanning(wpa_s, 1); if (wpa_s->clear_driver_scan_cache) params->only_new_results = 1; ret = wpa_drv_scan(wpa_s, params); + wpa_scan_free_params(params); + work->ctx = NULL; if (ret) { wpa_supplicant_notify_scanning(wpa_s, 0); wpas_notify_scan_done(wpa_s, 0); - } else { - os_get_reltime(&wpa_s->scan_trigger_time); - wpa_s->scan_runs++; - wpa_s->normal_scans++; - wpa_s->own_scan_requested = 1; - wpa_s->clear_driver_scan_cache = 0; + radio_work_done(work); + return; } - return ret; + os_get_reltime(&wpa_s->scan_trigger_time); + wpa_s->scan_runs++; + wpa_s->normal_scans++; + wpa_s->own_scan_requested = 1; + wpa_s->clear_driver_scan_cache = 0; + wpa_s->scan_work = work; +} + + +/** + * wpa_supplicant_trigger_scan - Request driver to start a scan + * @wpa_s: Pointer to wpa_supplicant data + * @params: Scan parameters + * Returns: 0 on success, -1 on failure + */ +int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params) +{ + struct wpa_driver_scan_params *ctx; + + if (wpa_s->scan_work) { + wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending"); + return -1; + } + + ctx = wpa_scan_clone_params(params); + if (ctx == NULL) + return -1; + + if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0) + { + wpa_scan_free_params(ctx); + return -1; + } + + return 0; } @@ -1699,6 +1732,11 @@ void scan_only_handler(struct wpa_supplicant *wpa_s, } wpas_notify_scan_results(wpa_s); wpas_notify_scan_done(wpa_s, 1); + if (wpa_s->scan_work) { + struct wpa_radio_work *work = wpa_s->scan_work; + wpa_s->scan_work = NULL; + radio_work_done(work); + } } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index fa819ec..f04d60d 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2903,6 +2903,13 @@ static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s, static void radio_work_free(struct wpa_radio_work *work) { + if (work->wpa_s->scan_work == work) { + /* This should not really happen. */ + wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work", + work->type, work, work->started); + work->wpa_s->scan_work = NULL; + } + dl_list_del(&work->list); os_free(work); } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 46db3dc..c2d0a36 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -442,6 +442,7 @@ struct wpa_supplicant { struct ctrl_iface_priv *ctrl_iface; enum wpa_states wpa_state; + struct wpa_radio_work *scan_work; int scanning; int sched_scanning; int new_connection; |