Retry initial 20/40 MHz co-ex scan if the driver is busy
authorPeng Xu <pxu@qca.qualcomm.com>
Wed, 16 Apr 2014 15:45:53 +0000 (18:45 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 29 Apr 2014 09:52:09 +0000 (12:52 +0300)
This makes the initial OBSS scans in AP mode before starting 40 MHz BSS
more robust. In addition, HT20 can be used as a backup option if none of
the scans succeed.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/hostapd.c
src/ap/hostapd.h
src/ap/hw_features.c
src/ap/hw_features.h

index 3398859..391d774 100644 (file)
@@ -1355,6 +1355,7 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
 
 #ifdef CONFIG_IEEE80211N
 #ifdef NEED_AP_MLME
+       hostapd_stop_setup_timers(iface);
        eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
 #endif /* NEED_AP_MLME */
 #endif /* CONFIG_IEEE80211N */
index dba9bb2..bd85c54 100644 (file)
@@ -363,6 +363,7 @@ struct hostapd_iface {
 #endif /* CONFIG_ACS */
 
        void (*scan_cb)(struct hostapd_iface *iface);
+       int num_ht40_scan_tries;
 };
 
 /* hostapd.c */
index 43cb243..b361834 100644 (file)
@@ -602,9 +602,55 @@ static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface,
 }
 
 
+static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
+{
+#define HT2040_COEX_SCAN_RETRY 15
+       struct hostapd_iface *iface = eloop_data;
+       struct wpa_driver_scan_params params;
+       int ret;
+
+       os_memset(&params, 0, sizeof(params));
+       if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
+               ieee80211n_scan_channels_2g4(iface, &params);
+       else
+               ieee80211n_scan_channels_5g(iface, &params);
+
+       ret = hostapd_driver_scan(iface->bss[0], &params);
+       iface->num_ht40_scan_tries++;
+       os_free(params.freqs);
+
+       if (ret == -EBUSY &&
+           iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) {
+               wpa_printf(MSG_ERROR,
+                          "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)",
+                          ret, strerror(-ret), iface->num_ht40_scan_tries);
+               eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
+               return;
+       }
+
+       if (ret == 0) {
+               iface->scan_cb = ieee80211n_check_scan;
+               return;
+       }
+
+       wpa_printf(MSG_DEBUG,
+                  "Failed to request a scan in device, bringing up in HT20 mode");
+       iface->conf->secondary_channel = 0;
+       iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+       hostapd_setup_interface_complete(iface, 0);
+}
+
+
+void hostapd_stop_setup_timers(struct hostapd_iface *iface)
+{
+       eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
+}
+
+
 static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
 {
        struct wpa_driver_scan_params params;
+       int ret;
 
        if (!iface->conf->secondary_channel)
                return 0; /* HT40 not used */
@@ -617,13 +663,26 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
                ieee80211n_scan_channels_2g4(iface, &params);
        else
                ieee80211n_scan_channels_5g(iface, &params);
-       if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
-               wpa_printf(MSG_ERROR, "Failed to request a scan of "
-                          "neighboring BSSes");
-               os_free(params.freqs);
+
+       ret = hostapd_driver_scan(iface->bss[0], &params);
+       os_free(params.freqs);
+
+       if (ret == -EBUSY) {
+               wpa_printf(MSG_ERROR,
+                          "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again",
+                          ret, strerror(-ret));
+               iface->num_ht40_scan_tries = 1;
+               eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
+               eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
+               return 1;
+       }
+
+       if (ret < 0) {
+               wpa_printf(MSG_ERROR,
+                          "Failed to request a scan of neighboring BSSes ret=%d (%s)",
+                          ret, strerror(-ret));
                return -1;
        }
-       os_free(params.freqs);
 
        iface->scan_cb = ieee80211n_check_scan;
        return 1;
index 783ae5e..0f67ab8 100644 (file)
@@ -23,6 +23,7 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
 int hostapd_check_ht_capab(struct hostapd_iface *iface);
 int hostapd_prepare_rates(struct hostapd_iface *iface,
                          struct hostapd_hw_modes *mode);
+void hostapd_stop_setup_timers(struct hostapd_iface *iface);
 #else /* NEED_AP_MLME */
 static inline void
 hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -61,6 +62,10 @@ static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
        return 0;
 }
 
+static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface)
+{
+}
+
 #endif /* NEED_AP_MLME */
 
 #endif /* HW_FEATURES_H */