Merge "wlan: Address memory corruption due to double free"
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 5e82fb2..f8bfbe9 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -220,6 +220,16 @@
 #define CFG_IMPS_MAXIMUM_SLEEP_TIME_MAX        ( 65535 )
 #define CFG_IMPS_MAXIMUM_SLEEP_TIME_DEFAULT    ( 15 )
 
+/*If there is scan on STA interface back to back with
+ *time diff nDeferScanTimeInterval, driver will not
+ *issue a new scan. Driver will return cached result to kernel.
+ *the interval is in msec
+ */
+#define CFG_DEFER_SCAN_TIME_INTERVAL            "gDeferScanTimeInterval"
+#define CFG_DEFER_SCAN_TIME_INTERVAL_MIN        ( 0 )
+#define CFG_DEFER_SCAN_TIME_INTERVAL_MAX        ( 65535 )
+#define CFG_DEFER_SCAN_TIME_INTERVAL_DEFAULT    ( 2000  )
+
 //BMPS = BeaconModePowerSave
 #define CFG_ENABLE_BMPS_NAME                   "gEnableBmps"
 #define CFG_ENABLE_BMPS_MIN                    ( 0 )
@@ -2393,6 +2403,7 @@
    v_BOOL_t      ShortSlotTimeEnabled;
    v_BOOL_t      Is11dSupportEnabled;
    v_BOOL_t      Is11hSupportEnabled;
+   v_U32_t       nDeferScanTimeInterval;
    v_BOOL_t      fEnforce11dChannels;
    v_BOOL_t      fSupplicantCountryCodeHasPriority;
    v_BOOL_t      fEnforceCountryCodeMatch;
@@ -2809,7 +2820,7 @@
 #endif
    char                        overrideCountryCode[4];
    v_U32_t                     gAsdProbeInterval;
-   v_U32_t                     gAsdTriggerThreshold;
+   v_S7_t                      gAsdTriggerThreshold;
    v_U32_t                     gAsdRTTRssiHystThreshold;
    v_BOOL_t                    debugP2pRemainOnChannel;
    v_U32_t                     cfgBtcCTS2SduringSCO;
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index df67b4e..ebf03cf 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -767,6 +767,10 @@
 
    hdd_scan_pending_option_e scan_pending_option;
    tANI_U8 sessionId;
+   /* time to store last station scan done. */
+   v_TIME_t     last_scan_timestamp;
+   tANI_U8 last_scan_channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+   tANI_U8 last_scan_numChannels;
 
 }hdd_scaninfo_t;
 
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index f53e85e..5acb5b6 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -417,6 +417,13 @@
                  CFG_IMPS_MAXIMUM_SLEEP_TIME_MIN,
                  CFG_IMPS_MAXIMUM_SLEEP_TIME_MAX ),
 
+   REG_VARIABLE( CFG_DEFER_SCAN_TIME_INTERVAL, WLAN_PARAM_Integer,
+                 hdd_config_t, nDeferScanTimeInterval,
+                 VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+                 CFG_DEFER_SCAN_TIME_INTERVAL_DEFAULT,
+                 CFG_DEFER_SCAN_TIME_INTERVAL_MIN,
+                 CFG_DEFER_SCAN_TIME_INTERVAL_MAX ),
+
    REG_VARIABLE( CFG_IMPS_MODERATE_SLEEP_TIME_NAME, WLAN_PARAM_Integer,
                  hdd_config_t, nImpsModSleepTime,
                  VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -2904,7 +2911,7 @@
                  CFG_ASD_PROBE_INTERVAL_MIN,
                  CFG_ASD_PROBE_INTERVAL_MAX),
 
-   REG_VARIABLE( CFG_ASD_TRIGGER_THRESHOLD_NAME, WLAN_PARAM_Integer,
+   REG_VARIABLE( CFG_ASD_TRIGGER_THRESHOLD_NAME, WLAN_PARAM_SignedInteger,
                  hdd_config_t, gAsdTriggerThreshold,
                  VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
                  CFG_ASD_TRIGGER_THRESHOLD_DEFAULT,
@@ -3612,12 +3619,13 @@
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [overrideCountryCode] Value = [%s] ",pHddCtx->cfg_ini->overrideCountryCode);
 
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAsdProbeInterval] Value = [%u]",pHddCtx->cfg_ini->gAsdProbeInterval);
-  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAsdTriggerThreshold] Value = [%u]",pHddCtx->cfg_ini->gAsdTriggerThreshold);
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAsdTriggerThreshold] Value = [%hhd]",pHddCtx->cfg_ini->gAsdTriggerThreshold);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAsdRTTRssiHystThreshold]Value = [%u]",pHddCtx->cfg_ini->gAsdRTTRssiHystThreshold);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gRoamtoDFSChannel] Value = [%u] ",pHddCtx->cfg_ini->allowDFSChannelRoam);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gMaxConcurrentActiveSessions] Value = [%u] ", pHddCtx->cfg_ini->gMaxConcurrentActiveSessions);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAcsScanBandPreference] Value = [%u] ",pHddCtx->cfg_ini->acsScanBandPreference);
-  VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,"Name = [gACSBandSwitchThreshold] value = [%u]\n",pHddCtx->cfg_ini->acsBandSwitchThreshold);
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gACSBandSwitchThreshold] value = [%u]\n",pHddCtx->cfg_ini->acsBandSwitchThreshold);
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gDeferScanTimeInterval] value = [%u]\n",pHddCtx->cfg_ini->nDeferScanTimeInterval);
 }
 
 
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index cf86cab..ae0a6b5 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -9426,6 +9426,7 @@
     int ret = 0;
     bool aborted = false;
     long waitRet = 0;
