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);