Use radio work for GAS requests
authorJouni Malinen <j@w1.fi>
Fri, 3 Jan 2014 13:09:50 +0000 (15:09 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 7 Jan 2014 08:45:09 +0000 (10:45 +0200)
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 <j@w1.fi>

wpa_supplicant/gas_query.c
wpa_supplicant/gas_query.h
wpa_supplicant/scan.c

index dd10a75..fda7c84 100644 (file)
@@ -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 <j@w1.fi>
  *
  * 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;
-}
index 6b6c77c..5c3d161 100644 (file)
@@ -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
index b36c87c..b84d537 100644 (file)
@@ -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 {