wlan: Make Passive channel to Active channel when beacon is received.

When any beacon or probe resp is present on any passive channel,
mark that passive channel as active channel for 30 sec. If there is
no activity for 30 sec on that channel then mark it again as Passive
channel.

CRs-Fixed: 477109
Change-Id: Ia173b51b094ef2d4722dff989c2d4e54b25e957b
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index 357c134..fd78b7a 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -253,6 +253,11 @@
     TX_TIMER           gLimDeauthAckTimer;
     // This timer is started when single shot NOA insert msg is sent to FW for scan in P2P GO mode
     TX_TIMER           gLimP2pSingleShotNoaInsertTimer;
+    /* This timer is used to convert active channel to
+     * passive channel when there is no beacon
+     * for a period of time on a particular DFS channel
+     */
+    TX_TIMER           gLimActiveToPassiveChannelTimer;
 //********************TIMER SECTION ENDS**************************************************
 // ALL THE FIELDS BELOW THIS CAN BE ZEROED OUT in limInitialize
 //****************************************************************************************
@@ -909,6 +914,7 @@
 #endif
     tLimDisassocDeauthCnfReq limDisassocDeauthCnfReq;
     tANI_U8 deferredMsgCnt;
+    tSirDFSChannelList    dfschannelList;
 } tAniSirLim, *tpAniSirLim;
 
 typedef struct sLimMgmtFrameRegistration
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 837a5c0..ee1845d 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -90,6 +90,11 @@
 
 #define SIR_MDIE_SIZE               3
 
+/* Max number of channels are 165, but to access 165th element of array,
+ *array of 166 is required.
+ */
+#define SIR_MAX_24G_5G_CHANNEL_RANGE      166
+
 
 
 #define SIR_NUM_11B_RATES 4   //1,2,5.5,11
@@ -719,6 +724,12 @@
     tANI_U8          channelNumber[1];
 } tSirChannelList, *tpSirChannelList;
 
+typedef struct sSirDFSChannelList
+{
+    tANI_U32         timeStamp[SIR_MAX_24G_5G_CHANNEL_RANGE];
+
+} tSirDFSChannelList, *tpSirDFSChannelList;
+
 #ifdef FEATURE_WLAN_CCX
 typedef struct sTspecInfo {
     tANI_U8         valid;
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 43d9e1b..b51574d 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -669,6 +669,7 @@
 #define SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x2A)
 #define SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x2B)
 #endif
+#define SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE (SIR_LIM_TIMEOUT_MSG_START + 0x2C)
 #define SIR_LIM_MSG_TYPES_END            (SIR_LIM_MSG_TYPES_BEGIN+0xFF)
 
 // SCH message types
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index f186f20..e458129 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -140,6 +140,7 @@
     // abort scan is used to abort an on-going scan
     pMac->lim.abortScan = 0;
     palZeroMemory(pMac->hHdd, &pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo));
+    palZeroMemory(pMac->hHdd, &pMac->lim.dfschannelList, sizeof(tSirDFSChannelList));
 
 //WLAN_SUSPEND_LINK Related
     pMac->lim.gpLimSuspendCallback = NULL;
diff --git a/CORE/MAC/src/pe/lim/limP2P.c b/CORE/MAC/src/pe/lim/limP2P.c
index 96d32ce..6801371 100644
--- a/CORE/MAC/src/pe/lim/limP2P.c
+++ b/CORE/MAC/src/pe/lim/limP2P.c
@@ -79,6 +79,11 @@
 #define   ADDR2_OFFSET           10
 #define   ACTION_OFFSET          24
 
+/* A DFS channel can be ACTIVE for max 30000 msec, from the last
+   received Beacon/Prpbe Resp. */
+#define   MAX_TIME_TO_BE_ACTIVE_CHANNEL 30000
+
+
 
 void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status,
                                        tANI_U32 *data);
@@ -407,6 +412,56 @@
     return;
 }
 
