prima: Adding new queue in TL for handling eapol packets

This fix contains the necessary changes in TL and HDD for adding a
new queue in HDD and netdev for handling frames like epaol, dhcp and
wapi. This new queue is used only in case of a STA interface, for
other interfaces like SAP and IBSS the new queue is currently not
being used. Also, changes are made to not flush packets in HDD queues
before roaming start but to later transmit them after a successful
reassociation.

Change-Id: I2037b1bf63c70b3149d548163484fe08e0c2e80b
CRs-Fixed: 796839
diff --git a/CORE/BAP/src/bapApiData.c b/CORE/BAP/src/bapApiData.c
index 93769a7..1a1e67d 100644
--- a/CORE/BAP/src/bapApiData.c
+++ b/CORE/BAP/src/bapApiData.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -400,6 +400,7 @@
     // Now copy the AC values from the Logical Link context
     *pucAC = pLogLinkContext->btampAC;
     // Now copy the values from the Logical Link context to the MetaInfo 
+    tlMetaInfo->ac = *pucAC;
     tlMetaInfo->ucTID = pLogLinkContext->ucTID;
     tlMetaInfo->ucUP = pLogLinkContext->ucUP;
     tlMetaInfo->ucIsEapol = VOS_FALSE;
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index aa81049..4b1b43e 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -69,8 +69,11 @@
 /** Number of attempts to detect/remove card */
 #define LIBRA_CARD_INSERT_DETECT_MAX_COUNT      5
 #define LIBRA_CARD_REMOVE_DETECT_MAX_COUNT      5
-/** Number of Tx Queues */  
-#define NUM_TX_QUEUES 4
+
+/** Number of Tx Queues. This should be same as the one
+ *  used in TL WLANTL_NUM_TX_QUEUES */
+#define NUM_TX_QUEUES 5
+
 /** HDD's internal Tx Queue Length. Needs to be a power of 2 */
 #define HDD_TX_QUEUE_MAX_LEN 128
 /** HDD internal Tx Queue Low Watermark. Net Device TX queue is disabled
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 30cc232..b5e1286 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1035,6 +1035,56 @@
     complete(&pAdapter->disconnect_comp_var);
     return( status );
 }
+
+static void hdd_postTLPacketPendingInd(hdd_adapter_t *pAdapter,
+                                       v_U8_t staId)
+{
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+    v_SINT_t i;
+    v_SIZE_t size;
+    VOS_STATUS status;
+    v_BOOL_t granted = VOS_FALSE;
+
+    if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
+        (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
+        (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE))
+    {
+        //Indicate to TL that there is pending data if a queue is non empty
+        for (i = WLANTL_AC_HIGH_PRIO; i>=0; --i)
+        {
+            size = 0;
+            hdd_list_size(&pAdapter->wmm_tx_queue[i], &size);
+            if (size > 0)
+            {
+               if (i != WLANTL_AC_HIGH_PRIO)
+               {
+                  if (VOS_FALSE ==
+                      pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessAllowed)
+                  {
+                     hdd_wmm_acquire_access(pAdapter,
+                                           (WLANTL_ACEnumType)i, &granted);
+                     pAdapter->psbChanged |= (1 << i);
+                  }
+                  else
+                     granted = VOS_TRUE;
+               }
+
+               if (granted || (i == WLANTL_AC_HIGH_PRIO))
+               {
+                  status = WLANTL_STAPktPending(pHddCtx->pvosContext,
+                                                staId, (WLANTL_ACEnumType)i);
+                  if (!VOS_IS_STATUS_SUCCESS(status))
+                  {
+                     VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+                               "%s: Failure in indicating pkt to TL for QID=%d",
+                               __func__, i);
+                  }
+               }
+            }
+        }
+    }
+}
+
 static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter,
                                        tCsrRoamInfo *pRoamInfo,
                                        v_U8_t staId,
@@ -1191,6 +1241,8 @@
                                          WLANTL_STA_AUTHENTICATED );
 
       pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE;
+
+      hdd_postTLPacketPendingInd(pAdapter, staDesc.ucSTAId);
    }
    else
    {
@@ -1590,6 +1642,8 @@
                                                    pHddStaCtx->conn_info.staId[ 0 ],
                                                    WLANTL_STA_AUTHENTICATED );
                 pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE;
+                hdd_postTLPacketPendingInd(pAdapter,
+                                           pHddStaCtx->conn_info.staId[0]);
             }
         }
 
@@ -2103,6 +2157,7 @@
    VOS_STATUS vosStatus    = VOS_STATUS_E_FAILURE;
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+   WLANTL_STAStateType prevTLState = WLANTL_STA_INIT;
    ENTER();
 
    if (NULL == pRoamInfo)
@@ -2159,9 +2214,13 @@
          if ( ( eCSR_ROAM_RESULT_AUTHENTICATED == roamResult ) &&
              (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired )
          {
-            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, "Key set "
-                       "for StaId= %d.  Changing TL state to AUTHENTICATED",
-                       pHddStaCtx->conn_info.staId[ 0 ] );
+            WLANTL_GetSTAState(pHddCtx->pvosContext,
+                               pHddStaCtx->conn_info.staId[0],
+                               &prevTLState);
+
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, "Key set "
+                      "for StaId=%d. Changing TL state to AUTHENTICATED from"
+                      " state:%d", pHddStaCtx->conn_info.staId[0], prevTLState);
 
             // Connections that do not need Upper layer authentication,
             // transition TL to 'Authenticated' state after the keys are set.
@@ -2170,6 +2229,10 @@
                                                WLANTL_STA_AUTHENTICATED );
 
             pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE;
+
+            if (WLANTL_STA_AUTHENTICATED != prevTLState)
+                hdd_postTLPacketPendingInd(pAdapter,
+                                           pHddStaCtx->conn_info.staId[0]);
             //Need to call offload because when roaming happen at that time fwr
             //clean offload info as part of the DelBss
             // No need to configure offload if host was not suspended
@@ -2834,23 +2897,21 @@
                     vos_record_roam_event(e_HDD_DISABLE_TX_QUEUE, NULL, 0);
                 }
                 /*
-                 * Deregister for this STA with TL with the objective to flush
-                 * all the packets for this STA from wmm_tx_queue. If not done here,
-                 * we would run into a race condition (CR390567) wherein TX
-                 * thread would schedule packets from wmm_tx_queue AFTER peer STA has
-                 * been deleted. And, these packets get assigned with a STA idx of
-                 * self-sta (since the peer STA has been deleted) and get transmitted
-                 * on the new channel before the reassoc request. Since there will be
-                 * no ACK on the new channel, each packet gets retransmitted which
-                 * takes several seconds before the transmission of reassoc request.
-                 * This leads to reassoc-timeout and roam failure.
+                 * Deregister this STA with TL, but do not flush the packets
+                 * for this STA from wmm_tx_queue. Since there is no valid STA
+                 * for these packets they will not be transmitted. Eventually
+                 * after the reassociation is successful, these packets will be
+                 * transmitted after registering STA with TL again. This ensures
+                 * that driver does not drop packets during roaming.
                  */
