From 0edeba0e83ef8fbec4b209549b6fd77a3f9c2b53 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Tue, 5 Jun 2018 10:04:08 +0530 Subject: [PATCH] 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 --- core/hdd/src/wlan_hdd_assoc.c | 9 ++++++++ core/hdd/src/wlan_hdd_cfg80211.c | 37 ++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index db61cb510a7b..8feab3cbf72a 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/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; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 1981f753bbf2..a764d92231e9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/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);