+/*-----------------------------------------------------------------
+ * lim Insert Timer callback function to check active DFS channels
+ * and convert them to passive channels if there was no
+ * beacon/proberesp for MAX_TIME_TO_BE_ACTIVE_CHANNEL time
+ *------------------------------------------------------------------*/
+void limConvertActiveChannelToPassiveChannel(tpAniSirGlobal pMac )
+{
+    tANI_U32 currentTime;
+    tANI_U32 lastTime = 0;
+    tANI_U32 timeDiff;
+    tANI_U8 i;
+    currentTime = vos_timer_get_system_time();
+    for (i = 1; i < SIR_MAX_24G_5G_CHANNEL_RANGE ; i++)
+    {
+        if ((pMac->lim.dfschannelList.timeStamp[i]) != 0)
+        {
+            lastTime = pMac->lim.dfschannelList.timeStamp[i];
+            if (currentTime >= lastTime)
+            {
+                timeDiff = (currentTime - lastTime);
+            }
+            else
+            {
+                timeDiff = (0xFFFFFFFF - lastTime) + currentTime;
+            }
+
+            if (timeDiff >= MAX_TIME_TO_BE_ACTIVE_CHANNEL)
+            {
+                limCovertChannelScanType( pMac, i,FALSE);
+                pMac->lim.dfschannelList.timeStamp[i] = 0;
+            }
+        }
+    }
+    /* lastTime is zero if there is no DFS active channels in the list.
+     * If this is non zero then we have active DFS channels so restart the timer.
+    */
+    if (lastTime != 0)
+    {
+        if (tx_timer_activate(
+                         &pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)
+                          != TX_SUCCESS)
+        {
+            limLog(pMac, LOGE, FL("Could not activate Active to Passive Channel  timer"));
+        }
+    }
+
+    return;
+
+}
+
 /*------------------------------------------------------------------
  *
  * limchannelchange callback, on success channel change, set the
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 6dc5dfc..f71cd3e 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -1497,6 +1497,7 @@
         case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT:
         case SIR_LIM_DISASSOC_ACK_TIMEOUT:
         case SIR_LIM_DEAUTH_ACK_TIMEOUT:
+        case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE:
             // These timeout messages are handled by MLM sub module
 
             limProcessMlmReqMessages(pMac,
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
index dc45eb2..549aab2 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
@@ -169,6 +169,8 @@
         case SIR_LIM_REMAIN_CHN_TIMEOUT:    limProcessRemainOnChnTimeout(pMac); break;
         case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT:   
                                             limProcessInsertSingleShotNOATimeout(pMac); break;
+        case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE:
+                                            limConvertActiveChannelToPassiveChannel(pMac); break;
         case SIR_LIM_DISASSOC_ACK_TIMEOUT:  limProcessDisassocAckTimeout(pMac); break;
         case SIR_LIM_DEAUTH_ACK_TIMEOUT:    limProcessDeauthAckTimeout(pMac); break;
         case LIM_MLM_ADDBA_REQ:             limProcessMlmAddBAReq( pMac, Msg->bodyptr ); break;
@@ -606,6 +608,133 @@
 
 
 
+
+/* limCovertChannelScanType()
+ *
+ *FUNCTION:
+ * This function is called to get the list, change the channel type and set again.
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE: If a channel is ACTIVE, this function will make it as PASSIVE
+ *      If a channel is PASSIVE, this fucntion will make it as ACTIVE
+ * NA
+ *
+ * @param  pMac    - Pointer to Global MAC structure
+ *         channelNum - Channel which need to be convert
+           PassiveToActive - Boolean flag to convert channel
+ *
+ * @return None
+ */
+
+
+void limCovertChannelScanType(tpAniSirGlobal pMac,tANI_U8 channelNum, tANI_BOOLEAN passiveToActive)
+{
+
+    tANI_U32 i;
+    tANI_U8  channelPair[WNI_CFG_SCAN_CONTROL_LIST_LEN];
+    tANI_U32 len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
+    if (wlan_cfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len)
+                    != eSIR_SUCCESS)
+    {
+        PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list"));)
+        return ;
+    }
+    if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN)
+    {
+        limLog(pMac, LOGE, FL("Invalid scan control list length:%d"), len);
+        return ;
+    }
+    for (i=0; (i+1) < len; i+=2)
+    {
+        if (channelPair[i] == channelNum)
+        {
+             if ((eSIR_PASSIVE_SCAN == channelPair[i+1]) && TRUE == passiveToActive)
+             {
+                 PELOG1(limLog(pMac, LOG1, FL("Channel %d changed from Passive to Active"),
+                                 channelNum);)
+                 channelPair[i+1] = eSIR_ACTIVE_SCAN;
+                 break ;
+             }
+             if ((eSIR_ACTIVE_SCAN == channelPair[i+1]) && FALSE == passiveToActive)
+             {
+                 PELOG1(limLog(pMac, LOG1, FL("Channel %d changed from Active to Passive"),
+                                 channelNum);)
+                 channelPair[i+1] = eSIR_PASSIVE_SCAN;
+                 break ;
+             }
+       }
+    }
+
+    cfgSetStrNotify(pMac, WNI_CFG_SCAN_CONTROL_LIST, (tANI_U8 *)channelPair, len, FALSE);
+    return ;
+}
+
+
+
+
+/* limSetDFSChannelList()
+ *
+ *FUNCTION:
+ * This function is called to convert DFS channel list to active channel list when any
+ * beacon is present on that channel. This function store time for passive channels
+ * which help to know that for how much time channel has been passive.
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE: If a channel is ACTIVE, it won't store any time
+ *      If a channel is PAssive, it will store time as timestamp
+ * NA
+ *
+ * @param  pMac    - Pointer to Global MAC structure
+ *         dfsChannelList - DFS channel list.
+ * @return None
+ */
+
+void limSetDFSChannelList(tpAniSirGlobal pMac,tANI_U8 channelNum, tSirDFSChannelList *dfsChannelList)
+{
+
+    tANI_BOOLEAN passiveToActive = TRUE;
+    if ((1 <= channelNum) && (165 >= channelNum))
+    {
+       if (eANI_BOOLEAN_TRUE == limIsconnectedOnDFSChannel(channelNum))
+       {
+          if (dfsChannelList->timeStamp[channelNum] == 0)
+          {
+             //Received first beacon; Convert DFS channel to Active channel.
+             PELOG1(limLog(pMac, LOG1, FL("Received first beacon on DFS channel: %d"), channelNum);)
+             limCovertChannelScanType(pMac,channelNum, passiveToActive);
+          }
+          dfsChannelList->timeStamp[channelNum] = vos_timer_get_system_time();
+       }
+       else
+       {
+          PELOG1(limLog(pMac, LOG1, FL("Channel %d is Active"), channelNum);)
+          return;
+       }
+       if (!tx_timer_running(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer))
+       {
+          tx_timer_activate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
+       }
+    }
+    else
+    {
+       PELOGE(limLog(pMac, LOGE, FL("Invalid Channel: %d"), channelNum);)
+       return;
+    }
+
+    return;
+}
+
+
+
+
 /*
 * Creates a Raw frame to be sent before every Scan, if required.
 * If only infra link is active (mlmState = Link Estb), then send Data Null
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index 8e06ea0..df92f10 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -1466,6 +1466,12 @@
 
     PELOG1(limLog(pMac, LOG1, FL("Received SME_JOIN_REQ"));)
 
+    /* After connection, DFS channel list needs to be fill again
+     * so clearing DFS list just before connection.
+     */
+    palZeroMemory(pMac->hHdd, &pMac->lim.dfschannelList, sizeof(tSirDFSChannelList));
+
+
 #ifdef WLAN_FEATURE_VOWIFI
     /* Need to read the CFG here itself as this is used in limExtractAPCapability() below.
     * This CFG is actually read in rrmUpdateConfig() which is called later. Because this is not
diff --git a/CORE/MAC/src/pe/lim/limScanResultUtils.c b/CORE/MAC/src/pe/lim/limScanResultUtils.c
index 4bc027e..355a763 100644
--- a/CORE/MAC/src/pe/lim/limScanResultUtils.c
+++ b/CORE/MAC/src/pe/lim/limScanResultUtils.c
@@ -216,7 +216,7 @@
       pBssDescr->channelId = rxChannel;
    }
 
-    pBssDescr->channelIdSelf = rxChannel;
+    pBssDescr->channelIdSelf = pBssDescr->channelId;
     //set the network type in bss description
     channelNum = pBssDescr->channelId;
     pBssDescr->nwType = limGetNwType(pMac, channelNum, SIR_MAC_MGMT_FRAME, pBPR);
@@ -503,7 +503,10 @@
     limCollectBssDescription(pMac, &pBssDescr->bssDescription,
                              pBPR, pRxPacketInfo);
 #endif
-
+    /* Calling dfsChannelList which will convert DFS channel
+     * to Active channel for x secs if this channel is DFS channel */
+    limSetDFSChannelList(pMac, pBssDescr->bssDescription.channelIdSelf,
+                               &pMac->lim.dfschannelList);
     pBssDescr->bssDescription.fProbeRsp = fProbeRsp;
 
     pBssDescr->next = NULL;
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index aac265b..2d5ae82 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -71,6 +71,11 @@
 
 //default beacon interval value used in HB timer interval calculation
 #define LIM_HB_TIMER_BEACON_INTERVAL             100
+
+/* This timer is a periodic timer which expires at every 5 sec to
+   convert  ACTIVE DFS channel to DFS channels */
+#define ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT     5000
+
 /**
  * limCreateTimers()
  *
@@ -738,6 +743,18 @@
         goto err_timer;
     }
 
+    cfgValue = ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT;
+    cfgValue = SYS_MS_TO_TICKS(cfgValue);
+    if (tx_timer_create(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer,
+                                  "ACTIVE TO PASSIVE CHANNEL", limTimerHandler,
+                 SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE, cfgValue, 0,
+                 TX_NO_ACTIVATE) != TX_SUCCESS)
+    {
+        limLog(pMac, LOGW,FL("could not create timer for passive channel to active channel"));
+        goto err_timer;
+    }
+
+
     return TX_SUCCESS;
 
     err_timer:
@@ -771,6 +788,7 @@
         tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer);
         tx_timer_delete(&pMac->lim.limTimers.gLimMinChannelTimer);
         tx_timer_delete(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer);
+        tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
 
         if(NULL != pMac->lim.gLimPreAuthTimerTable.pTable)
             palFreeMemory(pMac->hHdd, pMac->lim.gLimPreAuthTimerTable.pTable);
@@ -1685,6 +1703,32 @@
                 return;
             }
             break;
+
+    case eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE:
+            if (tx_timer_deactivate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer) != TX_SUCCESS)
+            {
+                /**
+                ** Could not deactivate Active to passive channel timer.
+                ** Log error.
+                **/
+                limLog(pMac, LOGP, FL("Unable to Deactivate "
+                                      "Active to passive channel timer"));
+                return;
+            }
+            val = ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT;
+            val = SYS_MS_TO_TICKS(val);
+            if (tx_timer_change(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer,
+                                                val, 0) != TX_SUCCESS)
+            {
+                /**
+                * Could not change timer to check scan type for passive channel.
+                * timer. Log error.
+                */
+                limLog(pMac, LOGP, FL("Unable to change timer"));
+                return;
+            }
+            break;
+
     case eLIM_DISASSOC_ACK_TIMER:
             if (tx_timer_deactivate(&pMac->lim.limTimers.gLimDisassocAckTimer) != TX_SUCCESS)
             {
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.h b/CORE/MAC/src/pe/lim/limTimerUtils.h
index a1e6700..0715227 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.h
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.h
@@ -97,6 +97,7 @@
     eLIM_DEAUTH_ACK_TIMER,
     eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER,
     eLIM_INSERT_SINGLESHOT_NOA_TIMER,
+    eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE
 };
 
 #define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT         500
