Эх сурвалжийг харах

qcacld-3.0: Fix to handle SAP+STA DFS MCC scenario

1) If STA is on 2G channel and SAP is coming up on 5G DFS channel then
   it should be allowed given that DBS is supported.
2) If STA is on 5G channel and SAP is coming up on 5G DFS channel then
   it shoudln't be allowed as it will create DFS MCC scenario
3) If SAP is on 5G DFS and STA is coming up on 2G channel then it should
   be allowed given that DBS is supported.
4) If SAP is on 5G or 2G channel and STA is coming up on either of the
   bands then allow  connections to go through.
Make necessary adjustment to apply all above 4 rules.

Change-Id: I0a4dfe57cad1d2a62ada1bd8c258f7f3f6ac5dc2
CRs-Fixed: 1083376
(cherry picked from commit c6b307e0bc8ea638f44bd8ef86d09737a930b3ba)
Krunal Soni 8 жил өмнө
parent
commit
35fc8ea8b8

+ 99 - 95
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++;
-		}
-
-		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);

+ 26 - 4
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:

+ 9 - 4
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;