wlan: Enhance LLStats to Separate data between HDD and SME

This commit enhances LLStats implementation to ensure SME does a
separate copy of HDD data.Also , this commit checks for this feature
capability before functioning and returns failure if not enabled.

Change-Id: I4ec1ca0893ef82b991e1f1078a2ac8999f21d057
CRs-Fixed:  689686
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 0a69123..32d438c 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1839,6 +1839,13 @@
 #define CFG_TDLS_SCAN_COEX_SUPPORT_ENABLE_DEFAULT    (0)
 #endif
 
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+#define CFG_LINK_LAYER_STATS_ENABLE                  "gEnableLLStats"
+#define CFG_LINK_LAYER_STATS_ENABLE_MIN              (0)
+#define CFG_LINK_LAYER_STATS_ENABLE_MAX              (1)
+#define CFG_LINK_LAYER_STATS_ENABLE_DEFAULT          (0)
+#endif
+
 #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
 #define CFG_ACTIVEMODE_OFFLOAD_ENABLE         "gEnableActiveModeOffload"
 #define CFG_ACTIVEMODE_OFFLOAD_ENABLE_MIN     ( 0 )
@@ -2578,13 +2585,16 @@
    v_U32_t                     fEnableTDLSWmmMode;
    v_BOOL_t                    fEnableTDLSScanCoexSupport;
 #endif
-   v_U32_t                     enableLpwrImgTransition;
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+   v_BOOL_t                    fEnableLLStats;
+#endif
 #ifdef WLAN_SOFTAP_VSTA_FEATURE
    v_BOOL_t                    fEnableVSTASupport;
 #endif
 #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
    v_BOOL_t                    fEnableActiveModeOffload;
 #endif
+   v_U32_t                     enableLpwrImgTransition;
    v_U8_t                      scanAgingTimeout;
    v_BOOL_t                    enableTxLdpc;
    v_U8_t                      disableLDPCWithTxbfAP;
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 3bb2212..0c2f800 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -2540,6 +2540,15 @@
               CFG_TDLS_SCAN_COEX_SUPPORT_ENABLE_MAX ),
 #endif
 
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+REG_VARIABLE( CFG_LINK_LAYER_STATS_ENABLE, WLAN_PARAM_Integer,
+              hdd_config_t, fEnableLLStats,
+              VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+              CFG_LINK_LAYER_STATS_ENABLE_DEFAULT,
+              CFG_LINK_LAYER_STATS_ENABLE_MIN,
+              CFG_LINK_LAYER_STATS_ENABLE_MAX ),
+#endif
+
 #ifdef WLAN_SOFTAP_VSTA_FEATURE
    REG_VARIABLE( CFG_VSTA_SUPPORT_ENABLE, WLAN_PARAM_Integer,
               hdd_config_t, fEnableVSTASupport,
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 2d14f63..f7323f0 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -1496,7 +1496,7 @@
 {
     int status;
     struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1];
-    tpSirLLStatsSetReq pLinkLayerStatsSetReq;
+    tSirLLStatsSetReq linkLayerStatsSetReq;
     struct net_device *dev = wdev->netdev;
     hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
     hdd_context_t *pHddCtx = wiphy_priv(wiphy);
@@ -1515,6 +1515,14 @@
                FL("HDD adapter is Null"));
         return -ENODEV;
     }
+    /* check the LLStats Capability */
+    if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
+         (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
+    {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("Link Layer Statistics not supported by Firmware"));
+        return -EINVAL;
+    }
 
     if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX,
            (struct nlattr *)data,
@@ -1535,21 +1543,14 @@
         hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Stats Gathering Not Present"));
         return -EINVAL;
     }
-    pLinkLayerStatsSetReq = vos_mem_malloc(sizeof(tSirLLStatsSetReq));
-    if (NULL == pLinkLayerStatsSetReq)
-    {
-        hddLog(VOS_TRACE_LEVEL_ERROR,
-               FL(" Unable to allocate memory to pLinkLayerStatsSetReq") );
-        return -ENOMEM;
-    }
     // Shall take the request Id if the Upper layers pass. 1 For now.
-    pLinkLayerStatsSetReq->reqId = 1;
+    linkLayerStatsSetReq.reqId = 1;
 
-    pLinkLayerStatsSetReq->mpduSizeThreshold =
+    linkLayerStatsSetReq.mpduSizeThreshold =
         nla_get_u32(
             tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]);
 
-    pLinkLayerStatsSetReq->aggressiveStatisticsGathering =
+    linkLayerStatsSetReq.aggressiveStatisticsGathering =
         nla_get_u32(
             tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]);
 
@@ -1557,20 +1558,20 @@
      * Hence the interface staId start from 1. Hence the staId matching the
      * interface in the firmware is sessionId + 1.
      */
-    pLinkLayerStatsSetReq->staId = pAdapter->sessionId + 1;
+    linkLayerStatsSetReq.staId = pAdapter->sessionId + 1;
 
 
     hddLog(VOS_TRACE_LEVEL_INFO,
            "LL_STATS_SET reqId = %d",
-           pLinkLayerStatsSetReq->reqId);
+           linkLayerStatsSetReq.reqId);
     hddLog(VOS_TRACE_LEVEL_INFO,
-            "LL_STATS_SET staId = %d", pLinkLayerStatsSetReq->staId);
+            "LL_STATS_SET staId = %d", linkLayerStatsSetReq.staId);
     hddLog(VOS_TRACE_LEVEL_INFO,
             "LL_STATS_SET mpduSizeThreshold = %d",
-            pLinkLayerStatsSetReq->mpduSizeThreshold);
+            linkLayerStatsSetReq.mpduSizeThreshold);
     hddLog(VOS_TRACE_LEVEL_INFO,
             "LL_STATS_SET aggressive Statistics Gathering  = %d",
-            pLinkLayerStatsSetReq->aggressiveStatisticsGathering);
+            linkLayerStatsSetReq.aggressiveStatisticsGathering);
 
     if (eHAL_STATUS_SUCCESS != sme_SetLinkLayerStatsIndCB(
                                pHddCtx->hHal,
@@ -1580,16 +1581,14 @@
     {
         hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
            "sme_SetLinkLayerStatsIndCB Failed", __func__);
-        vos_mem_free(pLinkLayerStatsSetReq);
         return -EINVAL;
 
     }
     if (eHAL_STATUS_SUCCESS != sme_LLStatsSetReq( pHddCtx->hHal,
-                                            pLinkLayerStatsSetReq))
+                                            &linkLayerStatsSetReq))
     {
         hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
            "sme_LLStatsSetReq Failed", __func__);
-        vos_mem_free(pLinkLayerStatsSetReq);
         return -EINVAL;
     }
 
@@ -1622,7 +1621,7 @@
 {
     hdd_context_t *pHddCtx = wiphy_priv(wiphy);
     struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1];
-    tpSirLLStatsGetReq pLinkLayerStatsGetReq;
+    tSirLLStatsGetReq linkLayerStatsGetReq;
     struct net_device *dev = wdev->netdev;
     hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
     int status;
@@ -1641,6 +1640,15 @@
                "%s: HDD adapter is Null", __func__);
         return -ENODEV;
     }
+    /* check the LLStats Capability */
+    if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
+         (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
+    {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("Link Layer Statistics not supported by Firmware"));
+        return -EINVAL;
+    }
+
 
     if (!pAdapter->isLinkLayerStatsSet)
     {
@@ -1672,19 +1680,11 @@
        return -EINVAL;
     }
 
-    pLinkLayerStatsGetReq = vos_mem_malloc(sizeof(tSirLLStatsGetReq));
 
-    if (NULL == pLinkLayerStatsGetReq)
-    {
-        hddLog(VOS_TRACE_LEVEL_ERROR,
-               FL("Unable to allocate memory to pLinkLayerStatsGetReq"));
-        return -ENOMEM;
-    }
-
-    pLinkLayerStatsGetReq->reqId =
+    linkLayerStatsGetReq.reqId =
         nla_get_u32( tb_vendor[
             QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]);
-    pLinkLayerStatsGetReq->paramIdMask =
+    linkLayerStatsGetReq.paramIdMask =
         nla_get_u32( tb_vendor[
             QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]);
 
@@ -1692,22 +1692,21 @@
      * Hence the interface staId start from 1. Hence the staId matching the
      * interface in the firmware is sessionId + 1.
      */
-    pLinkLayerStatsGetReq->staId = pAdapter->sessionId + 1;
+    linkLayerStatsGetReq.staId = pAdapter->sessionId + 1;
 
     hddLog(VOS_TRACE_LEVEL_INFO,
-           "LL_STATS_GET reqId = %d", pLinkLayerStatsGetReq->reqId);
+           "LL_STATS_GET reqId = %d", linkLayerStatsGetReq.reqId);
     hddLog(VOS_TRACE_LEVEL_INFO,
-           "LL_STATS_GET staId = %d", pLinkLayerStatsGetReq->staId);
+           "LL_STATS_GET staId = %d", linkLayerStatsGetReq.staId);
     hddLog(VOS_TRACE_LEVEL_INFO,
            "LL_STATS_GET paramIdMask = %d",
-           pLinkLayerStatsGetReq->paramIdMask);
+           linkLayerStatsGetReq.paramIdMask);
 
     if (eHAL_STATUS_SUCCESS  != sme_LLStatsGetReq( pHddCtx->hHal,
-                                                pLinkLayerStatsGetReq))
+                                                &linkLayerStatsGetReq))
     {
         hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
                "sme_LLStatsGetReq Failed", __func__);