diff --git a/CORE/MAC/src/pe/lim/limTrace.c b/CORE/MAC/src/pe/lim/limTrace.c
index d383ad4..95744c8 100644
--- a/CORE/MAC/src/pe/lim/limTrace.c
+++ b/CORE/MAC/src/pe/lim/limTrace.c
@@ -109,6 +109,7 @@
         CASE_RETURN_STRING(eLIM_DEAUTH_ACK_TIMER);
         CASE_RETURN_STRING(eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
         CASE_RETURN_STRING(eLIM_INSERT_SINGLESHOT_NOA_TIMER);
+        CASE_RETURN_STRING(eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE);
         default:
             return( "UNKNOWN" );
             break;
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index 9e7143c..00bff88 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.h
@@ -840,6 +840,8 @@
 void limSendHalFinishScanReq( tpAniSirGlobal, tLimLimHalScanState);
 
 void limContinuePostChannelScan(tpAniSirGlobal pMac);
+void limCovertChannelScanType(tpAniSirGlobal pMac,tANI_U8 channelNum, tANI_BOOLEAN passiveToActive);
+void limSetDFSChannelList(tpAniSirGlobal pMac,tANI_U8 channelNum, tSirDFSChannelList *dfsChannelList);
 void limContinueChannelLearn( tpAniSirGlobal );
 //WLAN_SUSPEND_LINK Related
 tANI_U8 limIsLinkSuspended(tpAniSirGlobal pMac);
@@ -1070,6 +1072,7 @@
                     tANI_S8 rxRssi);
 void limProcessRemainOnChnTimeout(tpAniSirGlobal pMac);
 void limProcessInsertSingleShotNOATimeout(tpAniSirGlobal pMac);
+void limConvertActiveChannelToPassiveChannel(tpAniSirGlobal pMac);
 void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
 void limAbortRemainOnChan(tpAniSirGlobal pMac);
 tSirRetStatus __limProcessSmeNoAUpdate(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf);
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index 1bc5d08..a977b71 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -576,6 +576,7 @@
 #endif
         CASE_RETURN_STRING(SIR_LIM_REMAIN_CHN_TIMEOUT);
         CASE_RETURN_STRING(SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT);
+        CASE_RETURN_STRING(SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE);
 #ifdef WMM_APSD
         CASE_RETURN_STRING(SIR_LIM_WMM_APSD_SP_START_MSG_TYPE );
         CASE_RETURN_STRING(SIR_LIM_WMM_APSD_SP_END_MSG_TYPE );