From 7fa56233aeef5ff10927a8b66cc029dcf0ed83f7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Apr 2012 12:12:32 +0300 Subject: [PATCH] Scan only affected frequencies for 20/40 MHz co-ex check for When starting an AP with HT40 on 2.4 GHz, limit the set of channels to scan for based on the affected frequency range to speed up the AP setup. Signed-hostap: Jouni Malinen --- src/ap/hw_features.c | 49 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 8c6fef2f8..76c42118d 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -2,7 +2,7 @@ * hostapd / Hardware feature query and different modes * Copyright 2002-2003, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008-2011, Jouni Malinen + * Copyright (c) 2008-2012, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -416,7 +416,7 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface) int res; /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is - * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */ + * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ iface->scan_cb = NULL; @@ -447,6 +447,46 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface) } +static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, + struct wpa_driver_scan_params *params) +{ + /* Scan only the affected frequency range */ + int pri_freq, sec_freq; + int affected_start, affected_end; + int i, pos; + struct hostapd_hw_modes *mode; + + if (iface->current_mode == NULL) + return; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + if (iface->conf->secondary_channel > 0) + sec_freq = pri_freq + 20; + else + sec_freq = pri_freq - 20; + affected_start = (pri_freq + sec_freq) / 2 - 25; + affected_end = (pri_freq + sec_freq) / 2 + 25; + wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + + mode = iface->current_mode; + params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int)); + if (params->freqs == NULL) + return; + pos = 0; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + if (chan->freq < affected_start || + chan->freq > affected_end) + continue; + params->freqs[pos++] = chan->freq; + } +} + + static int ieee80211n_check_40mhz(struct hostapd_iface *iface) { struct wpa_driver_scan_params params; @@ -457,12 +497,15 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface) wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " "40 MHz channel"); os_memset(¶ms, 0, sizeof(params)); - /* TODO: scan only the needed frequency */ + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + ieee80211n_scan_channels_2g4(iface, ¶ms); if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { wpa_printf(MSG_ERROR, "Failed to request a scan of " "neighboring BSSes"); + os_free(params.freqs); return -1; } + os_free(params.freqs); iface->scan_cb = ieee80211n_check_scan; return 1;