wlan: MCC Adaptive Scheduler

MCC Adaptive Scheduler. By default this feature is disabled and can be
enabled using gEnableMCCAdaptiveScheduler=1 in INI file.

CR-Fixed: 434878
Change-Id: I9e5c41f2f2bf8318b4a4ce2bbd11fb1a04e69837
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index f21a3f5..d7bac61 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1496,7 +1496,16 @@
 #define CFG_TX_LDPC_ENABLE_FEATURE_MIN     ( 0 )
 #define CFG_TX_LDPC_ENABLE_FEATURE_MAX     ( 3 )
 #define CFG_TX_LDPC_ENABLE_FEATURE_DEFAULT ( 0 )
- 
+
+/*
+ * Enable / Disable MCC Adaptive Scheduler feature
+ * Default: Enable
+ */
+#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_NAME             "gEnableMCCAdaptiveScheduler"      
+#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MIN              ( 0 )
+#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MAX              ( 1 )
+#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_DEFAULT          ( 0 ) 
+
 /*--------------------------------------------------------------------------- 
   Type declarations
   -------------------------------------------------------------------------*/ 
@@ -1823,6 +1832,7 @@
 #endif
    v_U8_t                      scanAgingTimeout;
    v_BOOL_t                    enableTxLdpc;
+   v_U8_t                      enableMCCAdaptiveScheduler;
 } hdd_config_t;
 /*--------------------------------------------------------------------------- 
   Function declarations and documenation
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index e908d23..e69e282 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -1831,6 +1831,12 @@
               CFG_TX_LDPC_ENABLE_FEATURE_MIN,
               CFG_TX_LDPC_ENABLE_FEATURE_MAX ),
 
+REG_VARIABLE( CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_NAME, WLAN_PARAM_Integer,
+             hdd_config_t, enableMCCAdaptiveScheduler, 
+             VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, 
+             CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_DEFAULT, 
+             CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MIN, 
+             CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MAX ),             
 };
 
 /*
@@ -3270,6 +3276,12 @@
       hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_LPWR_IMG_TRANSITION to CCM\n");
    }
 
+   if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, pConfig->enableMCCAdaptiveScheduler,
+      NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+   {
+      fStatus = FALSE;
+      hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED to CCM\n");
+   }
    return fStatus;
 }
 
diff --git a/CORE/MAC/inc/wniCfgAp.h b/CORE/MAC/inc/wniCfgAp.h
index 1149233..cb062a4 100644
--- a/CORE/MAC/inc/wniCfgAp.h
+++ b/CORE/MAC/inc/wniCfgAp.h
@@ -356,6 +356,7 @@
 #define WNI_CFG_ENABLE_MC_ADDR_LIST    291
 #define WNI_CFG_ENABLE_UC_FILTER    292
 #define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION    293
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED    294
 
 /*
  * String parameter lengths 
@@ -2450,10 +2451,18 @@
 #define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_APMAX    1
 #define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_APDEF    0
 
-#define CFG_PARAM_MAX_NUM         294
-#define CFG_AP_IBUF_MAX_SIZE      233
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMIN    0
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX    1
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STADEF    0
+
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_APMIN    0
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_APMAX    1
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_APDEF    0
+
+#define CFG_PARAM_MAX_NUM         295
+#define CFG_AP_IBUF_MAX_SIZE      234
 #define CFG_AP_SBUF_MAX_SIZE      3422
-#define CFG_STA_IBUF_MAX_SIZE     228
+#define CFG_STA_IBUF_MAX_SIZE     229
 #define CFG_STA_SBUF_MAX_SIZE     3388
 #define CFG_SEM_MAX_NUM           19
 
diff --git a/CORE/MAC/inc/wniCfgSta.h b/CORE/MAC/inc/wniCfgSta.h
index 70de087..862ddfa 100644
--- a/CORE/MAC/inc/wniCfgSta.h
+++ b/CORE/MAC/inc/wniCfgSta.h
@@ -350,6 +350,7 @@
 #define WNI_CFG_ENABLE_MC_ADDR_LIST    291
 #define WNI_CFG_ENABLE_UC_FILTER    292
 #define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION    293
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED    294
 
 /*
  * String parameter lengths 
@@ -1595,8 +1596,12 @@
 #define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMAX    1
 #define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STADEF    0
 
-#define CFG_PARAM_MAX_NUM        294
-#define CFG_STA_IBUF_MAX_SIZE    228
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMIN    0
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX    1
+#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STADEF    0
+
+#define CFG_PARAM_MAX_NUM        295
+#define CFG_STA_IBUF_MAX_SIZE    229
 #define CFG_STA_SBUF_MAX_SIZE    3388
 #define CFG_SEM_MAX_NUM          19
 
diff --git a/CORE/MAC/src/cfg/cfgParamName.c b/CORE/MAC/src/cfg/cfgParamName.c
index b868caf..ee2ad08 100644
--- a/CORE/MAC/src/cfg/cfgParamName.c
+++ b/CORE/MAC/src/cfg/cfgParamName.c
@@ -347,6 +347,7 @@
     (unsigned char *)"ENABLE_MC_ADDR_LIST",
     (unsigned char *)"ENABLE_UC_FILTER",
     (unsigned char *)"ENABLE_LPWR_IMG_TRANSITION",
+    (unsigned char *)"ENABLE_MCC_ADAPTIVE_SCHED",
 };
 
 
diff --git a/CORE/MAC/src/cfg/cfgUtil/cfg.txt b/CORE/MAC/src/cfg/cfgUtil/cfg.txt
index 7fd1016..5207f5c 100644
--- a/CORE/MAC/src/cfg/cfgUtil/cfg.txt
+++ b/CORE/MAC/src/cfg/cfgUtil/cfg.txt
@@ -4435,4 +4435,16 @@
 0    1     0
 V    RW    NP
 NONE
+
+*
+* MCC Adaptive Scheduler will be enabled if value is set to 1
+* 
+*
+*
+WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED  I   4   0
+V    RW    NP
+NONE
+0    1     0
+V    RW    NP
+NONE
 0    1     0
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index d3d690b..0cea47c 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -573,6 +573,8 @@
 #define SIR_HAL_TDLS_LINK_TEARDOWN         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 190)
 #endif
 
+#define SIR_HAL_TRAFFIC_STATS_IND          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 195)
+
 #define SIR_HAL_MSG_TYPES_END              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 0xFF)
 // CFG message types
 #define SIR_CFG_MSG_TYPES_BEGIN        (SIR_CFG_MODULE_ID << 8)
diff --git a/CORE/MAC/src/pe/lim/limLogDump.c b/CORE/MAC/src/pe/lim/limLogDump.c
index b1caa1f..c79e96a 100644
--- a/CORE/MAC/src/pe/lim/limLogDump.c
+++ b/CORE/MAC/src/pe/lim/limLogDump.c
@@ -70,6 +70,9 @@
 #include <limFT.h>
 #endif
 #include "smeInside.h"
+#include "wlan_qct_wda.h"
+
+void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA);
 
 static char *getRole( tLimSystemRole role )
 {
@@ -2466,6 +2469,65 @@
 
   return p;
 }
+
+
+static char *
+dump_lim_mcc_policy_maker(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+   VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_FATAL, "dump_lim_mcc_policy_maker arg = %d",arg1);
+    
+   if(arg1 == 0) //Disable feature completely
+   {  
+      WDA_TrafficStatsTimerActivate(FALSE);
+      if (ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, FALSE,
+          NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+      {
+         limLog( pMac, LOGE, FL("Could not get WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED"));
+      }
+   }
+   else if(arg1 == 1) //Enable feature
+   {   
+      if (ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE,
+         NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+      {
+        limLog( pMac, LOGE, FL("Could not set WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED"));
+      }    
+   }
+   else if(arg1 == 2) //Enable feature and activate periodic timer
+   {   
+      if (ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE,
+          NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
+      {
+         limLog( pMac, LOGE, FL("Could not set WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED"));
+      }
+      WDA_TrafficStatsTimerActivate(TRUE);
+   }
+   else if(arg1 == 3) //Enable only stats collection - Used for unit testing
+   {
+      VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_FATAL, "Enabling Traffic Stats in DTS");
+      WDI_DS_ActivateTrafficStats();
+   }
+   else if(arg1 == 4) //Send current stats snapshot to Riva -- Used for unit testing
+   {
+      v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
+      tWDA_CbContext *pWDA =  vos_get_context(VOS_MODULE_ID_WDA, pVosContext);
+      ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE, NULL, eANI_BOOLEAN_FALSE);
+      WDA_TimerTrafficStatsInd(pWDA);
+      WDA_TrafficStatsTimerActivate(FALSE);
+      ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, FALSE,NULL, eANI_BOOLEAN_FALSE);
+   }
+   else if (arg1 == 5) //Change the periodicity of TX stats timer
+   {
+      v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
+      tWDA_CbContext *pWDA =  vos_get_context(VOS_MODULE_ID_WDA, pVosContext);
+      if (tx_timer_change(&pWDA->wdaTimers.trafficStatsTimer, arg2, arg2) != TX_SUCCESS)
+      {
+          limLog(pMac, LOGP, FL("Disable timer before changing timeout value"));
+      }
+   }
+   return p;
+}
+
 static tDumpFuncEntry limMenuDumpTable[] = {
     {0,     "PE (300-499)",                                          NULL},
     {300,   "LIM: Dump state(s)/statistics <session id>",            dump_lim_info},
@@ -2535,6 +2597,7 @@
 #ifdef WLAN_FEATURE_11AC
     {366,   "PE.LIM: Send a VHT OPMode Action Frame",                dump_lim_vht_opmode_notification},
     {367,   "PE.LIM: Send a VHT Channel Switch Announcement",        dump_lim_vht_channel_switch_notification},
+    {368,   "PE.LIM: MCC Policy Maker",                              dump_lim_mcc_policy_maker},
 #endif
 };
 
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
index df36d03..23787f1 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
@@ -309,6 +309,8 @@
    pMac->lim.gpLimSuspendCallback = callback;
    pMac->lim.gpLimSuspendData = data;
    limSendHalInitScanReq(pMac, eLIM_HAL_SUSPEND_LINK_WAIT_STATE, trafficCheck );
+
+   WDA_TrafficStatsTimerActivate(FALSE);
 }
 
 /**
@@ -349,6 +351,11 @@
    pMac->lim.gpLimResumeCallback = callback;
    pMac->lim.gpLimResumeData = data;
    limSendHalFinishScanReq(pMac, eLIM_HAL_RESUME_LINK_WAIT_STATE );
+
+   if(limIsInMCC(pMac))
+   {
+      WDA_TrafficStatsTimerActivate(TRUE);
+   }
 }
 //end WLAN_SUSPEND_LINK Related
 
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
index d196390..3077079 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
@@ -2085,6 +2085,11 @@
 #if defined(ANI_PRODUCT_TYPE_CLIENT) || defined(ANI_AP_CLIENT_SDK)
     limProcessStaMlmDelBssRsp(pMac, limMsgQ,psessionEntry);
 #endif
+
+   if(!limIsInMCC(pMac))
+   {
+      WDA_TrafficStatsTimerActivate(FALSE);
+   }
 }
 
 void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry)
@@ -3330,6 +3335,11 @@
             /* Called while processing assoc response */
             limProcessStaMlmAddBssRsp( pMac, limMsgQ,psessionEntry);
     }
+
+    if(limIsInMCC(pMac))
+    {
+       WDA_TrafficStatsTimerActivate(TRUE);
+    }
 }
 /**
  * limProcessMlmSetKeyRsp()
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 109f66f..f113fae 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -379,6 +379,9 @@
 
    /* Tx Complete Timeout timer */
    TX_TIMER TxCompleteTimer ;
+
+   /* Traffic Stats timer */
+   TX_TIMER trafficStatsTimer ;
 }tWdaTimers ;
 #ifdef WLAN_SOFTAP_VSTA_FEATURE
 #define WDA_MAX_STA    (38)
@@ -1160,6 +1163,8 @@
 #define WDA_TIMER_CHIP_MONITOR_TIMEOUT SIR_HAL_TIMER_CHIP_MONITOR_TIMEOUT
 #define WDA_TIMER_TRAFFIC_ACTIVITY_REQ SIR_HAL_TIMER_TRAFFIC_ACTIVITY_REQ
 #define WDA_TIMER_ADC_RSSI_STATS       SIR_HAL_TIMER_ADC_RSSI_STATS
+#define WDA_TIMER_TRAFFIC_STATS_IND    SIR_HAL_TRAFFIC_STATS_IND
+
 
 #ifdef FEATURE_WLAN_CCX
 #define WDA_TSM_STATS_REQ              SIR_HAL_TSM_STATS_REQ
@@ -2097,4 +2102,19 @@
    v_BOOL_t   displaySnapshot,
    v_BOOL_t   toggleStallDetect
 );
+
+/*==========================================================================
+  FUNCTION   WDA_TrafficStatsTimerActivate
+
+  DESCRIPTION
+    API to activate/deactivate Traffic Stats timer. Traffic stats timer is only needed during MCC
+  PARAMETERS
+    activate : Activate or not
+
+  RETURN VALUE
+    NONE
+
+===========================================================================*/
+void WDA_TrafficStatsTimerActivate(wpt_boolean activate);
+
 #endif
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 77c8cd4..2ba7d23 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -133,6 +133,7 @@
 #define WDA_INVALID_KEY_INDEX  0xFF
 #define WDA_NUM_PWR_SAVE_CFG       11
 #define WDA_TX_COMPLETE_TIME_OUT_VALUE 1000
+#define WDA_TRAFFIC_STATS_TIME_OUT_VALUE 1000
   
 #define WDA_MAX_RETRIES_TILL_RING_EMPTY  1000   /* MAX 10000 msec = 10 seconds wait */
 
@@ -168,6 +169,7 @@
 static VOS_STATUS wdaCreateTimers(tWDA_CbContext *pWDA) ;
 static VOS_STATUS wdaDestroyTimers(tWDA_CbContext *pWDA);
 void WDA_BaCheckActivity(tWDA_CbContext *pWDA) ;
+void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA);
 void WDA_HALDumpCmdCallback(WDI_HALDumpCmdRspParamsType *wdiRspParams, void* pUserData);
 #ifdef WLAN_FEATURE_VOWIFI_11R
 VOS_STATUS WDA_ProcessAggrAddTSReq(tWDA_CbContext *pWDA, tAggrAddTsParams *pAggrAddTsReqParams);
@@ -1441,6 +1443,22 @@
                             + sizeof(tHalCfg) + tlvStruct->length) ;
 #endif
 
+   /* QWLAN_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER */
+   tlvStruct->type = QWLAN_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER;
+   tlvStruct->length = sizeof(tANI_U32);
+   configDataValue = (tANI_U32 *)(tlvStruct + 1);
+
+   if(wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, configDataValue) 
+                                                      != eSIR_SUCCESS)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                    "Failed to get value for WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED");
+      goto handle_failure;
+   }
+
+   tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct 
+                            + sizeof(tHalCfg) + tlvStruct->length) ;
+
    wdiStartParams->usConfigBufferLen = (tANI_U8 *)tlvStruct - tlvStructStart ;
 #ifdef WLAN_DEBUG
    {
@@ -9909,6 +9927,13 @@
          WDA_BaCheckActivity(pWDA) ;
          break ;
       }
+
+      /* timer related messages */
+      case WDA_TIMER_TRAFFIC_STATS_IND:
+      {
+         WDA_TimerTrafficStatsInd(pWDA);
+         break;
+      }
 #ifdef WLAN_FEATURE_VOWIFI_11R
       case WDA_AGGR_QOS_REQ:
       {
@@ -10530,6 +10555,132 @@
    }
    return ;
 }
+
+
+/*
+ * API to activate/deactivate Traffic Stats timer. Traffic stats timer is only needed
+ * during MCC
+ */
+void WDA_TrafficStatsTimerActivate(wpt_boolean activate)
+{
+   wpt_uint32 enabled;
+   v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
+   tWDA_CbContext *pWDA =  vos_get_context(VOS_MODULE_ID_WDA, pVosContext);
+   tpAniSirGlobal pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pVosContext);
+   
+   if(wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, &enabled) 
+                                                      != eSIR_SUCCESS)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                 "Failed to get WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED");
+      return;
+   }
+
+   if(!enabled)
+   {
+      return;
+   }
+
+   if(NULL == pWDA)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                 "%s:WDA context is NULL", __func__);
+      VOS_ASSERT(0);
+      return;
+   }
+
+   if(activate)
+   {
+      if( VOS_STATUS_SUCCESS != 
+         WDA_START_TIMER(&pWDA->wdaTimers.trafficStatsTimer))
+      {
+         VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                    "Traffic Stats Timer Start Failed ");
+         return;
+      }
+      WDI_DS_ActivateTrafficStats();
+   }
+   else
+   {
+      WDI_DS_DeactivateTrafficStats();
+      WDI_DS_ClearTrafficStats();
+
+      if( VOS_STATUS_SUCCESS !=
+         WDA_STOP_TIMER(&pWDA->wdaTimers.trafficStatsTimer))
+      {
+         VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                    "Traffic Stats Timer Stop Failed ");
+         return;
+      }
+   }
+}
+
+/*
+ * Traffic Stats Timer handler
+ */
+void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA)
+{
+   WDI_Status wdiStatus;
+   WDI_TrafficStatsType *pWdiTrafficStats = NULL;
+   WDI_TrafficStatsIndType trafficStatsIndParams;
+   wpt_uint32 length, enabled;
+   tpAniSirGlobal pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pWDA->pVosContext);
+
+   if(wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, &enabled) 
+                                                      != eSIR_SUCCESS)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                    "Failed to get WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED");
+      return;
+   }
+
+   if(!enabled)
+   {
+      WDI_DS_DeactivateTrafficStats();
+      return;
+   }
+
+   WDI_DS_GetTrafficStats(&pWdiTrafficStats, &length);
+
+   if(pWdiTrafficStats != NULL)
+   {
+      trafficStatsIndParams.pTrafficStats = pWdiTrafficStats;
+      trafficStatsIndParams.length = length;
+      trafficStatsIndParams.duration =
+         pWDA->wdaTimers.trafficStatsTimer.rescheduleTimeInMsecs;
+      trafficStatsIndParams.wdiReqStatusCB = WDA_WdiIndicationCallback;
+      trafficStatsIndParams.pUserData = pWDA;
+
+      wdiStatus = WDI_TrafficStatsInd(&trafficStatsIndParams);
+
+      if(WDI_STATUS_PENDING == wdiStatus)
+      {
+         VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                 "Pending received for %s:%d ",__func__,__LINE__ );
+      }
+      else if( WDI_STATUS_SUCCESS_SYNC != wdiStatus )
+      {
+         VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                 "Failure in %s:%d ",__func__,__LINE__ );
+      }
+      
+      WDI_DS_ClearTrafficStats();
+   }
+   else
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_WARN,
+         "pWdiTrafficStats is Null");
+   }
+
+   if( VOS_STATUS_SUCCESS != 
+      WDA_START_TIMER(&pWDA->wdaTimers.trafficStatsTimer))
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_WARN,
+                              "Traffic Stats Timer Start Failed ");
+      return;
+   }
+}
+
 /*
  * BA Activity check timer handler
  */
@@ -10731,6 +10882,33 @@
       } 
       return VOS_STATUS_E_FAILURE ;
    }
+
+   val = SYS_MS_TO_TICKS( WDA_TRAFFIC_STATS_TIME_OUT_VALUE );
+
+   /* Traffic Stats timer */
+   status = WDA_CREATE_TIMER(&pWDA->wdaTimers.trafficStatsTimer,
+                         "Traffic Stats timer", WDA_TimerHandler,
+                         WDA_TIMER_TRAFFIC_STATS_IND, val, val, TX_NO_ACTIVATE) ;
+   if(status != TX_SUCCESS)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                               "Unable to create traffic stats timer");
+      /* Destroy timer of BA activity check timer */
+      status = WDA_DESTROY_TIMER(&pWDA->wdaTimers.baActivityChkTmr);
+      if(status != TX_SUCCESS)
+      {
+         VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                                  "Unable to Destroy BA activity timer");
+      }
+      /* Destroy timer of tx complete timer */
+      status = WDA_DESTROY_TIMER(&pWDA->wdaTimers.TxCompleteTimer);
+      if(status != TX_SUCCESS)
+      {
+         VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                                  "Unable to Tx complete timer");
+      }
+      return VOS_STATUS_E_FAILURE ;
+   }
    return VOS_STATUS_SUCCESS ;
 }
 /*
@@ -10753,7 +10931,13 @@
                                "Unable to Destroy BA activity timer");
       return eSIR_FAILURE ;
    }
-                           
+   status = WDA_DESTROY_TIMER(&pWDA->wdaTimers.trafficStatsTimer);
+   if(status != TX_SUCCESS)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                               "Unable to Destroy traffic stats timer");
+      return eSIR_FAILURE ;
+   }
    return eSIR_SUCCESS ;
 }
 /*
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index 0f94526..bc17b97 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -3964,6 +3964,38 @@
 }WDI_SuspendParamsType;
 
 /*---------------------------------------------------------------------------
+  WDI_TrafficStatsType - This is collected for each STA
+---------------------------------------------------------------------------*/
+
+typedef struct
+{
+  /* TX stats */
+  wpt_uint32 txBytesPushed;
+  wpt_uint32 txPacketsPushed;
+
+  /* RX stats */
+  wpt_uint32 rxBytesRcvd;
+  wpt_uint32 rxPacketsRcvd;
+  wpt_uint32 rxTimeTotal;
+}WDI_TrafficStatsType;
+
+typedef struct
+{
+  WDI_TrafficStatsType *pTrafficStats;
+  wpt_uint32 length;
+  wpt_uint32 duration;
+
+   /*Request status callback offered by UMAC - it is called if the current
+    req has returned PENDING as status; it delivers the status of sending
+    the message over the BUS */
+  WDI_ReqStatusCb   wdiReqStatusCB; 
+
+  /*The user data passed in by UMAC, it will be sent back when the above
+    function pointer will be called */
+  void*             pUserData;  
+}WDI_TrafficStatsIndType;
+
+/*---------------------------------------------------------------------------
   WDI_WlanResumeInfoType
 ---------------------------------------------------------------------------*/
 typedef struct 
@@ -8662,6 +8694,24 @@
   WDI_SuspendParamsType*    pwdiSuspendIndParams
 );
 
+/**
+ @brief WDI_TrafficStatsInd
+
+       Traffic Stats from the upper layer will be sent
+        down to HAL
+
+ @param WDI_TrafficStatsIndType
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_TrafficStatsInd
+(
+  WDI_TrafficStatsIndType *pWdiTrafficStatsIndParams
+);
+
 #ifdef FEATURE_WLAN_SCAN_PNO
 /**
  @brief WDI_SetPreferredNetworkList
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index cd44994..93079cf 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -446,6 +446,9 @@
   /*Send a suspend Indication down to HAL*/
   WDI_HOST_SUSPEND_IND          = WDI_MAX_REQ ,
 
+  /* Send a traffic stats indication to HAL */
+  WDI_TRAFFIC_STATS_IND,
+
   /*Keep adding the indications to the max request
     such that we keep them sepparate */
 
@@ -2648,6 +2651,21 @@
 );
 
 
+/**
+ @brief Process Traffic Stats Indications function (called when Main FSM allows it)
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+         pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessTrafficStatsInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
 /*========================================================================
           Main DAL Control Path Response Processing API 
 ========================================================================*/
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index 6436104..75f647d 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -355,6 +355,7 @@
     Indications
   -------------------------------------------------------------------------*/
   WDI_ProcessHostSuspendInd,            /* WDI_HOST_SUSPEND_IND*/
+  WDI_ProcessTrafficStatsInd,           /* WDI_TRAFFIC_STATS_IND*/
 };
 
 
@@ -861,6 +862,7 @@
     CASE_RETURN_STRING( WDI_HAL_DUMP_CMD_REQ );
     CASE_RETURN_STRING( WDI_SHUTDOWN_REQ );
     CASE_RETURN_STRING( WDI_SET_POWER_PARAMS_REQ );
+    CASE_RETURN_STRING( WDI_TRAFFIC_STATS_IND );
     default:
         return "Unknown WDI MessageId";
   }
@@ -5562,6 +5564,51 @@
 }/*WDI_HostSuspendInd*/
 
 /**
+ @brief WDI_TrafficStatsInd
+       Traffic Stats from the upper layer will be sent
+        down to HAL
+
+ @param WDI_TrafficStatsIndType
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_TrafficStatsInd
+(
+  WDI_TrafficStatsIndType *pWdiTrafficStatsIndParams
+)
+{
+
+  WDI_EventInfoType      wdiEventData;
+  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+  /*------------------------------------------------------------------------
+    Sanity Check
+  ------------------------------------------------------------------------*/
+  if ( eWLAN_PAL_FALSE == gWDIInitialized )
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+              "WDI API call before module is initialized - Fail request");
+
+    return WDI_STATUS_E_NOT_ALLOWED;
+  }
+
+  /*------------------------------------------------------------------------
+    Fill in Event data and post to the Main FSM
+  ------------------------------------------------------------------------*/
+  wdiEventData.wdiRequest      = WDI_TRAFFIC_STATS_IND;
+  wdiEventData.pEventData      = pWdiTrafficStatsIndParams;
+  wdiEventData.uEventDataSize  = sizeof(*pWdiTrafficStatsIndParams);
+  wdiEventData.pCBfnc          = NULL;
+  wdiEventData.pUserData       = NULL;
+
+  return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+
+}/*WDI_TrafficStatsInd*/
+
+/**
  @brief WDI_HALDumpCmdReq
         Post HAL DUMP Command Event
 
@@ -10307,6 +10354,86 @@
   return  ( wdiStatus != WDI_STATUS_SUCCESS )?wdiStatus:WDI_STATUS_SUCCESS_SYNC;
 }/*WDI_ProcessHostSuspendInd*/
 
+
+
+/**
+ @brief Process Traffic Stats Indications function (called when Main FSM allows it)
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+              pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessTrafficStatsInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  WDI_TrafficStatsIndType*       pTrafficStatsIndParams;
+  wpt_uint8*                     pSendBuffer         = NULL;
+  wpt_uint16                     usDataOffset        = 0;
+  wpt_uint16                     usSendSize          = 0;
+  WDI_Status                     wdiStatus;
+  tStatsClassBIndParams*         pStatsClassBIndParams;
+  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+  /*-------------------------------------------------------------------------
+     Sanity check
+  -------------------------------------------------------------------------*/
+  if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ))
+  {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+               "%s: Invalid parameters in Traffic Stats ind",__func__);
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+  }
+
+  pTrafficStatsIndParams = (WDI_TrafficStatsIndType *)pEventData->pEventData;
+
+  if(pTrafficStatsIndParams->length != sizeof(tStaStatsClassB)*(HAL_NUM_STA))
+  {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+               "%s: Invalid parameters in Traffic Stats ind",__func__);
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+  }
+
+   /*-----------------------------------------------------------------------
+     Get message buffer
+   -----------------------------------------------------------------------*/
+  if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx,
+                         WDI_TRAFFIC_STATS_IND,
+                     sizeof(tStatsClassBIndParams),
+                     &pSendBuffer, &usDataOffset, &usSendSize))||
+        (usSendSize < (usDataOffset + sizeof(tStatsClassBIndParams))))
+  {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_FATAL,
+                  "Unable to get send buffer in Traffic Stats Ind ");
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+  }
+
+  pStatsClassBIndParams = (tStatsClassBIndParams*)(pSendBuffer+usDataOffset);
+
+  pStatsClassBIndParams->duration = pTrafficStatsIndParams->duration;
+
+  wpalMemoryCopy(pStatsClassBIndParams->staStatsClassB,
+                 pTrafficStatsIndParams->pTrafficStats,
+                 pTrafficStatsIndParams->length);
+
+  /*-------------------------------------------------------------------------
+    Send Suspend Request to HAL
+  -------------------------------------------------------------------------*/
+  pWDICtx->wdiReqStatusCB     = pTrafficStatsIndParams->wdiReqStatusCB;
+  pWDICtx->pReqStatusUserData = pTrafficStatsIndParams->pUserData;
+
+  wdiStatus = WDI_SendIndication( pWDICtx, pSendBuffer, usSendSize);
+  return  ( wdiStatus != WDI_STATUS_SUCCESS )?wdiStatus:WDI_STATUS_SUCCESS_SYNC;
+}/*WDI_ProcessTrafficStatsInd*/
+
 /*==========================================================================
                   MISC CONTROL PROCESSING REQUEST API
 ==========================================================================*/
@@ -20999,6 +21126,8 @@
     return WLAN_HAL_HOST_RESUME_REQ;
   case WDI_HOST_SUSPEND_IND:
     return WLAN_HAL_HOST_SUSPEND_IND;
+  case WDI_TRAFFIC_STATS_IND:
+    return WLAN_HAL_CLASS_B_STATS_IND;
   case WDI_KEEP_ALIVE_REQ:
     return WLAN_HAL_KEEP_ALIVE_REQ;
 
diff --git a/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h b/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
index 19caa94..2b21516 100644
--- a/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
+++ b/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
@@ -328,4 +328,34 @@
  */
 WDI_Status WDI_DS_ClearStaIdxPerBssIdx(void *pContext, wpt_uint8 bssIdx, wpt_uint8 staIdx);
 
+/* Tx/Rx stats function
+ * This function should be invoked to fetch the current stats
+  * Parameters:
+ *  pStats:Pointer to the collected stats
+ *  len: length of buffer pointed to by pStats
+ *  Return Status: None
+ */
+void WDI_DS_GetTrafficStats(WDI_TrafficStatsType** pStats, wpt_uint32 *len);
+
+/* WDI_DS_DeactivateTrafficStats
+ * This function should be invoked to deactivate traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDI_DS_DeactivateTrafficStats(void);
+
+/* WDI_DS_ActivateTrafficStats
+ * This function should be invoked to activate traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDI_DS_ActivateTrafficStats(void);
+
+/* WDI_DS_ClearTrafficStats
+ * This function should be invoked to clear all past stats
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDI_DS_ClearTrafficStats(void);
+
 #endif
diff --git a/CORE/WDI/DP/src/wlan_qct_wdi_ds.c b/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
index e10c5c8..4d8bde6 100644
--- a/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
+++ b/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
@@ -492,3 +492,46 @@
   /* Could not find associated STA index with BSS index */
   return WDI_STATUS_E_FAILURE;
 }
+
+/* Tx/Rx stats function
+ * This function should be invoked to fetch the current stats
+  * Parameters:
+ *  pStats:Pointer to the collected stats
+ *  len: length of buffer pointed to by pStats
+ *  Return Status: None
+ */
+void WDI_DS_GetTrafficStats(WDI_TrafficStatsType** pStats, wpt_uint32 *len)
+{
+   return WDTS_GetTrafficStats(pStats, len);
+}
+
+/* WDI_DS_DeactivateTrafficStats
+ * This function should be invoked to deactivate traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDI_DS_DeactivateTrafficStats(void)
+{
+   return WDTS_DeactivateTrafficStats();
+}
+
+/* WDI_DS_ActivateTrafficStats
+ * This function should be invoked to activate traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDI_DS_ActivateTrafficStats(void)
+{
+   return WDTS_ActivateTrafficStats();
+}
+
+/* WDI_DS_ClearTrafficStats
+ * This function should be invoked to clear all past stats
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDI_DS_ClearTrafficStats(void)
+{
+   return WDTS_ClearTrafficStats();
+}
+
diff --git a/CORE/WDI/TRP/DTS/inc/wlan_qct_wdi_dts.h b/CORE/WDI/TRP/DTS/inc/wlan_qct_wdi_dts.h
index a54a03a..398b8b2 100644
--- a/CORE/WDI/TRP/DTS/inc/wlan_qct_wdi_dts.h
+++ b/CORE/WDI/TRP/DTS/inc/wlan_qct_wdi_dts.h
@@ -41,6 +41,9 @@
 
 #ifndef __WLAN_QCT_DTS_H
 #define __WLAN_QCT_DTS_H
+
+#include "wlan_qct_wdi.h"
+
 /**=========================================================================
  *     
  *       \file  wlan_qct_wdi_dts.h
@@ -136,6 +139,36 @@
    void*        pUserData;
 } WDTS_SetPowerStateCbInfoType;
 
+/* Tx/Rx stats function
+ * This function should be invoked to fetch the current stats
+  * Parameters:
+ *  pStats:Pointer to the collected stats
+ *  len: length of buffer pointed to by pStats
+ *  Return Status: None
+ */
+void WDTS_GetTrafficStats(WDI_TrafficStatsType** pStats, wpt_uint32 *len);
+
+/* WDTS_DeactivateTrafficStats
+ * This function should be invoked to suspend traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDTS_DeactivateTrafficStats(void);
+
+/* WDTS_ActivateTrafficStats
+ * This function should be invoked to activate traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDTS_ActivateTrafficStats(void);
+
+/* WDTS_ClearTrafficStats
+ * This function should be invoked to clear all past stats
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDTS_ClearTrafficStats(void);
+
 /* DTS open  function. 
  * On open the transport device should initialize itself.
  * Parameters:
diff --git a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
index 008fa94..321dcb4 100644
--- a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
+++ b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
@@ -78,6 +78,270 @@
 
 static WDTS_SetPowerStateCbInfoType gSetPowerStateCbInfo;
 
+typedef struct 
+{
+   uint32 phyRate;   //unit in Mega bits per sec X 10
+   uint32 tputRate;  //unit in Mega bits per sec X 10
+   uint32 tputBpms;  //unit in Bytes per msec = (tputRateX1024x1024)/(8x10X1000) ~= (tputRate*13)
+   float  tputBpus;  //unit in Bytes per usec
+}WDTS_RateInfo;
+
+#define WDTS_MAX_RATE_NUM  137
+
+WDTS_RateInfo gRateInfo[WDTS_MAX_RATE_NUM]  = {
+    //11b rates
+    {  10,  9,  117, 0.12}, //index 0
+    {  20,  17, 221, 0.22}, //index 1
+    {  55,  41, 533, 0.53}, //index 2
+    { 110,  68, 884, 0.88}, //index 3
+
+    //11b short preamble
+    {  10,  10,  130, 0.13}, //index 4
+    {  20,  18,  234, 0.23}, //index 5
+    {  55,  44,  572, 0.57}, //index 6
+    { 110,  77, 1001, 1.00}, //index 7
+
+    //11ag
+    {  60,  50,  650, 0.65}, //index 8
+    {  90,  70,  910, 0.91}, //index 9
+    { 120, 100, 1300, 1.30}, //index 10
+    { 180, 150, 1950, 1.95}, //index 11
+    { 240, 190, 2470, 2.47}, //index 12
+    { 360, 280, 3640, 3.64}, //index 13
+    { 480, 350, 4550, 4.55}, //index 14
+    { 540, 380, 4940, 4.94}, //index 15
+
+    //11n SIMO
+    {  65,  54,  702, 0.70}, //index 16
+    { 130, 108, 1404, 1.40}, //index 17
+    { 195, 161, 2093, 2.09}, //index 18
+    { 260, 217, 2821, 2.82}, //index 19
+    { 390, 326, 4238, 4.24}, //index 20
+    { 520, 435, 5655, 5.66}, //index 21
+    { 585, 492, 6396, 6.40}, //index 22
+    { 650, 548, 7124, 7.12}, //index 23
+
+    //11n SIMO SGI
+    {  72,  59,  767, 0.77}, //index 24
+    { 144, 118, 1534, 1.53}, //index 25
+    { 217, 180, 2340, 2.34}, //index 26
+    { 289, 243, 3159, 3.16}, //index 27
+    { 434, 363, 4719, 4.72}, //index 28
+    { 578, 486, 6318, 6.32}, //index 29
+    { 650, 548, 7124, 7.12}, //index 30
+    { 722, 606, 7878, 7.88}, //index 31
+
+    //11n GF SIMO
+    {  65,  54,  702, 0.70}, //index 32
+    { 130, 108, 1404, 1.40}, //index 33
+    { 195, 161, 2093, 2.09}, //index 34
+    { 260, 217, 2821, 2.82}, //index 35
+    { 390, 326, 4238, 4.23}, //index 36
+    { 520, 435, 5655, 5.66}, //index 37
+    { 585, 492, 6396, 6.40}, //index 38
+    { 650, 548, 7124, 7.12}, //index 39
+
+    //11n SIMO CB MCS 0 - 7 
+    { 135,   110,  1430,  1.43}, //index 40
+    { 270,   223,  2899,  2.90}, //index 41
+    { 405,   337,  4381,  4.38}, //index 42
+    { 540,   454,  5902,  5.90}, //index 43
+    { 810,   679,  8827,  8.83}, //index 44
+    { 1080,  909, 11817, 11.81}, //index 45
+    { 1215, 1022, 13286, 13.29}, //index 46
+    { 1350, 1137, 14781, 14.78}, //index 47
+
+    //11n SIMO CB SGI MCS 0 - 7
+    { 150,   121,  1573,  1.57}, //index 48
+    { 300,   249,  3237,  3.24}, //index 49
+    { 450,   378,  4914,  4.91}, //index 50
+    { 600,   503,  6539,  6.54}, //index 51
+    { 900,   758,  9854,  9.85}, //index 52
+    { 1200, 1010, 13130, 13.13}, //index 53
+    { 1350, 1137, 14781, 14.78}, //index 54
+    { 1500, 1262, 16406, 16.41}, //index 55
+
+    //11n SIMO GF CB MCS 0 - 7 
+    { 135,   110,   1430,  1.43}, //index 56
+    { 270,   223,   2899,  2.90}, //index 57
+    { 405,   337,   4381,  4.38}, //index 58
+    { 540,   454,   5902,  5.90}, //index 59
+    { 810,   679,   8827,  8.83}, //index 60
+    { 1080,  909,  11817, 11.81}, //index 61
+    { 1215, 1022,  13286, 13.29}, //index 62
+    { 1350, 1137,  14781, 14.79}, //index 63
+
+    //11AC  
+    { 1350, 1137, 14781, 14.78}, //reserved 64
+    { 1350, 1137, 14781, 14.78}, //reserved 65
+    { 65,     65,   845,  0.85}, //index 66
+    { 130,   130,  1690,  1.69}, //index 67
+    { 195,   195,  2535,  2.54}, //index 68
+    { 260,   260,  3380,  3.38}, //index 69
+    { 390,   390,  5070,  5.07}, //index 70
+    { 520,   520,  6760,  6.76}, //index 71
+    { 585,   585,  7605,  7.61}, //index 72
+    { 650,   650,  8450,  8.45}, //index 73
+    { 780,   780,  2340,  2.34}, //index 74
+    { 1350, 1137, 14781, 14.78}, //reserved 75
+    { 1350, 1137, 14781, 14.78}, //reserved 76
+    { 1350, 1137, 14781, 14.78}, //reserved 77
+    { 1350, 1137, 14781, 14.78}, //index 78
+    { 1350, 1137, 14781, 14.78}, //index 79
+    { 1350, 1137, 14781, 14.78}, //index 80
+    { 1350, 1137, 14781, 14.78}, //index 81
+    { 1350, 1137, 14781, 14.78}, //index 82
+    { 1350, 1137, 14781, 14.78}, //index 83
+    { 655,   655,  8515,  8.52}, //index 84
+    { 722,   722,  9386,  9.39}, //index 85
+    { 866,   866, 11258, 11.26}, //index 86
+    { 1350, 1137, 14781, 14.78}, //reserved 87
+    { 1350, 1137, 14781, 14.78}, //reserved 88
+    { 1350, 1137, 14781, 14.78}, //reserved 89
+    { 135,   135,  1755,  1.76}, //index 90
+    { 270,   270,  3510,  3.51}, //index 91
+    { 405,   405,  5265,  5.27}, //index 92
+    { 540,   540,  7020,  7.02}, //index 93
+    { 810,   810, 10530, 10.53}, //index 94
+    { 1080, 1080, 14040, 14.04}, //index 95
+    { 1215, 1215, 15795, 15.80}, //index 96
+    { 1350, 1350, 17550, 17.55}, //index 97
+    { 1350, 1137, 14781, 14.78}, //index 98
+    { 1620, 1620, 21060, 21.06}, //index 99
+    { 1800, 1800, 23400, 23.40}, //index 100
+    { 1350, 1137, 14781, 14.78}, //reserved 101
+    { 1350, 1137, 14781, 14.78}, //index 102
+    { 1350, 1137, 14781, 14.78}, //index 103
+    { 1350, 1137, 14781, 14.78}, //index 104
+    { 1350, 1137, 14781, 14.78}, //index 105
+    { 1350, 1137, 14781, 14.78}, //index 106
+    { 1200, 1200, 15600, 15.60}, //index 107
+    { 1350, 1350, 17550, 17.55}, //index 108
+    { 1500, 1500, 19500, 19.50}, //index 109
+    { 1350, 1137, 14781, 14.78}, //index 110
+    { 1800, 1800, 23400, 23.40}, //index 111
+    { 2000, 2000, 26000, 26.00}, //index 112
+    { 1350, 1137, 14781, 14.78}, //index 113
+    { 292,   292,  3796,  3.80}, //index 114
+    { 585,   585,  7605,  7.61}, //index 115
+    { 877,   877, 11401, 11.40}, //index 116
+    { 1170, 1170, 15210, 15.21}, //index 117
+    { 1755, 1755, 22815, 22.82}, //index 118
+    { 2340, 2340, 30420, 30.42}, //index 119
+    { 2632, 2632, 34216, 34.22}, //index 120
+    { 2925, 2925, 38025, 38.03}, //index 121
+    { 1350, 1137, 14781, 14.78}, //index 122
+    { 3510, 3510, 45630, 45.63}, //index 123 
+    { 3900, 3900, 50700, 50.70}, //index 124
+    { 1350, 1137, 14781, 14.78}, //reserved 125    
+    { 1350, 1137, 14781, 14.78}, //index 126
+    { 1350, 1137, 14781, 14.78}, //index 127
+    { 1350, 1137, 14781, 14.78}, //index 128
+    { 1350, 1137, 14781, 14.78}, //index 129
+    { 1350, 1137, 14781, 14.78}, //index 130
+    { 1350, 1137, 14781, 14.78}, //index 131
+    { 2925, 2925, 38025, 38.03}, //index 132
+    { 3250, 3250, 42250, 42.25}, //index 133
+    { 1350, 1137, 14781, 14.78}, //index 134
+    { 3900, 3900, 50700, 50.70}, //index 135
+    { 4333, 4333, 56329, 56.33}  //index 136
+ };
+
+/* TX stats */
+typedef struct
+{
+  wpt_uint32 txBytesPushed;
+  wpt_uint32 txPacketsPushed; //Can be removed to optimize memory
+}WDI_DTS_TX_TrafficStatsType;
+
+/* RX stats */
+typedef struct
+{
+  wpt_uint32 rxBytesRcvd;
+  wpt_uint32 rxPacketsRcvd;  //Can be removed to optimize memory
+}WDI_DTS_RX_TrafficStatsType;
+
+typedef struct {
+   wpt_uint8 running;
+   WDI_DTS_RX_TrafficStatsType rxStats[HAL_NUM_STA][WDTS_MAX_RATE_NUM];
+   WDI_DTS_TX_TrafficStatsType txStats[HAL_NUM_STA];
+   WDI_TrafficStatsType        netTxRxStats[HAL_NUM_STA];
+}WDI_DTS_TrafficStatsType;
+
+static WDI_DTS_TrafficStatsType gDsTrafficStats;
+
+#define DTS_RATE_TPUT(x) gRateInfo[x].tputBpms
+
+/* Tx/Rx stats function
+ * This function should be invoked to fetch the current stats
+  * Parameters:
+ *  pStats:Pointer to the collected stats
+ *  len: length of buffer pointed to by pStats
+ *  Return Status: None
+ */
+void WDTS_GetTrafficStats(WDI_TrafficStatsType** pStats, wpt_uint32 *len)
+{
+   if(gDsTrafficStats.running)
+   {
+      uint8 staIdx, rate;
+      WDI_TrafficStatsType *pNetTxRxStats = gDsTrafficStats.netTxRxStats;
+      wpalMemoryZero(pNetTxRxStats, sizeof(gDsTrafficStats.netTxRxStats));
+
+      for(staIdx = 0; staIdx < HAL_NUM_STA; staIdx++, pNetTxRxStats++)
+      {
+          pNetTxRxStats->txBytesPushed += gDsTrafficStats.txStats[staIdx].txBytesPushed;
+          pNetTxRxStats->txPacketsPushed+= gDsTrafficStats.txStats[staIdx].txPacketsPushed;
+          for (rate = 0; rate < WDTS_MAX_RATE_NUM; rate++)
+          {
+             pNetTxRxStats->rxBytesRcvd += 
+               gDsTrafficStats.rxStats[staIdx][rate].rxBytesRcvd;
+             pNetTxRxStats->rxPacketsRcvd += 
+               gDsTrafficStats.rxStats[staIdx][rate].rxPacketsRcvd;
+             pNetTxRxStats->rxTimeTotal += 
+               gDsTrafficStats.rxStats[staIdx][rate].rxPacketsRcvd/DTS_RATE_TPUT(rate);
+          }
+      }
+      *pStats = gDsTrafficStats.netTxRxStats;
+      *len = sizeof(gDsTrafficStats.netTxRxStats);
+   }
+   else
+   {
+      *pStats = NULL;
+      *len = 0;
+   }
+}
+
+/* WDTS_DeactivateTrafficStats
+ * This function should be invoked to deactivate traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDTS_DeactivateTrafficStats(void)
+{
+   gDsTrafficStats.running = eWLAN_PAL_FALSE;
+}
+
+/* WDTS_ActivateTrafficStats
+ * This function should be invoked to activate traffic stats collection
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDTS_ActivateTrafficStats(void)
+{
+   gDsTrafficStats.running = eWLAN_PAL_TRUE;
+}
+
+/* WDTS_ClearTrafficStats
+ * This function should be invoked to clear traffic stats 
+  * Parameters: None
+ *  Return Status: None
+ */
+void WDTS_ClearTrafficStats(void)
+{
+   wpalMemoryZero(gDsTrafficStats.rxStats, sizeof(gDsTrafficStats.rxStats));
+   wpalMemoryZero(gDsTrafficStats.txStats, sizeof(gDsTrafficStats.txStats));
+}
+
 /* DTS Tx packet complete function. 
  * This function should be invoked by the transport device to indicate 
  * transmit complete for a frame.
@@ -381,6 +645,16 @@
       // Invoke Rx complete callback
       pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame);  
   }
+
+  //Log the RX Stats
+  if(gDsTrafficStats.running && pRxMetadata->staId < HAL_NUM_STA)
+  {
+     if(pRxMetadata->rateIndex < WDTS_MAX_RATE_NUM)
+     {
+        gDsTrafficStats.rxStats[pRxMetadata->staId][pRxMetadata->rateIndex].rxBytesRcvd += pRxMetadata->mpduLength;
+        gDsTrafficStats.rxStats[pRxMetadata->staId][pRxMetadata->rateIndex].rxPacketsRcvd++;
+     }
+  }
   return eWLAN_PAL_STATUS_SUCCESS;
 
 }
@@ -468,6 +742,8 @@
     return eWLAN_PAL_STATUS_E_NOMEM;
   }
 
+  wpalMemoryZero(&gDsTrafficStats, sizeof(gDsTrafficStats));
+
   return eWLAN_PAL_STATUS_SUCCESS;
 
 }
@@ -508,9 +784,18 @@
   WDI_DS_TxMetaInfoType     *pTxMetadata;
   WDTS_ChannelType channel = WDTS_CHANNEL_TX_LOW_PRI;
   wpt_status status = eWLAN_PAL_STATUS_SUCCESS;
+  WDI_TxBdType *pvBDHeader;
 
   // extract metadata from PAL packet
   pTxMetadata = WDI_DS_ExtractTxMetaData(pFrame);
+  pvBDHeader = (WDI_TxBdType*)WPAL_PACKET_GET_BD_POINTER(pFrame);
+
+  //Log the TX Stats
+  if(gDsTrafficStats.running && pvBDHeader->staIndex < HAL_NUM_STA)
+  {
+     gDsTrafficStats.txStats[pvBDHeader->staIndex].txBytesPushed += 
+        pvBDHeader->mpduLength;
+  }
 
   // assign MDPU to correct channel??
   channel =  (pTxMetadata->frmType & WDI_MAC_DATA_FRAME)? 
@@ -625,6 +910,8 @@
 
   status =  gTransportDriver.stop(pDTDriverContext);
 
+  wpalMemoryZero(&gDsTrafficStats, sizeof(gDsTrafficStats));
+
   return status;
 }
 
diff --git a/firmware_bin/WCNSS_cfg.dat b/firmware_bin/WCNSS_cfg.dat
index 5c7138f..296a30d 100755
--- a/firmware_bin/WCNSS_cfg.dat
+++ b/firmware_bin/WCNSS_cfg.dat
Binary files differ
diff --git a/riva/inc/wlan_hal_cfg.h b/riva/inc/wlan_hal_cfg.h
index ba56d31..f7e15aa 100644
--- a/riva/inc/wlan_hal_cfg.h
+++ b/riva/inc/wlan_hal_cfg.h
@@ -171,11 +171,12 @@
 #define QWLAN_HAL_CFG_ENABLE_UNICAST_FILTER              97
 #define QWLAN_HAL_CFG_MAX_ASSOC_LIMIT                    98
 #define QWLAN_HAL_CFG_ENABLE_LPWR_IMG_TRANSITION         99
-#define QWLAN_HAL_CFG_MAX_PARAMS                         100
+#define QWLAN_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER     100
+#define QWLAN_HAL_CFG_MAX_PARAMS                        101
 
 
 /* Total number of Integer CFGs. This is used while allocating the memory for TLV */
-#define QWLAN_HAL_CFG_INTEGER_PARAM                      96
+#define QWLAN_HAL_CFG_INTEGER_PARAM                      97
 
 
 /*-------------------------------------------------------------------------
@@ -745,6 +746,10 @@
 #define QWLAN_HAL_CFG_ENABLE_LPWR_IMG_TRANSITION_MAX    1
 #define QWLAN_HAL_CFG_ENABLE_LPWR_IMG_TRANSITION_DEF    0
 
+/* QWLAN_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER */
+#define QWLAN_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER_MIN    0
+#define QWLAN_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER_MAX    1
+#define QWLAN_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER_DEF    0
 
 typedef struct 
 {
diff --git a/riva/inc/wlan_hal_msg.h b/riva/inc/wlan_hal_msg.h
index 18aef61..5d6b37d 100755
--- a/riva/inc/wlan_hal_msg.h
+++ b/riva/inc/wlan_hal_msg.h
@@ -338,7 +338,7 @@
   WLAN_HAL_UPDATE_VHT_OP_MODE_RSP           = 183,
 
   WLAN_HAL_P2P_NOA_START_IND                = 184,
-
+   WLAN_HAL_CLASS_B_STATS_IND               = 197,
   WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE
 }tHalHostMsgType;
 
