wlan: Fetch from bad peers when no packets are pending for good peers

Currently as part of SAP TX flow control based on the station's weight
packets are fetched from their HDD WMM ac queues. Weights are updated
based on the ratio of RA rates. As a result even when there is no
traffic running on the good peer, packets pending for the bad peer are
not fetched based on the weight.

In this change when no packets are pending for the good link stations
fetch packet from relatively bad link peers.

Change-Id: Iecd4cf8d34f532281412b96eb0a5068cbb7aab8c
CRs-Fixed: 1106746
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index 0933b44..74a1fe9 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -11551,6 +11551,8 @@
   uint8           ucACMask; 
   uint8           i = 0;
   uint8           j;
+  uint8           minWeightSta;
+  uint32_t        sta_bitmask = 0;
   /*------------------------------------------------------------------------
     Extract TL control block
   ------------------------------------------------------------------------*/
@@ -11616,6 +11618,7 @@
   } //( WLAN_MAX_STA_COUNT == ucNextSTA )
 
   ucTempSTA = ucNextSTA;
+  minWeightSta = ucNextSTA;
 
   //decide how many loops to go. if current loop is partial, do one extra to make sure
   //we cover every station
@@ -11682,7 +11685,15 @@
          */
         if (pTLCb->atlSTAClients[ucNextSTA]->weight > WLANTL_GOOD_STA_WEIGHT) {
            if (pTLCb->atlSTAClients[ucNextSTA]->weight_count <=
-               pTLCb->atlSTAClients[ucNextSTA]->weight) {
+               pTLCb->atlSTAClients[ucNextSTA]->weight)
+           {
+              if (pTLCb->atlSTAClients[minWeightSta]->weight <= 1)
+                  minWeightSta = ucNextSTA;
+              else if (pTLCb->atlSTAClients[ucNextSTA]->weight <
+                  pTLCb->atlSTAClients[minWeightSta]->weight) {
+                 minWeightSta = ucNextSTA;
+              }
+              sta_bitmask |= (1 << ucNextSTA);
               pTLCb->atlSTAClients[ucNextSTA]->weight_count++;
               continue;
            }
@@ -11728,7 +11739,15 @@
 
          if (pTLCb->atlSTAClients[j]->weight > WLANTL_GOOD_STA_WEIGHT) {
             if (pTLCb->atlSTAClients[j]->weight_count <=
-                pTLCb->atlSTAClients[j]->weight) {
+                pTLCb->atlSTAClients[j]->weight)
+            {
+               if (pTLCb->atlSTAClients[minWeightSta]->weight <= 1)
+                  minWeightSta = j;
+               else if (pTLCb->atlSTAClients[j]->weight <
+                   pTLCb->atlSTAClients[minWeightSta]->weight) {
+                  minWeightSta = j;
+               }
+               sta_bitmask |= (1 << j);
                pTLCb->atlSTAClients[j]->weight_count++;
                continue;
             }
@@ -11746,6 +11765,34 @@
          return VOS_STATUS_SUCCESS;
       }
 
+      /* Fecth packet from the stations with minimum weight among them */
+      if (pTLCb->atlSTAClients[minWeightSta] &&
+          pTLCb->atlSTAClients[minWeightSta]->ucPktPending)
+      {
+         *pucSTAId = minWeightSta;
+         pTLCb->ucCurrentSTA = minWeightSta;
+         pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC = pTLCb->uCurServedAC;
+
+         for (j = 0; sta_bitmask != 0; sta_bitmask >>= 1, j++)
+         {
+            if (0 == (sta_bitmask & 0x1))
+               continue;
+
+            if (minWeightSta == j)
+               continue;
+            /* To ensure fairness between stations */
+            pTLCb->atlSTAClients[j]->weight_count +=
+                             pTLCb->atlSTAClients[minWeightSta]->weight -
+                             pTLCb->atlSTAClients[minWeightSta]->weight_count;
+         }
+         pTLCb->atlSTAClients[minWeightSta]->weight_count = 0;
+
+         TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
+                    " TL serve one station AC: %d  W: %d StaId: %d",
+                   pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight, pTLCb->ucCurrentSTA ));
+         return VOS_STATUS_SUCCESS;
+      }
+
       ucNextSTA = 0;
       if ( FALSE == isServed )
       {