diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 7ccddc2541..d18fc3d8d9 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -68,6 +68,10 @@ #define CSR_IS_SESSION_ANY(sessionId) (sessionId == SME_SESSION_ID_ANY) #define CSR_MAX_NUM_COUNTRY_CODE 100 +#define CSR_IS_DFS_CH_ROAM_ALLOWED(mac_ctx) \ + ( \ + (((mac_ctx)->roam.configParam.allowDFSChannelRoam) ? true : false) \ + ) #define CSR_IS_SELECT_5GHZ_MARGIN(pMac) \ ( \ (((pMac)->roam.configParam.nSelect5GHzMargin) ? true : false) \ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 041862f4b9..0c96ec5aee 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -476,8 +476,84 @@ static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * CDF_ASSERT(0); return 0; } + +/** + * csr_roam_arrange_ch_list() - Updates the channel list modified with greedy + * order for 5 Ghz preference and DFS channels. + * @mac_ctx: pointer to mac context. + * @chan_list: channel list updated with greedy channel order. + * @num_channel: Number of channels in list + * + * To allow Early Stop Roaming Scan feature to co-exist with 5G preference, + * this function moves 5G channels ahead of 2G channels. This function can + * also move 2G channels, ahead of DFS channel or vice versa. Order is + * maintained among same category channels + * + * Return: None + */ +void csr_roam_arrange_ch_list(tpAniSirGlobal mac_ctx, + tSirUpdateChanParam *chan_list, uint8_t num_channel) +{ + bool prefer_5g = CSR_IS_ROAM_PREFER_5GHZ(mac_ctx); + bool prefer_dfs = CSR_IS_DFS_CH_ROAM_ALLOWED(mac_ctx); + int i, j = 0; + tSirUpdateChanParam *tmp_list = NULL; + + if (!prefer_5g) + return; + + tmp_list = (tSirUpdateChanParam *) + cdf_mem_malloc(sizeof(tSirUpdateChanParam) * num_channel); + if (tmp_list == NULL) { + sms_log(mac_ctx, LOGE, FL("Memory allocation failed")); + return; + } + + /* Fist copy Non-DFS 5g channels */ + for (i = 0; i < num_channel; i++) { + if (CDS_IS_CHANNEL_5GHZ(chan_list[i].chanId) && + !CDS_IS_DFS_CH(chan_list[i].chanId)) { + cdf_mem_copy(&tmp_list[j++], + &chan_list[i], sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + if (prefer_dfs) { + /* next copy DFS channels (remaining channels in 5G) */ + for (i = 0; i < num_channel; i++) { + if (CDS_IS_CHANNEL_5GHZ(chan_list[i].chanId)) { + cdf_mem_copy(&tmp_list[j++], &chan_list[i], + sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + } else { + /* next copy 2G channels */ + for (i = 0; i < num_channel; i++) { + if (CDS_IS_CHANNEL_24GHZ(chan_list[i].chanId)) { + cdf_mem_copy(&tmp_list[j++], &chan_list[i], + sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + } + /* copy rest of the channels in same order to tmp list */ + for (i = 0; i < num_channel; i++) { + if (chan_list[i].chanId != INVALID_CHANNEL_ID) { + cdf_mem_copy(&tmp_list[j++], &chan_list[i], + sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + /* copy tmp list to original channel list buffer */ + cdf_mem_copy(chan_list, tmp_list, + sizeof(tSirUpdateChanParam) * num_channel); + cdf_mem_free(tmp_list); +} + /** * csr_roam_sort_channel_for_early_stop() - Sort the channels + * @mac_ctx: mac global context * @chan_list: Original channel list from the upper layers * @num_channel: Number of original channels * @@ -495,8 +571,8 @@ static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * * * Return: None */ -void csr_roam_sort_channel_for_early_stop(tSirUpdateChanList *chan_list, - uint8_t num_channel) +void csr_roam_sort_channel_for_early_stop(tpAniSirGlobal mac_ctx, + tSirUpdateChanList *chan_list, uint8_t num_channel) { tSirUpdateChanList *chan_list_greedy, *chan_list_non_greedy; uint8_t i, j; @@ -587,6 +663,9 @@ void csr_roam_sort_channel_for_early_stop(tSirUpdateChanList *chan_list, cdf_mem_copy(&chan_list->chanParam[i], &chan_list_non_greedy->chanParam[j], num_non_greedy_chan * sizeof(tSirUpdateChanParam)); + + /* Update channel list for 5g preference and allow DFS roam */ + csr_roam_arrange_ch_list(mac_ctx, chan_list->chanParam, num_channel); scan_list_sort_error: cdf_mem_free(chan_list_greedy); cdf_mem_free(chan_list_non_greedy); @@ -673,7 +752,8 @@ CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac) } } if (pMac->roam.configParam.early_stop_scan_enable) - csr_roam_sort_channel_for_early_stop(pChanList, num_channel); + csr_roam_sort_channel_for_early_stop(pMac, pChanList, + num_channel); else CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, FL("Early Stop Scan Feature not supported")); @@ -726,7 +806,6 @@ CDF_STATUS csr_start(tpAniSirGlobal pMac) CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "Scan offload is enabled, update default chan list"); status = csr_update_channel_list(pMac); - } while (0); return status; }