@@ -5695,6 +5695,36 @@
 
 }  tSetThermalMitigationResp, *tpSetThermalMitigationResp;
 
+/* Per STA Class B Statistics. Class B statistics are STA TX/RX stats  
+provided to FW from Host via periodic messages */
+typedef PACKED_PRE struct PACKED_POST {
+   /* TX stats */
+   uint32 txBytesPushed;
+   uint32 txPacketsPushed;
+
+   /* RX stats */
+   uint32 rxBytesRcvd;
+   uint32 rxPacketsRcvd;
+   uint32 rxTimeTotal;
+} tStaStatsClassB, *tpStaStatsClassB;
+
+typedef PACKED_PRE struct PACKED_POST {
+
+   /* Duration over which this stats was collected */
+   tANI_U32 duration;
+
+   /* Per STA Stats */
+   tStaStatsClassB staStatsClassB[HAL_NUM_STA];
+} tStatsClassBIndParams, *tpStatsClassBIndParams;
+
+typedef PACKED_PRE struct PACKED_POST {
+
+   tHalMsgHeader header;
+
+   /* Class B Stats */
+   tStatsClassBIndParams statsClassBIndParams;
+} tStatsClassBInd, *tpStatsClassBInd;
+
 #if defined(__ANI_COMPILER_PRAGMA_PACK_STACK)
 #pragma pack(pop)
 #elif defined(__ANI_COMPILER_PRAGMA_PACK)