diff options
| author | gaolez <gaolez@codeaurora.org> | 2017-01-09 14:21:32 +0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-13 17:37:11 -0800 |
| commit | bd80acddaef75f6a99bca41bdd579edc2fefa8e3 (patch) | |
| tree | fc9e0aab23be30cdcbc42ad356e77ebdaadc0c01 | |
| parent | e85a05376e3c09a8f958295f07acce09e78715eb (diff) | |
qcacld-2.0: Support manual channel width switch to 5/10M
Allow user to trigger channel width switch to 5/10M via nl80211
NL80211_CMD_CHANNEL_SWITCH command.
Change-Id: I19750b8411dc3d95cce7eb9b73c5614e1dc590f4
CRs-Fixed: 1108836
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg.h | 5 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_hostapd.h | 17 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg.c | 16 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg80211.c | 129 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_hostapd.c | 210 | ||||
| -rw-r--r-- | CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c | 20 | ||||
| -rw-r--r-- | CORE/SAP/inc/sapApi.h | 19 | ||||
| -rw-r--r-- | CORE/SAP/src/sapModule.c | 9 |
8 files changed, 357 insertions, 68 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index 7355f128982e..d83b1cd8adb1 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -4333,6 +4333,7 @@ FG_BTC_BT_INTERVAL_PAGE_P2P_STA_DEFAULT * g_sub20_channel_width=3: Switch between 5 and 20 MHz bandwidth dynamically * g_sub20_channel_width=4: Switch between 10 and 20 MHz bandwidth dynamically * g_sub20_channel_width=5: Switch between 5/10 and 20 MHz bandwidth dynamically + * g_sub20_channel_width=6: Switch between 5/10 and 20 MHz bandwidth manually * Default : Disable */ #define CFG_SUB_20_CHANNEL_WIDTH_NAME "g_sub20_channel_width" @@ -4342,8 +4343,10 @@ FG_BTC_BT_INTERVAL_PAGE_P2P_STA_DEFAULT #define CFG_SUB_20_CHANNEL_WIDTH_DYN_5MHZ (3) #define CFG_SUB_20_CHANNEL_WIDTH_DYN_10MHZ (4) #define CFG_SUB_20_CHANNEL_WIDTH_DYN_ALL (5) +#define CFG_SUB_20_CHANNEL_WIDTH_MANUAL (6) + #define CFG_SUB_20_CHANNEL_WIDTH_MIN (0) -#define CFG_SUB_20_CHANNEL_WIDTH_MAX (5) +#define CFG_SUB_20_CHANNEL_WIDTH_MAX (6) #define CFG_SUB_20_CHANNEL_WIDTH_DEFAULT (0) /* diff --git a/CORE/HDD/inc/wlan_hdd_hostapd.h b/CORE/HDD/inc/wlan_hdd_hostapd.h index bfc64a7a316f..07452cb67db1 100644 --- a/CORE/HDD/inc/wlan_hdd_hostapd.h +++ b/CORE/HDD/inc/wlan_hdd_hostapd.h @@ -228,6 +228,10 @@ bool hdd_hostapd_sub20_channelwidth_can_switch( hdd_adapter_t *adapter, uint32_t *sub20_channel_width); bool hdd_hostapd_sub20_channelwidth_can_restore( hdd_adapter_t *adapter); +bool hdd_hostapd_sub20_channelwidth_can_set( + hdd_adapter_t *adapter, uint32_t sub20_channel_width); +int hdd_softap_set_channel_sub20_chanwidth_change( + struct net_device *dev, uint32_t chan_width); #else static inline bool hdd_hostapd_sub20_channelwidth_can_switch( hdd_adapter_t *adapter, uint32_t *sub20_channel_width) @@ -240,5 +244,18 @@ static inline bool hdd_hostapd_sub20_channelwidth_can_restore( { return false; } + +static inline bool hdd_hostapd_sub20_channelwidth_can_set( + hdd_adapter_t *adapter, uint32_t sub20_channel_width) +{ + return false; +} + +static inline +int hdd_softap_set_channel_sub20_chanwidth_change( + struct net_device *dev, uint32_t chan_width) +{ + return -ENOTSUPP; +} #endif #endif // end #if !defined( WLAN_HDD_HOSTAPD_H ) diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 03dac1b066b5..25475d14a458 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -6502,20 +6502,20 @@ eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode( eHddDot11Mode dot11Mode ) uint8_t hdd_cfg_get_sub20_dyn_capabilities(hdd_context_t *hdd_ctx_ptr) { hdd_config_t *config_ptr = hdd_ctx_ptr->cfg_ini; + uint8_t sub_20_channel_width = config_ptr->sub_20_channel_width; - if (config_ptr->sub_20_channel_width == - CFG_SUB_20_CHANNEL_WIDTH_DYN_5MHZ) { + switch (sub_20_channel_width) { + case CFG_SUB_20_CHANNEL_WIDTH_DYN_5MHZ: return SUB20_MODE_5MHZ; - } else if (config_ptr->sub_20_channel_width == - CFG_SUB_20_CHANNEL_WIDTH_DYN_10MHZ) { + case CFG_SUB_20_CHANNEL_WIDTH_DYN_10MHZ: return SUB20_MODE_10MHZ; - } else if (config_ptr->sub_20_channel_width == - CFG_SUB_20_CHANNEL_WIDTH_DYN_ALL) { + case CFG_SUB_20_CHANNEL_WIDTH_DYN_ALL: + case CFG_SUB_20_CHANNEL_WIDTH_MANUAL: return SUB20_MODE_5MHZ | SUB20_MODE_10MHZ; + default: + return SUB20_MODE_NONE; } - return SUB20_MODE_NONE; } - /** * hdd_cfg_get_static_sub20_channel_width() * @hdd_ctx_ptr: HDD context diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 0a13285d4397..e21f502487ac 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -14314,6 +14314,10 @@ int wlan_hdd_cfg80211_init(struct device *dev, #ifdef CHANNEL_SWITCH_SUPPORTED wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; #endif + + if (pCfg->sub_20_channel_width) + wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; + wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0)) || \ @@ -15809,6 +15813,24 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->reduced_beacon_interval = iniConfig->reduced_beacon_interval; + switch (iniConfig->sub_20_channel_width) { + case CFG_SUB_20_CHANNEL_WIDTH_DISABLE: + pConfig->sub20_switch_mode = SUB20_NONE; + break; + case CFG_SUB_20_CHANNEL_WIDTH_5MHZ: + case CFG_SUB_20_CHANNEL_WIDTH_10MHZ: + pConfig->sub20_switch_mode = SUB20_STATIC; + break; + case CFG_SUB_20_CHANNEL_WIDTH_DYN_5MHZ: + case CFG_SUB_20_CHANNEL_WIDTH_DYN_10MHZ: + case CFG_SUB_20_CHANNEL_WIDTH_DYN_ALL: + pConfig->sub20_switch_mode = SUB20_DYN; + break; + case CFG_SUB_20_CHANNEL_WIDTH_MANUAL: + pConfig->sub20_switch_mode = SUB20_MANUAL; + break; + } + //channel is already set in the set_channel Call back //pConfig->channel = pCommitConfig->channel; @@ -17057,50 +17079,56 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, return -EINVAL; } - if (sub20_config != CFG_SUB_20_CHANNEL_WIDTH_DYN_ALL) { - sub20_channelwidth = (sub20_static_channelwidth != 0) ? - sub20_static_channelwidth : sub20_dyn_channelwidth; - phy_sub20_channel_width = - (sub20_channelwidth == SUB20_MODE_5MHZ) ? - CH_WIDTH_5MHZ : CH_WIDTH_10MHZ; - channel_support_sub20 = - vos_is_channel_support_sub20(channel, - phy_sub20_channel_width, - 0); - if (!channel_support_sub20) { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("ch%dwidth%d unsupport by reg domain"), - channel, phy_sub20_channel_width); - return -EINVAL; - } - } else { - channel_support_sub20 = - vos_is_channel_support_sub20(channel, - CH_WIDTH_5MHZ, 0); - if (!channel_support_sub20) { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("ch%dwidth5M unsupport by reg domain"), - channel); - sub20_dyn_channelwidth &= ~SUB20_MODE_5MHZ; - } + switch (sub20_config) { + case CFG_SUB_20_CHANNEL_WIDTH_5MHZ: + case CFG_SUB_20_CHANNEL_WIDTH_10MHZ: + case CFG_SUB_20_CHANNEL_WIDTH_DYN_5MHZ: + case CFG_SUB_20_CHANNEL_WIDTH_DYN_10MHZ: + sub20_channelwidth = (sub20_static_channelwidth != 0) ? + sub20_static_channelwidth : sub20_dyn_channelwidth; + phy_sub20_channel_width = + (sub20_channelwidth == SUB20_MODE_5MHZ) ? + CH_WIDTH_5MHZ : CH_WIDTH_10MHZ; + channel_support_sub20 = + vos_is_channel_support_sub20(channel, + phy_sub20_channel_width, + 0); + if (!channel_support_sub20) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("ch%dwidth%d unsupport by reg domain"), + channel, phy_sub20_channel_width); + return -EINVAL; + } + break; + case CFG_SUB_20_CHANNEL_WIDTH_DYN_ALL: + channel_support_sub20 = + vos_is_channel_support_sub20(channel, CH_WIDTH_5MHZ, 0); + if (!channel_support_sub20) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("ch%dwidth5M unsupport by reg domain"), + channel); + sub20_dyn_channelwidth &= ~SUB20_MODE_5MHZ; + } - channel_support_sub20 = - vos_is_channel_support_sub20(channel, - CH_WIDTH_10MHZ, 0); - if (!channel_support_sub20) { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("ch%dwidth10M unsupport by reg domain"), - channel); - sub20_dyn_channelwidth &= ~SUB20_MODE_10MHZ; - } + channel_support_sub20 = + vos_is_channel_support_sub20(channel, CH_WIDTH_10MHZ, 0); + if (!channel_support_sub20) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("ch%dwidth10M unsupport by reg domain"), + channel); + sub20_dyn_channelwidth &= ~SUB20_MODE_10MHZ; + } - if (sub20_dyn_channelwidth == 0) { - return -EINVAL; - } else { - sme_config.sub20_dynamic_channelwidth = + if (sub20_dyn_channelwidth == 0) { + return -EINVAL; + } else { + sme_config.sub20_dynamic_channelwidth = sub20_dyn_channelwidth; - sme_UpdateConfig(pHddCtx->hHal, &sme_config); - } + sme_UpdateConfig(pHddCtx->hHal, &sme_config); + } + break; + default: + break; } } @@ -27852,11 +27880,18 @@ static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *hdd_ctx; v_U8_t channel; + uint8_t current_channel; v_U16_t freq; int ret; + tsap_Config_t *sap_config; - hddLog(LOG1, FL(" Set Freq %d"), csa_params->chandef.chan->center_freq); + hddLog(LOG1, FL("Set Freq %d sub20 chanwidth %d"), + csa_params->chandef.chan->center_freq, + csa_params->chandef.width); + current_channel = + (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel; + sap_config = &((WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig); hdd_ctx = WLAN_HDD_GET_CTX(adapter); ret = wlan_hdd_validate_context(hdd_ctx); @@ -27871,7 +27906,15 @@ static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, freq = csa_params->chandef.chan->center_freq; channel = vos_freq_to_chan(freq); - ret = hdd_softap_set_channel_change(dev, channel); + if (channel != current_channel) { + ret = hdd_softap_set_channel_change(dev, channel); + } else if (sap_config->sub20_switch_mode == SUB20_MANUAL) { + ret = hdd_softap_set_channel_sub20_chanwidth_change( + dev, csa_params->chandef.width); + } else { + hddLog(LOGE, FL("nothing to do")); + return -EINVAL; + } return ret; } diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 4358e404d0e8..f47ad1550e62 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -368,8 +368,9 @@ bool hdd_hostapd_sub20_channelwidth_can_switch( int i; int sta_count = 0; uint8_t sap_s20_caps; + uint8_t sap_s20_config; uint8_t sta_s20_caps = SUB20_MODE_NONE; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter); + tHalHandle hal_ptr = WLAN_HDD_GET_HAL_CTX(adapter); tSmeConfigParams *sme_config; hdd_station_info_t *sta; hdd_ap_ctx_t *ap = WLAN_HDD_GET_AP_CTX_PTR(adapter); @@ -381,11 +382,13 @@ bool hdd_hostapd_sub20_channelwidth_can_switch( } vos_mem_zero(sme_config, sizeof(*sme_config)); - sme_GetConfigParam(hHal, sme_config); + sme_GetConfigParam(hal_ptr, sme_config); sap_s20_caps = sme_config->sub20_dynamic_channelwidth; + sap_s20_config = sme_config->sub20_config_info; vos_mem_free(sme_config); - if (sap_s20_caps == SUB20_MODE_NONE) { - hddLog(LOGE, FL("sub20 none")); + if (sap_s20_caps == SUB20_MODE_NONE || + sap_s20_config == CFG_SUB_20_CHANNEL_WIDTH_MANUAL) { + hddLog(LOGE, FL("sub20 not switch")); return false; } @@ -432,7 +435,7 @@ bool hdd_hostapd_sub20_channelwidth_can_restore( int sta_count = 0; uint8_t sap_s20_caps; uint8_t sta_s20_caps = SUB20_MODE_NONE; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter); + tHalHandle hal_ptr = WLAN_HDD_GET_HAL_CTX(adapter); tSmeConfigParams *sme_config; hdd_station_info_t *sta; hdd_ap_ctx_t *ap = WLAN_HDD_GET_AP_CTX_PTR(adapter); @@ -443,7 +446,7 @@ bool hdd_hostapd_sub20_channelwidth_can_restore( return false; } vos_mem_zero(sme_config, sizeof(*sme_config)); - sme_GetConfigParam(hHal, sme_config); + sme_GetConfigParam(hal_ptr, sme_config); sap_s20_caps = sme_config->sub20_dynamic_channelwidth; vos_mem_free(sme_config); @@ -471,6 +474,92 @@ bool hdd_hostapd_sub20_channelwidth_can_restore( return true; } } + +/** + * hdd_hostapd_sub20_channelwidth_can_set() - check + * channel width manual switch to 5/10M condition + * @adapter: pointer to HDD context + * @sub20_channel_width: new channel width + * + * Return: true or false + */ +bool hdd_hostapd_sub20_channelwidth_can_set( + hdd_adapter_t *adapter, uint32_t sub20_channel_width) +{ + int i; + int sta_count = 0; + uint8_t sap_s20_config; + uint8_t sta_s20_caps = SUB20_MODE_NONE; + tHalHandle hal_ptr = WLAN_HDD_GET_HAL_CTX(adapter); + tSmeConfigParams *sme_config; + hdd_station_info_t *sta; + hdd_ap_ctx_t *ap = WLAN_HDD_GET_AP_CTX_PTR(adapter); + bool channel_support_sub20 = true; + enum phy_ch_width phy_sub20_channel_width = CH_WIDTH_INVALID; + + sme_config = vos_mem_malloc(sizeof(*sme_config)); + if (!sme_config) { + hddLog(LOGE, FL("mem alloc failed for sme_config")); + return false; + } + vos_mem_zero(sme_config, sizeof(*sme_config)); + + sme_GetConfigParam(hal_ptr, sme_config); + sap_s20_config = sme_config->sub20_config_info; + vos_mem_free(sme_config); + sme_config = NULL; + if (sap_s20_config != CFG_SUB_20_CHANNEL_WIDTH_MANUAL) { + hddLog(LOGE, FL("ini unsupport manual set sub20")); + return false; + } + + switch (sub20_channel_width) { + case SUB20_MODE_5MHZ: + phy_sub20_channel_width = CH_WIDTH_5MHZ; + break; + case SUB20_MODE_10MHZ: + phy_sub20_channel_width = CH_WIDTH_10MHZ; + break; + case SUB20_MODE_NONE: + return true; + default: + return false; + } + + channel_support_sub20 = + vos_is_channel_support_sub20(ap->operatingChannel, + phy_sub20_channel_width, + 0); + if (!channel_support_sub20) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("ch%d width%d unsupport by reg domain"), + ap->operatingChannel, phy_sub20_channel_width); + return false; + } + + spin_lock_bh(&adapter->staInfo_lock); + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + sta = &adapter->aStaInfo[i]; + if (sta->isUsed && (ap->uBCStaId != i)) { + sta_count++; + sta_s20_caps |= + sta->sub20_dynamic_channelwidth; + } + } + spin_unlock_bh(&adapter->staInfo_lock); + if (sta_count != 1) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%d STAs connected with sub20 Channelwidth %d", + sta_count, sta_s20_caps); + return false; + } + + if (!(sta_s20_caps & sub20_channel_width)) + return false; + + return true; +} + #endif /** @@ -3023,6 +3112,115 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) return ret; } +#ifdef FEATURE_WLAN_SUB_20_MHZ +/** + * hdd_softap_set_channel_sub20_chanwidth_change() -This + * function to support SAP channel change with CSA IE + * set in the beacons. + * @dev: Pointer to the net device + * @chan_width: new sub20 channel width + * + * Return: true or false + */ +int hdd_softap_set_channel_sub20_chanwidth_change(struct net_device *dev, + uint32_t chan_width) +{ + VOS_STATUS status; + int ret; + hdd_adapter_t *hostapd_adapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx_ptr; + hdd_adapter_t *sta_adapter; + hdd_station_ctx_t *sta_ctx; + uint32_t sub20_chan_width; + bool sub20_operate_permission; + void *vos_ctx_ptr; + + hdd_ctx_ptr = WLAN_HDD_GET_CTX(hostapd_adapter); + ret = wlan_hdd_validate_context(hdd_ctx_ptr); + if (ret) + return ret; + + sta_adapter = hdd_get_adapter(hdd_ctx_ptr, WLAN_HDD_INFRA_STATION); + /* + * conc_custom_rule1: + * Force SCC for SAP + STA + * if STA is already connected then we shouldn't allow + * channel switch in SAP interface + */ + if (sta_adapter && hdd_ctx_ptr->cfg_ini->conc_custom_rule1) { + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter); + if (hdd_connIsConnected(sta_ctx)) { + hddLog(LOGE, + FL("sub20 chan switch not allowed")); + return -EBUSY; + } + } + + switch (chan_width) { + case NL80211_CHAN_WIDTH_5: + sub20_chan_width = SUB20_MODE_5MHZ; + break; + case NL80211_CHAN_WIDTH_10: + sub20_chan_width = SUB20_MODE_10MHZ; + break; + case NL80211_CHAN_WIDTH_20_NOHT: + sub20_chan_width = SUB20_MODE_NONE; + break; + default: + hddLog(LOGE, FL("invalid param %d"), chan_width); + return -EINVAL; + } + + sub20_operate_permission = + hdd_hostapd_sub20_channelwidth_can_set(hostapd_adapter, + sub20_chan_width); + if (!sub20_operate_permission) { + hddLog(LOGE, FL("can't set sub20_chan_width in curr chan")); + return -EINVAL; + } + + spin_lock_bh(&hdd_ctx_ptr->dfs_lock); + if (hdd_ctx_ptr->dfs_radar_found == VOS_TRUE) { + spin_unlock_bh(&hdd_ctx_ptr->dfs_lock); + hddLog(LOGE, + FL("sub20 chan width switch in progress!!")); + return -EBUSY; + } + /* + * Set the dfs_radar_found flag to mimic channel change + * when a radar is found. This will enable synchronizing + * SAP and HDD states similar to that of radar indication. + * Suspend the netif queues to stop queuing Tx frames + * from upper layers. netif queues will be resumed + * once the channel change is completed and SAP will + * post eSAP_START_BSS_EVENT success event to HDD. + */ + hdd_ctx_ptr->dfs_radar_found = VOS_TRUE; + spin_unlock_bh(&hdd_ctx_ptr->dfs_lock); + + vos_ctx_ptr = WLAN_HDD_GET_SAP_CTX_PTR(hostapd_adapter); + status = WLANSAP_set_sub20_channelwidth_with_csa(vos_ctx_ptr, + sub20_chan_width); + if (VOS_STATUS_SUCCESS != status) { + hddLog(LOGE, + FL("sub20 chan width %d switch failed"), + sub20_chan_width); + /* + * If channel change command fails then clear the + * radar found flag and also restart the netif + * queues. + */ + spin_lock_bh(&hdd_ctx_ptr->dfs_lock); + hdd_ctx_ptr->dfs_radar_found = VOS_FALSE; + spin_unlock_bh(&hdd_ctx_ptr->dfs_lock); + + ret = -EINVAL; + } + + return ret; +} +#endif + /** * hdd_sap_get_chan_width() - get channel width of sap * @adapter: adapter being queried diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index 553ff7464533..2de24be84841 100644 --- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -7463,6 +7463,7 @@ limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) tpPESession psessionEntry = NULL; tANI_U32 chanWidth = 0; tANI_U8 sessionId; + uint8_t target_channel; if ( pMsg == NULL ) { @@ -7487,11 +7488,12 @@ limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) return; } + target_channel = pDfsCsaIeRequest->targetChannel; + if ( psessionEntry ) { /* target channel */ - psessionEntry->gLimChannelSwitch.primaryChannel = - pDfsCsaIeRequest->targetChannel; + psessionEntry->gLimChannelSwitch.primaryChannel = target_channel; /* Channel switch announcement needs to be included in beacon */ psessionEntry->dfsIncludeChanSwIe = VOS_TRUE; @@ -7577,10 +7579,10 @@ limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) * Fetch the center channel based on the channel width */ psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = - limGetCenterChannel(pMac, - pDfsCsaIeRequest->targetChannel, - psessionEntry->htSecondaryChannelOffset, - psessionEntry->gLimWiderBWChannelSwitch.newChanWidth); + limGetCenterChannel( + pMac, target_channel, + psessionEntry->htSecondaryChannelOffset, + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth); /* * This is not applicable for 20/40/80 Mhz. * Only used when we support 80+80 Mhz @@ -7609,9 +7611,11 @@ limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) psessionEntry->gLimChannelSwitch.switchCount ); /** * Send Action frame after updating the beacon - * Action frame is not required for sub 20 channel width changing + * Action frame is not required for dynamical sub20 channel + * width change */ - if (pDfsCsaIeRequest->sub20_channelwidth == 0) { + if (pDfsCsaIeRequest->sub20_channelwidth == 0 || + psessionEntry->currentOperChannel != target_channel) { if (CHAN_HOP_ALL_BANDS_ENABLE) lim_send_chan_switch_action_frame (pMac, psessionEntry->gLimChannelSwitch.primaryChannel, diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h index bb98cab4bc02..4208fa0a757e 100644 --- a/CORE/SAP/inc/sapApi.h +++ b/CORE/SAP/inc/sapApi.h @@ -512,6 +512,24 @@ enum vendor_ie_access_policy { ACCESS_POLICY_DONOT_RESPOND_IF_IE_IS_PRESENT, }; +/* + * enum sub20_chan_switch_mode- sub20 channel + * switch mode + * @SUB20_NONE: unsupport sub20 channel width + * @SUB20_STATIC: support sub20 channel width, + * but unsupport sub20 channel width switch + * @SUB20_DYN: support sub20 channel width, + * sub20 channel width switch auto + * @SUB20_MANUAL: support sub20 channel width, + * sub20 channel width switch manual + */ +enum sub20_chan_switch_mode { + SUB20_NONE, + SUB20_STATIC, + SUB20_DYN, + SUB20_MANUAL +}; + typedef struct sap_Config { tSap_SSIDInfo_t SSIDinfo; eCsrPhyMode SapHw_mode; /* Wireless Mode */ @@ -592,6 +610,7 @@ typedef struct sap_Config { uint8_t sap_chanswitch_mode; bool dfs_beacon_tx_enhanced; uint16_t reduced_beacon_interval; + enum sub20_chan_switch_mode sub20_switch_mode; } tsap_Config_t; #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index c1e9a9ac496a..6efbc9777582 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -830,6 +830,9 @@ WLANSAP_StartBss pConfig->dfs_beacon_tx_enhanced; pmac->sap.SapDfsInfo.reduced_beacon_interval = pConfig->reduced_beacon_interval; + if (pConfig->sub20_switch_mode == SUB20_STATIC) + pmac->sap.SapDfsInfo.new_sub20_channelwidth = + pmac->sub20_channelwidth; // Copy MAC filtering settings to sap context pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; vos_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, sizeof(pConfig->accept_mac)); @@ -1852,8 +1855,10 @@ WLANSAP_set_sub20_channelwidth_with_csa(void *vos_ctx_ptr, uint32_t chan_width) } else { VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, - "%s: SAP is not in eSAP_STARTED state", - __func__); + "%s: orgl chan_width=%d new chan_width=%d", + __func__, + sap_context_ptr->sub20_channelwidth, + chan_width); return VOS_STATUS_E_FAULT; } |
