From b9e6d7001d5408b3dd9c9e74df3f75732823d216 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Jan 2014 15:09:50 +0200 Subject: [PATCH] Use radio work for GAS requests Avoid concurrent GAS operations with any other exclusive use of the radio by using the radio work queuing mechanism. This replaces some of the earlier constraints on concurrent operations with the more generic wpa_radio work concept. Signed-hostap: Jouni Malinen --- wpa_supplicant/gas_query.c | 65 +++++++++++++++++++++++++++----------- wpa_supplicant/gas_query.h | 1 - wpa_supplicant/scan.c | 9 ------ 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index dd10a75a9..fda7c849a 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -2,6 +2,7 @@ * Generic advertisement service (GAS) query * Copyright (c) 2009, Atheros Communications * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. + * Copyright (c) 2011-2014, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -31,6 +32,7 @@ */ struct gas_query_pending { struct dl_list list; + struct gas_query *gas; u8 addr[ETH_ALEN]; u8 dialog_token; u8 next_frag_id; @@ -55,6 +57,7 @@ struct gas_query { struct wpa_supplicant *wpa_s; struct dl_list pending; /* struct gas_query_pending */ struct gas_query_pending *current; + struct wpa_radio_work *work; }; @@ -106,6 +109,25 @@ static const char * gas_result_txt(enum gas_query_result result) } +static void gas_query_free(struct gas_query_pending *query, int del_list) +{ + struct gas_query *gas = query->gas; + + if (del_list) + dl_list_del(&query->list); + + if (gas->work && gas->work->ctx == query) { + radio_work_done(gas->work); + gas->work = NULL; + } + + wpabuf_free(query->req); + wpabuf_free(query->adv_proto); + wpabuf_free(query->resp); + os_free(query); +} + + static void gas_query_done(struct gas_query *gas, struct gas_query_pending *query, enum gas_query_result result) @@ -124,10 +146,7 @@ static void gas_query_done(struct gas_query *gas, dl_list_del(&query->list); query->cb(query->ctx, query->addr, query->dialog_token, result, query->adv_proto, query->resp, query->status_code); - wpabuf_free(query->req); - wpabuf_free(query->adv_proto); - wpabuf_free(query->resp); - os_free(query); + gas_query_free(query, 0); } @@ -516,11 +535,8 @@ static void gas_service_timeout(void *eloop_data, void *user_ctx) int conn; conn = wpas_wpa_is_in_progress(wpa_s, 1); - if (conn || wpa_s->scanning || gas->current) { - wpa_printf(MSG_DEBUG, "GAS: Delaying GAS query Tx while another operation is in progress:%s%s%s", - conn ? " connection" : "", - wpa_s->scanning ? " scanning" : "", - gas->current ? " gas_query" : ""); + if (conn) { + wpa_printf(MSG_DEBUG, "GAS: Delaying GAS query Tx while connection operation is in progress"); eloop_register_timeout( GAS_SERVICE_RETRY_PERIOD_MS / 1000, (GAS_SERVICE_RETRY_PERIOD_MS % 1000) * 1000, @@ -531,9 +547,7 @@ static void gas_service_timeout(void *eloop_data, void *user_ctx) if (gas_query_tx(gas, query, query->req) < 0) { wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to " MACSTR, MAC2STR(query->addr)); - dl_list_del(&query->list); - wpabuf_free(query->req); - os_free(query); + gas_query_free(query, 1); return; } gas->current = query; @@ -559,6 +573,20 @@ static int gas_query_dialog_token_available(struct gas_query *gas, } +static void gas_query_start_cb(struct wpa_radio_work *work, int deinit) +{ + struct gas_query_pending *query = work->ctx; + + if (deinit) { + gas_query_free(query, 1); + return; + } + + query->gas->work = work; + gas_service_timeout(query->gas, query); +} + + /** * gas_query_req - Request a GAS query * @gas: GAS query data from gas_query_init() @@ -599,6 +627,7 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, if (query == NULL) return -1; + query->gas = gas; os_memcpy(query->addr, dst, ETH_ALEN); query->dialog_token = dialog_token; query->freq = freq; @@ -613,7 +642,11 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, " dialog_token=%u freq=%d", MAC2STR(query->addr), query->dialog_token, query->freq); - eloop_register_timeout(0, 0, gas_service_timeout, gas, query); + if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb, + query) < 0) { + gas_query_free(query, 1); + return -1; + } return dialog_token; } @@ -634,9 +667,3 @@ void gas_query_cancel(struct gas_query *gas, const u8 *dst, u8 dialog_token) gas_query_done(gas, query, GAS_QUERY_CANCELLED); } - - -int gas_query_in_progress(struct gas_query *gas) -{ - return gas->current != NULL; -} diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h index 6b6c77ce2..5c3d161ad 100644 --- a/wpa_supplicant/gas_query.h +++ b/wpa_supplicant/gas_query.h @@ -18,7 +18,6 @@ struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s); void gas_query_deinit(struct gas_query *gas); int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa, const u8 *bssid, const u8 *data, size_t len, int freq); -int gas_query_in_progress(struct gas_query *gas); /** * enum gas_query_result - GAS query result diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index b36c87c6e..b84d537d8 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -21,7 +21,6 @@ #include "hs20_supplicant.h" #include "notify.h" #include "bss.h" -#include "gas_query.h" #include "scan.h" @@ -582,14 +581,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) } #endif /* CONFIG_P2P */ -#ifdef CONFIG_GAS - if (gas_query_in_progress(wpa_s->gas)) { - wpa_dbg(wpa_s, MSG_DEBUG, "Delay scan while GAS query is in progress"); - wpa_supplicant_req_scan(wpa_s, 1, 0); - return; - } -#endif /* CONFIG_GAS */ - if (wpa_s->conf->ap_scan == 2) max_ssids = 1; else {