aboutsummaryrefslogtreecommitdiffstats
path: root/src/ap
diff options
context:
space:
mode:
authorPeng Xu <pxu@qca.qualcomm.com>2014-11-18 18:11:09 (GMT)
committerJouni Malinen <j@w1.fi>2014-12-03 20:31:53 (GMT)
commit16689c7cfc99c66aecbf16eb2f4a8bc941cb5d0f (patch)
tree99569ec2374d7de19dcbc60749e221270334635d /src/ap
parentf34891a3af5148f48472ae225026b462b58225bd (diff)
downloadhostap-16689c7cfc99c66aecbf16eb2f4a8bc941cb5d0f.zip
hostap-16689c7cfc99c66aecbf16eb2f4a8bc941cb5d0f.tar.gz
hostap-16689c7cfc99c66aecbf16eb2f4a8bc941cb5d0f.tar.bz2
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>
Diffstat (limited to 'src/ap')
-rw-r--r--src/ap/acs.c8
-rw-r--r--src/ap/ap_drv_ops.c15
-rw-r--r--src/ap/ap_drv_ops.h1
-rw-r--r--src/ap/drv_callbacks.c52
4 files changed, 76 insertions, 0 deletions
diff --git a/src/ap/acs.c b/src/ap/acs.c
index b94b8a4..97cf26f 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -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);
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 262fdcd..9ebcf8f 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -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);
+}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 65061c9..7ad3ed7 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -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"
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 94df019..40a2a9c 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -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;