summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/cds/src/cds_concurrency.c194
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.c30
-rw-r--r--core/sap/src/sap_fsm.c13
3 files changed, 134 insertions, 103 deletions
diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c
index db2594c4cdef..b297c09f5873 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);
}
@@ -5294,6 +5300,39 @@ static bool cds_vht160_conn_exist(void)
}
/**
+ * 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
* @mode: new connection mode
@@ -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++;
- }
-
- 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++;
- }
+ 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;
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 199268dd1d40..8884800e31f3 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 2a091dbbbfbd..c7f263257bfa 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;