qcacld-2.0: Fix active cmd timeout issue

prima to qcacld-2.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
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
index 8a24f8f..8ac1883 100644
--- a/CORE/SME/inc/csrInternal.h
+++ b/CORE/SME/inc/csrInternal.h
@@ -1123,6 +1123,7 @@
 #endif
     vos_timer_t packetdump_timer;
     tANI_BOOLEAN pending_roam_disable;
+    vos_spin_lock_t roam_state_lock;
 }tCsrRoamStruct;
 
 
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 8527c7c..d31c16d 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -275,6 +275,21 @@
 void csrReinitPreauthCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
 void csrInitOperatingClasses(tHalHandle hHal);
 
+void csrRoamSubstateChange(tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate,
+                           tANI_U32 sessionId)
+{
+     smsLog(pMac, LOG1, FL("CSR RoamSubstate: [ %s <== %s ]"),
+                macTraceGetcsrRoamSubState(NewSubstate),
+                macTraceGetcsrRoamSubState(pMac->roam.curSubState[sessionId]));
+    if(pMac->roam.curSubState[sessionId] == NewSubstate)
+    {
+       return;
+    }
+    vos_spin_lock_acquire(&pMac->roam.roam_state_lock);
+    pMac->roam.curSubState[sessionId] = NewSubstate;
+    vos_spin_lock_release(&pMac->roam.roam_state_lock);
+}
+
 //Initialize global variables
 static void csrRoamInitGlobals(tpAniSirGlobal pMac)
 {
@@ -755,7 +770,7 @@
 
     for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
        csrRoamStateChange(pMac, eCSR_ROAMING_STATE_STOP, sessionId);
-       pMac->roam.curSubState[sessionId] = eCSR_ROAM_SUBSTATE_NONE;
+       csrRoamSubstateChange(pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
     }
 
 #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
@@ -902,6 +917,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);
 }
@@ -919,6 +935,7 @@
     vos_timer_destroy(&pMac->roam.tlStatsReqInfo.hTlStatsTimer);
     vos_timer_stop(&pMac->roam.packetdump_timer);
     vos_timer_destroy(&pMac->roam.packetdump_timer);
+    vos_spin_lock_destroy(&pMac->roam.roam_state_lock);
     return (eHAL_STATUS_SUCCESS);
 }
 
@@ -1183,18 +1200,6 @@
     }
 }
 
-void csrRoamSubstateChange( tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate, tANI_U32 sessionId)
-{
-     smsLog(pMac, LOG1, FL("CSR RoamSubstate: [ %s <== %s ]"),
-                           macTraceGetcsrRoamSubState(NewSubstate),
-                           macTraceGetcsrRoamSubState(pMac->roam.curSubState[sessionId]));
-    if(pMac->roam.curSubState[sessionId] == NewSubstate)
-    {
-       return;
-    }
-    pMac->roam.curSubState[sessionId] = NewSubstate;
-}
-
 eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId)
 {
     eCsrRoamState PreviousState;
@@ -11887,8 +11892,14 @@
            macTraceGetcsrRoamSubState(
            pMac->roam.curSubState[pInfo->sessionId]));
 
+    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, pInfo->sessionId))
         {
@@ -11906,13 +11917,6 @@
 #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);
-        }
-
         if( csrIsConnStateConnectedInfra(pMac, pInfo->sessionId) )
         {
             csrRoamLinkUp(pMac, pSession->connectedProfile.bssid);
@@ -11931,6 +11935,8 @@
                    __func__, pInfo->sessionId);
         }
     }
+    else
+        vos_spin_lock_release(&pMac->roam.roam_state_lock);
 }
 
 eHalStatus csrRoamStartWaitForKeyTimer(tpAniSirGlobal pMac, tANI_U32 interval)