wlan: (2)Decouple init scan and NOA insert in P2P GO case

Currently we have scan req coupled with NOA publishing for GO. This
blocks our MLME state to scan state for 3 beacon intervals which causes
1) Huge Throughput dip during scan since we suspend TL for 3 BIs
2) Sometimes connection problems since we are in scan state for longer
time though we are not doing scan (for 3 BIs) esp. since some frames get
delayed on both and client and GO sides during scan because of current
implementation.
So the change is decouple publishing of NOA from scan in a way that
while we wait for NOA publishing for 3 BIs we can do all other jobs at
lim module and below. Also, we will be suspending TL only when we are
actually doing scan
3) Changed the BIs for which NOA is published to 2 instead of 3

Change-Id: Id8f2db8019e132183f671aa4aa80d8dfdfe05f97
CR-Fixed: 426949
diff --git a/CORE/MAC/src/pe/include/limSession.h b/CORE/MAC/src/pe/include/limSession.h
index 3e0f546..6acb407 100644
--- a/CORE/MAC/src/pe/include/limSession.h
+++ b/CORE/MAC/src/pe/include/limSession.h
@@ -281,6 +281,7 @@
     tSirNoAParam p2pNoA;
     tSirP2PNoaAttr p2pGoPsUpdate;
     tANI_U32 defaultAuthFailureTimeout;
+    tSirP2PNoaStart p2pGoPsNoaStartInd;
 #endif
 
     /* EDCA QoS parameters
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index c352d7e..2317d56 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -99,6 +99,9 @@
 
     pMac->lim.gLimCurrentScanChannelId = 0;
     pMac->lim.gpLimMlmScanReq = NULL;
+#ifdef WLAN_FEATURE_P2P
+    pMac->lim.gpLimSmeScanReq = NULL;
+#endif
     pMac->lim.gLimMlmScanResultLength = 0;
     pMac->lim.gLimSmeScanResultLength = 0;
 
@@ -895,6 +898,14 @@
         pMac->lim.gpLimMlmRemoveKeyReq = NULL;
     }
 
+#ifdef WLAN_FEATURE_P2P
+    if (pMac->lim.gpLimSmeScanReq != NULL)
+    {
+        palFreeMemory(pMac->hHdd, pMac->lim.gpLimSmeScanReq);
+        pMac->lim.gpLimSmeScanReq = NULL;
+    }
+#endif
+
     if (pMac->lim.gpLimMlmScanReq != NULL)
     {
         palFreeMemory(pMac->hHdd, pMac->lim.gpLimMlmScanReq);
diff --git a/CORE/MAC/src/pe/lim/limP2P.c b/CORE/MAC/src/pe/lim/limP2P.c
index a037337..bdf9be2 100644
--- a/CORE/MAC/src/pe/lim/limP2P.c
+++ b/CORE/MAC/src/pe/lim/limP2P.c
@@ -375,6 +375,24 @@
 
 /*------------------------------------------------------------------
  *
+ * lim Insert NOA timer timeout callback - when timer fires, deactivate it and send
+ * scan rsp to csr/hdd
+ *
+ *------------------------------------------------------------------*/
+void limProcessInsertSingleShotNOATimeout(tpAniSirGlobal pMac)
+{
+    /* timeout means start NOA did not arrive; we need to restart the timer and
+     * send the scan response from here
+     */
+    limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER);
+    
+    // send the scan response back and do not even call insert NOA
+    limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_SCAN_FAILED, pMac->lim.gSmeSessionId, pMac->lim.gTransactionId);
+    return;
+}
+
+/*------------------------------------------------------------------
+ *
  * limchannelchange callback, on success channel change, set the
  * link_state to LISTEN
  *
@@ -1028,7 +1046,7 @@
     pMsgNoA->single_noa_duration = pNoA->single_noa_duration;
     pMsgNoA->psSelection = pNoA->psSelection;
 
-    msg.type = SIR_HAL_SET_P2P_GO_NOA_REQ;
+    msg.type = WDA_SET_P2P_GO_NOA_REQ;
     msg.reserved = 0;
     msg.bodyptr = pMsgNoA;
     msg.bodyval = 0;
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 614e4e7..d93eed5 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -81,6 +81,11 @@
 #include "vos_memory.h"
 #endif
 
+#ifdef WLAN_FEATURE_P2P
+/* In P2P GO case, we want to call scan on NOA start indication from limProcessMessages */
+extern void __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf);
+#endif
+
 void limLogSessionStates(tpAniSirGlobal pMac);
 
 /** -------------------------------------------------------------
@@ -1527,16 +1532,51 @@
             limMsg->bodyptr = NULL;
             break;
 
+        case SIR_HAL_P2P_NOA_START_IND:
+        {
+            tpPESession psessionEntry = &pMac->lim.gpSession[0];
+            tANI_U8  i;
+            
+            limLog(pMac, LOG1, "LIM received NOA start %x\n", limMsg->type);
+            for(i=0; i < pMac->lim.maxBssId; i++)
+            {
+                psessionEntry = &pMac->lim.gpSession[i];
+                if   ( (psessionEntry != NULL) && (psessionEntry->valid) &&
+                    (psessionEntry->pePersona == VOS_P2P_GO_MODE))
+                { //Save P2P NOA start attributes for P2P Go persona
+                    palCopyMemory(pMac->hHdd, &psessionEntry->p2pGoPsNoaStartInd, limMsg->bodyptr, sizeof(tSirP2PNoaStart));
+                    
+                    if ((pMac->lim.gpLimSmeScanReq != NULL) && (psessionEntry->p2pGoPsNoaStartInd.status == eHAL_STATUS_SUCCESS))
+                    {
+                        /* We received the NOA start indication. Now we can send down the scan request */
+                        __limProcessSmeScanReq(pMac, (tANI_U32 *)pMac->lim.gpLimSmeScanReq);
+                        /* Since insert NOA is done and NOA start msg received, we should deactivate the Insert NOA timer */
+                        limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER);
+                        /* __limProcessSmeScanReq consumed the buffer. We can free it. */
+                        palFreeMemory( pMac->hHdd, (tANI_U8 *) pMac->lim.gpLimSmeScanReq);
+                        pMac->lim.gpLimSmeScanReq = NULL;
+                    }
+                    else
+                        limLog(pMac, LOGE, FL("GO NOA start failure reported by FW - don't do scan\n"));
+                    break;
+                }
+            }
+        }
+            palFreeMemory(pMac->hHdd, (tANI_U8 *)limMsg->bodyptr);
+            limMsg->bodyptr = NULL;
+            break;
+            
+
         case SIR_HAL_P2P_NOA_ATTR_IND:
             {
                 tpPESession psessionEntry = &pMac->lim.gpSession[0];  
                 tANI_U8  i;
                 
-                
                 limLog(pMac, LOGW, FL("Received message Noa_ATTR %x\n"), limMsg->type);
                 for(i=0; i < pMac->lim.maxBssId; i++)
                 {
-                    if   ( (psessionEntry != NULL) && (pMac->lim.gpSession[i].valid) && 
+                    psessionEntry = &pMac->lim.gpSession[i];
+                    if   ( (psessionEntry != NULL) && (psessionEntry->valid) && 
                         (psessionEntry->pePersona == VOS_P2P_GO_MODE))
                     { //Save P2P attributes for P2P Go persona
                     
@@ -1756,6 +1796,7 @@
 #endif
 #ifdef WLAN_FEATURE_P2P
         case SIR_LIM_REMAIN_CHN_TIMEOUT:
+        case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT:
 #endif
         case SIR_LIM_DISASSOC_ACK_TIMEOUT:
         case SIR_LIM_DEAUTH_ACK_TIMEOUT:
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index 3c36c37..89ced2a 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -78,12 +78,17 @@
 
 #endif
 
+/* This overhead is time for sending NOA start to host in case of GO/sending NULL data & receiving ACK 
+ * in case of P2P Client and starting actual scanning with init scan req/rsp plus in case of concurrency,
+ * taking care of sending null data and receiving ACK to/from AP.
+ */
+#define SCAN_MESSAGING_OVERHEAD 5 // in msecs
 
 // SME REQ processing function templates
 static void __limProcessSmeStartReq(tpAniSirGlobal, tANI_U32 *);
 static tANI_BOOLEAN __limProcessSmeSysReadyInd(tpAniSirGlobal, tANI_U32 *);
 static tANI_BOOLEAN __limProcessSmeStartBssReq(tpAniSirGlobal, tpSirMsgQ pMsg);
-static void __limProcessSmeScanReq(tpAniSirGlobal, tANI_U32 *);
+void __limProcessSmeScanReq(tpAniSirGlobal, tANI_U32 *);
 static void __limProcessSmeJoinReq(tpAniSirGlobal, tANI_U32 *);
 static void __limProcessSmeReassocReq(tpAniSirGlobal, tANI_U32 *);
 static void __limProcessSmeDisassocReq(tpAniSirGlobal, tANI_U32 *);
@@ -1090,7 +1095,7 @@
  * @return None
  */
 
-static void
+void
 __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
 {
     tANI_U32            len;
@@ -1114,7 +1119,19 @@
            pScanReq->scanType,
            pScanReq->backgroundScanMode,
            pMac->lim.gLimRspReqd ? 1 : 0);)
-        
+
+    /* Since scan req always requires a response, we will overwrite response required here.
+     * This is added esp to take care of the condition where in p2p go case, we hold the scan req and
+     * insert single NOA. We send the held scan request to FW later on getting start NOA ind from FW so
+     * we lose state of the gLimRspReqd flag for the scan req if any other request comes by then.
+     * e.g. While unit testing, we found when insert single NOA is done, we see a get stats request which turns the flag
+     * gLimRspReqd to FALSE; now when we actually start the saved scan req for init scan after getting
+     * NOA started, the gLimRspReqd being a global flag is showing FALSE instead of TRUE value for 
+     * this saved scan req. Since all scan reqs coming to lim require a response, there is no harm in setting
+     * the global flag gLimRspReqd to TRUE here.
+     */
+     pMac->lim.gLimRspReqd = TRUE;
+
     /*copy the Self MAC address from SmeReq to the globalplace , used for sending probe req.discussed on code review sep18*/
     sirCopyMacAddr(pMac->lim.gSelfMacAddr,  pScanReq->selfMacAddr);
 
@@ -4851,6 +4868,71 @@
 
     return;
 } /*** end __limProcessSmeRegisterMgmtFrameReq() ***/
+
+static tANI_BOOLEAN
+__limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+    tpP2pPsParams pMsgNoA;
+    tSirMsgQ msg;
+    tpSirSmeScanReq     pScanReq;
+    pScanReq = (tpSirSmeScanReq) pMsgBuf;
+    if( eHAL_STATUS_SUCCESS != palAllocateMemory(
+                  pMac->hHdd, (void **) &pMsgNoA, sizeof( tP2pPsConfig )))
+    {
+        limLog( pMac, LOGP,
+                     FL( "Unable to allocate memory during NoA Update\n" ));
+        return TRUE;
+    }
+
+    palZeroMemory( pMac->hHdd, (tANI_U8 *)pMsgNoA, sizeof(tP2pPsConfig));
+    /* Below params used for opp PS/periodic NOA and are don't care in this case - so initialized to 0 */
+    pMsgNoA->opp_ps = 0;
+    pMsgNoA->ctWindow = 0;
+    pMsgNoA->duration = 0;
+    pMsgNoA->interval = 0;
+    pMsgNoA->count = 0;
+    /* Below params used for Single Shot NOA - so assign proper values */
+    /* Use min + max channel time to calculate the total duration of scan.
+    * Adding an overhead of 5ms to account for the scan messaging delays
+    */
+    pMsgNoA->single_noa_duration = ((pScanReq->minChannelTime + pScanReq->maxChannelTime)*
+                                    pScanReq->channelList.numChannels) + SCAN_MESSAGING_OVERHEAD;
+    pMsgNoA->psSelection = P2P_SINGLE_NOA;
+    pMac->lim.gpLimSmeScanReq = pScanReq;
+
+    /* Start Insert NOA timer
+     * If insert NOA req fails or NOA rsp fails or start NOA indication doesn't come from FW due to GO session deletion
+     * or any other failure or reason, we still need to send probe response to SME with failure status. The insert NOA
+     * timer of 500 ms will ensure a response back to SME/HDD for the scan req
+     */
+    if (tx_timer_activate(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer)
+                                      == TX_TIMER_ERROR)
+    {
+        /// Could not activate Insert NOA timer.
+        // Log error
+        limLog(pMac, LOGP, FL("could not activate Insert Single Shot NOA during scan timer\n"));
+
+        // send the scan response back with status failure and do not even call insert NOA
+        limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_SCAN_FAILED, pMac->lim.gSmeSessionId, pMac->lim.gTransactionId);
+        return TRUE;
+    }
+
+    msg.type = WDA_SET_P2P_GO_NOA_REQ;
+    msg.reserved = 0;
+    msg.bodyptr = pMsgNoA;
+    msg.bodyval = 0;
+
+    if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
+    {
+        /* In this failure case, timer is already started, so its expiration will take care of sending scan response */
+        limLog(pMac, LOGP, FL("wdaPost Msg failed\n"));
+        return TRUE;
+    }
+
+    return FALSE;
+
+}
+
 #endif
 
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
@@ -5206,8 +5288,19 @@
             break;
 
         case eWNI_SME_SCAN_REQ:
-            __limProcessSmeScanReq(pMac, pMsgBuf);
-
+#ifdef WLAN_FEATURE_P2P
+            /* If we are in P2P GO mode we need to insert NOA before actually starting a scan */
+            if ((limIsNOAInsertReqd(pMac) == TRUE) && IS_FEATURE_SUPPORTED_BY_FW(P2P_GO_NOA_DECOUPLE_INIT_SCAN))
+            {
+                bufConsumed = __limInsertSingleShotNOAForScan(pMac, pMsgBuf);
+            }
+            else
+            {
+#endif
+                __limProcessSmeScanReq(pMac, pMsgBuf);
+#ifdef WLAN_FEATURE_P2P
+            }
+#endif
             break;
 
 #ifdef FEATURE_OEM_DATA_SUPPORT
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index f9077fc..37f878c 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -737,16 +737,32 @@
     cfgValue = SYS_MS_TO_TICKS(cfgValue);
     if (tx_timer_create(&pMac->lim.limTimers.gLimDeauthAckTimer,
                                     "DISASSOC ACK TIMEOUT",
-                                    limTimerHandler, SIR_LIM_DISASSOC_ACK_TIMEOUT,
+                                    limTimerHandler, SIR_LIM_DEAUTH_ACK_TIMEOUT,
                                     cfgValue, 0,
                                     TX_NO_ACTIVATE) != TX_SUCCESS)
     {
         limLog(pMac, LOGP, FL("could not create DEAUTH ACK TIMEOUT timer\n"));
         goto err_timer;
     }
+
+#ifdef WLAN_FEATURE_P2P
+    cfgValue = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE; // (> no of BI* no of TUs per BI * 1TU in msec + p2p start time offset*1 TU in msec = 2*100*1.024 + 5*1.024 = 204.8 + 5.12 = 209.20)
+    cfgValue = SYS_MS_TO_TICKS(cfgValue);
+    if (tx_timer_create(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer,
+                                    "Single Shot NOA Insert timeout",
+                                    limTimerHandler, SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT,
+                                    cfgValue, 0,
+                                    TX_NO_ACTIVATE) != TX_SUCCESS)
+    {
+        limLog(pMac, LOGP, FL("could not create Single Shot NOA Insert Timeout timer\n"));
+        goto err_timer;
+    }
+#endif
+
     return TX_SUCCESS;
 
     err_timer:
+        tx_timer_delete(&pMac->lim.limTimers.gLimDeauthAckTimer);
         tx_timer_delete(&pMac->lim.limTimers.gLimDisassocAckTimer);
 #ifdef WLAN_FEATURE_P2P
         tx_timer_delete(&pMac->lim.limTimers.gLimRemainOnChannelTimer);
@@ -1736,6 +1752,7 @@
                 ** timer. Log error.
                 **/
                 limLog(pMac, LOGP, FL("Unable to deactivate Preauth response Failure timer\n"));
+                return;
             }
             val = 1000;
             val = SYS_MS_TO_TICKS(val);
@@ -1747,6 +1764,7 @@
                 * timer. Log error.
                 */
                 limLog(pMac, LOGP, FL("Unable to change Join Failure timer\n"));
+                return;
             }
             break;
 #endif
@@ -1768,6 +1786,7 @@
                 ** timer. Log error.
                 **/
                 limLog(pMac, LOGP, FL("Unable to deactivate Remain on Chn timer\n"));
+                return;
             }
             val = 1000;
             val = SYS_MS_TO_TICKS(val);
@@ -1779,6 +1798,7 @@
                 * timer. Log error.
                 */
                 limLog(pMac, LOGP, FL("Unable to change timer\n"));
+                return;
             }
             break;
 #endif
@@ -1790,6 +1810,7 @@
                 ** timer. Log error.
                 **/
                 limLog(pMac, LOGP, FL("Unable to deactivate Disassoc ack timer\n"));