-                status = hdd_roamDeregisterSTA( pAdapter, pHddStaCtx->conn_info.staId [0] );
-                if ( !VOS_IS_STATUS_SUCCESS(status ) )
+                status = WLANTL_ClearSTAClient(pHddCtx->pvosContext,
+                                               pHddStaCtx->conn_info.staId[0]);
+                if (!VOS_IS_STATUS_SUCCESS(status))
                 {
-                    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
-                            FL("hdd_roamDeregisterSTA() failed to for staID %d.  Status= %d [0x%x]"),
-                            pHddStaCtx->conn_info.staId[0], status, status );
+                    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                              FL("WLANTL_ClearSTAClient failed for staID %d."
+                              "Status= %d [0x%x]"), pHddStaCtx->conn_info.staId[0],
+                              status, status);
                     halStatus = eHAL_STATUS_FAILURE;
                 }
             }
diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
index a182f9e..56e8c2b 100644
--- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -1380,6 +1380,7 @@
    }
 //xg: @@@@: temporarily disble these. will revisit later
    {
+      pPktMetaInfo->ac = ac;
       pPktMetaInfo->ucUP = pktNode->userPriority;
       pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
    }
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index 225f909..5164879 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -80,6 +80,7 @@
    WLANTL_AC_VI,
    WLANTL_AC_BE,
    WLANTL_AC_BK,
+   WLANTL_AC_HIGH_PRIO,
 };
 
 #define HDD_TX_TIMEOUT_RATELIMIT_INTERVAL 20*HZ
@@ -763,7 +764,7 @@
 int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
    VOS_STATUS status;
-   WLANTL_ACEnumType ac;
+   WLANTL_ACEnumType qid, ac;
    sme_QosWmmUpType up;
    skb_list_node_t *pktNode = NULL;
    hdd_list_node_t *anchor = NULL;
@@ -791,8 +792,17 @@
        return NETDEV_TX_BUSY;
    }
 
-   //Get TL AC corresponding to Qdisc queue index/AC.
-   ac = hdd_QdiscAcToTlAC[skb->queue_mapping];
+   //Get TL Q index corresponding to Qdisc queue index/AC.
+   qid = hdd_QdiscAcToTlAC[skb->queue_mapping];
+   ac  = qid;
+
+   if (qid == WLANTL_AC_HIGH_PRIO)
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                "%s It must be a Eapol/Wapi/DHCP packet device_mode:%d",
+                __func__, pAdapter->device_mode);
+      ac = hddWmmUpToAcMap[skb->priority];
+   }
 
    if (WLAN_HDD_IBSS == pAdapter->device_mode)
    {
@@ -804,7 +814,7 @@
                    "%s: Tx frame in disconnected state in IBSS mode", __func__);
          ++pAdapter->stats.tx_dropped;
          ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
-         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
          kfree_skb(skb);
          return NETDEV_TX_OK;
       }
@@ -825,7 +835,7 @@
                     "%s: Received Unicast frame with invalid staID", __func__);
          ++pAdapter->stats.tx_dropped;
          ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
-         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
          kfree_skb(skb);
          return NETDEV_TX_OK;
       }
@@ -839,7 +849,7 @@
                     pAdapter->device_mode);
          ++pAdapter->stats.tx_dropped;
          ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
-         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
          kfree_skb(skb);
          return NETDEV_TX_OK;
       }
@@ -850,7 +860,7 @@
    //select_queue call back function
    up = skb->priority;
 
-   ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];
+   ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[qid];
 
 #ifdef HDD_WMM_DEBUG
    VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
@@ -862,19 +872,19 @@
        vos_record_roam_event(e_HDD_FIRST_XMIT_TIME, (void *)skb, 0);
    }
 
-   spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
+   spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
    /*CR 463598,384996*/
    /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
     *We check for +1 in the logic,to take care of Zero count which
     *occurs very frequently in low traffic cases */
-   if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
+   if((pAdapter->wmm_tx_queue[qid].count + 1) % 10 == 0)
    {
       /* Use the following debug statement during Engineering Debugging.There are chance that this will lead to a Watchdog Bark
             * if it is in the mainline code and if the log level is enabled by someone for debugging
            VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,"%s:Queue is Filling up.Inform TL again about pending packets", __func__);*/
 
       status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
-                                    STAId, ac
+                                    STAId, qid
                                     );
       if ( !VOS_IS_STATUS_SUCCESS( status ) )
       {
@@ -883,30 +893,30 @@
                     __func__, status);
          ++pAdapter->stats.tx_dropped;
          ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
-         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
          kfree_skb(skb);
-         spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+         spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
          return NETDEV_TX_OK;
       }
    }
    //If we have already reached the max queue size, disable the TX queue
-   if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
+   if ( pAdapter->wmm_tx_queue[qid].count == pAdapter->wmm_tx_queue[qid].max_size)
    {
          ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
-         ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];
-         hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for ac %d"),ac);
+         ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[qid];
+         hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queue for QId %d"), qid);
          netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
-         pAdapter->isTxSuspended[ac] = VOS_TRUE;
+         pAdapter->isTxSuspended[qid] = VOS_TRUE;
          txSuspended = VOS_TRUE;
          MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_NETDEV,
-                          pAdapter->sessionId, ac));
+                          pAdapter->sessionId, qid));
    }
 
    /* If 3/4th of the max queue size is used then enable the flag.
     * This flag indicates to place the DHCP packets in VOICE AC queue.*/
-   if (WLANTL_AC_BE == ac)
+   if (WLANTL_AC_BE == qid)
    {
-      if (pAdapter->wmm_tx_queue[ac].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
+      if (pAdapter->wmm_tx_queue[qid].count >= HDD_TX_QUEUE_LOW_WATER_MARK)
       {
           pAdapter->isVosLowResource = VOS_TRUE;
       }
@@ -916,7 +926,7 @@
       }
    }
 
-   spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+   spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
 
    if (( NULL != pHddCtx ) &&
       (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_PROTO_TYPE_DHCP))
@@ -927,8 +937,8 @@
    if (VOS_TRUE == txSuspended)
    {
        VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
-                  "%s: TX queue full for AC=%d Disable OS TX queue",
-                  __func__, ac );
+                  "%s: TX queue full for QId=%d Disable OS TX queue",
+                  __func__, qid );
       return NETDEV_TX_BUSY;
    }
 
@@ -945,22 +955,22 @@
    INIT_LIST_HEAD(&pktNode->anchor);
 
    //Insert the OS packet into the appropriate AC queue
-   spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
-   status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
-   spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+   spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
+   status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[qid], &pktNode->anchor, &pktListSize );
+   spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
 
    if ( !VOS_IS_STATUS_SUCCESS( status ) )
    {
       VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
       ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
-      ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+      ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
       ++pAdapter->stats.tx_dropped;
       kfree_skb(skb);
       return NETDEV_TX_OK;
    }
 
    ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
-   ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];
+   ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[qid];
    ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count;
 
    if (HDD_PSB_CHANGED == pAdapter->psbChanged)
@@ -985,22 +995,24 @@
    }
 
    if ( (granted && ( pktListSize == 1 )) ||
-        (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
+        (pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE) ||
+        (qid == WLANTL_AC_HIGH_PRIO))
    {
       //Let TL know we have a packet to send for this AC
       //VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __func__);
       status = WLANTL_STAPktPending(
                                   (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
-                                   STAId, ac );
+                                   STAId, qid );
       if ( !VOS_IS_STATUS_SUCCESS( status ) )
       {
-         VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d", __func__, ac );
+         VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
+                   "%s: Failed to signal TL for QId=%d", __func__, qid );
 
          //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
          //as we are in a soft irq context. Also it must be the same packet that we just allocated.
-         spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
-         status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
-         spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
+         spin_lock(&pAdapter->wmm_tx_queue[qid].lock);
+         status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[qid], &anchor );
+         spin_unlock(&pAdapter->wmm_tx_queue[qid].lock);
          /* Free the skb only if we are able to remove it from the list.
           * If we are not able to retrieve it from the list it means that
           * the skb was pulled by TX Thread and is use so we should not free
@@ -1014,7 +1026,7 @@
          }
          ++pAdapter->stats.tx_dropped;
          ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
-         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
+         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
          return NETDEV_TX_OK;
       }
    }
@@ -1577,6 +1589,7 @@
    v_U16_t packet_size;
    tANI_U8   acAdmitted, i;
    v_U8_t proto_type = 0;
+   WLANTL_ACEnumType actualAC;
 
    //Sanity check on inputs
    if ( ( NULL == vosContext ) || 
@@ -1611,10 +1624,10 @@
    *ppVosPacket = NULL;
 
    //Make sure the AC being asked for is sane
-   if( ac >= WLANTL_MAX_AC || ac < 0)
+   if (ac > WLANTL_AC_HIGH_PRIO || ac < 0)
    {
       VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
-                            "%s: Invalid AC %d passed by TL", __func__, ac);
+                            "%s: Invalid QId %d passed by TL", __func__, ac);
       return VOS_STATUS_E_FAILURE;
    }
 
@@ -1625,23 +1638,6 @@
                               "%s: AC %d passed by TL", __func__, ac);
 #endif // HDD_WMM_DEBUG
 
-   // We find an AC with packets
-   // or we determine we have no more packets to send
-   // HDD is not allowed to change AC.
-
-   // has this AC been admitted? or 
-   // To allow EAPOL packets when not authenticated
-   if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
-                (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
-   {
-      ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
-#ifdef HDD_WMM_DEBUG
-      VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
-                 "%s: no packets pending", __func__);
-#endif // HDD_WMM_DEBUG
-      return VOS_STATUS_E_FAILURE;
-   }
-      
    // do we have any packets pending in this AC?
    hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size ); 
    if( size >  0 )
@@ -1662,6 +1658,30 @@
       return VOS_STATUS_E_FAILURE;
    }
 
+   // Note here that we are not checking "wmmAcAccessAllowed" for packets
+   // in new queue since there is no one AC associated to the new queue.
+   // Since there will be either eapol or dhcp pkts in new queue overlooking
+   // this should be okay from implicit QoS perspective.
+   if (ac != WLANTL_AC_HIGH_PRIO)
+   {
+      // We find an AC with packets
+      // or we determine we have no more packets to send
+      // HDD is not allowed to change AC.
+
+      // has this AC been admitted? or
+      // To allow EAPOL packets when not authenticated
+      if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) &&
+                   (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated))
+      {
+         ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty;
+#ifdef HDD_WMM_DEBUG
+         VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
+                    "%s: no packets pending", __func__);
+#endif // HDD_WMM_DEBUG
+         return VOS_STATUS_E_FAILURE;
+      }
+   }
+
    //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources 
    //This simplifies the locking and unlocking of Tx queue
    status = vos_pkt_wrap_data_packet( &pVosPacket, 
@@ -1690,6 +1710,14 @@
       //If success then we got a valid packet from some AC
       pktNode = list_entry(anchor, skb_list_node_t, anchor);
       skb = pktNode->skb;
+      actualAC = hddWmmUpToAcMap[pktNode->userPriority];
+      if (actualAC >= WLANTL_MAX_AC)
+      {
+         /* To fix klocwork */
+         VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
+         "%s: Invalid AC for packet:%d", __func__, actualAC);
+         actualAC = WLANTL_AC_BE;
+      }
    }
    else
    {
@@ -1728,7 +1756,7 @@
         */
        if (vos_is_macaddr_group(pDestMacAddress))
        {
-            pAdapter->hdd_stats.hddTxRxStats.txMcast[ac]++;
+            pAdapter->hdd_stats.hddTxRxStats.txMcast[actualAC]++;
        }
 
    }
