aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2014-01-03 09:57:57 (GMT)
committerJouni Malinen <j@w1.fi>2014-01-05 20:39:25 (GMT)
commit1b5d4714dd96de7e9175a6d916932fd49d265e1b (patch)
treec167d5ac9f01e4ebac7b44a44515b6b4017c1e5c /wpa_supplicant
parentd12a51b5d2adbc5bca5df3ab459ac4fd67eeb7ef (diff)
downloadhostap-1b5d4714dd96de7e9175a6d916932fd49d265e1b.zip
hostap-1b5d4714dd96de7e9175a6d916932fd49d265e1b.tar.gz
hostap-1b5d4714dd96de7e9175a6d916932fd49d265e1b.tar.bz2
Use radio work for P2P scan requests
Avoid concurrent P2P scan requests with any other exclusive use of the radio by using the radio work queuing mechanism. This removes some of the earlier workarounds that postponed scans depending on other operations. Signed-hostap: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/events.c25
-rw-r--r--wpa_supplicant/p2p_supplicant.c160
-rw-r--r--wpa_supplicant/p2p_supplicant.h5
-rw-r--r--wpa_supplicant/scan.c19
-rw-r--r--wpa_supplicant/wpa_supplicant.c13
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h3
6 files changed, 97 insertions, 128 deletions
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index b0ea7a2..566f148 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -978,9 +978,6 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request "
"since there are no enabled networks");
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
-#ifdef CONFIG_P2P
- wpa_s->sta_scan_pending = 0;
-#endif /* CONFIG_P2P */
return;
}
@@ -1195,25 +1192,6 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
wpa_supplicant_notify_scanning(wpa_s, 0);
-#ifdef CONFIG_P2P
- if (own_request && wpa_s->global->p2p_cb_on_scan_complete &&
- !wpa_s->global->p2p_disabled &&
- wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending &&
- !wpa_s->scan_res_handler) {
- wpa_s->global->p2p_cb_on_scan_complete = 0;
- if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
- "stopped scan processing");
- wpa_s->scan_req = wpa_s->last_scan_req;
- wpa_s->sta_scan_pending = 1;
- wpa_supplicant_req_scan(wpa_s, 5, 0);
- ret = -1;
- goto scan_work_done;
- }
- }
- wpa_s->sta_scan_pending = 0;
-#endif /* CONFIG_P2P */
-
scan_res = wpa_supplicant_get_scan_results(wpa_s,
data ? &data->scan_info :
NULL, 1);
@@ -2885,9 +2863,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_supplicant_event_scan_results(wpa_s, data);
wpa_s->own_scan_running = 0;
wpa_s->external_scan_running = 0;
- if (wpa_s->wpa_state != WPA_AUTHENTICATING &&
- wpa_s->wpa_state != WPA_ASSOCIATING)
- wpas_p2p_continue_after_scan(wpa_s);
break;
#endif /* CONFIG_NO_SCAN_PROCESSING */
case EVENT_ASSOCINFO:
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index a71cbbe..e84db58 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1,6 +1,7 @@
/*
* wpa_supplicant - P2P
* Copyright (c) 2009-2010, Atheros Communications
+ * Copyright (c) 2010-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -196,6 +197,12 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
{
size_t i;
+ if (wpa_s->p2p_scan_work) {
+ struct wpa_radio_work *work = wpa_s->p2p_scan_work;
+ wpa_s->p2p_scan_work = NULL;
+ radio_work_done(work);
+ }
+
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return;
@@ -234,95 +241,125 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
}
+static void wpas_p2p_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;
+ }
+
+ ret = wpa_drv_scan(wpa_s, params);
+ wpa_scan_free_params(params);
+ work->ctx = NULL;
+ if (ret) {
+ radio_work_done(work);
+ return;
+ }
+
+ os_get_reltime(&wpa_s->scan_trigger_time);
+ wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
+ wpa_s->own_scan_requested = 1;
+ wpa_s->p2p_scan_work = work;
+}
+
+
static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
unsigned int num_req_dev_types,
const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
{
struct wpa_supplicant *wpa_s = ctx;
- struct wpa_supplicant *ifs;
- struct wpa_driver_scan_params params;
- int ret;
+ struct wpa_driver_scan_params *params = NULL;
struct wpabuf *wps_ie, *ies;
- int social_channels[] = { 2412, 2437, 2462, 0, 0 };
size_t ielen;
+ u8 *n;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
- for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
- if (ifs->sta_scan_pending &&
- (wpas_scan_scheduled(ifs) || ifs->scanning) &&
- wpas_p2p_in_progress(wpa_s) == 2) {
- wpa_printf(MSG_DEBUG, "Delaying P2P scan to allow "
- "pending station mode scan to be "
- "completed on interface %s", ifs->ifname);
- wpa_s->global->p2p_cb_on_scan_complete = 1;
- wpa_supplicant_req_scan(ifs, 0, 0);
- return 1;
- }
+ if (wpa_s->p2p_scan_work) {
+ wpa_dbg(wpa_s, MSG_INFO, "P2P: Reject scan trigger since one is already pending");
+ return -1;
}
- os_memset(&params, 0, sizeof(params));
+ params = os_zalloc(sizeof(*params));
+ if (params == NULL)
+ return -1;
/* P2P Wildcard SSID */
- params.num_ssids = 1;
- params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
- params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+ params->num_ssids = 1;
+ n = os_malloc(P2P_WILDCARD_SSID_LEN);
+ if (n == NULL)
+ goto fail;
+ os_memcpy(n, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
+ params->ssids[0].ssid = n;
+ params->ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
wpa_s->wps->dev.p2p = 1;
wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
wpa_s->wps->uuid, WPS_REQ_ENROLLEE,
num_req_dev_types, req_dev_types);
if (wps_ie == NULL)
- return -1;
+ goto fail;
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
if (ies == NULL) {
wpabuf_free(wps_ie);
- return -1;
+ goto fail;
}
wpabuf_put_buf(ies, wps_ie);
wpabuf_free(wps_ie);
p2p_scan_ie(wpa_s->global->p2p, ies, dev_id);
- params.p2p_probe = 1;
- params.extra_ies = wpabuf_head(ies);
- params.extra_ies_len = wpabuf_len(ies);
+ params->p2p_probe = 1;
+ n = os_malloc(wpabuf_len(ies));
+ if (n == NULL) {
+ wpabuf_free(ies);
+ goto fail;
+ }
+ os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies));
+ params->extra_ies = n;
+ params->extra_ies_len = wpabuf_len(ies);
+ wpabuf_free(ies);
switch (type) {
case P2P_SCAN_SOCIAL:
- params.freqs = social_channels;
+ params->freqs = os_malloc(4 * sizeof(int));
+ if (params->freqs == NULL)
+ goto fail;
+ params->freqs[0] = 2412;
+ params->freqs[1] = 2437;
+ params->freqs[2] = 2462;
+ params->freqs[3] = 0;
break;
case P2P_SCAN_FULL:
break;
case P2P_SCAN_SOCIAL_PLUS_ONE:
- social_channels[3] = freq;
- params.freqs = social_channels;
+ params->freqs = os_malloc(5 * sizeof(int));
+ if (params->freqs == NULL)
+ goto fail;
+ params->freqs[0] = 2412;
+ params->freqs[1] = 2437;
+ params->freqs[2] = 2462;
+ params->freqs[3] = freq;
+ params->freqs[4] = 0;
break;
}
- ret = wpa_drv_scan(wpa_s, &params);
-
- wpabuf_free(ies);
-
- if (ret) {
- for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
- if (ifs->scanning ||
- ifs->scan_res_handler == wpas_p2p_scan_res_handler) {
- wpa_s->global->p2p_cb_on_scan_complete = 1;
- ret = 1;
- break;
- }
- }
- } else {
- os_get_reltime(&wpa_s->scan_trigger_time);
- wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
- wpa_s->own_scan_requested = 1;
- }
+ radio_remove_unstarted_work(wpa_s, "p2p-scan");
+ if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb,
+ params) < 0)
+ goto fail;
+ return 0;
- return ret;
+fail:
+ wpa_scan_free_params(params);
+ return -1;
}
@@ -513,7 +550,6 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
wpa_config_remove_network(wpa_s->conf, id);
wpa_supplicant_clear_status(wpa_s);
wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_s->sta_scan_pending = 0;
} else {
wpa_printf(MSG_DEBUG, "P2P: Temporary group network not "
"found");
@@ -5092,7 +5128,6 @@ static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s)
wpa_s->p2p_long_listen = 0;
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
- wpa_s->global->p2p_cb_on_scan_complete = 0;
if (wpa_s->global->p2p)
p2p_stop_find(wpa_s->global->p2p);
@@ -5408,7 +5443,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
}
if (!wpa_s->show_group_started || !ssid)
- goto done;
+ return;
wpa_s->show_group_started = 0;
@@ -5450,9 +5485,6 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
if (network_id < 0)
network_id = ssid->id;
wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1);
-
-done:
- wpas_p2p_continue_after_scan(wpa_s);
}
@@ -6250,30 +6282,6 @@ unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s)
}
-void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s)
-{
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Station mode scan operation not "
- "pending anymore (sta_scan_pending=%d "
- "p2p_cb_on_scan_complete=%d)", wpa_s->sta_scan_pending,
- wpa_s->global->p2p_cb_on_scan_complete);
- wpa_s->sta_scan_pending = 0;
-
- if (!wpa_s->global->p2p_cb_on_scan_complete)
- return;
- wpa_s->global->p2p_cb_on_scan_complete = 0;
-
- if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
- return;
-
- if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
- "continued after successful connection");
- p2p_increase_search_delay(wpa_s->global->p2p,
- wpas_p2p_search_delay(wpa_s));
- }
-}
-
-
static int wpas_p2p_remove_psk_entry(struct wpa_supplicant *wpa_s,
struct wpa_ssid *s, const u8 *addr,
int iface_addr)
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 9605136..49122ca 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -149,14 +149,9 @@ void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
int iface_addr);
#ifdef CONFIG_P2P
-void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s);
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);
void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s);
#else /* CONFIG_P2P */
-static inline void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s)
-{
-}
-
static inline int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
{
return 0;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 763fc13..b36c87c 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -524,14 +524,12 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
- wpas_p2p_continue_after_scan(wpa_s);
return;
}
if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
- wpas_p2p_continue_after_scan(wpa_s);
return;
}
@@ -560,7 +558,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
wpa_s->scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
- wpas_p2p_continue_after_scan(wpa_s);
return;
}
@@ -579,18 +576,9 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
#ifdef CONFIG_P2P
if (wpas_p2p_in_progress(wpa_s) || wpas_wpa_is_in_progress(wpa_s, 0)) {
- if (wpa_s->sta_scan_pending &&
- wpas_p2p_in_progress(wpa_s) == 2 &&
- wpa_s->global->p2p_cb_on_scan_complete) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Process pending station "
- "mode scan during P2P search");
- } else {
- wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan "
- "while P2P operation is in progress");
- wpa_s->sta_scan_pending = 1;
- wpa_supplicant_req_scan(wpa_s, 5, 0);
- return;
- }
+ wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
+ wpa_supplicant_req_scan(wpa_s, 5, 0);
+ return;
}
#endif /* CONFIG_P2P */
@@ -1202,7 +1190,6 @@ void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
{
wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
- wpas_p2p_continue_after_scan(wpa_s);
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f04d60d..138e975 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -195,8 +195,6 @@ static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
* So, wait a second until scanning again.
*/
wpa_supplicant_req_scan(wpa_s, 1, 0);
-
- wpas_p2p_continue_after_scan(wpa_s);
}
@@ -2910,6 +2908,15 @@ static void radio_work_free(struct wpa_radio_work *work)
work->wpa_s->scan_work = NULL;
}
+#ifdef CONFIG_P2P
+ if (work->wpa_s->p2p_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 p2p_scan_work",
+ work->type, work, work->started);
+ work->wpa_s->p2p_scan_work = NULL;
+ }
+#endif /* CONFIG_P2P */
+
dl_list_del(&work->list);
os_free(work);
}
@@ -3966,8 +3973,6 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
*/
wpa_supplicant_req_scan(wpa_s, timeout / 1000,
1000 * (timeout % 1000));
-
- wpas_p2p_continue_after_scan(wpa_s);
}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index c2d0a36..25739f1 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -257,7 +257,6 @@ struct wpa_global {
WPA_CONC_PREF_STA,
WPA_CONC_PREF_P2P
} conc_pref;
- unsigned int p2p_cb_on_scan_complete:1;
unsigned int p2p_per_sta_psk:1;
#ifdef CONFIG_WIFI_DISPLAY
@@ -680,7 +679,6 @@ struct wpa_supplicant {
*/
char cross_connect_uplink[100];
- unsigned int sta_scan_pending:1;
unsigned int p2p_auto_join:1;
unsigned int p2p_auto_pd:1;
unsigned int p2p_persistent_group:1;
@@ -698,6 +696,7 @@ struct wpa_supplicant {
int p2p_connect_freq;
struct os_reltime p2p_auto_started;
struct wpa_ssid *p2p_last_4way_hs_fail;
+ struct wpa_radio_work *p2p_scan_work;
#endif /* CONFIG_P2P */
struct wpa_ssid *bgscan_ssid;