wlan: Fix active cmd timeout issue
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: 2148178
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 544373a..178f9fa 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -764,7 +764,7 @@
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
{
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_STOP, i );
- pMac->roam.curSubState[i] = eCSR_ROAM_SUBSTATE_NONE;
+ csrRoamSubstateChange(pMac, eCSR_ROAM_SUBSTATE_NONE, i);
}
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
@@ -855,6 +855,7 @@
smsLog(pMac, LOGE, FL("cannot allocate memory for summary Statistics timer"));
return eHAL_STATUS_FAILURE;
}
+ vos_spin_lock_init(&pMac->roam.roam_state_lock);
}while (0);
return (status);
}
@@ -870,6 +871,7 @@
vos_timer_destroy(&pMac->roam.hTimerWaitForKey);
vos_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer);
vos_timer_destroy(&pMac->roam.tlStatsReqInfo.hTlStatsTimer);
+ vos_spin_lock_destroy(&pMac->roam.roam_state_lock);
return (eHAL_STATUS_SUCCESS);
}
@@ -1154,7 +1156,9 @@
{
return;
}
+ vos_spin_lock_acquire(&pMac->roam.roam_state_lock);
pMac->roam.curSubState[sessionId] = NewSubstate;
+ vos_spin_lock_release(&pMac->roam.roam_state_lock);
}
eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId)
@@ -11206,8 +11210,15 @@
if (pSession)
{
+ vos_spin_lock_acquire(&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;
+ vos_spin_lock_release(&pMac->roam.roam_state_lock);
+
#ifdef FEATURE_WLAN_LFR
if (csrNeighborRoamIsHandoffInProgress(pMac))
{
@@ -11223,14 +11234,8 @@
NULL, eANI_BOOLEAN_FALSE);
}
#endif
- smsLog(pMac, LOGE, " SME pre-auth state timeout. ");
- //Change the substate so command queue is unblocked.
- if (CSR_ROAM_SESSION_MAX > pInfo->sessionId)
- {
- csrRoamSubstateChange(pMac, eCSR_ROAM_SUBSTATE_NONE,
- pInfo->sessionId);
- }
+ smsLog(pMac, LOGE, " SME pre-auth state timeout. ");
if( csrIsConnStateConnectedInfra(pMac, pInfo->sessionId) )
{
@@ -11252,6 +11257,7 @@
}
else
{
+ vos_spin_lock_release(&pMac->roam.roam_state_lock);
smsLog(pMac, LOGW, "%s: session not found", __func__);
}
}