mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 16:46:15 -04:00
qcacld-3.0: Fix race condition when disconnecting
Fix one more scenario which is not covered by the change Ib6a30057469d60efcc905d97b5234ea5a0e097a8 For some timing issue, HDD conn state is set to disconnecting after hdd_association_completion_handler is called. So hddDisconInProgress is not set and disconnect_comp_var will not be completed in hdd_association_completion_handler. To fix this issue, QDF_STATUS_CMD_NOT_QUEUED should be set only when scan for ssid is in progress, with pSession->scan_info.profile we can check if scan for ssid is in progress. So set QDF_STATUS_CMD_NOT_QUEUED only when pSession->scan_info.profile is set. Also if disconnect from LIM was already in progress (i.e. csr_is_conn_state_connected and csr_is_roam_command_waiting_for_session are false and pSession->scan_info.profile is set), return failure and wait for WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS ms for the disconnect to be completed. Change-Id: Ib490021775a39614646f8e518860c878cc0fdaae CRs-Fixed: 2564992
This commit is contained in:
parent
23b0263034
commit
818395d83e
2 changed files with 17 additions and 23 deletions
|
|
@ -20810,31 +20810,25 @@ int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason)
|
|||
|
||||
status = sme_roam_disconnect(mac_handle,
|
||||
adapter->vdev_id, reason);
|
||||
if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
|
||||
prev_conn_state != eConnectionState_Connecting) {
|
||||
hdd_debug("status = %d, already disconnected", status);
|
||||
result = 0;
|
||||
/*
|
||||
* Wait here instead of returning directly. This will block the
|
||||
* next connect command and allow processing of the disconnect
|
||||
* in SME else we might hit some race conditions leading to SME
|
||||
* and HDD out of sync. 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 (QDF_STATUS_CMD_NOT_QUEUED == status) {
|
||||
if (QDF_STATUS_CMD_NOT_QUEUED == status &&
|
||||
prev_conn_state == eConnectionState_Connecting) {
|
||||
/*
|
||||
* 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.
|
||||
* 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("csr_roam_disconnect failure, status: %d", (int)status);
|
||||
sta_ctx->sta_debug_state = status;
|
||||
result = -EINVAL;
|
||||
goto disconnected;
|
||||
hdd_debug("CSR is not in connected state but scan for SSID is in progress, wait for scan to be aborted or completed.");
|
||||
} else if (QDF_IS_STATUS_ERROR(status)) {
|
||||
hdd_debug("status = %d, already disconnect in progress or SME is disconencted OR connect removed from pending queue",
|
||||
status);
|
||||
/*
|
||||
* Wait here instead of returning directly. This will block the
|
||||
* next connect command and allow processing of the disconnect
|
||||
* in SME. As disconnect is already in progress, wait here for
|
||||
* WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS instead of
|
||||
* SME_DISCONNECT_TIMEOUT.
|
||||
*/
|
||||
wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
|
||||
}
|
||||
wait_for_disconnect:
|
||||
rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
|
||||
|
|
@ -20844,7 +20838,6 @@ wait_for_disconnect:
|
|||
hdd_err("Failed to disconnect, timed out");
|
||||
result = -ETIMEDOUT;
|
||||
}
|
||||
disconnected:
|
||||
hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
|
||||
/* Sending disconnect event to userspace for kernel version < 3.11
|
||||
|
|
|
|||
|
|
@ -9010,7 +9010,7 @@ QDF_STATUS csr_roam_issue_stop_bss_cmd(struct mac_context *mac, uint32_t session
|
|||
QDF_STATUS csr_roam_disconnect_internal(struct mac_context *mac, uint32_t sessionId,
|
||||
eCsrRoamDisconnectReason reason)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
||||
struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
|
||||
|
||||
if (!pSession) {
|
||||
|
|
@ -9026,7 +9026,7 @@ QDF_STATUS csr_roam_disconnect_internal(struct mac_context *mac, uint32_t sessio
|
|||
sme_debug("called");
|
||||
status = csr_roam_issue_disassociate_cmd(mac, sessionId,
|
||||
reason);
|
||||
} else {
|
||||
} else if (pSession->scan_info.profile) {
|
||||
mac->roam.roamSession[sessionId].connectState =
|
||||
eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING;
|
||||
csr_scan_abort_mac_scan(mac, sessionId, INVAL_SCAN_ID);
|
||||
|
|
@ -9034,6 +9034,7 @@ QDF_STATUS csr_roam_disconnect_internal(struct mac_context *mac, uint32_t sessio
|
|||
sme_debug("Disconnect cmd not queued, Roam command is not present return with status: %d",
|
||||
status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue