clear the interface stats in host for set and clear commands

Host collects the following stats to provide them to the
llstats get request.
1. mgmtRx
2. rssiData
3. rxMcast
4. rxMpdu
5. rxAmpdu
6. txMcast

Clear the same when host receives corresponding clear request.

Firmware collects txMpdu stats, host need not to collect the same.

Change-Id: Iffd06d45622b386c79da5734c97c8a600468a6bb
CRs-Fixed: 751709
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index a3bdfd8..61f999f 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -866,44 +866,40 @@
 
             pWifiIfaceStat->mgmtRx = pWifiIfaceStat->beaconRx +
                 pWifiIfaceStatTL->mgmtRx;
-            pWifiIfaceStat->mgmtActionRx = pWifiIfaceStatTL->mgmtActionRx;
-            pWifiIfaceStat->mgmtActionTx = pWifiIfaceStatTL->mgmtActionTx;
             pWifiIfaceStat->rssiData = pWifiIfaceStatTL->rssiData;
 
-            vos_mem_copy(
-                  (void *) &pWifiIfaceStat->AccessclassStats[WIFI_AC_VO],
-                  (void *) &pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VO],
-                  sizeof(WLANTL_AccessCategoryStatsType));
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].rxMcast
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VO].rxMcast;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].rxMcast
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VI].rxMcast;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].rxMcast
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BE].rxMcast;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].rxMcast
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BK].rxMcast;
 
-            vos_mem_copy(
-                  (void *) &pWifiIfaceStat->AccessclassStats[WIFI_AC_VI],
-                  (void *) &pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VI],
-                  sizeof(WLANTL_AccessCategoryStatsType));
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].rxMpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VO].rxMpdu;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].rxMpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VI].rxMpdu;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].rxMpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BE].rxMpdu;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].rxMpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BK].rxMpdu;
 
-            vos_mem_copy(
-                  (void *) &pWifiIfaceStat->AccessclassStats[WIFI_AC_BE],
-                  (void *) &pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BE],
-                  sizeof(WLANTL_AccessCategoryStatsType));
-
-            vos_mem_copy(
-                  (void *) &pWifiIfaceStat->AccessclassStats[WIFI_AC_BK],
-                  (void *) &pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BK],
-                  sizeof(WLANTL_AccessCategoryStatsType));
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].rxAmpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VO].rxAmpdu;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].rxAmpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VI].rxAmpdu;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].rxAmpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BE].rxAmpdu;
+            pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].rxAmpdu
+                = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BK].rxAmpdu;
         }
         else
         {
             hddLog(VOS_TRACE_LEVEL_ERROR, FL("Error in getting stats from TL"));
         }
 
-        pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].txMpdu =
-            pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[WLANTL_AC_VO];
-        pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].txMpdu =
-            pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[WLANTL_AC_VI];
-        pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].txMpdu =
-            pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[WLANTL_AC_BE];
-        pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].txMpdu =
-            pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[WLANTL_AC_BK];
-
         pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].txMcast =
             pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VO];
         pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].txMcast =
@@ -1631,6 +1627,7 @@
     struct net_device *dev = wdev->netdev;
     hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
     hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+    hdd_station_ctx_t *pHddStaCtx;
 
     status = wlan_hdd_validate_context(pHddCtx);
     if (0 != status)
@@ -1709,6 +1706,22 @@
         return -EINVAL;
 
     }
+
+    pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+    if (VOS_STATUS_SUCCESS !=
+        WLANTL_ClearInterfaceStats((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+        pHddStaCtx->conn_info.staId[0], WIFI_STATS_IFACE))
+    {
+        hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
+                "WLANTL_ClearInterfaceStats Failed", __func__);
+        return -EINVAL;
+    }
+
+    pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VO] = 0;
+    pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VI] = 0;
+    pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BE] = 0;
+    pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BK] = 0;
+
     if (eHAL_STATUS_SUCCESS != sme_LLStatsSetReq( pHddCtx->hHal,
                                             &linkLayerStatsSetReq))
     {
@@ -1936,6 +1949,25 @@
                                                      &linkLayerStatsClearReq))
     {
         struct sk_buff *temp_skbuff;
+        hdd_station_ctx_t *pHddStaCtx;
+
+        pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+        if (VOS_STATUS_SUCCESS !=
+           WLANTL_ClearInterfaceStats((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+           pHddStaCtx->conn_info.staId[0], statsClearReqMask))
+        {
+            hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
+                    "WLANTL_ClearInterfaceStats Failed", __func__);
+            return -EINVAL;
+        }
+        if ((statsClearReqMask & WIFI_STATS_IFACE_AC) ||
+                (statsClearReqMask & WIFI_STATS_IFACE)) {
+            pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VO] = 0;
+            pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VI] = 0;
+            pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BE] = 0;
+            pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BK] = 0;
+        }
+
         temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
                                 2 * sizeof(u32) +
                             NLMSG_HDRLEN);
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index 8d26fe0..e7005ba 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -1223,6 +1223,39 @@
   v_U8_t          ucSTAId,
   WLANTL_InterfaceStatsType  *vosDataBuff
 );
+
+/*==========================================================================
+
+  FUNCTION    WLANTL_ClearInterfaceStats
+
+  DESCRIPTION
+    Utility function used by TL to clear the statitics
+
+  DEPENDENCIES
+
+
+  PARAMETERS
+
+    IN
+
+    ucSTAId:    station for which the statistics need to collected
+
+  RETURN VALUE
+    The result code associated with performing the operation
+
+    VOS_STATUS_E_INVAL:   Input parameters are invalid
+    VOS_STATUS_SUCCESS:   Everything is good :)
+
+  SIDE EFFECTS
+
+============================================================================*/
+VOS_STATUS
+WLANTL_ClearInterfaceStats
+(
+  v_PVOID_t       pvosGCtx,
+  v_U8_t          ucSTAId,
+  v_U8_t          statsClearReqMask
+);
 #endif
 
 /*===========================================================================
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index 2f8a09a..a8530aa 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -6191,11 +6191,108 @@
           "WLAN TL:Client Memory was not allocated on %s", __func__));
       return VOS_STATUS_E_FAILURE;
   }
+  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+              "WLAN TL: collect WIFI_STATS_IFACE results"));
+
   vos_mem_copy(vosDataBuff, &pTLCb->atlSTAClients[ucSTAId]->interfaceStats,
           sizeof(WLANTL_InterfaceStatsType));
   return VOS_STATUS_SUCCESS;
 }
 
+/*==========================================================================
+
+  FUNCTION    WLANTL_ClearInterfaceStats
+
+  DESCRIPTION
+    Utility function used by TL to clear the statitics
+
+  DEPENDENCIES
+
+
+  PARAMETERS
+
+    IN
+
+    ucSTAId:    station for which the statistics need to collected
+
+  RETURN VALUE
+    The result code associated with performing the operation
+
+    VOS_STATUS_E_INVAL:   Input parameters are invalid
+    VOS_STATUS_SUCCESS:   Everything is good :)
+
+  SIDE EFFECTS
+
+============================================================================*/
+VOS_STATUS
+WLANTL_ClearInterfaceStats
+(
+  v_PVOID_t       pvosGCtx,
+  v_U8_t          ucSTAId,
+  v_U8_t          statsClearReqMask
+)
+{
+    WLANTL_CbType*  pTLCb = NULL;
+    WLANTL_STAClientType* pClientSTA = NULL;
+    /*------------------------------------------------------------------------
+      Sanity check
+      ------------------------------------------------------------------------*/
+    if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
+    {
+        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+               "WLAN TL:Invalid station id requested on WLANTL_CollectStats"));
+        return VOS_STATUS_E_FAULT;
+    }
+    /*------------------------------------------------------------------------
+      Extract TL control block
+      ------------------------------------------------------------------------*/
+    pTLCb = VOS_GET_TL_CB(pvosGCtx);
+    if ( NULL == pTLCb )
+    {
+        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+            "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_CollectStats"));
+        return VOS_STATUS_E_FAULT;
+    }
+
+    pClientSTA = pTLCb->atlSTAClients[ucSTAId];
+    if ( NULL == pClientSTA )
+    {
+        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+                    "WLAN TL:Client Memory was not allocated on %s", __func__));
+        return VOS_STATUS_E_FAILURE;
+    }
+
+    if ((statsClearReqMask & WIFI_STATS_IFACE_AC) ||
+            (statsClearReqMask & WIFI_STATS_IFACE)) {
+        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+                    "WLAN TL:cleared WIFI_STATS_IFACE_AC results"));
+        pClientSTA->interfaceStats.accessCategoryStats[0].rxMcast = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[1].rxMcast = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[2].rxMcast = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[3].rxMcast = 0;
+
+        pClientSTA->interfaceStats.accessCategoryStats[0].rxMpdu = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[1].rxMpdu = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[2].rxMpdu = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[3].rxMpdu = 0;
+
+        pClientSTA->interfaceStats.accessCategoryStats[0].rxAmpdu = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[1].rxAmpdu = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[2].rxAmpdu = 0;
+        pClientSTA->interfaceStats.accessCategoryStats[3].rxAmpdu = 0;
+    }
+
+    if (statsClearReqMask & WIFI_STATS_IFACE) {
+        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+                    "WLAN TL:cleared WIFI_STATS_IFACE results"));
+        pClientSTA->interfaceStats.mgmtRx = 0;
+        pClientSTA->interfaceStats.rssiData = 0;
+        return VOS_STATUS_SUCCESS;
+    }
+
+    return VOS_STATUS_SUCCESS;
+}
+
 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
 
 /*==========================================================================