Browse Source

qcacld-3.0: Avoid timeout in case of back to back connect req

In case of back to back connect req, if the 1st connect is in scan for
ssid phase, the 2nd connect req try to cleanup the 1st connect and wait
for disconnect complete variable for 5 sec. In this scenario as cleanup is
pending, the scan for ssid will fail and result in the association
failure.

But in association failure the disconnect complete variable is not
completed and thus the 2nd connect req keeps on waiting for 5 sec.

To fix this complete the disconnect complete variable in association
failure, if reason is scan for ssid failure and hdd disconnect is pending.

Change-Id: Ibc0cfb72d04442e82847dd624ede15eda340b766
CRs-Fixed: 2256376
Abhishek Singh 6 years ago
parent
commit
0edeba0e83
2 changed files with 35 additions and 11 deletions
  1. 9 0
      core/hdd/src/wlan_hdd_assoc.c
  2. 26 11
      core/hdd/src/wlan_hdd_cfg80211.c

+ 9 - 0
core/hdd/src/wlan_hdd_assoc.c

@@ -3423,6 +3423,15 @@ hdd_association_completion_handler(struct hdd_adapter *adapter,
 		wlan_hdd_netif_queue_control(adapter,
 					   WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 					   WLAN_CONTROL_PATH);
+		/*
+		 * if hddDisconInProgress is set and roamResult is
+		 * eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE that mean HDD is
+		 * waiting on disconnect_comp_var so unblock anyone waiting for
+		 * disconnect to complete.
+		 */
+		if ((roamResult == eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE) &&
+		    hddDisconInProgress)
+			complete(&adapter->disconnect_comp_var);
 	}
 
 	return QDF_STATUS_SUCCESS;

+ 26 - 11
core/hdd/src/wlan_hdd_cfg80211.c

@@ -19261,6 +19261,7 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
 	struct hdd_station_ctx *sta_ctx;
 	int status, result = 0;
 	tHalHandle hal;
+	uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT;
 
 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
 	hal = WLAN_HDD_GET_HAL_CTX(adapter);
@@ -19295,6 +19296,9 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
 	  (eConnectionState_Associated == sta_ctx->conn_info.connState) ||
 	  (eConnectionState_Connecting == sta_ctx->conn_info.connState) ||
 	  (eConnectionState_IbssConnected == sta_ctx->conn_info.connState)) {
+		eConnectionState prev_conn_state;
+
+		prev_conn_state = sta_ctx->conn_info.connState;
 		hdd_conn_set_connection_state(adapter,
 						eConnectionState_Disconnecting);
 		/* Issue disconnect to CSR */
@@ -19303,13 +19307,25 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
 		status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
 				adapter->session_id,
 				eCSR_DISCONNECT_REASON_UNSPECIFIED);
-		/*
-		 * Wait here instead of returning directly, this will block the
-		 * next connect command and allow processing of the scan for
-		 * ssid and the previous connect command in CSR. Else we might
-		 * hit some race conditions leading to SME and HDD out of sync.
-		 */
-		if (QDF_STATUS_CMD_NOT_QUEUED == status) {
+
+		if ((status == QDF_STATUS_CMD_NOT_QUEUED) &&
+		    prev_conn_state != eConnectionState_Connecting) {
+			hdd_debug("Already disconnect in progress");
+			result = 0;
+			/*
+			 * Wait here instead of returning directly. This will
+			 * block the connect command and allow processing
+			 * of the disconnect in SME. As disconnect is already
+			 * in progress, wait here for 1 sec instead of 5 sec.
+			 */
+			wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
+		} else if (status == QDF_STATUS_CMD_NOT_QUEUED) {
+			/*
+			 * Wait here instead of returning directly, this will
+			 * block the connect command and allow processing
+			 * of the scan for ssid and the previous connect command
+			 * in CSR.
+			 */
 			hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
 		} else if (0 != status) {
 			hdd_err("sme_roam_disconnect failure, status: %d",
@@ -19319,9 +19335,8 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
 			goto disconnected;
 		}
 
-		rc = wait_for_completion_timeout(
-			&adapter->disconnect_comp_var,
-			msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+		rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
+						 msecs_to_jiffies(wait_time));
 		if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
 			hdd_err("Sme disconnect event timed out session Id: %d sta_debug_state: %d",
 				adapter->session_id, sta_ctx->sta_debug_state);
@@ -19330,7 +19345,7 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
 	} else if (eConnectionState_Disconnecting ==
 				sta_ctx->conn_info.connState) {
 		rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
-				msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
+						 msecs_to_jiffies(wait_time));
 		if (!rc) {
 			hdd_err("Disconnect event timed out session Id: %d sta_debug_state: %d",
 				adapter->session_id, sta_ctx->sta_debug_state);