+    tANI_U8 i;
 
     ENTER();
 
@@ -9510,6 +9511,27 @@
     /* Scan is no longer pending */
     pScanInfo->mScanPending = VOS_FALSE;
 
+    /* last_scan_timestamp is used to decide if new scan
+     * is needed or not on station interface. If last station
+     *  scan time and new station scan time is less then
+     * last_scan_timestamp ; driver will return cached scan.
+     */
+    if (req->no_cck == FALSE && status == eCSR_SCAN_SUCCESS) // no_cck will be set during p2p find
+    {
+        pScanInfo->last_scan_timestamp = vos_timer_get_system_time();
+
+        if ( req->n_channels )
+        {
+            for (i = 0; i < req->n_channels ; i++ )
+            {
+                pHddCtx->scan_info.last_scan_channelList[i] = req->channels[i]->hw_value;
+            }
+            /* store no of channel scanned */
+            pHddCtx->scan_info.last_scan_numChannels= req->n_channels;
+        }
+
+    }
+
     /*
      * cfg80211_scan_done informing NL80211 about completion
      * of scanning
@@ -9656,6 +9678,7 @@
     int status;
     hdd_scaninfo_t *pScanInfo = NULL;
     v_U8_t* pP2pIe = NULL;
+    int ret = 0;
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
     struct net_device *dev = NULL;
@@ -9786,6 +9809,7 @@
     hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
            (int)request->n_ssids);
 
+
     /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
      * Becasue of this, driver is assuming that this is not wildcard scan and so
      * is not aging out the scan results.
@@ -9888,6 +9912,39 @@
     /* set requestType to full scan */
     scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
 
+    /* if there is back to back scan happening in driver with in
+     * nDeferScanTimeInterval interval driver should defer new scan request
+     * and should provide last cached scan results instead of new channel list.
+     * This rule is not applicable if scan is p2p scan.
+     * This condition will work only in case when last request no of channels
+     * and channels are exactly same as new request.
+     */
+    if (pScanInfo->last_scan_timestamp !=0 &&
+           (FALSE == request->no_cck) && // no_cck is set during p2p find.
+          ((vos_timer_get_system_time() - pScanInfo->last_scan_timestamp ) < pHddCtx->cfg_ini->nDeferScanTimeInterval))
+    {
+        if (pScanInfo->last_scan_numChannels == scanRequest.ChannelInfo.numOfChannels &&
+               vos_mem_compare(pScanInfo->last_scan_channelList,
+                     channelList, pScanInfo->last_scan_numChannels))
+       {
+           hddLog(VOS_TRACE_LEVEL_WARN,
+                " New and old station scan time differ is less then %u",
+            pHddCtx->cfg_ini->nDeferScanTimeInterval);
+
+           ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
+                                        pAdapter);
+
+           hddLog(VOS_TRACE_LEVEL_WARN,
+                "Return old cached scan as all channels"
+                "and no of channles are same");
+           if (0 > ret)
+                hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
+
+           cfg80211_scan_done(request, eCSR_SCAN_SUCCESS);
+           return eHAL_STATUS_SUCCESS ;
+       }
+    }
+
     /* Flush the scan results(only p2p beacons) for STA scan and P2P
      * search (Flush on both full  scan and social scan but not on single
      * channel scan).P2P  search happens on 3 social channels (1, 6, 11)
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 8919893..0d88f2e 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -171,8 +171,18 @@
   --------------------------------------------------------------------------*/
 int hdd_hostapd_open (struct net_device *dev)
 {
+   hdd_adapter_t *pAdapter =  WLAN_HDD_GET_PRIV_PTR(dev);
+
    ENTER();
 
+   if(!test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
+   {
+       //WMM_INIT OR BSS_START not completed
+       hddLog( LOGW, "Ignore hostadp open request");
+       EXIT();
+       return 0;
+   }
+
    MTRACE(vos_trace(VOS_MODULE_ID_HDD,
                     TRACE_CODE_HDD_HOSTAPD_OPEN_REQUEST, NO_SESSION, 0));
    //Turn ON carrier state
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 80bebbc..ab6df87 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -7193,6 +7193,11 @@
           clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
       }
 
+      if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
+      {
+          clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
+      }
+
 #ifdef FEATURE_WLAN_BATCH_SCAN
       if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
       {
diff --git a/CORE/MAC/inc/wniCfgAp.h b/CORE/MAC/inc/wniCfgAp.h
index b7fc34a..f9cbb3e 100644
--- a/CORE/MAC/inc/wniCfgAp.h
+++ b/CORE/MAC/inc/wniCfgAp.h
@@ -2644,13 +2644,13 @@
 #define WNI_CFG_ASD_PROBE_INTERVAL_APMAX    100
 #define WNI_CFG_ASD_PROBE_INTERVAL_APDEF    50
 
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMIN    0
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMAX    120
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STADEF    45
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMIN   -120
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMAX    0
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STADEF   -75
 
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_APMIN    0
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_APMAX    120
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_APDEF    45
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_APMIN    -120
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_APMAX     0
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_APDEF    -75
 
 #define WNI_CFG_ASD_RTT_RSSI_HYST_THRESHOLD_STAMIN    0
 #define WNI_CFG_ASD_RTT_RSSI_HYST_THRESHOLD_STAMAX    100
diff --git a/CORE/MAC/inc/wniCfgSta.h b/CORE/MAC/inc/wniCfgSta.h
index 4cf0894..8785e3f 100644
--- a/CORE/MAC/inc/wniCfgSta.h
+++ b/CORE/MAC/inc/wniCfgSta.h
@@ -1717,9 +1717,9 @@
 #define WNI_CFG_ASD_PROBE_INTERVAL_STAMAX    100
 #define WNI_CFG_ASD_PROBE_INTERVAL_STADEF    50
 
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMIN    0
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMAX    120
-#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STADEF    45
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMIN    -120
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STAMAX     0
+#define WNI_CFG_ASD_TRIGGER_THRESHOLD_STADEF    -75
 
 #define WNI_CFG_ASD_RTT_RSSI_HYST_THRESHOLD_STAMIN    0
 #define WNI_CFG_ASD_RTT_RSSI_HYST_THRESHOLD_STAMAX    100
diff --git a/CORE/MAC/src/cfg/cfgApi.c b/CORE/MAC/src/cfg/cfgApi.c
index a9ea14a..4fa4bc5 100644
--- a/CORE/MAC/src/cfg/cfgApi.c
+++ b/CORE/MAC/src/cfg/cfgApi.c
@@ -232,10 +232,20 @@
         PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);)
         retVal = eSIR_CFG_INVALID_ID;
     }