@@ -1815,10 +1843,10 @@
     *    delts Applications have to again do Addts or STA will never
     *    go for Addts.
     */
-
-   if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired ||
-      (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid &&
-       pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecInfo.medium_time))
+   pPktMetaInfo->ac = actualAC;
+   if(!pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcAccessRequired ||
+      (pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid &&
+       pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecInfo.medium_time))
    {
       pPktMetaInfo->ucUP = pktNode->userPriority;
       pPktMetaInfo->ucTID = pPktMetaInfo->ucUP;
@@ -1826,9 +1854,9 @@
    else
    {
      //Downgrade the UP
-      acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid;
+      acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[actualAC].wmmAcTspecValid;
       newAc = WLANTL_AC_BK;
-      for (i=ac-1; i>0; i--)
+      for (i=actualAC-1; i>0; i--)
       {
          if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0)
          {
diff --git a/CORE/HDD/src/wlan_hdd_wmm.c b/CORE/HDD/src/wlan_hdd_wmm.c
index b95d798..b709a53 100644
--- a/CORE/HDD/src/wlan_hdd_wmm.c
+++ b/CORE/HDD/src/wlan_hdd_wmm.c
@@ -130,13 +130,21 @@
 {
    hdd_adapter_t* pAdapter = pQosContext->pAdapter;
    WLANTL_ACEnumType acType = pQosContext->acType;
-   hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+   hdd_wmm_ac_status_t *pAc = NULL;
    VOS_STATUS status;
    v_U32_t service_interval;
    v_U32_t suspension_interval;
    sme_QosWmmDirType direction;
    v_BOOL_t psb;
 
+   if (acType >= WLANTL_MAX_AC)
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Invalid AC: %d", __func__, acType);
+      return;
+   }
+
+   pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
 
    // The TSPEC must be valid
    if (pAc->wmmAcTspecValid == VOS_FALSE)
@@ -250,13 +258,22 @@
 {
    hdd_adapter_t* pAdapter = pQosContext->pAdapter;
    WLANTL_ACEnumType acType = pQosContext->acType;
-   hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+   hdd_wmm_ac_status_t *pAc = NULL;
    VOS_STATUS status;
    v_U32_t service_interval;
    v_U32_t suspension_interval;
    v_U8_t uapsd_mask;
    v_U8_t ActiveTspec = INVALID_TSPEC;
 
+   if (acType >= WLANTL_MAX_AC)
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Invalid AC: %d", __func__, acType);
+      return;
+   }
+
+   pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
    // have we previously enabled UAPSD?
    if (pAc->wmmAcUapsdInfoValid == VOS_TRUE)
    {
@@ -293,6 +310,10 @@
             service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv;
             suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv;
             break;
+         default:
+            VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                    "%s: Invalid AC %d", __func__, acType );
+            return;
          }
 
          status = WLANTL_EnableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
@@ -1480,7 +1501,6 @@
       qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVi;
       qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv;
       break;
-   default:
    case WLANTL_AC_BE:
       qosInfo.ts_info.up = SME_QOS_WMM_UP_BE;
       /* Check if there is any valid configuration from framework */
@@ -1515,6 +1535,10 @@
       qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBk;
       qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv;
       break;
+   default:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Invalid AC %d", __func__, acType );
+      return;
    }
 #ifdef FEATURE_WLAN_ESE
    qosInfo.inactivity_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraInactivityInterval;
@@ -1790,14 +1814,14 @@
 }
 
 /**============================================================================
-  @brief is_dhcp_packet() - Function which will check OS packet for
+  @brief hdd_is_dhcp_packet() - Function which will check OS packet for
   DHCP packet
 
   @param skb      : [in]  pointer to OS packet (sk_buff)
   @return         : VOS_TRUE if the OS packet is DHCP packet
                   : otherwise VOS_FALSE
   ===========================================================================*/
