wlan: [Part 1]Implement Soft AP Tx flow control

Implement timer to collect the samples of TX frames fetched from
stations which helps to keep track of number of frames pushed to DXE
in 100ms duration during flow control mechanism.

Change-Id: I4d9698dca3e271e9771135e6f10cb75aab96690d
CRs-Fixed: 1097660
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index 9b80e04..9d1a7ea 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -3376,4 +3376,16 @@
  * Return: none
  */
 void WLANTL_SetDataPktFilter(v_PVOID_t pvosGCtx, uint8_t ucSTAId, bool flag);
+
+/**
+ * WLANTL_SampleTx() - collect tx samples
+ * @data: TL context pointer
+ *
+ * This function records the frames fetched from stations
+ * during TX sample interval
+ *
+ * Return: void
+ */
+void WLANTL_SampleTx(void *data);
+
 #endif /* #ifndef WLAN_QCT_WLANTL_H */
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index da81f27..f03689e 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -696,6 +696,8 @@
   pTLCb->ucCurLeftWeight = 1;
   pTLCb->ucCurrentSTA = WLAN_MAX_STA_COUNT-1;
 
+  vos_timer_init(&pTLCb->tx_frames_timer, VOS_TIMER_TYPE_SW,
+                         WLANTL_SampleTx, (void *)pTLCb);
 #if 0
   //flow control field init
   vos_mem_zero(&pTLCb->tlFCInfo, sizeof(tFcTxParams_type));
@@ -833,8 +835,10 @@
 
   /* Enable transmission */
   vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0);
-
   pTLCb->uResCount = uResCount;
+
+  vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL);
+
   return VOS_STATUS_SUCCESS;
 }/* WLANTL_Start */
 
@@ -917,6 +921,10 @@
   }
 #endif
 
+   if (VOS_TIMER_STATE_STOPPED !=
+                  vos_timer_getCurrentState(&pTLCb->tx_frames_timer))
+      vos_timer_stop(&pTLCb->tx_frames_timer);
+
   /*-------------------------------------------------------------------------
     Clean client stations
    -------------------------------------------------------------------------*/
@@ -1011,6 +1019,15 @@
   }
 #endif
 
+   if (VOS_TIMER_STATE_RUNNING ==
+                       vos_timer_getCurrentState(&pTLCb->tx_frames_timer)) {
+         vos_timer_stop(&pTLCb->tx_frames_timer);
+   }
+   if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(&pTLCb->tx_frames_timer))) {
+         TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+                "%s: Cannot deallocate TX frames sample timer", __func__));
+   }
+
   /*------------------------------------------------------------------------
     Cleanup TL control block.
    ------------------------------------------------------------------------*/
@@ -4912,6 +4929,8 @@
           pClientSTA->uBuffThresholdMax = (pClientSTA->uBuffThresholdMax >= uResLen) ?
             (pClientSTA->uBuffThresholdMax - uResLen) : 0;
 
+          pClientSTA->tx_frames ++;
+
         }
         else
         {
@@ -13847,6 +13866,61 @@
    }
 }
 
+/**
+ * WLANTL_ShiftArrByOne() - utility function to shift array by one
+ * @arr: pointer to array
+ * @len: length of the array
+ *
+ * Caller responsibility to provide the correct length of the array
+ * other may leads to bugs.
+ *
+ * Return: void
+ */
+static void WLANTL_ShiftArrByOne(uint32_t *arr, uint8_t len)
+{
+   int i;
+   for (i = 0; i < len - 1; i ++)
+      arr[i] = arr[i + 1];
+   arr[i] = 0;
+}
+
+/**
+ * WLANTL_SampleTx() - collect tx samples
+ * @data: TL context pointer
+ *
+ * This function records the last five tx bytes sent samples
+ * collected after tx_bytes_timer expire.
+ *
+ * Return: void
+ */
+void WLANTL_SampleTx(void *data)
+{
+   WLANTL_CbType* pTLCb = (WLANTL_CbType *)data;
+   WLANTL_STAClientType* pClientSTA = NULL;
+   uint8_t count = pTLCb->sample_count;
+   uint8_t i;
+
+   for ( i = 0; i < WLAN_MAX_STA_COUNT; i++) {
+       if (NULL != pTLCb->atlSTAClients[i] &&
+           pTLCb->atlSTAClients[i]->ucExists) {
+          pClientSTA = pTLCb->atlSTAClients[i];
+
+          if (count > (WLANTL_SAMPLE_COUNT - 1)) {
+              count = WLANTL_SAMPLE_COUNT - 1;
+              pClientSTA->tx_samples_sum -= pClientSTA->tx_sample[0];
+              WLANTL_ShiftArrByOne(pClientSTA->tx_sample, WLANTL_SAMPLE_COUNT);
+          }
+
+          pClientSTA->tx_sample[count] = pClientSTA->tx_frames;
+          pClientSTA->tx_samples_sum += pClientSTA->tx_sample[count];
+          pClientSTA->tx_frames = 0;
+          count++;
+          pTLCb->sample_count = count;
+       }
+   }
+
+   vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL);
+}
 #ifdef WLAN_FEATURE_RMC
 VOS_STATUS WLANTL_RmcInit
 (
diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h
index 4d23eb2..480673c 100644
--- a/CORE/TL/src/wlan_qct_tli.h
+++ b/CORE/TL/src/wlan_qct_tli.h
@@ -190,6 +190,9 @@
 #define WLANTL_RMC_HASH_TABLE_SIZE (32)
 #endif
 
+#define WLANTL_SAMPLE_INTERVAL 50
+#define WLANTL_SAMPLE_COUNT 2
+
 /*-------------------------------------------------------------------------
   BT-AMP related definition - !!! should probably be moved to BT-AMP header
 ---------------------------------------------------------------------------*/
@@ -727,6 +730,12 @@
 
   /* Disassoc in progress */
   v_BOOL_t disassoc_progress;
+
+  /* sample timer Tx frames */
+  uint64_t tx_frames;
+  uint32_t tx_sample[WLANTL_SAMPLE_COUNT];
+  uint64_t tx_samples_sum;
+
 }WLANTL_STAClientType;
 
 /*---------------------------------------------------------------------------
@@ -967,6 +976,10 @@
   WLANTL_RoamMonitorType gDsRxRoamStats;
 #endif
 
+  /* TX sample data timer */
+  vos_timer_t tx_frames_timer;
+  uint8_t sample_count;
+
 }WLANTL_CbType;