Use radio work for scan requests
Avoid concurrent scan requests by using the radio work queuing mechanism. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
b1ae396f59
commit
d12a51b5d2
4 changed files with 96 additions and 43 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -142,6 +142,40 @@ static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
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);
|
||||
radio_work_done(work);
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -151,25 +185,24 @@ static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
|
|||
int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_driver_scan_params *params)
|
||||
{
|
||||
int ret;
|
||||
struct wpa_driver_scan_params *ctx;
|
||||
|
||||
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);
|
||||
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;
|
||||
if (wpa_s->scan_work) {
|
||||
wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue