wlan: Do not send  wrong/out of sync RSO cmd to firmware

Below Table describe whether RSO command can be sent down
to firmware or not. Host checks it on the basis of previous
RSO command sent down to firmware.

============================================================
New cmd       |          LAST SENT COMMAND --->
===|========================================================
   V          |RSO_START|RSO_STOP|RSO_RESTART|RSO_UPDATE_CFG
------------------------------------------------------------
RSO_START     |   NO    | YES    |   NO      |     NO
RSO_STOP      |  YES    | YES    |   YES     |     YES
RSO_RESTART   |  YES    | NO     |   NO      |     YES
RSO_UPDATE_CFG|  YES    | NO     |   YES     |     YES
============================================================

If RSO cmd which is supposed to be sent down is out of sync,
Then host will drop it.

Change-Id: I9a842d349e1616ac7032fd6dc09a4bdf8e2bfbe6
CRs-Fixed: 825786
diff --git a/CORE/SME/inc/csrNeighborRoam.h b/CORE/SME/inc/csrNeighborRoam.h
index e5caac9..6a0d812 100644
--- a/CORE/SME/inc/csrNeighborRoam.h
+++ b/CORE/SME/inc/csrNeighborRoam.h
@@ -205,6 +205,7 @@
     tSirMacAddr                 cfgRoambssId;
     vos_timer_t                 forcedInitialRoamTo5GHTimer;
     tANI_U8                     isForcedInitialRoamTo5GH;
+    tANI_U8                     lastSentCmd;
 } tCsrNeighborRoamControlInfo, *tpCsrNeighborRoamControlInfo;
 
 
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 4d1c09c..6a5bba3 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -16279,6 +16279,59 @@
         return eSIR_SUCCESS;
 }
 
+/*
+ * Below Table describe whether RSO command can be send down to fimrware or not.
+ * Host check it on the basis of previous RSO command sent down to firmware.
+||===========================================================================||
+|| New cmd        |            LAST SENT COMMAND --->                        ||
+||====|======================================================================||
+||    V           |  RSO_START  |  RSO_STOP  |  RSO_RESTART | RSO_UPDATE_CFG ||
+|| --------------------------------------------------------------------------||
+|| RSO_START      |     NO      |   YES      |     NO       |      NO        ||
+|| RSO_STOP       |    YES      |   YES      |     YES      |      YES       ||
+|| RSO_RESTART    |    YES      |   NO       |     NO       |      YES       ||
+|| RSO_UPDATE_CFG |    YES      |   NO       |     YES      |      YES       ||
+||===========================================================================||
+*/
+
+#define RSO_START_BIT       (1<<ROAM_SCAN_OFFLOAD_START)
+#define RSO_STOP_BIT        (1<<ROAM_SCAN_OFFLOAD_STOP)
+#define RSO_RESTART_BIT     (1<<ROAM_SCAN_OFFLOAD_RESTART)
+#define RSO_UPDATE_CFG_BIT  (1<<ROAM_SCAN_OFFLOAD_UPDATE_CFG)
+
+#define RSO_START_ALLOW_MASK   ( RSO_STOP_BIT )
+#define RSO_STOP_ALLOW_MASK    ( RSO_UPDATE_CFG_BIT | RSO_RESTART_BIT | \
+                                 RSO_STOP_BIT | RSO_START_BIT )
+#define RSO_RESTART_ALLOW_MASK ( RSO_UPDATE_CFG_BIT | RSO_START_BIT )
+#define RSO_UPDATE_CFG_ALLOW_MASK  (RSO_UPDATE_CFG_BIT | RSO_STOP_BIT | \
+                                    RSO_START_BIT)
+
+tANI_BOOLEAN CsrIsRSOCommandAllowed(tpAniSirGlobal pMac, tANI_U8 command)
+{
+    tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+    tANI_U8 desiredMask = 0;
+    switch(command)
+    {
+        case ROAM_SCAN_OFFLOAD_START:
+             desiredMask = RSO_START_ALLOW_MASK;
+             break;
+        case ROAM_SCAN_OFFLOAD_STOP:
+             desiredMask = RSO_STOP_ALLOW_MASK;
+             break;
+        case ROAM_SCAN_OFFLOAD_RESTART:
+             desiredMask = RSO_RESTART_ALLOW_MASK;
+             break;
+        case ROAM_SCAN_OFFLOAD_UPDATE_CFG:
+             desiredMask = RSO_UPDATE_CFG_ALLOW_MASK;
+             break;
+        default:
+             VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                       FL("Wrong RSO command %d, not allowed"), command);
+             return 0;/*Cmd Not allowed*/
+    }
+    return ( desiredMask & ( 1 << pNeighborRoamInfo->lastSentCmd) );
+}
+
 eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason)
 {
    vos_msg_t msg;
@@ -16328,6 +16381,14 @@
       return eHAL_STATUS_FAILURE;
    }
 
+   if (!CsrIsRSOCommandAllowed(pMac, command))
+   {
+       VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+            FL("RSO command %d lastSentCmd %d, RSO is out of sync in HOST-FWR"),
+            command, pNeighborRoamInfo->lastSentCmd);
+       return eHAL_STATUS_FAILURE;
+   }
+
    /* We dont need psession during ROAM_SCAN_OFFLOAD_STOP
     * Also there are cases where pNeighborRoamInfo->currAPbssid
     * is set to 0 during disconnect and so we might return without stopping
@@ -16743,6 +16804,9 @@
             bRoamScanOffloadStarted = VOS_TRUE;
         else if (ROAM_SCAN_OFFLOAD_STOP == command)
             bRoamScanOffloadStarted = VOS_FALSE;
+
+        /*update the last sent cmd*/
+        pNeighborRoamInfo->lastSentCmd = command;
     }
 
    VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Roam Scan Offload Command %d, Reason %d", command, reason);
diff --git a/CORE/SME/src/csr/csrNeighborRoam.c b/CORE/SME/src/csr/csrNeighborRoam.c
index 51894d9..8cb1419 100644
--- a/CORE/SME/src/csr/csrNeighborRoam.c
+++ b/CORE/SME/src/csr/csrNeighborRoam.c
@@ -4891,6 +4891,9 @@
 
     CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
     pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE;
+
+    //Set the Last Sent Cmd as RSO_STOP
+    pNeighborRoamInfo->lastSentCmd = ROAM_SCAN_OFFLOAD_STOP;
     return eHAL_STATUS_SUCCESS;
 }