-v_BOOL_t is_dhcp_packet(struct sk_buff *skb)
+v_BOOL_t hdd_is_dhcp_packet(struct sk_buff *skb)
 {
    if (*((u16*)((u8*)skb->data+34)) == DHCP_SOURCE_PORT ||
        *((u16*)((u8*)skb->data+34)) == DHCP_DESTINATION_PORT)
@@ -1807,6 +1831,28 @@
 }
 
 /**============================================================================
+  @brief hdd_skb_is_eapol_or_wai_packet() - Function which will check OS packet
+  for Eapol/Wapi packet
+
+  @param skb      : [in]  pointer to OS packet (sk_buff)
+  @return         : VOS_TRUE if the OS packet is an Eapol or a Wapi packet
+                  : otherwise VOS_FALSE
+  ===========================================================================*/
+v_BOOL_t hdd_skb_is_eapol_or_wai_packet(struct sk_buff *skb)
+{
+    if ((*((u16*)((u8*)skb->data+HDD_ETHERTYPE_802_1_X_FRAME_OFFSET))
+         == vos_cpu_to_be16(HDD_ETHERTYPE_802_1_X))
+#ifdef FEATURE_WLAN_WAPI
+         || (*((u16*)((u8*)skb->data+HDD_ETHERTYPE_802_1_X_FRAME_OFFSET))
+         == vos_cpu_to_be16(HDD_ETHERTYPE_WAI))
+#endif
+       )
+       return VOS_TRUE;
+
+    return VOS_FALSE;
+}
+
+/**============================================================================
   @brief hdd_wmm_classify_pkt() - Function which will classify an OS packet
   into a WMM AC based on either 802.1Q or DSCP
 
@@ -2045,7 +2091,7 @@
       /* Get the user priority from IP header & corresponding AC */
       hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
       //If 3/4th of Tx queue is used then place the DHCP packet in VOICE AC queue
-      if (pSapCtx->aStaInfo[STAId].vosLowResource && is_dhcp_packet(skb))
+      if (pSapCtx->aStaInfo[STAId].vosLowResource && hdd_is_dhcp_packet(skb))
       {
          VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
                     "%s: Making priority of DHCP packet as VOICE", __func__);
@@ -2120,10 +2166,14 @@
    /* All traffic will get equal opportuniy to transmit data frames. */
    /* Get the user priority from IP header & corresponding AC */
    hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
+
    /* If 3/4th of BE AC Tx queue is full,
-    * then place the DHCP packet in VOICE AC queue
+    * then place the DHCP packet in VOICE AC queue.
+    * Doing this for IBSS alone, since for STA interface
+    * types, these packets will be queued to the new queue.
     */
-   if (pAdapter->isVosLowResource && is_dhcp_packet(skb))
+   if ((WLAN_HDD_IBSS == pAdapter->device_mode) &&
+       pAdapter->isVosLowResource && hdd_is_dhcp_packet(skb))
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
                 "%s: BestEffort Tx Queue is 3/4th full"
@@ -2131,6 +2181,7 @@
       up = SME_QOS_WMM_UP_VO;
       ac = hddWmmUpToAcMap[up];
    }
+
 done:
    skb->priority = up;
    if(skb->priority < SME_QOS_WMM_UP_MAX)
@@ -2142,6 +2193,19 @@
       queueIndex = hddLinuxUpToAcMap[SME_QOS_WMM_UP_BE];
    }
 
+   if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
+       (hdd_is_dhcp_packet(skb) ||
+        hdd_skb_is_eapol_or_wai_packet(skb)))
+   {
+       /* If the packet is a DHCP packet or a Eapol packet or
+        * a Wapi packet, then queue it to the new queue for
+        * STA interfaces alone.
+        */
+       queueIndex = WLANTL_AC_HIGH_PRIO;
+       VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                 "%s: up=%d QIndex:%d", __func__, up, queueIndex);
+   }
+
    return queueIndex;
 }
 
diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h
index d29aea5..b818e48 100644
--- a/CORE/SAP/src/sapInternal.h
+++ b/CORE/SAP/src/sapInternal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -80,6 +80,8 @@
 #include "sapFsm_ext.h"
 #include "sapChSelect.h"
 #include "wlan_hdd_dp_utils.h"
+#include "wlan_hdd_main.h"
+
 /*----------------------------------------------------------------------------
  * Preprocessor Definitions and Constants
  * -------------------------------------------------------------------------*/
@@ -160,16 +162,13 @@
     WLANTL_STAStateType tlSTAState;
 
    /** Transmit queues for each AC (VO,VI,BE etc). */
-   //hdd_list_t wmm_tx_queue[NUM_TX_QUEUES];
-   hdd_list_t wmm_tx_queue[4];
+   hdd_list_t wmm_tx_queue[NUM_TX_QUEUES];
 
    /** Might need to differentiate queue depth in contention case */
-   //v_U16_t aTxQueueDepth[NUM_TX_QUEUES];
-   v_U16_t aTxQueueDepth[4];
+   v_U16_t aTxQueueDepth[NUM_TX_QUEUES];
 
    /**Track whether OS TX queue has been disabled.*/
