wlan: Disable indoor channel on sap start
There are scenario where indoor channel operations
(like active/passive scan/connect/roam etc)
are not desired/permitted specially in sap case.
Hence add support of disabling indoor channel
on sap start and revert it on sap stop.
Change-Id: Id90805cb4c670e1f46bae204d27bd85ea7422bc7
CRs-Fixed: 2160561
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 685f6ea..52c1a2e 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -209,6 +209,14 @@
CFG_RTS_THRESHOLD_MIN,
CFG_RTS_THRESHOLD_MAX ),
+ REG_VARIABLE(CFG_MARK_INDOOR_AS_DISABLE_NAME,
+ WLAN_PARAM_Integer,
+ hdd_config_t, disable_indoor_channel,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_MARK_INDOOR_AS_DISABLE_DEFAULT,
+ CFG_MARK_INDOOR_AS_DISABLE_MIN,
+ CFG_MARK_INDOOR_AS_DISABLE_MAX),
+
REG_VARIABLE( CFG_FRAG_THRESHOLD_NAME, WLAN_PARAM_Integer,
hdd_config_t, FragmentationThreshold,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -4414,6 +4422,9 @@
"Name = [gEnableDelAck] Value = [%u] ",
pHddCtx->cfg_ini->enable_delack);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Name = [g_mark_indoor_as_disable] Value = [%u]",
+ pHddCtx->cfg_ini->disable_indoor_channel);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
"Name = [disableBarWakeUp] Value = [%u] ",
pHddCtx->cfg_ini->disableBarWakeUp);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index aa54a44..d6e3b7d 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -10260,6 +10260,90 @@
}
#endif /* DHCP_SERVER_OFFLOAD */
+/*
+ * hdd_modify_indoor_channel_state_flags() - modify wiphy flags and cds state
+ * @wiphy_chan: wiphy channel number
+ * @rfChannel: channel hw value
+ * @disable: Disable/enable the flags
+ *
+ * Modify wiphy flags and cds state if channel is indoor.
+ *
+ * Return: void
+ */
+void hdd_modify_indoor_channel_state_flags(struct ieee80211_channel *wiphy_chan,
+ v_U32_t rfChannel, bool disable)
+{
+ v_U32_t channelLoop;
+ eRfChannels channelEnum = INVALID_RF_CHANNEL;
+
+ for (channelLoop = 0; channelLoop <= RF_CHAN_165; channelLoop++) {
+
+ if (rfChannels[channelLoop].channelNum == rfChannel) {
+ channelEnum = (eRfChannels)channelLoop;
+ break;
+ }
+ }
+
+ if (INVALID_RF_CHANNEL == channelEnum)
+ return;
+
+ if (disable) {
+ if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) {
+ wiphy_chan->flags |=
+ IEEE80211_CHAN_DISABLED;
+ regChannels[channelEnum].enabled =
+ NV_CHANNEL_DISABLE;
+ }
+ } else {
+ if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) {
+ wiphy_chan->flags &=
+ ~IEEE80211_CHAN_DISABLED;
+ /*
+ * Indoor channels are marked as DFS
+ * during regulatory processing
+ */
+
+ regChannels[channelEnum].enabled =
+ NV_CHANNEL_DFS;
+ }
+ }
+
+}
+
+void hdd_update_indoor_channel(hdd_context_t *hdd_ctx,
+ bool disable)
+{
+ int band_num;
+ int chan_num;
+ v_U32_t rfChannel;
+ struct ieee80211_channel *wiphy_chan;
+ struct wiphy *wiphy;
+
+ ENTER();
+ hddLog(VOS_TRACE_LEVEL_INFO, "disable: %d", disable);
+
+ wiphy = hdd_ctx->wiphy;
+ for (band_num = 0; band_num < IEEE80211_NUM_BANDS; band_num++) {
+
+ if (wiphy->bands[band_num] == NULL)
+ continue;
+
+ for (chan_num = 0;
+ chan_num < wiphy->bands[band_num]->n_channels;
+ chan_num++) {
+
+ wiphy_chan =
+ &(wiphy->bands[band_num]->channels[chan_num]);
+ rfChannel = wiphy->bands[band_num]->channels[chan_num].hw_value;
+
+ hdd_modify_indoor_channel_state_flags(wiphy_chan, rfChannel,
+ disable);
+ }
+ }
+ EXIT();
+}
+
+
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
struct beacon_parameters *params)
@@ -10300,6 +10384,19 @@
wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
iniConfig = pHddCtx->cfg_ini;
+ /* Mark the indoor channel (passive) to disable */
+ if (iniConfig->disable_indoor_channel) {
+ hdd_update_indoor_channel(pHddCtx, true);
+
+ if (!VOS_IS_STATUS_SUCCESS(
+ sme_update_channel_list((tpAniSirGlobal)pHddCtx->hHal))) {
+ hdd_update_indoor_channel(pHddCtx, false);
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+ FL("Can't start BSS: update channel list failed"));
+ return eHAL_STATUS_FAILURE;
+ }
+ }
+
pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
@@ -10890,6 +10987,12 @@
return 0;
error:
+ /* Revert the indoor to passive marking if START BSS fails */
+ if (iniConfig->disable_indoor_channel) {
+ hdd_update_indoor_channel(pHddCtx, false);
+ sme_update_channel_list((tpAniSirGlobal)pHddCtx->hHal);
+ }
+
clear_bit(SOFTAP_INIT_DONE, &pHostapdAdapter->event_flags);
return ret;
}
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index db9d5ba..afc9435 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1162,7 +1162,6 @@
pHddCtx = (hdd_context_t*)(pHostapdAdapter->pHddCtx);
cfg_param = pHddCtx->cfg_ini;
-
switch(sapEvent)
{
case eSAP_START_BSS_EVENT :
diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
index 7d3502d..69d4c38 100644
--- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -2129,6 +2129,12 @@
}
}
+ /* Mark the indoor channel (passive) to enable */
+ if (pHddCtx->cfg_ini->disable_indoor_channel) {
+ hdd_update_indoor_channel(pHddCtx, false);
+ sme_update_channel_list((tpAniSirGlobal)pHddCtx->hHal);
+ }
+
return vosStatus;
}