summaryrefslogtreecommitdiff
path: root/core/sme/src/csr/csr_api_roam.c
diff options
context:
space:
mode:
authorPadma, Santhosh Kumar <skpadma@codeaurora.org>2017-12-07 16:36:34 +0530
committersnandini <snandini@codeaurora.org>2017-12-13 02:46:45 -0800
commit39f0c4ca863ad1b61820a9a288cc9babcaa927e0 (patch)
tree80c5719a59507304f03f8d5c11278f700fad2721 /core/sme/src/csr/csr_api_roam.c
parentf77b5d8016d2899ea21118007cff76eb321366c5 (diff)
downloadqcacld-39f0c4ca863ad1b61820a9a288cc9babcaa927e0.tar.gz
qcacld-3.0: Fix active cmd timeout issue
qcacld-2.0 to qcacld-3.0 propagation There can be a possible race in updation of roam substate between csrRoamWaitForKeyTimeOutHandler and upper layer disconnect in csrRoamIssueDeauth. Race can be as follows. Driver roam substate is eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY by the time csrRoamWaitForKeyTimeOutHandler is invoked. This can allow check CSR_IS_WAIT_FOR_KEY to pass. If MC thread gets preempted and if driver processes upper layer disconnect, then driver changes roam substate to eCSR_ROAM_SUBSTATE_DEAUTH_REQ in csrRoamIssueDeauth. When MC thread resumes processing of csrRoamWaitForKeyTimeOutHandler, then driver changes roam substate to eCSR_ROAM_SUBSTATE_NONE. This can result in unhandling of eWNI_SME_DEAUTH_RSP as roam substate is not in eCSR_ROAM_SUBSTATE_DEAUTH_REQ and can result in active command timeout. Hence, update roam substate atomically in same context if CSR_IS_WAIT_FOR_KEY passes in csrRoamWaitForKeyTimeOutHandler. Change-Id: I05cfc8de54fe4196df941c2fd48db8bedc7df779 CRs-Fixed: 2155141
Diffstat (limited to 'core/sme/src/csr/csr_api_roam.c')
-rw-r--r--core/sme/src/csr/csr_api_roam.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 700a6198cc..8005672622 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -1097,7 +1097,8 @@ QDF_STATUS csr_stop(tpAniSirGlobal pMac, tHalStopType stopType)
for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
csr_roam_state_change(pMac, eCSR_ROAMING_STATE_STOP, sessionId);
- pMac->roam.curSubState[sessionId] = eCSR_ROAM_SUBSTATE_NONE;
+ csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE,
+ sessionId);
}
return QDF_STATUS_SUCCESS;
@@ -1244,6 +1245,7 @@ static QDF_STATUS csr_roam_open(tpAniSirGlobal pMac)
sme_err("cannot allocate memory for summary Statistics timer");
return QDF_STATUS_E_FAILURE;
}
+ spin_lock_init(&pMac->roam.roam_state_lock);
} while (0);
return status;
}
@@ -1560,7 +1562,9 @@ void csr_roam_substate_change(tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate,
if (pMac->roam.curSubState[sessionId] == NewSubstate)
return;
+ spin_lock(&pMac->roam.roam_state_lock);
pMac->roam.curSubState[sessionId] = NewSubstate;
+ spin_unlock(&pMac->roam.roam_state_lock);
}
eCsrRoamState csr_roam_state_change(tpAniSirGlobal pMac,
@@ -12498,7 +12502,14 @@ void csr_roam_wait_for_key_time_out_handler(void *pv)
mac_trace_getcsr_roam_sub_state(pMac->roam.
curSubState[pInfo->sessionId]));
+ spin_lock(&pMac->roam.roam_state_lock);
if (CSR_IS_WAIT_FOR_KEY(pMac, pInfo->sessionId)) {
+ /* Change the substate so command queue is unblocked. */
+ if (CSR_ROAM_SESSION_MAX > pInfo->sessionId)
+ pMac->roam.curSubState[pInfo->sessionId] =
+ eCSR_ROAM_SUBSTATE_NONE;
+ spin_unlock(&pMac->roam.roam_state_lock);
+
if (csr_neighbor_roam_is_handoff_in_progress(pMac,
pInfo->sessionId)) {
/*
@@ -12512,12 +12523,6 @@ void csr_roam_wait_for_key_time_out_handler(void *pv)
}
sme_debug("SME pre-auth state timeout");
- /* Change the substate so command queue is unblocked. */
- if (CSR_ROAM_SESSION_MAX > pInfo->sessionId) {
- csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE,
- pInfo->sessionId);
- }
-
if (csr_is_conn_state_connected_infra(pMac, pInfo->sessionId)) {
csr_roam_link_up(pMac,
pSession->connectedProfile.bssid);
@@ -12530,8 +12535,9 @@ void csr_roam_wait_for_key_time_out_handler(void *pv)
}
} else
sme_err("%s: session not found", __func__);
+ } else {
+ spin_unlock(&pMac->roam.roam_state_lock);
}
-
}
#ifdef WLAN_FEATURE_ROAM_OFFLOAD