Reset external_scan_running on interface deletion
Currently, the external_scan_running flag is not reset when an interface is removed. Thus, if a connection attempt is made on another iface, it will fail due to wpa_supplicant incorrectly assuming the radio is still busy due to the ongoing scan. To fix this, convert external_scan_running to a pointer to the interface that started the scan. If this interface is removed, also reset the pointer to NULL so that other operations may continue on this radio. Test: 1. Start scan on wlan0 2. Remove wlan0 3. Can connect to a network on wlan1 Signed-off-by: David Su <dysu@google.com>
This commit is contained in:
parent
630b1fdba8
commit
11355a122d
4 changed files with 23 additions and 8 deletions
|
@ -4792,7 +4792,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
|
wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
|
||||||
wpa_s->radio->external_scan_running = 1;
|
wpa_s->radio->external_scan_req_interface = wpa_s;
|
||||||
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
|
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4800,7 +4800,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
|
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
|
||||||
wpa_s->scan_res_handler = NULL;
|
wpa_s->scan_res_handler = NULL;
|
||||||
wpa_s->own_scan_running = 0;
|
wpa_s->own_scan_running = 0;
|
||||||
wpa_s->radio->external_scan_running = 0;
|
wpa_s->radio->external_scan_req_interface = NULL;
|
||||||
wpa_s->last_scan_req = NORMAL_SCAN_REQ;
|
wpa_s->last_scan_req = NORMAL_SCAN_REQ;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4820,7 +4820,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
if (!(data && data->scan_info.external_scan))
|
if (!(data && data->scan_info.external_scan))
|
||||||
wpa_s->own_scan_running = 0;
|
wpa_s->own_scan_running = 0;
|
||||||
if (data && data->scan_info.nl_scan_event)
|
if (data && data->scan_info.nl_scan_event)
|
||||||
wpa_s->radio->external_scan_running = 0;
|
wpa_s->radio->external_scan_req_interface = NULL;
|
||||||
radio_work_check_next(wpa_s);
|
radio_work_check_next(wpa_s);
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_NO_SCAN_PROCESSING */
|
#endif /* CONFIG_NO_SCAN_PROCESSING */
|
||||||
|
|
|
@ -247,7 +247,7 @@ static void wpas_p2p_scan_res_handled(struct wpa_supplicant *wpa_s)
|
||||||
unsigned int delay = wpas_p2p_search_delay(wpa_s);
|
unsigned int delay = wpas_p2p_search_delay(wpa_s);
|
||||||
|
|
||||||
/* In case of concurrent P2P and external scans, delay P2P search. */
|
/* In case of concurrent P2P and external scans, delay P2P search. */
|
||||||
if (wpa_s->radio->external_scan_running) {
|
if (external_scan_running(wpa_s->radio)) {
|
||||||
delay = wpa_s->conf->p2p_search_delay;
|
delay = wpa_s->conf->p2p_search_delay;
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"P2P: Delay next P2P search by %d ms to let externally triggered scan complete",
|
"P2P: Delay next P2P search by %d ms to let externally triggered scan complete",
|
||||||
|
|
|
@ -5868,7 +5868,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
|
||||||
dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
|
dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
|
||||||
list) {
|
list) {
|
||||||
if (os_strcmp(tmp->type, "scan") == 0 &&
|
if (os_strcmp(tmp->type, "scan") == 0 &&
|
||||||
radio->external_scan_running &&
|
external_scan_running(radio) &&
|
||||||
(((struct wpa_driver_scan_params *)
|
(((struct wpa_driver_scan_params *)
|
||||||
tmp->ctx)->only_new_results ||
|
tmp->ctx)->only_new_results ||
|
||||||
tmp->wpa_s->clear_driver_scan_cache))
|
tmp->wpa_s->clear_driver_scan_cache))
|
||||||
|
@ -5924,7 +5924,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
|
||||||
* rejected by kernel.
|
* rejected by kernel.
|
||||||
*/
|
*/
|
||||||
if (os_strcmp(tmp->type, "scan") == 0 &&
|
if (os_strcmp(tmp->type, "scan") == 0 &&
|
||||||
radio->external_scan_running &&
|
external_scan_running(radio) &&
|
||||||
(((struct wpa_driver_scan_params *)
|
(((struct wpa_driver_scan_params *)
|
||||||
tmp->ctx)->only_new_results ||
|
tmp->ctx)->only_new_results ||
|
||||||
tmp->wpa_s->clear_driver_scan_cache))
|
tmp->wpa_s->clear_driver_scan_cache))
|
||||||
|
@ -5963,7 +5963,7 @@ static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
|
||||||
if (work->started)
|
if (work->started)
|
||||||
return; /* already started and still in progress */
|
return; /* already started and still in progress */
|
||||||
|
|
||||||
if (wpa_s && wpa_s->radio->external_scan_running) {
|
if (wpa_s && external_scan_running(wpa_s->radio)) {
|
||||||
wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
|
wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -6059,6 +6059,10 @@ static void radio_remove_interface(struct wpa_supplicant *wpa_s)
|
||||||
wpa_s->ifname, radio->name);
|
wpa_s->ifname, radio->name);
|
||||||
dl_list_del(&wpa_s->radio_list);
|
dl_list_del(&wpa_s->radio_list);
|
||||||
radio_remove_works(wpa_s, NULL, 0);
|
radio_remove_works(wpa_s, NULL, 0);
|
||||||
|
/* If the interface that triggered the external scan was removed, the
|
||||||
|
* external scan is no longer running. */
|
||||||
|
if (wpa_s == radio->external_scan_req_interface)
|
||||||
|
radio->external_scan_req_interface = NULL;
|
||||||
wpa_s->radio = NULL;
|
wpa_s->radio = NULL;
|
||||||
if (!dl_list_empty(&radio->ifaces))
|
if (!dl_list_empty(&radio->ifaces))
|
||||||
return; /* Interfaces remain for this radio */
|
return; /* Interfaces remain for this radio */
|
||||||
|
|
|
@ -332,12 +332,23 @@ struct wpa_global {
|
||||||
struct wpa_radio {
|
struct wpa_radio {
|
||||||
char name[16]; /* from driver_ops get_radio_name() or empty if not
|
char name[16]; /* from driver_ops get_radio_name() or empty if not
|
||||||
* available */
|
* available */
|
||||||
unsigned int external_scan_running:1;
|
/** NULL if no external scan running. */
|
||||||
|
struct wpa_supplicant *external_scan_req_interface;
|
||||||
unsigned int num_active_works;
|
unsigned int num_active_works;
|
||||||
struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
|
struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
|
||||||
struct dl_list work; /* struct wpa_radio_work::list entries */
|
struct dl_list work; /* struct wpa_radio_work::list entries */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether an external scan is running on a given radio.
|
||||||
|
* @radio: Pointer to radio struct
|
||||||
|
* Returns: true if an external scan is running, false otherwise.
|
||||||
|
*/
|
||||||
|
static inline bool external_scan_running(struct wpa_radio *radio)
|
||||||
|
{
|
||||||
|
return radio && radio->external_scan_req_interface;
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_ACTIVE_WORKS 2
|
#define MAX_ACTIVE_WORKS 2
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue