diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c index e6f465d31831..723b9e4d1d73 100644 --- a/core/sap/src/sap_api_link_cntl.c +++ b/core/sap/src/sap_api_link_cntl.c @@ -532,6 +532,7 @@ wlansap_roam_process_dfs_chansw_update(tHalHandle hHal, QDF_STATUS qdf_status; tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal); uint8_t dfs_beacon_start_req = 0; + bool sap_scc_dfs; if (sap_ctx->csr_roamProfile.disableDFSChSwitch) { QDF_TRACE(QDF_MODULE_ID_SAP, @@ -590,9 +591,22 @@ wlansap_roam_process_dfs_chansw_update(tHalHandle hHal, * immediately, as in this case the both SAP will be in different band * and channel change on one SAP doesnt mean channel change on * other interface. + * + * For example, + * Let's say SAP(2G) + SAP(5G-DFS) is initial connection which triggered + * DualBand HW mode and if SAP(5G-DFS) is moving to some channel then + * SAP(2G) doesn't need to move. + * + * If both SAPs are not doing SCC DFS then each of them can change the + * channel independently. Channel change of one SAP became dependent + * second SAP's channel change due to some previous platform's single + * radio limitation. + * */ + sap_scc_dfs = sap_is_conc_sap_doing_scc_dfs(hHal, sap_ctx); if (sap_get_total_number_sap_intf(hHal) <= 1 || - policy_mgr_is_current_hwmode_dbs(mac_ctx->psoc)) { + policy_mgr_is_current_hwmode_dbs(mac_ctx->psoc) || + !sap_scc_dfs) { /* Send channel switch request */ sap_event.event = eWNI_SME_CHANNEL_CHANGE_REQ; sap_event.params = 0; @@ -615,6 +629,14 @@ wlansap_roam_process_dfs_chansw_update(tHalHandle hHal, * both the SAPs. If no then simply return success & we will * issue channel change when second AP's 5 CSA beacon Tx is * completed. + * + * This check is added to take care of following scenario: + * if SAP1 + SAP2 is doing DFS SCC and radar is detected on that channel + * then SAP1 sends 5 beacons with CSA/ECSA IE and wait for SAP2 to + * finish sending 5 beacons. if SAP1 changes channel before SAP2 finish + * sending beacons then it ends up in + * (SAP1 new channel + SAP2 old channel) MCC with DFS scenario + * which causes some of the stability issues in old platforms. */ if (false == is_concurrent_sap_ready_for_channel_change(hHal, sap_ctx)) { @@ -631,7 +653,6 @@ wlansap_roam_process_dfs_chansw_update(tHalHandle hHal, if (!((QDF_SAP_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona) && (mac_ctx->sap.sapCtxList[intf].pSapContext != NULL))) continue; - pSapContext = mac_ctx->sap.sapCtxList[intf].pSapContext; QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_MED, FL("sapdfs:issue chnl change for sapctx[%pK]"), @@ -1038,6 +1059,8 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, /* Issue stopbss for each sapctx */ for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { struct sap_context *pSapContext; + tCsrRoamProfile *profile; + if (((QDF_SAP_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona) || (QDF_P2P_GO_MODE == @@ -1046,6 +1069,10 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, NULL) { pSapContext = mac_ctx->sap.sapCtxList[intf].pSapContext; + profile = &pSapContext->csr_roamProfile; + if (!wlan_reg_is_dfs_ch(mac_ctx->pdev, + profile->operationChannel)) + continue; QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, FL("sapdfs: no available channel for sapctx[%pK], StopBss"), diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 2b40afa59a0a..12840c0c721e 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2796,11 +2796,18 @@ static QDF_STATUS sap_cac_start_notify(tHalHandle hHal) for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { struct sap_context *pSapContext = pMac->sap.sapCtxList[intf].pSapContext; + tCsrRoamProfile *profile; + if (((QDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) || (QDF_P2P_GO_MODE == pMac->sap.sapCtxList[intf].sapPersona)) && pMac->sap.sapCtxList[intf].pSapContext != NULL && (false == pSapContext->isCacStartNotified)) { + /* Don't start CAC for non-dfs channel, its violation */ + profile = &pSapContext->csr_roamProfile; + if (!wlan_reg_is_dfs_ch(pMac->pdev, + profile->operationChannel)) + continue; QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_MED, "sapdfs: Signaling eSAP_DFS_CAC_START to HDD for sapctx[%pK]", pSapContext); @@ -2888,6 +2895,8 @@ static QDF_STATUS sap_cac_end_notify(tHalHandle hHal, tCsrRoamInfo *roamInfo) for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { struct sap_context *pSapContext = pMac->sap.sapCtxList[intf].pSapContext; + tCsrRoamProfile *profile; + if (((QDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) || (QDF_P2P_GO_MODE == pMac->sap.sapCtxList[intf].sapPersona)) @@ -2895,6 +2904,11 @@ static QDF_STATUS sap_cac_end_notify(tHalHandle hHal, tCsrRoamInfo *roamInfo) (false == pSapContext->isCacEndNotified) && (pSapContext->sapsMachine == eSAP_DFS_CAC_WAIT)) { pSapContext = pMac->sap.sapCtxList[intf].pSapContext; + /* Don't check CAC for non-dfs channel */ + profile = &pSapContext->csr_roamProfile; + if (!wlan_reg_is_dfs_ch(pMac->pdev, + profile->operationChannel)) + continue; /* If this is an end notification of a pre cac, the * SAP must not start beaconing and must delete the @@ -3242,6 +3256,8 @@ static QDF_STATUS sap_fsm_state_dfs_cac_wait(struct sap_context *sap_ctx, for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { struct sap_context *t_sap_ctx; + tCsrRoamProfile *profile; + t_sap_ctx = mac_ctx->sap.sapCtxList[intf].pSapContext; if (((QDF_SAP_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona) || @@ -3249,8 +3265,12 @@ static QDF_STATUS sap_fsm_state_dfs_cac_wait(struct sap_context *sap_ctx, mac_ctx->sap.sapCtxList[intf].sapPersona)) && t_sap_ctx != NULL && t_sap_ctx->sapsMachine != eSAP_DISCONNECTED) { + profile = &t_sap_ctx->csr_roamProfile; + if (!wlan_reg_is_dfs_ch(mac_ctx->pdev, + profile->operationChannel)) + continue; /* SAP to be moved to DISCONNECTING state */ - sap_ctx->sapsMachine = eSAP_DISCONNECTING; + t_sap_ctx->sapsMachine = eSAP_DISCONNECTING; /* * eSAP_DFS_CHANNEL_CAC_RADAR_FOUND: * A Radar is found on current DFS Channel @@ -3460,6 +3480,8 @@ static QDF_STATUS sap_fsm_state_started(struct sap_context *sap_ctx, */ for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { struct sap_context *temp_sap_ctx; + tCsrRoamProfile *profile; + if (((QDF_SAP_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona) || (QDF_P2P_GO_MODE == @@ -3467,6 +3489,14 @@ static QDF_STATUS sap_fsm_state_started(struct sap_context *sap_ctx, mac_ctx->sap.sapCtxList[intf].pSapContext != NULL) { temp_sap_ctx = mac_ctx->sap.sapCtxList[intf].pSapContext; + /* + * Radar won't come on non-dfs channel, so + * no need to move them + */ + profile = &temp_sap_ctx->csr_roamProfile; + if (!wlan_reg_is_dfs_ch(mac_ctx->pdev, + profile->operationChannel)) + continue; QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_MED, FL("sapdfs: Sending CSAIE for sapctx[%pK]"), @@ -4505,9 +4535,17 @@ uint8_t sap_get_total_number_sap_intf(tHalHandle hHal) return intf_count; } -/* +/** + * is_concurrent_sap_ready_for_channel_change() - to check all saps are ready + * for channel change + * @hHal: HAL pointer + * @sapContext: sap context for which this function has been called + * * This function will find the concurrent sap context apart from * passed sap context and return its channel change ready status + * + * + * Return: true if other SAP personas are ready to channel switch else false */ bool is_concurrent_sap_ready_for_channel_change(tHalHandle hHal, struct sap_context *sapContext) @@ -4541,3 +4579,54 @@ bool is_concurrent_sap_ready_for_channel_change(tHalHandle hHal, } return false; } + +/** + * sap_is_conc_sap_doing_scc_dfs() - check if conc SAPs are doing SCC DFS + * @hal: pointer to hal + * @sap_context: current SAP persona's channel + * + * If provided SAP's channel is DFS then Loop through each SAP or GO persona and + * check if other beaconing entity's channel is same DFS channel. If they are + * same then concurrent sap is doing SCC DFS. + * + * Return: true if two or more beaconing entitity doing SCC DFS else false + */ +bool sap_is_conc_sap_doing_scc_dfs(tHalHandle hal, + struct sap_context *given_sapctx) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct sap_context *sap_ctx; + uint8_t intf = 0, scc_dfs_counter = 0; + + /* + * current SAP persona's channel itself is not DFS, so no need to check + * what other persona's channel is + */ + if (!wlan_reg_is_dfs_ch(mac->pdev, + given_sapctx->csr_roamProfile.operationChannel)) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_DEBUG, + FL("skip this loop as provided channel is non-dfs")); + return false; + } + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + if ((QDF_SAP_MODE != mac->sap.sapCtxList[intf].sapPersona) && + (QDF_P2P_GO_MODE != mac->sap.sapCtxList[intf].sapPersona)) + continue; + if (!mac->sap.sapCtxList[intf].pSapContext) + continue; + sap_ctx = mac->sap.sapCtxList[intf].pSapContext; + /* if same SAP contexts then skip to next context */ + if (sap_ctx == given_sapctx) + continue; + if (given_sapctx->csr_roamProfile.operationChannel == + sap_ctx->csr_roamProfile.operationChannel) + scc_dfs_counter++; + } + + /* Found atleast two of the beaconing entities doing SCC DFS */ + if (scc_dfs_counter) + return true; + + return false; +} diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h index 9306da5be4fd..3eae7c86cebe 100644 --- a/core/sap/src/sap_internal.h +++ b/core/sap/src/sap_internal.h @@ -391,7 +391,8 @@ sap_channel_matrix_check(struct sap_context *sapContext, bool is_concurrent_sap_ready_for_channel_change(tHalHandle hHal, struct sap_context *sapContext); - +bool sap_is_conc_sap_doing_scc_dfs(tHalHandle hal, + struct sap_context *given_sapctx); uint8_t sap_get_total_number_sap_intf(tHalHandle hHal); bool sap_dfs_is_w53_invalid(tHalHandle hHal, uint8_t channelID);