-    else if ((pMac->cfg.gCfgIBufMin[index] > value) ||
-             (pMac->cfg.gCfgIBufMax[index] < value))
+    else if ((pMac->cfg.gCfgIBufMin[index] < pMac->cfg.gCfgIBufMax[index]) &&
+             ((pMac->cfg.gCfgIBufMin[index] > value) ||
+             (pMac->cfg.gCfgIBufMax[index] < value)))
     {
-        PELOGE(cfgLog(pMac, LOGE, FL("Value %d out of range [%d,%d] cfg id %d"),
+        PELOGE(cfgLog(pMac, LOGE, FL("Value %u out of range [%u,%u] cfgid %hu"),
+               value, pMac->cfg.gCfgIBufMin[index],
+               pMac->cfg.gCfgIBufMax[index], cfgId);)
+        retVal = eSIR_CFG_INVALID_ID;
+    }
+    else if (!(pMac->cfg.gCfgIBufMin[index] < pMac->cfg.gCfgIBufMax[index]) &&
+             (((tANI_S32)(pMac->cfg.gCfgIBufMin[index]) > (tANI_S32)value) ||
+              ((tANI_S32)(pMac->cfg.gCfgIBufMax[index]) < (tANI_S32)value)))
+    {
+        PELOGE(cfgLog(pMac, LOGE, FL("Value %d out of range [%d,%d] cfgid %hu"),
                value, pMac->cfg.gCfgIBufMin[index],
                pMac->cfg.gCfgIBufMax[index], cfgId);)
         retVal = eSIR_CFG_INVALID_ID;
diff --git a/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/CORE/SVC/src/logging/wlan_logging_sock_svc.c
index 16c0159..7a0b678 100644
--- a/CORE/SVC/src/logging/wlan_logging_sock_svc.c
+++ b/CORE/SVC/src/logging/wlan_logging_sock_svc.c
@@ -309,11 +309,6 @@
 		pr_err("%s\n", to_be_sent);
 	}
 
-	// wlan logging svc resources are not yet initialized
-	if (!gwlan_logging.pcur_node) {
-	    return -EIO;
-	}
-
 	/* Format the Log time [Secondselapsedinaday.microseconds] */
 	do_gettimeofday(&tv);
 	tlen = snprintf(tbuf, sizeof(tbuf), "[%s][%5lu.%06lu] ", current->comm,
@@ -325,6 +320,12 @@
 
 	spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
 
+	// wlan logging svc resources are not yet initialized
+	if (!gwlan_logging.pcur_node) {
+	    spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
+	    return -EIO;
+	}
+
 	pfilled_length = &gwlan_logging.pcur_node->filled_length;
 
 	 /* Check if we can accomodate more log into current node/buffer */