summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmar Singhal <asinghal@qca.qualcomm.com>2014-10-06 12:21:32 -0700
committerAnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com>2014-10-14 17:52:33 +0530
commit6ad1677fcb7feceabaf663c407ad375dc14699e6 (patch)
treed84693979a818b2d2076479d68e2ad7d0d4cc4f1
parent296a010d54715d77d157796fcac2df2b7ef55259 (diff)
wlan: Dynamically enable/disable DFS channel scan.
All types of scans on DFS channels can be dynamically enabled or disabled. By default, the passive scan on DFS channels is enabled. When the scan is disabled, pass a new channel list to the firmware that has the channels disabled. Also, do not honor the dynamic command if SAP is already running on DFS channel. Change-Id: I3fcf975f2cdf343ec481fbecb30dc1657d1a8350 CRs-Fixed: 729786
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg80211.h14
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h3
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c140
-rwxr-xr-xCORE/HDD/src/wlan_hdd_main.c3
-rw-r--r--CORE/SAP/src/sapFsm.c6
-rw-r--r--CORE/SME/inc/sme_Api.h8
-rw-r--r--CORE/SME/src/csr/csrApiRoam.c61
-rw-r--r--CORE/SME/src/csr/csrApiScan.c25
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c28
9 files changed, 242 insertions, 46 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index a9a9726ab88c..1413d2820b1f 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -169,6 +169,8 @@ enum qca_nl80211_vendor_subcmds {
/* Set scanning_mac_oui */
QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI = 39,
+ /* Set nodfs_flag */
+ QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG = 40
};
enum qca_nl80211_vendor_subcmds_index {
@@ -814,6 +816,18 @@ enum qca_wlan_vendor_attr_set_scanning_mac_oui {
QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_AFTER_LAST - 1,
};
+enum qca_wlan_vendor_attr_set_no_dfs_flag
+{
+ QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_INVALID = 0,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG = 1,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX =
+ QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_AFTER_LAST - 1,
+};
+
+
/* Feature defines */
#define WIFI_FEATURE_INFRA 0x0001 /* Basic infrastructure mode */
#define WIFI_FEATURE_INFRA_5G 0x0002 /* Support for 5 GHz Band */
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index c90e2ee66df3..dde032f07ad9 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1668,6 +1668,9 @@ void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter);
#endif /*End of FEATURE_WLAN_BATCH_SCAN*/
+VOS_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *pHddCtx);
+
+
#ifdef WLAN_FEATURE_LPSS
void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter,
hdd_station_ctx_t *pHddStaCtx,
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 3fd7123b06e2..46803952d003 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -3831,6 +3831,129 @@ static int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy,
#endif
+static const struct nla_policy
+wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
+ +1] =
+{
+ [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
+};
+
+
+static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ void *data,
+ int data_len)
+{
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+ hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
+ eHalStatus status;
+ int ret_val = -EPERM;
+ u32 no_dfs_flag = 0;
+ hdd_adapter_list_node_t *p_adapter_node = NULL, *p_next = NULL;
+ hdd_adapter_t *p_adapter;
+ VOS_STATUS vos_status;
+ hdd_ap_ctx_t *p_ap_ctx;
+ hdd_station_ctx_t *p_sta_ctx;
+
+ if (wlan_hdd_validate_context(pHddCtx)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("HDD context is not valid"));
+ return -EINVAL;
+ }
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
+ data, data_len,
+ wlan_hdd_set_no_dfs_flag_config_policy)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid attr"));
+ return -EINVAL;
+ }
+
+ if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr dfs flag failed"));
+ return -EINVAL;
+ }
+
+ no_dfs_flag = nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
+
+ hddLog(VOS_TRACE_LEVEL_INFO, FL(" DFS flag = %d"),
+ no_dfs_flag);
+
+ if (no_dfs_flag > 1) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid value of dfs flag"));
+ return -EINVAL;
+ }
+
+ if (no_dfs_flag == pHddCtx->cfg_ini->enableDFSChnlScan) {
+ if (no_dfs_flag) {
+
+ vos_status = hdd_get_front_adapter( pHddCtx, &p_adapter_node);
+ while ((NULL != p_adapter_node) &&
+ (VOS_STATUS_SUCCESS == vos_status))
+ {
+ p_adapter = p_adapter_node->pAdapter;
+
+ if (WLAN_HDD_SOFTAP == p_adapter->device_mode) {
+ p_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(p_adapter);
+
+ /* if there is SAP already running on DFS channel,
+ do not disable scan on dfs channels. Note that with
+ SAP on DFS, there cannot be conurrency on single
+ radio. But then we can have multiple radios !!!!! */
+ if (NV_CHANNEL_DFS ==
+ vos_nv_getChannelEnabledState(
+ p_ap_ctx->operatingChannel)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("SAP running on DFS channel"));
+ return -EOPNOTSUPP;
+ }
+ }
+
+ if (WLAN_HDD_INFRA_STATION == p_adapter->device_mode) {
+ p_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(p_adapter);
+
+ /* if STA is already connected on DFS channel,
+ do not disable scan on dfs channels */
+ if (hdd_connIsConnected(p_sta_ctx) &&
+ (NV_CHANNEL_DFS ==
+ vos_nv_getChannelEnabledState(
+ p_sta_ctx->conn_info.operationChannel))) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("client connected on DFS channel"));
+ return -EOPNOTSUPP;
+ }
+ }
+
+ vos_status = hdd_get_next_adapter(pHddCtx, p_adapter_node,
+ &p_next);
+ p_adapter_node = p_next;
+ }
+ }
+
+ pHddCtx->cfg_ini->enableDFSChnlScan = !no_dfs_flag;
+
+ hdd_abort_mac_scan_all_adapters(pHddCtx);
+
+ /* call the SME API to tunnel down the new channel list
+ to the firmware */
+ status = sme_handle_dfs_chan_scan(hHal,
+ pHddCtx->cfg_ini->enableDFSChnlScan);
+
+ if (eHAL_STATUS_SUCCESS == status)
+ ret_val = 0;
+
+ } else {
+ hddLog(VOS_TRACE_LEVEL_INFO, FL(" the DFS flag has not changed"));
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
+
+
const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
{
{
@@ -4005,6 +4128,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = wlan_hdd_cfg80211_set_scanning_mac_oui
},
+
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
+ },
};
@@ -5585,6 +5716,15 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
"%s: Invalid Channel [%d]", __func__, pConfig->channel);
return -EINVAL;
}
+
+ /* reject SAP if DFS channel scan is not allowed */
+ if ((VOS_FALSE == pHddCtx->cfg_ini->enableDFSChnlScan) &&
+ (NV_CHANNEL_DFS ==
+ vos_nv_getChannelEnabledState(pConfig->channel))) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("not allowed to start SAP on DFS channel"));
+ return -EOPNOTSUPP;
+ }
}
else
{
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 9cd93261842d..5610729e9576 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -10561,7 +10561,8 @@ static inline VOS_STATUS hdd_UnregisterWext_all_adapters(hdd_context_t *pHddCtx)
return VOS_STATUS_SUCCESS;
}
-static inline VOS_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *pHddCtx)
+
+VOS_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *pHddCtx)
{
hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
VOS_STATUS status;
diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c
index 169b7643262f..bb7808b90900 100644
--- a/CORE/SAP/src/sapFsm.c
+++ b/CORE/SAP/src/sapFsm.c
@@ -3747,6 +3747,7 @@ static VOS_STATUS sapGetChannelList(ptSapContext sapContext,
#ifdef FEATURE_WLAN_CH_AVOID
v_U8_t i;
#endif
+ tpAniSirGlobal pmac = PMAC_STRUCT(hHal);
if (NULL == hHal)
{
@@ -3846,7 +3847,10 @@ static VOS_STATUS sapGetChannelList(ptSapContext sapContext,
if((startChannelNum <= rfChannels[loopCount].channelNum)&&
(endChannelNum >= rfChannels[loopCount].channelNum ))
{
- if( regChannels[loopCount].enabled )
+ if (((TRUE == pmac->scan.fEnableDFSChnlScan) &&
+ (regChannels[loopCount].enabled)) ||
+ ((FALSE == pmac->scan.fEnableDFSChnlScan) &&
+ (NV_CHANNEL_ENABLE == regChannels[loopCount].enabled)))
{
#ifdef FEATURE_WLAN_CH_AVOID
for( i = 0; i < NUM_20MHZ_RF_CHANNELS; i++ )
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 6b2498ba6cf1..766d4ea21adf 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4092,5 +4092,13 @@ eHalStatus sme_setDhcpSrvOffload(tHalHandle hHal,
eHalStatus sme_SetLedFlashing (tHalHandle hHal, tANI_U8 type,
tANI_U32 x0, tANI_U32 x1);
#endif
+/* ---------------------------------------------------------------------------
+ \fn sme_handle_dfS_chan_scan
+ \brief SME API to enable/disable DFS channel scan
+ \param hHal
+ \param dfs_flag: whether dfs needs to be enabled or disabled
+ \return eHalStatus
+ -------------------------------------------------------------------------*/
+eHalStatus sme_handle_dfs_chan_scan(tHalHandle hHal, tANI_U8 dfs_flag);
#endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index eaea4cdb0120..e7e60bf181eb 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -458,68 +458,79 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac)
tSirUpdateChanList *pChanList;
tCsrScanStruct *pScan = &pMac->scan;
tANI_U8 numChan = pScan->base20MHzChannels.numChannels;
+ tANI_U8 num_channel = 0;
tANI_U32 bufLen;
vos_msg_t msg;
tANI_U8 i, j, social_channel[MAX_SOCIAL_CHANNELS] = {1,6,11};
+ tANI_U8 channel_state;
if (CSR_IS_5G_BAND_ONLY(pMac))
{
for (i = 0; i < MAX_SOCIAL_CHANNELS; i++)
{
if (vos_nv_getChannelEnabledState(social_channel[i])
- == NV_CHANNEL_ENABLE)
+ == NV_CHANNEL_ENABLE)
numChan++;
}
}
bufLen = sizeof(tSirUpdateChanList) +
- (sizeof(tSirUpdateChanParam) * (numChan - 1));
+ (sizeof(tSirUpdateChanParam) * (numChan));
csrInitOperatingClasses((tHalHandle)pMac);
pChanList = (tSirUpdateChanList *) vos_mem_malloc(bufLen);
if (!pChanList)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
- "Failed to allocate memory for tSirUpdateChanList");
+ "Failed to allocate memory for tSirUpdateChanList");
return eHAL_STATUS_FAILED_ALLOC;
}
- msg.type = WDA_UPDATE_CHAN_LIST_REQ;
- msg.reserved = 0;
- msg.bodyptr = pChanList;
- pChanList->numChan = numChan;
for (i = 0; i < pScan->base20MHzChannels.numChannels; i++)
{
- pChanList->chanParam[i].chanId =
- pScan->base20MHzChannels.channelList[i];
- pChanList->chanParam[i].pwr =
- csrFindChannelPwr(pScan->defaultPowerTable,
- pChanList->chanParam[i].chanId);
- /*Set DFS flag for DFS channel*/
- if (vos_nv_getChannelEnabledState(pChanList->chanParam[i].chanId) ==
- NV_CHANNEL_DFS)
- pChanList->chanParam[i].dfsSet = VOS_TRUE;
- else
- pChanList->chanParam[i].dfsSet = VOS_FALSE;
+ channel_state =
+ vos_nv_getChannelEnabledState(
+ pScan->base20MHzChannels.channelList[i]);
+ if ((NV_CHANNEL_ENABLE == channel_state) ||
+ pMac->scan.fEnableDFSChnlScan)
+ {
+ pChanList->chanParam[num_channel].chanId =
+ pScan->base20MHzChannels.channelList[i];
+ pChanList->chanParam[num_channel].pwr =
+ csrFindChannelPwr(pScan->defaultPowerTable,
+ pChanList->chanParam[num_channel].chanId);
+ if (NV_CHANNEL_ENABLE == channel_state)
+ pChanList->chanParam[num_channel].dfsSet = VOS_FALSE;
+ else
+ pChanList->chanParam[num_channel].dfsSet = VOS_TRUE;
+ num_channel++;
+ }
}
+
if (CSR_IS_5G_BAND_ONLY(pMac))
{
for (j = 0; j < MAX_SOCIAL_CHANNELS; j++)
{
if (vos_nv_getChannelEnabledState(social_channel[j])
- == NV_CHANNEL_ENABLE)
+ == NV_CHANNEL_ENABLE)
{
- pChanList->chanParam[i].chanId = social_channel[j];
- pChanList->chanParam[i].pwr =
- csrFindChannelPwr(pScan->defaultPowerTable, social_channel[j]);
- pChanList->chanParam[i].dfsSet = VOS_FALSE;
- i++;
+ pChanList->chanParam[num_channel].chanId = social_channel[j];
+ pChanList->chanParam[num_channel].pwr =
+ csrFindChannelPwr(pScan->defaultPowerTable,
+ social_channel[j]);
+ pChanList->chanParam[num_channel].dfsSet = VOS_FALSE;
+ num_channel++;
}
}
}
- if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
+ msg.type = WDA_UPDATE_CHAN_LIST_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pChanList;
+ pChanList->numChan = num_channel;
+
+ if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
"%s: Failed to post msg to WDA", __func__);
diff --git a/CORE/SME/src/csr/csrApiScan.c b/CORE/SME/src/csr/csrApiScan.c
index 094031e9ba7f..76a976e1f453 100644
--- a/CORE/SME/src/csr/csrApiScan.c
+++ b/CORE/SME/src/csr/csrApiScan.c
@@ -3415,36 +3415,23 @@ void csrApplyPower2Current( tpAniSirGlobal pMac )
void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode, tANI_BOOLEAN updateRiva)
{
int i;
- eNVChannelEnabledType channelEnabledType;
tANI_U8 numChannels = 0;
tANI_U8 tempNumChannels = 0;
tCsrChannel ChannelList;
- if( pChannelList->numChannels )
+ if (pChannelList->numChannels)
{
tempNumChannels = CSR_MIN(pChannelList->numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
- /* If user doesn't want to scan the DFS channels lets trim them from
- the valid channel list*/
- for(i=0; i < tempNumChannels; i++)
+
+ for (i = 0; i < tempNumChannels; i++)
{
- if( FALSE == pMac->scan.fEnableDFSChnlScan )
- {
- channelEnabledType =
- vos_nv_getChannelEnabledState(pChannelList->channelList[i]);
- }
- else
- {
- channelEnabledType = NV_CHANNEL_ENABLE;
- }
- if( NV_CHANNEL_ENABLE == channelEnabledType )
- {
- ChannelList.channelList[numChannels] = pChannelList->channelList[i];
- numChannels++;
- }
+ ChannelList.channelList[numChannels] = pChannelList->channelList[i];
+ numChannels++;
}
ChannelList.numChannels = numChannels;
csrSetCfgValidChannelList(pMac, ChannelList.channelList, ChannelList.numChannels);
+
// extend scan capability
// build a scan list based on the channel list : channel# + active/passive scan
csrSetCfgScanControlList(pMac, countryCode, &ChannelList);
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index b8fbf4325c34..f481f452d60a 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -14179,3 +14179,31 @@ eHalStatus sme_SetLedFlashing (tHalHandle hHal, tANI_U8 type,
}
#endif
+/* ---------------------------------------------------------------------------
+ \fn sme_handle_dfS_chan_scan
+ \brief SME API to enable/disable DFS channel scan
+ \param hHal
+ \param dfs_flag: whether dfs needs to be enabled or disabled
+ \return eHalStatus
+ -------------------------------------------------------------------------*/
+eHalStatus sme_handle_dfs_chan_scan(tHalHandle hHal, tANI_U8 dfs_flag)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ status = sme_AcquireGlobalLock(&pMac->sme);
+
+ if (eHAL_STATUS_SUCCESS == status) {
+
+ pMac->scan.fEnableDFSChnlScan = dfs_flag;
+
+ /* update the channel list to the firmware */
+ status = csrUpdateChannelList(pMac);
+
+ sme_ReleaseGlobalLock(&pMac->sme);
+ }
+
+ return status;
+}
+
+