-        vos_mem_free(pLinkLayerStatsGetReq);
         return -EINVAL;
     }
     return 0;
@@ -1730,7 +1729,7 @@
 {
     hdd_context_t *pHddCtx = wiphy_priv(wiphy);
     struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
-    tpSirLLStatsClearReq pLinkLayerStatsClearReq;
+    tSirLLStatsClearReq linkLayerStatsClearReq;
     struct net_device *dev = wdev->netdev;
     hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
     u32 statsClearReqMask;
@@ -1751,6 +1750,14 @@
                    "%s: HDD adapter is Null", __func__);
         return -ENODEV;
     }
+    /* check the LLStats Capability */
+    if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
+         (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
+    {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("Enable LLStats Capability"));
+        return -EINVAL;
+    }
 
     if (!pAdapter->isLinkLayerStatsSet)
     {
@@ -1777,44 +1784,37 @@
 
     }
 
-    pLinkLayerStatsClearReq = vos_mem_malloc(sizeof(tSirLLStatsClearReq));
-    if (NULL == pLinkLayerStatsClearReq)
-    {
-        hddLog(VOS_TRACE_LEVEL_ERROR,
-               FL("Unable to allocate memory to pLinkLayerStatsClearReq"));
-        return -ENOMEM;
-    }
 
-    statsClearReqMask = pLinkLayerStatsClearReq->statsClearReqMask =
+    statsClearReqMask = linkLayerStatsClearReq.statsClearReqMask =
         nla_get_u32(
             tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK]);
 
-    stopReq = pLinkLayerStatsClearReq->stopReq =
+    stopReq = linkLayerStatsClearReq.stopReq =
         nla_get_u8(
             tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]);
 
     // Shall take the request Id if the Upper layers pass. 1 For now.
-    pLinkLayerStatsClearReq->reqId = 1;
+    linkLayerStatsClearReq.reqId = 1;
 
     /* staId 0 in Firmware is reserved for Broadcast/Multicast data.
      * Hence the interface staId start from 1. Hence the staId matching the
      * interface in the firmware is sessionId + 1.
      */
-    pLinkLayerStatsClearReq->staId = pAdapter->sessionId + 1;
+    linkLayerStatsClearReq.staId = pAdapter->sessionId + 1;
 
     hddLog(VOS_TRACE_LEVEL_INFO,
-            "LL_STATS_CLEAR reqId = %d", pLinkLayerStatsClearReq->reqId);
+            "LL_STATS_CLEAR reqId = %d", linkLayerStatsClearReq.reqId);
     hddLog(VOS_TRACE_LEVEL_INFO,
-            "LL_STATS_CLEAR staId = %d", pLinkLayerStatsClearReq->staId);
+            "LL_STATS_CLEAR staId = %d", linkLayerStatsClearReq.staId);
     hddLog(VOS_TRACE_LEVEL_INFO,
             "LL_STATS_CLEAR statsClearReqMask = 0x%X",
-            pLinkLayerStatsClearReq->statsClearReqMask);
+            linkLayerStatsClearReq.statsClearReqMask);
     hddLog(VOS_TRACE_LEVEL_INFO,
             "LL_STATS_CLEAR stopReq  = %d",
-            pLinkLayerStatsClearReq->stopReq);
+            linkLayerStatsClearReq.stopReq);
 
     if (eHAL_STATUS_SUCCESS == sme_LLStatsClearReq(pHddCtx->hHal,
-                                                     pLinkLayerStatsClearReq))
+                                                     &linkLayerStatsClearReq))
     {
         struct sk_buff *temp_skbuff;
         temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
@@ -1839,16 +1839,15 @@
              * (stopReq = 1) , ensure that no further requests of get
              * go to the firmware by having isLinkLayerStatsSet set to 0.
              * However it the stopReq as part of the clear request is 0 ,
-             * the request to get the statistics are ehonoured as in this
+             * the request to get the statistics are honoured as in this
              * case the firmware is just asked to clear the statistics.
              */
-            if (pLinkLayerStatsClearReq->stopReq == 1)
+            if (linkLayerStatsClearReq.stopReq == 1)
                 pAdapter->isLinkLayerStatsSet = 0;
             return cfg80211_vendor_cmd_reply(temp_skbuff);
         }
         return -ENOMEM;
     }