-   //v_BOOL_t txSuspended[NUM_TX_QUEUES];
-   v_BOOL_t txSuspended[4];
+   v_BOOL_t txSuspended[NUM_TX_QUEUES];
 
    /**Track whether 3/4th of resources are used */
    v_BOOL_t vosLowResource;
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index fec61af..46c070b 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -102,7 +102,10 @@
 #define WLANTL_LLC_SNAP_OFFSET                0
 
 /*Size of the LLC/SNAP header*/
-#define WLANTL_LLC_SNAP_SIZE                   8
+#define WLANTL_LLC_SNAP_SIZE                  8
+
+/* Number of Tx Queues, this should be same as NUM_TX_QUEUES in HDD */
+#define WLANTL_NUM_TX_QUEUES                  5
 
 /*============================================================================
  *     GENERIC STRUCTURES - not belonging to TL 
@@ -153,10 +156,18 @@
  --------------------------------------------------------------------------*/
 typedef enum
 {
+  /* The values from 0-3 correspond both to the TL tx queue
+   * id and the also the AC corresponding to the packets queued
+   */
   WLANTL_AC_BK = 0,
   WLANTL_AC_BE = 1,
   WLANTL_AC_VI = 2,
-  WLANTL_AC_VO = 3
+  WLANTL_AC_VO = 3,
+  /* WLANTL_AC_HIGH_PRIO corresponds to the new queue
+   * added for handling eapol/wapi/dhcp packets. The AC for the
+   * packets in this queue has to be extracted separately
+   */
+  WLANTL_AC_HIGH_PRIO = 4
 }WLANTL_ACEnumType; 
 
 typedef struct
