From 2111d3c9b620166b817c7130b08862693e50fb4d Mon Sep 17 00:00:00 2001 From: Sandeep Puligilla Date: Wed, 3 Feb 2016 01:46:15 -0800 Subject: [PATCH] qcacld-3.0: SAP DFS-3 channel selection suppport for 80+80MHz/160MHz Add support for setting channel width for CSA and modify the SAP DFS channel width fallback algoritham to support DFS for 80+80Mhz and 160Mhz bandwidth. Also, compile out channel matrix restriction from channel selection process after radar indication is received for newer platforms and only compile for older platforms Change-Id: I771fc162b18aa1e485c513046a265b2d94612972 CRs-Fixed: 964262 --- Kbuild | 4 +- .../src/pe/lim/lim_process_mlm_req_messages.c | 20 +- .../src/pe/lim/lim_process_sme_req_messages.c | 17 +- core/mac/src/pe/lim/lim_send_messages.c | 15 +- .../src/pe/lim/lim_send_sme_rsp_messages.c | 20 +- core/sap/src/sap_api_link_cntl.c | 18 +- core/sap/src/sap_fsm.c | 218 ++++++++++++++---- core/sap/src/sap_module.c | 19 +- 8 files changed, 262 insertions(+), 69 deletions(-) diff --git a/Kbuild b/Kbuild index 8bf73d63cf..0fad9cac9c 100755 --- a/Kbuild +++ b/Kbuild @@ -1206,8 +1206,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_RX_WAKELOCK), y) CDEFINES += -DWLAN_FEATURE_HOLD_RX_WAKELOCK endif -#Enable Channel Matrix restriction for all targets +#Enable Channel Matrix restriction for all Rome only targets +ifneq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS))) CDEFINES += -DWLAN_ENABLE_CHNL_MATRIX_RESTRICTION +endif #features specific to mobile router use case ifeq ($(CONFIG_MOBILE_ROUTER), y) diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index e9abe6f2c9..a7be64004e 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -582,6 +582,7 @@ lim_mlm_add_bss(tpAniSirGlobal mac_ctx, tSirMsgQ msg_buf; tpAddBssParams addbss_param = NULL; uint32_t retcode; + bool is_ch_dfs = false; /* Package WMA_ADD_BSS_REQ message parameters */ addbss_param = qdf_mem_malloc(sizeof(tAddBssParams)); @@ -673,8 +674,23 @@ lim_mlm_add_bss(tpAniSirGlobal mac_ctx, /* pass on the session persona to hal */ addbss_param->halPersona = session->pePersona; - addbss_param->bSpectrumMgtEnabled = session->spectrumMgtEnabled || - lim_isconnected_on_dfs_channel(mlm_start_req->channelNumber); + if (session->ch_width == CH_WIDTH_160MHZ) { + is_ch_dfs = true; + } else if (session->ch_width == CH_WIDTH_80P80MHZ) { + if (cds_get_channel_state(mlm_start_req->channelNumber) == + CHANNEL_STATE_DFS || + cds_get_channel_state(session->ch_center_freq_seg1 - + SIR_80MHZ_START_CENTER_CH_DIFF) == + CHANNEL_STATE_DFS) + is_ch_dfs = true; + } else { + if (cds_get_channel_state(mlm_start_req->channelNumber) == + CHANNEL_STATE_DFS) + is_ch_dfs = true; + } + + addbss_param->bSpectrumMgtEnabled = + session->spectrumMgtEnabled || is_ch_dfs; addbss_param->extSetStaKeyParamValid = 0; addbss_param->dot11_mode = session->dot11mode; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index c3f2ad9862..1d2058b81c 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -5665,6 +5665,15 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, session_entry->dfsIncludeChanWrapperIe = true; wider_bw_ch_switch->newChanWidth = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; + /* + * This is not applicable for 20/40/80 Mhz. + * Only used when we support 80+80 Mhz operation. + * In case of 80+80 Mhz, this parameter indicates + * center channel frequency index of 80 Mhz channel of + * frequency segment 1. + */ + wider_bw_ch_switch->newCenterChanFreq1 = + dfs_csa_ie_req->ch_params.center_freq_seg1; break; default: session_entry->dfsIncludeChanWrapperIe = false; @@ -5678,14 +5687,6 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, /* Fetch the center channel based on the channel width */ wider_bw_ch_switch->newCenterChanFreq0 = dfs_csa_ie_req->ch_params.center_freq_seg0; - /* - * This is not applicable for 20/40/80 Mhz.Only used when we support - * 80+80 Mhz operation. In case of 80+80 Mhz, this parameter indicates - * center channel frequency index of 80 Mhz channel of - * frequency segment 1. - */ - wider_bw_ch_switch->newCenterChanFreq1 = - dfs_csa_ie_req->ch_params.center_freq_seg1; skip_vht: /* Send CSA IE request from here */ if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) != diff --git a/core/mac/src/pe/lim/lim_send_messages.c b/core/mac/src/pe/lim/lim_send_messages.c index 1023060347..3c844b85c5 100644 --- a/core/mac/src/pe/lim/lim_send_messages.c +++ b/core/mac/src/pe/lim/lim_send_messages.c @@ -244,10 +244,21 @@ tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, lim_log(pMac, LOG2, FL("nss value: %d"), pChnlParams->nss); /*Set DFS flag for DFS channel */ - if (cds_get_channel_state(chnlNumber) == CHANNEL_STATE_DFS) + if (ch_width == CH_WIDTH_160MHZ) { pChnlParams->isDfsChannel = true; - else + } else if (ch_width == CH_WIDTH_80P80MHZ) { pChnlParams->isDfsChannel = false; + if (cds_get_channel_state(chnlNumber) == CHANNEL_STATE_DFS || + cds_get_channel_state(pChnlParams->ch_center_freq_seg1 - + SIR_80MHZ_START_CENTER_CH_DIFF) == + CHANNEL_STATE_DFS) + pChnlParams->isDfsChannel = true; + } else { + if (cds_get_channel_state(chnlNumber) == CHANNEL_STATE_DFS) + pChnlParams->isDfsChannel = true; + else + pChnlParams->isDfsChannel = false; + } pChnlParams->restart_on_chan_switch = is_restart; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index fa2dcd3a0b..9f9a145c42 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2397,6 +2397,9 @@ lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac, tSirMsgQ mmhMsg; tpSwitchChannelParams pSmeSwithChnlParams; uint8_t channelId; + bool is_ch_dfs = false; + enum ch_width ch_width; + uint8_t ch_center_freq_seg1; pSmeSwithChnlParams = (tSwitchChannelParams *) qdf_mem_malloc(sizeof(tSwitchChannelParams)); @@ -2413,6 +2416,8 @@ lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac, sizeof(tSwitchChannelParams)); channelId = pSmeSwithChnlParams->channelNumber; + ch_width = pSmeSwithChnlParams->ch_width; + ch_center_freq_seg1 = pSmeSwithChnlParams->ch_center_freq_seg1; /* * Pass the sme sessionID to SME instead @@ -2432,7 +2437,20 @@ lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac, * upper layers to start the beacon transmission . */ - if (CHANNEL_STATE_DFS != cds_get_channel_state(channelId)) { + if (ch_width == CH_WIDTH_160MHZ) { + is_ch_dfs = true; + } else if (ch_width == CH_WIDTH_80P80MHZ) { + if (cds_get_channel_state(channelId) == CHANNEL_STATE_DFS || + cds_get_channel_state(ch_center_freq_seg1 - + SIR_80MHZ_START_CENTER_CH_DIFF) == + CHANNEL_STATE_DFS) + is_ch_dfs = true; + } else { + if (cds_get_channel_state(channelId) == CHANNEL_STATE_DFS) + is_ch_dfs = true; + } + + if (!is_ch_dfs) { if (channelId == psessionEntry->currentOperChannel) { lim_apply_configuration(pMac, psessionEntry); lim_send_beacon_ind(pMac, psessionEntry); diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c index 81713b077c..78b71b4b0c 100644 --- a/core/sap/src/sap_api_link_cntl.c +++ b/core/sap/src/sap_api_link_cntl.c @@ -430,6 +430,7 @@ wlansap_roam_process_ch_change_success(tpAniSirGlobal mac_ctx, { tWLAN_SAPEvent sap_event; QDF_STATUS qdf_status; + bool is_ch_dfs = false; /* * Channel change is successful. If the new channel is a DFS channel, * then we will to perform channel availability check for 60 seconds @@ -442,8 +443,23 @@ wlansap_roam_process_ch_change_success(tpAniSirGlobal mac_ctx, if (eSAP_DISCONNECTING != sap_ctx->sapsMachine) return; + if (sap_ctx->ch_params.ch_width == CH_WIDTH_160MHZ) { + is_ch_dfs = true; + } else if (sap_ctx->ch_params.ch_width == CH_WIDTH_80P80MHZ) { + if (cds_get_channel_state(sap_ctx->channel) == + CHANNEL_STATE_DFS || + cds_get_channel_state(sap_ctx->ch_params.center_freq_seg1 - + SIR_80MHZ_START_CENTER_CH_DIFF) == + CHANNEL_STATE_DFS) + is_ch_dfs = true; + } else { + if (cds_get_channel_state(sap_ctx->channel) == + CHANNEL_STATE_DFS) + is_ch_dfs = true; + } + /* check if currently selected channel is a DFS channel */ - if (CHANNEL_STATE_DFS == cds_get_channel_state(sap_ctx->channel)) { + if (is_ch_dfs) { if ((false == mac_ctx->sap.SapDfsInfo.ignore_cac) && (eSAP_DFS_DO_NOT_SKIP_CAC == mac_ctx->sap.SapDfsInfo.cac_state)) { diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 42fa493790..44d8a8c557 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -1078,6 +1078,8 @@ static uint8_t sap_populate_available_channels(chan_bonding_bitmap *bitmap, switch (ch_width) { /* VHT80 */ + case CH_WIDTH_160MHZ: + case CH_WIDTH_80P80MHZ: case CH_WIDTH_80MHZ: for (i = 0; i < MAX_80MHZ_BANDS; i++) { start_channel = bitmap->chanBondingSet[i].startChannel; @@ -1499,28 +1501,28 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) * channel list from bitmap */ if (ch_width != CH_WIDTH_20MHZ) { + bool flag = false; + uint8_t count = 0, new_160_startchannel = 0; + uint8_t index = 0, sec_seg_ch = 0; + uint8_t primary_seg_start_ch = 0; available_ch_cnt = sap_populate_available_channels(&channelBitmap, ch_width, availableChannels); + /* - * if no valid channel bonding found, + * If no valid channel bonding found, * fallback to lower bandwidth */ if (available_ch_cnt == 0) { - if (ch_width == CH_WIDTH_80MHZ) { + if ((ch_width == CH_WIDTH_160MHZ) || + (ch_width == CH_WIDTH_80P80MHZ) || + (ch_width == CH_WIDTH_80MHZ)) { QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_WARN, - FL - ("sapdfs:No 80MHz cb found, falling to 40MHz")); - QDF_TRACE(QDF_MODULE_ID_SAP, - QDF_TRACE_LEVEL_WARN, - FL - ("sapdfs:Changing chanWidth from [%d] to [%d]"), - ch_width, - CH_WIDTH_40MHZ); + FL("sapdfs:Changing chanWidth from [%d] to 40Mhz"), + ch_width); ch_width = CH_WIDTH_40MHZ; - /* continue to start of do loop */ continue; } else if (ch_width == CH_WIDTH_40MHZ) { QDF_TRACE(QDF_MODULE_ID_SAP, @@ -1538,47 +1540,167 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) continue; } } - } - /* - * by now, available channels list will be populated or - * no channels are avaialbe - */ - if (available_ch_cnt) { - for (i = 0; i < available_ch_cnt; i++) { - if (CDS_IS_DFS_CH(availableChannels[i])) { - avail_dfs_chan_list[ - avail_dfs_chan_count++] = - availableChannels[i]; - } else { - avail_non_dfs_chan_list[ - avail_non_dfs_chan_count++] = - availableChannels[i]; - } + /* + * Number of channel count should be more than 8 to + * switch new channel in 160Mhz band + */ + if (((ch_width == CH_WIDTH_160MHZ) || + (ch_width == CH_WIDTH_80P80MHZ)) && + (available_ch_cnt < SIR_DFS_MAX_20M_SUB_CH)) { + QDF_TRACE(QDF_MODULE_ID_SAP, + QDF_TRACE_LEVEL_WARN, + FL("sapdfs:Changing chanWidth from [%d] to [%d]"), + ch_width, CH_WIDTH_80MHZ); + ch_width = CH_WIDTH_80MHZ; + continue; } - } else { - QDF_TRACE(QDF_MODULE_ID_SAP, + if (ch_width == CH_WIDTH_160MHZ) { + /* + * NA supports only 2 blocks for 160Mhz + * bandwidth i.e 36-64 & 100-128 and + * all the channels in these blocks are + * continuous and seperated by 4Mhz. + */ + for (i = 1; ((i < available_ch_cnt)); i++) { + if ((availableChannels[i] - + availableChannels[i-1]) == 4) + count++; + else + count = 0; + if (count == + SIR_DFS_MAX_20M_SUB_CH - 1) { + flag = true; + new_160_startchannel = + availableChannels[i-7]; + break; + } + } + } else if (ch_width == CH_WIDTH_80P80MHZ) { + flag = true; + } + if ((flag == false) && (ch_width > CH_WIDTH_80MHZ)) { + ch_width = CH_WIDTH_80MHZ; + continue; + } + + if (ch_width == CH_WIDTH_160MHZ) { + cds_rand_get_bytes(0, (uint8_t *)&random_byte, + 1); + random_byte = (random_byte + + qdf_mc_timer_get_system_ticks()) + % SIR_DFS_MAX_20M_SUB_CH; + pMac->sap.SapDfsInfo.new_chanWidth = ch_width; + target_channel = new_160_startchannel + + (random_byte * 4); + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_LOW, - FL("No target channel found")); + FL("sapdfs: New Channel width = %d"), + pMac->sap.SapDfsInfo.new_chanWidth); + QDF_TRACE(QDF_MODULE_ID_SAP, + QDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: target_channel = %d"), + target_channel); + + qdf_mem_free(tmp_ch_lst); + return target_channel; + } else if (ch_width == CH_WIDTH_80P80MHZ) { + cds_rand_get_bytes(0, + (uint8_t *)&random_byte, 1); + index = (random_byte + + qdf_mc_timer_get_system_ticks()) % + available_ch_cnt; + target_channel = availableChannels[index]; + index -= (index % 4); + primary_seg_start_ch = availableChannels[index]; + + /* reset channels associate with primary 80Mhz */ + for (i = 0; i < 4; i++) + availableChannels[i + index] = 0; + /* + * select and calculate center frequency for + * secondary segement + */ + for (i = 0; i < available_ch_cnt / 4; i++) { + if (availableChannels[i * 4] && + (abs(primary_seg_start_ch - + availableChannels[i * 4]) > + (SIR_DFS_MAX_20M_SUB_CH * 2))) { + + sec_seg_ch = + availableChannels[i * 4] + + SIR_80MHZ_START_CENTER_CH_DIFF; + + break; + } + } + if (!sec_seg_ch && + (available_ch_cnt == + SIR_DFS_MAX_20M_SUB_CH)) + ch_width = CH_WIDTH_160MHZ; + else if (!sec_seg_ch) + ch_width = CH_WIDTH_80MHZ; + + pMac->sap.SapDfsInfo.new_ch_params.center_freq_seg1 + = sec_seg_ch; + pMac->sap.SapDfsInfo.new_chanWidth = ch_width; + + QDF_TRACE(QDF_MODULE_ID_SAP, + QDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: New Channel width = %d"), + pMac->sap.SapDfsInfo.new_chanWidth); + QDF_TRACE(QDF_MODULE_ID_SAP, + QDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: New Center Freq Seg1 = %d"), + sec_seg_ch); + QDF_TRACE(QDF_MODULE_ID_SAP, + QDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: target_channel = %d"), + target_channel); + + qdf_mem_free(tmp_ch_lst); + + return target_channel; + } + /* + * by now, available channels list will be populated or + * no channels are avaialbe + */ + if (available_ch_cnt) { + for (i = 0; i < available_ch_cnt; i++) { + if (CDS_IS_DFS_CH(availableChannels[i])) { + avail_dfs_chan_list[ + avail_dfs_chan_count++] = + availableChannels[i]; + } else { + avail_non_dfs_chan_list[ + avail_non_dfs_chan_count++] = + availableChannels[i]; + } + } + } else { + QDF_TRACE(QDF_MODULE_ID_SAP, + QDF_TRACE_LEVEL_INFO_LOW, + FL("No target channel found")); + } + + cds_rand_get_bytes(0, (uint8_t *)&random_byte, 1); + + /* Give preference to non-DFS channel */ + if (!pMac->f_prefer_non_dfs_on_radar) { + i = (random_byte + qdf_mc_timer_get_system_ticks()) % + available_ch_cnt; + target_channel = availableChannels[i]; + } else if (avail_non_dfs_chan_count) { + i = (random_byte + qdf_mc_timer_get_system_ticks()) % + avail_non_dfs_chan_count; + target_channel = avail_non_dfs_chan_list[i]; + } else { + i = (random_byte + qdf_mc_timer_get_system_ticks()) % + avail_dfs_chan_count; + target_channel = avail_dfs_chan_list[i]; + } } - - cds_rand_get_bytes(0, (uint8_t *)&random_byte, 1); - - /* Give preference to non-DFS channel */ - if (!pMac->f_prefer_non_dfs_on_radar) { - i = (random_byte + qdf_mc_timer_get_system_ticks()) % - available_ch_cnt; - target_channel = availableChannels[i]; - } else if (avail_non_dfs_chan_count) { - i = (random_byte + qdf_mc_timer_get_system_ticks()) % - avail_non_dfs_chan_count; - target_channel = avail_non_dfs_chan_list[i]; - } else { - i = (random_byte + qdf_mc_timer_get_system_ticks()) % - avail_dfs_chan_count; - target_channel = avail_dfs_chan_list[i]; - } - pMac->sap.SapDfsInfo.new_chanWidth = ch_width; QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_LOW, diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 9961c66101..07fd127728 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -2279,7 +2279,7 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t target_channel) void *hHal = NULL; tpAniSirGlobal mac_ctx = NULL; eCsrPhyMode phy_mode; - struct ch_params_s ch_params; + struct ch_params_s *ch_params; sapContext = (ptSapContext) pSapCtx; if (NULL == sapContext) { @@ -2302,16 +2302,16 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t target_channel) * because we've implemented channel width fallback mechanism for DFS * which will result in channel width changing dynamically. */ - ch_params.ch_width = mac_ctx->sap.SapDfsInfo.new_chanWidth; - sme_set_ch_params(hHal, phy_mode, target_channel, 0, &ch_params); - sapContext->ch_params.ch_width = ch_params.ch_width; + ch_params = &mac_ctx->sap.SapDfsInfo.new_ch_params; + sme_set_ch_params(hHal, phy_mode, target_channel, 0, ch_params); + sapContext->ch_params.ch_width = ch_params->ch_width; /* Update the channel as this will be used to * send event to supplicant */ sapContext->channel = target_channel; - sapContext->csr_roamProfile.ch_params.ch_width = ch_params.ch_width; + sapContext->csr_roamProfile.ch_params.ch_width = ch_params->ch_width; qdf_ret_status = sme_roam_channel_change_req(hHal, sapContext->bssid, - &ch_params, &sapContext->csr_roamProfile); + ch_params, &sapContext->csr_roamProfile); if (qdf_ret_status == QDF_STATUS_SUCCESS) { sap_signal_hdd_event(sapContext, NULL, @@ -2430,6 +2430,13 @@ QDF_STATUS wlansap_dfs_send_csa_ie_request(void *pSapCtx) } pMac = PMAC_STRUCT(hHal); + pMac->sap.SapDfsInfo.new_ch_params.ch_width = + pMac->sap.SapDfsInfo.new_chanWidth; + + sme_set_ch_params(hHal, sapContext->csr_roamProfile.phyMode, + pMac->sap.SapDfsInfo.target_channel, 0, + &pMac->sap.SapDfsInfo.new_ch_params); + qdf_ret_status = sme_roam_csa_ie_request(hHal, sapContext->bssid, pMac->sap.SapDfsInfo.target_channel,