-    vos_mem_free(pLinkLayerStatsClearReq);
     return -EINVAL;
 }
 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 0f925a1..cc61609 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -105,6 +105,9 @@
 #ifdef FEATURE_WLAN_TDLS
    TDLS_SCAN_COEXISTENCE  = 39,
 #endif
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+   LINK_LAYER_STATS_MEAS  = 40,
+#endif
 
    //MAX_FEATURE_SUPPORTED = 128
 } placeHolderInCapBitmap;
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 5a46741..bfbdc5a 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -10621,20 +10621,26 @@
     tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
     vos_msg_t msg;
     eHalStatus status = eHAL_STATUS_FAILURE;
+    tSirLLStatsSetReq *plinkLayerSetReq;
 
-    VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
-      "%s:  pLinkLayerStatsSetReq.mpdu_size = %u", __func__,
-        pLinkLayerStatsSetReq->mpduSizeThreshold);
+    plinkLayerSetReq = vos_mem_malloc(sizeof(*plinkLayerSetReq));
+    if ( !plinkLayerSetReq)
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                "%s: Not able to allocate memory for "
+                "WDA_LINK_LAYER_STATS_SET_REQ",
+                __func__);
+        return eHAL_STATUS_FAILURE;
+    }
 
-    VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
-      " pLinkLayerStatsSetReq->mpdu_size = %u",
-      pLinkLayerStatsSetReq->mpduSizeThreshold);
+    *plinkLayerSetReq = *pLinkLayerStatsSetReq;
+
 
     if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme )))
     {
         msg.type = WDA_LINK_LAYER_STATS_SET_REQ;
         msg.reserved = 0;
-        msg.bodyptr = pLinkLayerStatsSetReq;
+        msg.bodyptr = plinkLayerSetReq;
 
         if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
         {
@@ -10669,13 +10675,24 @@
     tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
     vos_msg_t msg;
     eHalStatus status = eHAL_STATUS_FAILURE;
+    tSirLLStatsGetReq *pGetStatsReq;
 
+    pGetStatsReq = vos_mem_malloc(sizeof(*pGetStatsReq));
+    if ( !pGetStatsReq)
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                "%s: Not able to allocate memory for "
+                "WDA_LINK_LAYER_STATS_GET_REQ",
+                __func__);
+        return eHAL_STATUS_FAILURE;
+    }
+    *pGetStatsReq = *pLinkLayerStatsGetReq;
 
     if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme )))
     {
         msg.type = WDA_LINK_LAYER_STATS_GET_REQ;
         msg.reserved = 0;
-        msg.bodyptr = pLinkLayerStatsGetReq;
+        msg.bodyptr = pGetStatsReq;
         if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
         {
             VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
@@ -10709,6 +10726,7 @@
     tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
     vos_msg_t msg;
     eHalStatus status = eHAL_STATUS_FAILURE;
+    tSirLLStatsClearReq *pClearStatsReq;
 
 
     VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
@@ -10721,11 +10739,23 @@
     VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
               "stopReq = %u", pLinkLayerStatsClear->stopReq);
 
+    pClearStatsReq = vos_mem_malloc(sizeof(*pClearStatsReq));
+    if ( !pClearStatsReq)
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                "%s: Not able to allocate memory for "
+                "WDA_LINK_LAYER_STATS_CLEAR_REQ",
+                __func__);
+        return eHAL_STATUS_FAILURE;
+    }
+
+    *pClearStatsReq = *pLinkLayerStatsClear;
+
     if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme )))
     {
         msg.type = WDA_LINK_LAYER_STATS_CLEAR_REQ;
         msg.reserved = 0;
-        msg.bodyptr = pLinkLayerStatsClear;
+        msg.bodyptr = pClearStatsReq;
 
         if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
         {
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index a3327fc..ce2733b 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -175,6 +175,11 @@
 #else
     ,FEATURE_NOT_SUPPORTED          //39
 #endif
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+    ,LINK_LAYER_STATS_MEAS          //40
+#else
+    ,FEATURE_NOT_SUPPORTED          //40
+#endif
 
 };
 
@@ -1342,6 +1347,11 @@
                      case CH_SWITCH_V1: snprintf(pCapStr, sizeof("CH_SWITCH_V1"), "%s", "CH_SWITCH_V1");
                           pCapStr += strlen("CH_SWITCH_V1");
                           break;
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+                     case LINK_LAYER_STATS_MEAS: snprintf(pCapStr, sizeof("LINK_LAYER_STATS_MEAS"), "%s", "LINK_LAYER_STATS_MEAS");
+                          pCapStr += strlen("LINK_LAYER_STATS_MEAS");
+                          break;
+#endif
 
                  }
                  *pCapStr++ = ',';