qcacld-3.0: Avoid new connection while HW mode change is issued

In the case of concurrency, when the session decrements, the
opportunistic timer is started. After a while, when the
opportunistic time is expired, and the hw mode change for SMM
is issued, and the same time new interface comes up, then the
new forms MCC with the existing connection instead of forming
DBS.

The change is to avoid the race condition to form MCC instead of
DBS.

Change-Id: I977039138509676b964ba089e3cb479cd16968bb
CRs-Fixed: 2006350
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 220e6e6..9eb174e 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -12819,11 +12819,18 @@
 
 	status = wlan_hdd_validate_context(pHddCtx);
 	if (status)
-		return status;
+		goto ret_status;
 
 	if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
 		hdd_err("wrong SSID len");
-		return -EINVAL;
+		status = -EINVAL;
+		goto ret_status;
+	}
+
+	if (true == cds_is_connection_in_progress()) {
+		hdd_err("Connection refused: conn in progress");
+		status = -EINVAL;
+		goto ret_status;
 	}
 
 	pRoamProfile = &pWextState->roamProfile;
@@ -12834,6 +12841,24 @@
 		hdd_station_ctx_t *pHddStaCtx;
 		pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 
+		/* Restart the opportunistic timer
+		 *
+		 * If hw_mode_change_in_progress is true, then wait
+		 * till firmware sends the callback for hw_mode change.
+		 *
+		 * Else set connect_in_progress as true and proceed.
+		 */
+		cds_restart_opportunistic_timer(false);
+		if (cds_is_hw_mode_change_in_progress()) {
+			status = qdf_wait_for_connection_update();
+			if (!QDF_IS_STATUS_SUCCESS(status)) {
+				hdd_err("qdf wait for event failed!!");
+				status = -EINVAL;
+				goto ret_status;
+			}
+		}
+		cds_set_connection_in_progress(true);
+
 		if (HDD_WMM_USER_MODE_NO_QOS ==
 		    (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
 			/*QoS not enabled in cfg file */
@@ -12965,7 +12990,8 @@
 
 			if (QDF_STATUS_SUCCESS != status) {
 				hdd_err("Set IBSS Power Save Params Failed");
-				return -EINVAL;
+				status = -EINVAL;
+				goto conn_failure;
 			}
 			pRoamProfile->ch_params.ch_width =
 				hdd_map_nl_chan_width(ch_width);
@@ -12991,12 +13017,9 @@
 					pWextState->roamProfile.MFPEnabled,
 					pWextState->roamProfile.MFPRequired,
 					pWextState->roamProfile.MFPCapable);
-			return -EINVAL;
-		}
 
-		if (true == cds_is_connection_in_progress()) {
-			hdd_err("Connection refused: conn in progress");
-			return -EINVAL;
+			status = -EINVAL;
+			goto conn_failure;
 		}
 
 		/*
@@ -13023,8 +13046,10 @@
 		if (wma_is_hw_dbs_capable() == false) {
 			cds_handle_conc_rule1(pAdapter, pRoamProfile);
 			if (true != cds_handle_conc_rule2(
-					pAdapter, pRoamProfile, &roamId))
-				return 0;
+					pAdapter, pRoamProfile, &roamId)) {
+				status = 0;
+				goto conn_failure;
+			}
 		}
 
 		if ((wma_is_hw_dbs_capable() == true) &&
@@ -13033,7 +13058,8 @@
 			hdd_err("sap-sta conc will fail, can't allow sta");
 			hdd_conn_set_connection_state(pAdapter,
 					eConnectionState_NotConnected);
-			return -ENOMEM;
+			status = -ENOMEM;
+			goto conn_failure;
 		}
 
 		sme_config = qdf_mem_malloc(sizeof(*sme_config));
@@ -13041,7 +13067,8 @@
 			hdd_err("unable to allocate sme_config");
 			hdd_conn_set_connection_state(pAdapter,
 					eConnectionState_NotConnected);
-			return -ENOMEM;
+			status = -ENOMEM;
+			goto conn_failure;
 		}
 		sme_get_config_param(pHddCtx->hHal, sme_config);
 		/* These values are not sessionized. So, any change in these SME
@@ -13100,6 +13127,9 @@
 						     connect);
 		}
 
+		/* Reset connect_in_progress */
+		cds_set_connection_in_progress(false);
+
 		pRoamProfile->ChannelInfo.ChannelList = NULL;
 		pRoamProfile->ChannelInfo.numOfChannels = 0;
 
@@ -13114,8 +13144,15 @@
 
 	} else {
 		hdd_err("No valid Roam profile");
-		return -EINVAL;
+		status = -EINVAL;
 	}
+	goto ret_status;
+
+conn_failure:
+	/* Reset connect_in_progress */
+	cds_set_connection_in_progress(false);
+
+ret_status:
 	EXIT();
 	return status;
 }