From 2d9c99e37b29a639dafa431df38e1586a31ba887 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 19 Jan 2015 20:10:00 +0200 Subject: [PATCH] Retry scan-for-connect if driver trigger fails This restores some of the pre-radio work behavior for scanning by retrying scan trigger if the driver rejects it (most likely returning EBUSY in case of nl80211-drivers). Retry is indicated in the CTRL-EVENT-SCAN-FAILED event with "retry=1". For manual scans (e.g., triggered through "SCAN" control interface command), no additional retries are performed. In other words, if upper layers want to retry, they can do so based on the CTRL-EVENT-SCAN-FAILED event. Signed-off-by: Jouni Malinen --- wpa_supplicant/scan.c | 26 ++++++++++++++++++++------ wpa_supplicant/wpa_supplicant_i.h | 1 + 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 75d6a85f4..08af9fbac 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -177,11 +177,25 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) wpa_scan_free_params(params); work->ctx = NULL; if (ret) { + int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ; + + if (wpa_s->disconnected) + retry = 0; + wpa_supplicant_notify_scanning(wpa_s, 0); wpas_notify_scan_done(wpa_s, 0); - wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=%d", - ret); + if (wpa_s->wpa_state == WPA_SCANNING) + wpa_supplicant_set_state(wpa_s, + wpa_s->scan_prev_wpa_state); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=%d%s", + ret, retry ? " retry=1" : ""); radio_work_done(work); + + if (retry) { + /* Restore scan_req since we will try to scan again */ + wpa_s->scan_req = wpa_s->last_scan_req; + wpa_supplicant_req_scan(wpa_s, 1, 0); + } return; } @@ -613,7 +627,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) struct wpa_driver_scan_params params; struct wpa_driver_scan_params *scan_params; size_t max_ssids; - enum wpa_states prev_state; if (wpa_s->pno || wpa_s->pno_sched_pending) { wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress"); @@ -681,7 +694,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) os_memset(¶ms, 0, sizeof(params)); - prev_state = wpa_s->wpa_state; + wpa_s->scan_prev_wpa_state = wpa_s->wpa_state; if (wpa_s->wpa_state == WPA_DISCONNECTED || wpa_s->wpa_state == WPA_INACTIVE) wpa_supplicant_set_state(wpa_s, WPA_SCANNING); @@ -1001,8 +1014,9 @@ scan: if (ret) { wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan"); - if (prev_state != wpa_s->wpa_state) - wpa_supplicant_set_state(wpa_s, prev_state); + if (wpa_s->scan_prev_wpa_state != wpa_s->wpa_state) + wpa_supplicant_set_state(wpa_s, + wpa_s->scan_prev_wpa_state); /* Restore scan_req since we will try to scan again */ wpa_s->scan_req = wpa_s->last_scan_req; wpa_supplicant_req_scan(wpa_s, 1, 0); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index e363967c1..7f1e27fa9 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -585,6 +585,7 @@ struct wpa_supplicant { */ MANUAL_SCAN_REQ } scan_req, last_scan_req; + enum wpa_states scan_prev_wpa_state; struct os_reltime scan_trigger_time, scan_start_time; int scan_runs; /* number of scan runs since WPS was started */ int *next_scan_freqs;