+                return;
             }
             val = 1000;
             val = SYS_MS_TO_TICKS(val);
@@ -1801,6 +1822,7 @@
                 * timer. Log error.
                 */
                 limLog(pMac, LOGP, FL("Unable to change timer\n"));
+                return;
             }
             break;
 
@@ -1812,6 +1834,7 @@
                 ** timer. Log error.
                 **/
                 limLog(pMac, LOGP, FL("Unable to deactivate Deauth ack timer\n"));
+                return;
             }
             val = 1000;
             val = SYS_MS_TO_TICKS(val);
@@ -1823,8 +1846,36 @@
                 * timer. Log error.
                 */
                 limLog(pMac, LOGP, FL("Unable to change timer\n"));
+                return;
             }
             break;
+
+#ifdef WLAN_FEATURE_P2P
+    case eLIM_INSERT_SINGLESHOT_NOA_TIMER:
+        if (tx_timer_deactivate(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer) != TX_SUCCESS)
+        {
+            /**
+       ** Could not deactivate SingleShot NOA Insert
+       ** timer. Log error.
+       **/
+            limLog(pMac, LOGP, FL("Unable to deactivate SingleShot NOA Insert timer\n"));
+            return;
+        }
+        val = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE;
+        val = SYS_MS_TO_TICKS(val);
+        if (tx_timer_change(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer,
+                                            val, 0) != TX_SUCCESS)
+        {
+            /**
+       * Could not change Single Shot NOA Insert
+       * timer. Log error.
+       */
+            limLog(pMac, LOGP, FL("Unable to change timer\n"));
+            return;
+        }
+        break;
+#endif
+            
         default:
             // Invalid timerId. Log error
             break;
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.h b/CORE/MAC/src/pe/lim/limTimerUtils.h
index 5a98d72..6bfbe22 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.h
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.h
@@ -83,9 +83,12 @@
     eLIM_DISASSOC_ACK_TIMER,
     eLIM_DEAUTH_ACK_TIMER,
     eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER,
+    eLIM_INSERT_SINGLESHOT_NOA_TIMER,
 };
 
 #define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT         500
+#define LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE  500
+
 
 // Timer Handler functions
 v_UINT_t limCreateTimers(tpAniSirGlobal);
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 5b23c36..d2d580e 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -662,7 +662,6 @@
 
 char *limResultCodeStr(tSirResultCodes resultCode)
 {
-#ifdef FIXME_GEN6
     switch (resultCode)
     {
       case eSIR_SME_SUCCESS:
@@ -814,8 +813,6 @@
         default:
             return "INVALID resultCode\n";
     }
-#endif
-return "";
 }
 
 void
@@ -7833,6 +7830,23 @@
     return;
 }
 
+tANI_BOOLEAN limIsNOAInsertReqd(tpAniSirGlobal pMac)
+{
+    tANI_U8 i;
+    for(i =0; i < pMac->lim.maxBssId; i++)
+    {
+        if(pMac->lim.gpSession[i].valid == TRUE)
+        {
+            if( (eLIM_AP_ROLE == pMac->lim.gpSession[i].limSystemRole ) 
+                    && ( VOS_P2P_GO_MODE == pMac->lim.gpSession[i].pePersona )
+                   )
+            {
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
 
 #endif
 
diff --git a/CORE/MAC/src/pe/lim/limUtils.h b/CORE/MAC/src/pe/lim/limUtils.h
index d54c5af..f851a5d 100644
--- a/CORE/MAC/src/pe/lim/limUtils.h
+++ b/CORE/MAC/src/pe/lim/limUtils.h
@@ -394,6 +394,7 @@
 v_U8_t limGetNoaAttrStream(tpAniSirGlobal pMac, v_U8_t*pNoaStream,tpPESession psessionEntry);
 
 v_U8_t limBuildP2pIe(tpAniSirGlobal pMac, tANI_U8 *ie, tANI_U8 *data, tANI_U8 ie_len);
+tANI_BOOLEAN limIsNOAInsertReqd(tpAniSirGlobal pMac);
 #endif
 v_U8_t* limGetVendorIEOuiPtr(tpAniSirGlobal pMac, tANI_U8 *oui, tANI_U8 oui_size, tANI_U8 *ie, tANI_U16 ie_len);
 tANI_BOOLEAN limIsconnectedOnDFSChannel(tANI_U8 currentChannel);