hostapd: Allow ACS to be offloaded to the driver

Using QCA vendor command, allow ACS function to be offloaded to the
driver. Once channels are selected, hostapd is notified to perform OBSS
operation.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Peng Xu 2014-11-18 20:11:09 +02:00 committed by Jouni Malinen
parent f34891a3af
commit 16689c7cfc
10 changed files with 242 additions and 1 deletions

View file

@ -816,6 +816,14 @@ enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
wpa_printf(MSG_INFO, "ACS: Automatic channel selection started, this may take a bit");
if (iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) {
wpa_printf(MSG_INFO, "ACS: Offloading to driver");
err = hostapd_drv_do_acs(iface->bss[0]);
if (err)
return HOSTAPD_CHAN_INVALID;
return HOSTAPD_CHAN_ACS;
}
acs_cleanup(iface);
err = acs_request_scan(iface);

View file

@ -793,3 +793,18 @@ int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
qos_map_set_len);
}
int hostapd_drv_do_acs(struct hostapd_data *hapd)
{
struct drv_acs_params params;
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
return 0;
os_memset(&params, 0, sizeof(params));
params.hw_mode = hapd->iface->conf->hw_mode;
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
params.ht40_enabled = !!(hapd->iface->conf->ht_capab |
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
return hapd->driver->do_acs(hapd->drv_priv, &params);
}

View file

@ -111,6 +111,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, int mode,
int vht_enabled, int sec_channel_offset,
int vht_oper_chwidth, int center_segment0,
int center_segment1, u32 vht_caps);
int hostapd_drv_do_acs(struct hostapd_data *hapd);
#include "drivers/driver.h"

View file

@ -525,6 +525,51 @@ void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
}
#ifdef CONFIG_ACS
static void hostapd_acs_channel_selected(struct hostapd_data *hapd,
u8 pri_channel, u8 sec_channel)
{
int channel;
int ret;
if (hapd->iconf->channel) {
wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
hapd->iconf->channel);
return;
}
hapd->iface->freq = hostapd_hw_get_freq(hapd, pri_channel);
channel = pri_channel;
if (!channel) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver switched to bad channel");
return;
}
hapd->iconf->channel = channel;
if (sec_channel == 0)
hapd->iconf->secondary_channel = 0;
else if (sec_channel < pri_channel)
hapd->iconf->secondary_channel = -1;
else if (sec_channel > pri_channel)
hapd->iconf->secondary_channel = 1;
else {
wpa_printf(MSG_ERROR, "Invalid secondary channel!");
return;
}
ret = hostapd_acs_completed(hapd->iface, 0);
if (ret) {
wpa_printf(MSG_ERROR,
"ACS: Possibly channel configuration is invalid");
}
}
#endif /* CONFIG_ACS */
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len,
int ssi_signal)
@ -1169,6 +1214,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_INTERFACE_DISABLED:
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
break;
#ifdef CONFIG_ACS
case EVENT_ACS_CHANNEL_SELECTED:
hostapd_acs_channel_selected(
hapd, data->acs_selected_channels.pri_channel,
data->acs_selected_channels.sec_channel);
break;
#endif /* CONFIG_ACS */
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;