From 80aabd45839e604495d6f5b6b4092c592608046f Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Mon, 21 Dec 2015 12:17:16 -0800 Subject: [PATCH] qcacld-3.0: Do not allow STA scan on IBSS channel's band As per the requirement when IBSS connection co-exist with STA connection and scan request is coming from STA adapter, don't include those channels which fall in same band as IBSS channel's band. Change-Id: Ifb42ea6b463bd5020bf544eee504b9c3ceefcfc2 CRs-Fixed: 953788 --- core/cds/inc/cds_concurrency.h | 1 + core/cds/src/cds_concurrency.c | 41 ++++++++++++ core/sme/src/csr/csr_api_scan.c | 114 ++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 261b97460d..bb799cb35c 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -688,6 +688,7 @@ CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, CDF_STATUS cds_current_connections_update(uint32_t session_id, uint8_t channel, enum cds_conn_update_reason); +bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel); #ifdef MPC_UT_FRAMEWORK CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 6d24eb1b84..2f97b41185 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3245,6 +3245,7 @@ void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) case CDF_P2P_CLIENT_MODE: case CDF_P2P_GO_MODE: case CDF_SAP_MODE: + case CDF_IBSS_MODE: hdd_ctx->concurrency_mode |= (1 << mode); hdd_ctx->no_of_open_sessions[mode]++; break; @@ -4557,6 +4558,41 @@ bool cds_allow_new_home_channel(hdd_context_t *hdd_ctx, return status; } +/** + * cds_is_ibss_conn_exist() - to check if IBSS connection already present + * @hdd_ctx: pointer to hdd context + * @ibss_channel: pointer to ibss channel which needs to be filled + * + * this routine will check if IBSS connection already exist or no. If it + * exist then this routine will return true and fill the ibss_channel value. + * + * Return: true if ibss connection exist else false + */ +bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel) +{ + uint32_t count = 0, index = 0; + uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; + bool status = false; + if ((NULL == hdd_ctx) || (NULL == ibss_channel)) { + cds_err("Null pointer error"); + return false; + } + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_IBSS_MODE, list); + if (count == 0) { + /* No IBSS connection */ + status = false; + } else if (count == 1) { + *ibss_channel = conc_connection_list[list[index]].chan; + status = true; + } else { + *ibss_channel = conc_connection_list[list[index]].chan; + cds_notice("Multiple IBSS connections, picking first one"); + status = true; + } + return status; +} + /** * cds_allow_concurrency() - Check for allowed concurrency * combination @@ -4723,6 +4759,11 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, cds_err("No IBSS + STA SCC/MCC, IBSS is on DFS channel"); goto done; } + /* + * This logic protects STA and IBSS to come up on same + * band. If requirement changes then this condition + * needs to be removed + */ if ((conc_connection_list[0].chan != channel) && CDS_IS_SAME_BAND_CHANNELS( conc_connection_list[0].chan, channel)) { diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 2ca632d2da..921288b960 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -5273,6 +5273,99 @@ static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, dst_req->ChannelInfo.numOfChannels = new_index; } +/** + * csr_scan_filter_ibss_chnl_band() - filter all channels which matches IBSS + * channel's band + * @mac_ctx: pointer to mac context + * @ibss_channel: Given IBSS channel + * @dst_req: destination scan request + * + * when ever IBSS connection already exist, STA should not scan the channels + * which fall under same band as IBSS channel's band. this routine will filter + * out those channels + * + * Return: true if success otherwise false for any failure + */ +static bool csr_scan_filter_ibss_chnl_band(tpAniSirGlobal mac_ctx, + uint8_t ibss_channel, tCsrScanRequest *dst_req) { + uint8_t valid_chnl_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + uint8_t filtered_chnl_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + uint32_t filter_chnl_len = 0, i = 0; + uint32_t valid_chnl_len = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + if (ibss_channel == 0) { + sms_log(mac_ctx, LOG1, + FL("Nothing to filter as no IBSS session")); + return true; + } + + if (!dst_req) { + sms_log(mac_ctx, LOGE, + FL("No valid scan requests")); + return false; + } + /* + * In case of concurrent IBSS session exist, scan only + * those channels which are not in IBSS channel's band. + * In case if no-concurrent IBSS session exist then scan + * full band + */ + if ((dst_req->ChannelInfo.numOfChannels == 0)) { + csr_get_cfg_valid_channels(mac_ctx, valid_chnl_list, + &valid_chnl_len); + } else { + valid_chnl_len = (WNI_CFG_VALID_CHANNEL_LIST_LEN > + dst_req->ChannelInfo.numOfChannels) ? + dst_req->ChannelInfo.numOfChannels : + WNI_CFG_VALID_CHANNEL_LIST_LEN; + cdf_mem_copy(valid_chnl_list, dst_req->ChannelInfo.ChannelList, + valid_chnl_len); + } + for (i = 0; i < valid_chnl_len; i++) { + /* + * Don't allow DSRC channel when IBSS concurrent connection + * is up + */ + if (valid_chnl_list[i] >= MIN_11P_CHANNEL) + continue; + if (CDS_IS_CHANNEL_5GHZ(ibss_channel) && + CDS_IS_CHANNEL_24GHZ(valid_chnl_list[i])) { + filtered_chnl_list[filter_chnl_len] = + valid_chnl_list[i]; + filter_chnl_len++; + } else if (CDS_IS_CHANNEL_24GHZ(ibss_channel) && + CDS_IS_CHANNEL_5GHZ(valid_chnl_list[i])) { + filtered_chnl_list[filter_chnl_len] = + valid_chnl_list[i]; + filter_chnl_len++; + } + } + if (filter_chnl_len == 0) { + sms_log(mac_ctx, LOGE, + FL("there no channels to scan due to IBSS session")); + return false; + } + + if (dst_req->ChannelInfo.ChannelList) { + cdf_mem_free(dst_req->ChannelInfo.ChannelList); + dst_req->ChannelInfo.ChannelList = NULL; + dst_req->ChannelInfo.numOfChannels = 0; + } + + dst_req->ChannelInfo.ChannelList = + cdf_mem_malloc(filter_chnl_len * + sizeof(*dst_req->ChannelInfo.ChannelList)); + dst_req->ChannelInfo.numOfChannels = filter_chnl_len; + if (NULL == dst_req->ChannelInfo.ChannelList) { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed")); + return false; + } + cdf_mem_copy(dst_req->ChannelInfo.ChannelList, filtered_chnl_list, + filter_chnl_len); + return true; +} + /** * csr_scan_copy_request() - Function to copy scan request * @mac_ctx : pointer to Global Mac Structure @@ -5292,6 +5385,7 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, uint32_t index = 0; uint32_t new_index = 0; CHANNEL_STATE channel_state; + uint8_t ibss_channel = 0; bool skip_dfs_chnl = mac_ctx->roam.configParam.initial_scan_no_dfs_chnl || !mac_ctx->scan.fEnableDFSChnlScan; @@ -5389,6 +5483,26 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, new_index; } } /* Allocate memory for Channel List */ + + /* + * If IBSS concurrent connection exist, and if the scan + * request comes from STA adapter then we need to filter + * out IBSS channel's band otherwise it will cause issue + * in IBSS+STA concurrency + */ + if (true == cds_is_ibss_conn_exist(mac_ctx->hHdd, &ibss_channel)) { + sms_log(mac_ctx, LOG1, + FL("Conc IBSS exist, channel list will be modified")); + } + + if ((ibss_channel > 0) && + (false == csr_scan_filter_ibss_chnl_band(mac_ctx, + ibss_channel, dst_req))) { + sms_log(mac_ctx, LOGE, + FL("Can't filter channels due to IBSS")); + goto complete; + } + if (src_req->SSIDs.numOfSSIDs == 0) { dst_req->SSIDs.numOfSSIDs = 0; dst_req->SSIDs.SSIDList = NULL;