@@ -308,7 +319,7 @@
 typedef struct
 {
   /*AC weight for WFQ*/
-  v_U8_t   ucAcWeights[WLANTL_MAX_AC]; 
+  v_U8_t   ucAcWeights[WLANTL_NUM_TX_QUEUES];
 
   /*Delayed trigger frame timmer: - used by TL to send trigger frames less 
     often when it has established that the App is suspended*/
@@ -407,6 +418,9 @@
 ---------------------------------------------------------------------------*/      
 typedef struct
 {
+  /* Save the AC of the packet */
+  WLANTL_ACEnumType ac;
+
   /* TID of the packet being sent */
   v_U8_t    ucTID;
 
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index 1d4a815..3378207 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -215,7 +215,7 @@
 /*MAX Allowed len processed by TL - MAx MTU + 802.3 header + BD+DXE+XTL*/
 #define WLANTL_MAX_ALLOWED_LEN    (1514 + 100)
 
-#define WLANTL_MASK_AC  0x03
+#define WLANTL_DATA_FLOW_MASK 0x0F
 
 //some flow_control define
 //LWM mode will be enabled for this station if the egress/ingress falls below this ratio
@@ -320,7 +320,7 @@
   do\
   {\
     _ucACMask = 0; \
-    for ( i = 0; i < WLANTL_MAX_AC; i++ ) \
+    for ( i = 0; i < WLANTL_NUM_TX_QUEUES; i++ ) \
     { \
       if ( 0 != (_pSTA)->aucACMask[i] ) \
       { \
@@ -529,7 +529,7 @@
 
   WLANTL_CleanCB(pTLCb, 0 /*do not empty*/);
 
-  for ( ucIndex = 0; ucIndex < WLANTL_MAX_AC ; ucIndex++)
+  for ( ucIndex = 0; ucIndex < WLANTL_NUM_TX_QUEUES ; ucIndex++)
   {
     pTLCb->tlConfigInfo.ucAcWeights[ucIndex] = pTLConfig->ucAcWeights[ucIndex];
   }
@@ -1382,7 +1382,7 @@
       made in the main TL loop after the supported mask is properly
       updated in the pending packets call
     --------------------------------------------------------------------*/
-  pClientSTA->ucCurrentAC     = WLANTL_AC_VO;
+  pClientSTA->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
   pClientSTA->ucCurrentWeight = 0;
   pClientSTA->ucServicedAC    = WLANTL_AC_BK;
   pClientSTA->ucEapolPktPending = 0;
@@ -4457,21 +4457,34 @@
         /* Serve EAPOL frame with HI_FLOW_MASK */
         ucSTAId = i;
 
-        MTRACE(vos_trace(VOS_MODULE_ID_TL,
-                   TRACE_CODE_TL_GET_FRAMES_EAPOL, ucSTAId, pTLCb->atlSTAClients[i]->tlState));
-
-        for (j = WLANTL_MAX_AC ; j > 0; j--)
-        {
-          if (0 != pTLCb->atlSTAClients[ucSTAId]->aucACMask[j-1])
-          {
-            pTLCb->atlSTAClients[ucSTAId]->ucCurrentAC = j-1;
-            pTLCb->uCurServedAC = j-1;
-            break;
-          }
-        }
-
         pClientSTA = pTLCb->atlSTAClients[ucSTAId];
 
+        MTRACE(vos_trace(VOS_MODULE_ID_TL,
+               TRACE_CODE_TL_GET_FRAMES_EAPOL, ucSTAId, pClientSTA->tlState));
+
+        if (pClientSTA->wSTADesc.wSTAType == WLAN_STA_INFRA)
+        {
+            if(0 != pClientSTA->aucACMask[WLANTL_AC_HIGH_PRIO])
+            {
+              pClientSTA->ucCurrentAC = WLANTL_AC_HIGH_PRIO;
+              pTLCb->uCurServedAC = WLANTL_AC_HIGH_PRIO;
+            }
+            else
+                break;
+        }
+        else
+        {
+            for (j = WLANTL_MAX_AC ; j > 0; j--)
+            {
+              if (0 != pClientSTA->aucACMask[j-1])
+              {
+                pClientSTA->ucCurrentAC = j-1;
+                pTLCb->uCurServedAC = j-1;
+                break;
+              }
+            }
+        }
+
         wSTAEvent = WLANTL_TX_EVENT;
 
         pfnSTAFsm = tlSTAFsm[pClientSTA->tlState].
@@ -4545,10 +4558,7 @@
 
     else if (( WDA_TLI_MIN_RES_DATA <= pTLCb->uResCount ) &&
              ( 0 == pTLCb->ucTxSuspended ) &&
-             (( uFlowMask & ( 1 << WDA_TXFLOW_AC_BK ) ) ||
-              ( uFlowMask & ( 1 << WDA_TXFLOW_AC_BE ) ) ||
-              ( uFlowMask & ( 1 << WDA_TXFLOW_AC_VI ) ) ||
-              ( uFlowMask & ( 1 << WDA_TXFLOW_AC_VO ) )) )
+             ( uFlowMask & WLANTL_DATA_FLOW_MASK))
     {
       /*---------------------------------------------------------------------
         Check to see if there was any packet left behind previously due to
@@ -4658,7 +4668,7 @@
 
         if ( ( pTLCb->uResCount >= (uResLen + WDA_TLI_MIN_RES_BAP ) ) &&
              ( uRemaining > uTotalPktLen ) &&
-             ( uFlowMask & ( 1 << ucAC ) ) )
+             ( uFlowMask & WLANTL_DATA_FLOW_MASK ) )
         {
           TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                     "WLAN TL:Chaining data frame on GetFrame"));
@@ -4721,10 +4731,7 @@
       /* TL is starving even when DXE is not in low resource condition 
          Return min resource number required and Let DXE deceide what to do */
       if(( 0 == pTLCb->ucTxSuspended ) && 
-         (( uFlowMask & ( 1 << WDA_TXFLOW_AC_BK ) ) || 
-          ( uFlowMask & ( 1 << WDA_TXFLOW_AC_BE ) ) ||
-          ( uFlowMask & ( 1 << WDA_TXFLOW_AC_VI ) ) || 
-          ( uFlowMask & ( 1 << WDA_TXFLOW_AC_VO ) )))
+         ( uFlowMask & WLANTL_DATA_FLOW_MASK ) )
       {
          TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "WLAN TL:Returning from GetFrame: resources = %d",
@@ -7496,7 +7503,7 @@
     Even if this AC is not supported by the station, correction will be
     made in the main TL loop
     --------------------------------------------------------------------*/
-    pClientSTA->ucCurrentAC     = WLANTL_AC_VO;
+    pClientSTA->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
     pClientSTA->ucCurrentWeight = 0;
 
     VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
@@ -7839,8 +7846,8 @@
   {
 
     VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
-               "WLAN TL:Failed while attempting to fetch pkt from HDD %d",
-                   vosStatus);
+               "WLAN TL:Failed while attempting to fetch pkt from HDD QId:%d status:%d",
+               ucAC, vosStatus);
     *pvosDataBuff = NULL;
     /*--------------------------------------------------------------------
       Reset AC for the serviced station to the highest priority AC
@@ -7848,7 +7855,7 @@
       Even if this AC is not supported by the station, correction will be
       made in the main TL loop
     --------------------------------------------------------------------*/
-    pStaClient->ucCurrentAC     = WLANTL_AC_VO;
+    pStaClient->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
     pStaClient->ucCurrentWeight = 0;
 
     return vosStatus;
@@ -7913,7 +7920,11 @@
     -----------------------------------------------------------------------*/
     while ( 0 != ucACMask ) 
     {
-      ucNextAC = (WLANTL_ACEnumType)(( tempAC - 1 ) & WLANTL_MASK_AC); 
+      if(tempAC == WLANTL_AC_BK)
+         ucNextAC = WLANTL_AC_HIGH_PRIO;
+      else
+         ucNextAC = (tempAC - 1);
+
       if ( 0 != pStaClient->aucACMask[ucNextAC] )
       {
          pStaClient->ucCurrentAC     = ucNextAC;
@@ -8037,7 +8048,11 @@
     ucTypeSubtype |= (WLANTL_80211_DATA_QOS_SUBTYPE);
   }
 
-  ucTxFlag  = (0 != pStaClient->wUAPSDInfo[ucAC].ucSet)?
+  /* ucAC now points to TL Q ID with a new queue added in TL,
+   * hence look for the uapsd info for the correct AC that
+   * this packet belongs to.
+   */
+  ucTxFlag  = (0 != pStaClient->wUAPSDInfo[tlMetaInfo.ac].ucSet)?
               HAL_TRIGGER_ENABLED_AC_MASK:0;
 
 #ifdef FEATURE_WLAN_WAPI
@@ -10770,7 +10785,7 @@
   v_U8_t          ucACFilter = 1;
   v_U8_t          ucNextSTA ; 
   v_BOOL_t        isServed = TRUE;  //current round has find a packet or not
-  v_U8_t          ucACLoopNum = WLANTL_AC_VO + 1; //number of loop to go
+  v_U8_t          ucACLoopNum = WLANTL_AC_HIGH_PRIO + 1; //number of loop to go
   v_U8_t          uFlowMask; // TX FlowMask from WDA
   uint8           ucACMask; 
   uint8           i = 0; 
@@ -10794,6 +10809,22 @@
     return VOS_STATUS_E_FAULT;
   }
 
+  /* The flow mask does not differentiate between different ACs/Qs
+   * since we use a single dxe channel for all ACs/Qs, hence it is
+   * enough to check that there are dxe resources on data channel
+   */
+  uFlowMask &= WLANTL_DATA_FLOW_MASK;
+
+  if (0 == uFlowMask)
+  {
+    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+           "WLAN TL: No resources to send packets"));
+
+    // Setting STA Id to invalid if mask is 0
+    *pucSTAId = WLAN_MAX_STA_COUNT;
+    return VOS_STATUS_E_FAULT;
+  }
+
   ucNextSTA = pTLCb->ucCurrentSTA;
 
   ++ucNextSTA;
@@ -10810,7 +10841,7 @@
       if ( WLANTL_AC_BK == (WLANTL_ACEnumType)pTLCb->uCurServedAC )
       {
         //end of current VO, VI, BE, BK loop. Reset priority.
-        pTLCb->uCurServedAC = WLANTL_AC_VO;
+        pTLCb->uCurServedAC = WLANTL_AC_HIGH_PRIO;
       }
       else 
       {
@@ -10837,7 +10868,7 @@
     ucACFilter = 1 << pTLCb->uCurServedAC;
 
     // pTLCb->ucCurLeftWeight keeps previous results.
-    for (; (pTLCb->ucCurLeftWeight > 0) && (uFlowMask & ucACFilter); pTLCb->ucCurLeftWeight-- )
+    for (; (pTLCb->ucCurLeftWeight > 0) ; pTLCb->ucCurLeftWeight-- )
     {
 
       for ( ; ucNextSTA < WLAN_MAX_STA_COUNT; ucNextSTA ++ )
@@ -10903,7 +10934,7 @@
 
     if (WLANTL_AC_BK == pTLCb->uCurServedAC)
     {
-      pTLCb->uCurServedAC = WLANTL_AC_VO;
+      pTLCb->uCurServedAC = WLANTL_AC_HIGH_PRIO;
     }
     else
     {
@@ -11010,6 +11041,22 @@
     return VOS_STATUS_E_FAULT;
   }
 
+  /* The flow mask does not differentiate between different ACs/Qs
+   * since we use a single dxe channel for all ACs/Qs, hence it is
+   * enough to check that there are dxe resources on data channel
+   */
+  uFlowMask &= WLANTL_DATA_FLOW_MASK;
+
+  if (0 == uFlowMask)
+  {
+    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+      "WLAN TL: No resources to send packets"));
+
+    // Setting STA id to invalid if mask is 0
+    *pucSTAId = WLAN_MAX_STA_COUNT;
+    return VOS_STATUS_E_FAULT;
+  }
+
   /*STA id - no priority yet implemented */
   /*-----------------------------------------------------------------------
     Choose the next STA for tx - for now go in a round robin fashion
@@ -11099,7 +11146,7 @@
              " AC Mask: %d Next: %d Res : %d",
                ucACMask, ( 1 << ucNextAC ), ( ucACMask & ( 1 << ucNextAC ))));
 
-    if ( 0 != ( ucACMask & ( 1 << ucNextAC ) & uFlowMask ))
+    if ( 0 != ( ucACMask & ( 1 << ucNextAC )))
     {
        pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC     =
                                    (WLANTL_ACEnumType)ucNextAC;
@@ -11113,11 +11160,13 @@
        break;
     }
 
-    ucNextAC = ( ucNextAC - 1 ) & WLANTL_MASK_AC;
+    if (ucNextAC == WLANTL_AC_BK)
+        ucNextAC = WLANTL_AC_HIGH_PRIO;
+    else
+        ucNextAC--;
 
     TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                "Next AC %d", ucNextAC));
-
   }
 
   TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
@@ -11550,7 +11599,7 @@
   /*-------------------------------------------------------------------------
      QOS information for the STA
     -------------------------------------------------------------------------*/
-   ptlSTAClient->ucCurrentAC     = WLANTL_AC_VO;
+   ptlSTAClient->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
    ptlSTAClient->ucCurrentWeight = 0;
    ptlSTAClient->ucServicedAC    = WLANTL_AC_BK;
 
@@ -12571,6 +12620,7 @@
     pTLCb->tlConfigInfo.ucAcWeights[ucIndex] = pACWeights[ucIndex];
   }
 
+  pTLCb->tlConfigInfo.ucAcWeights[WLANTL_AC_HIGH_PRIO] = pACWeights[WLANTL_AC_VO];
   return VOS_STATUS_SUCCESS;
 }
 
diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h
index 704a51a..93794d2 100644
--- a/CORE/TL/src/wlan_qct_tli.h
+++ b/CORE/TL/src/wlan_qct_tli.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -584,7 +584,7 @@
   v_U8_t                        ucMPDUHeaderLen;
 
   /* Enabled ACs currently serviced by TL (automatic setup in TL)*/
-  v_U8_t                        aucACMask[WLANTL_MAX_AC];
+  v_U8_t                        aucACMask[WLANTL_NUM_TX_QUEUES];
 
   /* Current AC to be retrieved */
   WLANTL_ACEnumType             ucCurrentAC;
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 190062b..4c08e50 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1940,6 +1940,7 @@
   pTLConfig->ucAcWeights[1] = pConfig->WfqBeWeight;
   pTLConfig->ucAcWeights[2] = pConfig->WfqViWeight;
   pTLConfig->ucAcWeights[3] = pConfig->WfqVoWeight;
+  pTLConfig->ucAcWeights[4] = pConfig->WfqVoWeight;
   pTLConfig->ucReorderAgingTime[0] = pConfig->BkReorderAgingTime;/*WLANTL_AC_BK*/
   pTLConfig->ucReorderAgingTime[1] = pConfig->BeReorderAgingTime;/*WLANTL_AC_BE*/
   pTLConfig->ucReorderAgingTime[2] = pConfig->ViReorderAgingTime;/*WLANTL_AC_VI*/