diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index db2594c4cd..b297c09f58 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3344,7 +3344,6 @@ void cds_dump_concurrency_info(void) status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); adapterNode = pNext; } - cds_dump_current_concurrency(); hdd_ctx->mcc_mode = cds_current_concurrency_is_mcc(); } @@ -3572,6 +3571,52 @@ static void cds_pdev_set_pcl(enum tQDF_ADAPTER_MODE mode) cds_info("Set PCL to FW for mode:%d", mode); } + +/** + * cds_set_pcl_for_existing_combo() - Set PCL for existing connection + * @mode: Connection mode of type 'cds_con_mode' + * + * Set the PCL for an existing connection + * + * Return: None + */ +static void cds_set_pcl_for_existing_combo(enum cds_con_mode mode) +{ + struct cds_conc_connection_info info; + enum tQDF_ADAPTER_MODE pcl_mode; + + switch (mode) { + case CDS_STA_MODE: + pcl_mode = QDF_STA_MODE; + break; + case CDS_SAP_MODE: + pcl_mode = QDF_SAP_MODE; + break; + case CDS_P2P_CLIENT_MODE: + pcl_mode = QDF_P2P_CLIENT_MODE; + break; + case CDS_P2P_GO_MODE: + pcl_mode = QDF_P2P_GO_MODE; + break; + case CDS_IBSS_MODE: + pcl_mode = QDF_IBSS_MODE; + break; + default: + cds_err("Invalid mode to set PCL"); + return; + }; + + if (cds_mode_specific_connection_count(mode, NULL) > 0) { + /* Check, store and temp delete the mode's parameter */ + cds_store_and_del_conn_info(mode, &info); + /* Set the PCL to the FW since connection got updated */ + cds_pdev_set_pcl(pcl_mode); + cds_info("Set PCL to FW for mode:%d", mode); + /* Restore the connection info */ + cds_restore_deleted_conn_info(&info); + } +} + /** * cds_incr_active_session() - increments the number of active sessions * @mode: Adapter mode @@ -3633,9 +3678,14 @@ void cds_incr_active_session(enum tQDF_ADAPTER_MODE mode, cds_info("Set PCL of STA to FW"); } cds_incr_connection_count(session_id); + if ((cds_mode_specific_connection_count(CDS_STA_MODE, NULL) > 0) && + (mode != QDF_STA_MODE)) { + cds_set_pcl_for_existing_combo(CDS_STA_MODE); + } /* set tdls connection tracker state */ cds_set_tdls_ct_mode(hdd_ctx); + cds_dump_current_concurrency(); qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); } @@ -3709,52 +3759,6 @@ done: return upgrade; } - -/** - * cds_set_pcl_for_existing_combo() - Set PCL for existing connection - * @mode: Connection mode of type 'cds_con_mode' - * - * Set the PCL for an existing connection - * - * Return: None - */ -static void cds_set_pcl_for_existing_combo(enum cds_con_mode mode) -{ - struct cds_conc_connection_info info; - enum tQDF_ADAPTER_MODE pcl_mode; - - switch (mode) { - case CDS_STA_MODE: - pcl_mode = QDF_STA_MODE; - break; - case CDS_SAP_MODE: - pcl_mode = QDF_SAP_MODE; - break; - case CDS_P2P_CLIENT_MODE: - pcl_mode = QDF_P2P_CLIENT_MODE; - break; - case CDS_P2P_GO_MODE: - pcl_mode = QDF_P2P_GO_MODE; - break; - case CDS_IBSS_MODE: - pcl_mode = QDF_IBSS_MODE; - break; - default: - cds_err("Invalid mode to set PCL"); - return; - }; - - if (cds_mode_specific_connection_count(mode, NULL) > 0) { - /* Check, store and temp delete the mode's parameter */ - cds_store_and_del_conn_info(mode, &info); - /* Set the PCL to the FW since connection got updated */ - cds_pdev_set_pcl(pcl_mode); - cds_info("Set PCL to FW for mode:%d", mode); - /* Restore the connection info */ - cds_restore_deleted_conn_info(&info); - } -} - /** * cds_get_pcl_for_existing_conn() - Get PCL for existing connection * @mode: Connection mode of type 'cds_con_mode' @@ -3908,6 +3912,8 @@ void cds_decr_active_session(enum tQDF_ADAPTER_MODE mode, /* set tdls connection tracker state */ cds_set_tdls_ct_mode(hdd_ctx); + cds_dump_current_concurrency(); + qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); } @@ -5293,6 +5299,39 @@ static bool cds_vht160_conn_exist(void) return status; } +/** + * cds_is_5g_channel_allowed() - check if 5g channel is allowed + * @channel: channel number which needs to be validated + * @list: list of existing connections. + * @mode: mode against which channel needs to be validated + * + * This API takes the channel as input and compares with existing + * connection channels. If existing connection's channel is DFS channel + * and provided channel is 5G channel then don't allow concurrency to + * happen as MCC with DFS channel is not yet supported + * + * Return: true if 5G channel is allowed, false if not allowed + * + */ +static bool cds_is_5g_channel_allowed(uint8_t channel, uint32_t *list, + enum cds_con_mode mode) +{ + uint32_t index = 0, count = 0; + + count = cds_mode_specific_connection_count(mode, list); + while (index < count) { + if (CDS_IS_DFS_CH(conc_connection_list[list[index]].chan) && + CDS_IS_CHANNEL_5GHZ(channel) && + (channel != conc_connection_list[list[index]].chan)) { + cds_err("don't allow MCC if SAP/GO on DFS channel"); + return false; + } + index++; + } + return true; + +} + /** * cds_allow_concurrency() - Check for allowed concurrency * combination @@ -5356,59 +5395,24 @@ bool cds_allow_concurrency(enum cds_con_mode mode, if (channel) { /* don't allow 3rd home channel on same MAC */ - if (!cds_allow_new_home_channel(channel, - num_connections)) - goto done; - - /* - * If you already have STA connection then don't - * allow any other persona to make connection on DFS channel - * because STA might be on non-DFS right now but later on as - * part of roaming if STA connects to DFS channel which happens - * to be different than requested DFS channel then MCC DFS - * scenario will be encountered - */ - count = cds_mode_specific_connection_count(CDS_STA_MODE, - list); - if ((count > 0) && CDS_IS_DFS_CH(channel)) { - cds_err("STA active, don't allow DFS channel for 2nd connection"); + if (!cds_allow_new_home_channel(channel, num_connections)) goto done; - } /* - * don't allow MCC if SAP/GO on DFS channel or about to come up - * on DFS channel + * 1) DFS MCC is not yet supported + * 2) If you already have STA connection on 5G channel then + * don't allow any other persona to make connection on DFS + * channel because STA 5G + DFS MCC is not allowed. + * 3) If STA is on 2G channel and SAP is coming up on + * DFS channel then allow concurrency but make sure it is + * going to DBS and send PCL to firmware indicating that + * don't allow STA to roam to 5G channels. */ - count = cds_mode_specific_connection_count( - CDS_P2P_GO_MODE, list); - while (index < count) { - if ((CDS_IS_DFS_CH( - conc_connection_list[list[index]].chan)) && - (CDS_IS_CHANNEL_5GHZ(channel)) && - (channel != - conc_connection_list[list[index]].chan)) { - cds_err("don't allow MCC if SAP/GO on DFS channel"); - goto done; - } - index++; - } + if (!cds_is_5g_channel_allowed(channel, list, CDS_P2P_GO_MODE)) + goto done; + if (!cds_is_5g_channel_allowed(channel, list, CDS_SAP_MODE)) + goto done; - index = 0; - count = cds_mode_specific_connection_count( - CDS_SAP_MODE, list); - while (index < count) { - if ((CDS_IS_DFS_CH( - conc_connection_list[list[index]].chan)) && - (CDS_IS_CHANNEL_5GHZ(channel)) && - (channel != - conc_connection_list[list[index]].chan)) { - cds_err("don't allow MCC if SAP/GO on DFS channel"); - goto done; - } - index++; - } - - index = 0; if ((CDS_P2P_GO_MODE == mode) || (CDS_SAP_MODE == mode)) { if (CDS_IS_DFS_CH(channel)) match = cds_disallow_mcc(channel); diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 199268dd1d..8884800e31 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1049,11 +1049,15 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, pHostapdState->qdf_status = pSapEvent->sapevt.sapStartBssCompleteEvent.status; - qdf_status = qdf_event_set(&pHostapdState->qdf_event); - - if (!QDF_IS_STATUS_SUCCESS(qdf_status) - || pHostapdState->qdf_status) { + if (pHostapdState->qdf_status) { hdd_err("ERROR: startbss event failed!!"); + /* + * Make sure to set the event before proceeding + * for error handling otherwise caller thread will + * wait till 10 secs and no other connection will + * go through before that. + */ + qdf_event_set(&pHostapdState->qdf_event); goto stopbss; } else { sme_ch_avoid_update_req(pHddCtx->hHal); @@ -1084,6 +1088,13 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, pHostapdAdapter->dev->dev_addr); if (status) { hdd_err("WLAN_AP_CONNECT event failed!!"); + /* + * Make sure to set the event before proceeding + * for error handling otherwise caller thread + * will wait till 10 secs and no other + * connection will go through before that. + */ + qdf_event_set(&pHostapdState->qdf_event); goto stopbss; } } @@ -1209,6 +1220,17 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, hdd_info("set hw mode change not done"); cds_set_do_hw_mode_change_flag(false); } + /* + * set this event at the very end because once this events + * get set, caller thread is waiting to do further processing. + * so once this event gets set, current worker thread might get + * pre-empted by caller thread. + */ + qdf_status = qdf_event_set(&pHostapdState->qdf_event); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + hdd_err("ERROR: startbss event set failed!!"); + goto stopbss; + } break; /* Event will be sent after Switch-Case stmt */ case eSAP_STOP_BSS_EVENT: diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 2a091dbbbf..c7f263257b 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -4733,10 +4733,15 @@ static QDF_STATUS sap_get_5ghz_channel_list(ptSapContext sapContext) " Memory Allocation failed sap_get_channel_list"); return QDF_STATUS_E_NOMEM; } - - status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE, - pcl.pcl_list, &pcl.pcl_len, - pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list)); + if (cds_mode_specific_connection_count(CDS_SAP_MODE, NULL) == 0) { + status = cds_get_pcl(CDS_SAP_MODE, + pcl.pcl_list, &pcl.pcl_len, pcl.weight_list, + QDF_ARRAY_SIZE(pcl.weight_list)); + } else { + status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE, + pcl.pcl_list, &pcl.pcl_len, pcl.weight_list, + QDF_ARRAY_SIZE(pcl.weight_list)); + } if (status != QDF_STATUS_SUCCESS) { cds_err("Get PCL failed"); return status;