prima: WLAN Driver Release 3.1.7.9

This is the initial release of the Prima WLAN Driver
diff --git a/CORE/HDD/src/wlan_hdd_wmm.c b/CORE/HDD/src/wlan_hdd_wmm.c
new file mode 100644
index 0000000..c8da218
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_wmm.c
@@ -0,0 +1,2501 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*============================================================================
+  @file wlan_hdd_wmm.c
+
+  This module (wlan_hdd_wmm.h interface + wlan_hdd_wmm.c implementation)
+  houses all the logic for WMM in HDD.
+
+  On the control path, it has the logic to setup QoS, modify QoS and delete
+  QoS (QoS here refers to a TSPEC). The setup QoS comes in two flavors: an
+  explicit application invoked and an internal HDD invoked.  The implicit QoS
+  is for applications that do NOT call the custom QCT WLAN OIDs for QoS but
+  which DO mark their traffic for priortization. It also has logic to start,
+  update and stop the U-APSD trigger frame generation. It also has logic to
+  read WMM related config parameters from the registry.
+
+  On the data path, it has the logic to figure out the WMM AC of an egress
+  packet and when to signal TL to serve a particular AC queue. It also has the
+  logic to retrieve a packet based on WMM priority in response to a fetch from
+  TL.
+
+  The remaining functions are utility functions for information hiding.
+
+
+               Copyright (c) 2008-9 QUALCOMM Incorporated.
+               All Rights Reserved.
+               Qualcomm Confidential and Proprietary
+============================================================================*/
+
+/*---------------------------------------------------------------------------
+  Include files
+  -------------------------------------------------------------------------*/
+#include <wlan_hdd_tx_rx.h>
+#include <wlan_hdd_dp_utils.h>
+#include <wlan_hdd_wmm.h>
+#include <wlan_hdd_ether.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/semaphore.h>
+#include <wlan_hdd_hostapd.h>
+#ifdef FEATURE_WLAN_INTEGRATED_SOC
+#include <wlan_hdd_softap_tx_rx.h>
+#endif
+
+// change logging behavior based upon debug flag
+#ifdef HDD_WMM_DEBUG
+#define WMM_TRACE_LEVEL_FATAL      VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_ERROR      VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_WARN       VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_INFO       VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_INFO_HIGH  VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_INFO_LOW   VOS_TRACE_LEVEL_FATAL
+#else
+#define WMM_TRACE_LEVEL_FATAL      VOS_TRACE_LEVEL_FATAL
+#define WMM_TRACE_LEVEL_ERROR      VOS_TRACE_LEVEL_ERROR
+#define WMM_TRACE_LEVEL_WARN       VOS_TRACE_LEVEL_WARN
+#define WMM_TRACE_LEVEL_INFO       VOS_TRACE_LEVEL_INFO
+#define WMM_TRACE_LEVEL_INFO_HIGH  VOS_TRACE_LEVEL_INFO_HIGH
+#define WMM_TRACE_LEVEL_INFO_LOW   VOS_TRACE_LEVEL_INFO_LOW
+#endif
+
+
+// UAPSD Mask bits
+// (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored)
+#define HDD_AC_VO 0x1
+#define HDD_AC_VI 0x2
+#define HDD_AC_BK 0x4
+#define HDD_AC_BE 0x8
+
+#define WLAN_HDD_MAX_DSCP 0x3f
+
+static sme_QosWmmUpType hddWmmDscpToUpMap[WLAN_HDD_MAX_DSCP+1];
+
+const v_U8_t hddWmmUpToAcMap[] = {
+   WLANTL_AC_BE,
+   WLANTL_AC_BK,
+   WLANTL_AC_BK,
+   WLANTL_AC_BE,
+   WLANTL_AC_VI,
+   WLANTL_AC_VI,
+   WLANTL_AC_VO,
+   WLANTL_AC_VO
+};
+
+//Linux based UP -> AC Mapping
+const v_U8_t hddLinuxUpToAcMap[8] = {
+   HDD_LINUX_AC_BE,
+   HDD_LINUX_AC_BK,
+   HDD_LINUX_AC_BK,
+   HDD_LINUX_AC_BE,
+   HDD_LINUX_AC_VI,
+   HDD_LINUX_AC_VI,
+   HDD_LINUX_AC_VO,
+   HDD_LINUX_AC_VO
+};
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+/**
+  @brief hdd_wmm_enable_tl_uapsd() - function which decides whether and
+  how to update UAPSD parameters in TL
+
+  @param pQosContext : [in] the pointer the QoS instance control block
+
+  @return
+  None
+*/
+static void hdd_wmm_enable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext)
+{
+   hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+   WLANTL_ACEnumType acType = pQosContext->acType;
+   hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+   VOS_STATUS status;
+   v_U32_t service_interval;
+   v_U32_t suspension_interval;
+   sme_QosWmmDirType direction;
+
+
+   // The TSPEC must be valid
+   if (pAc->wmmAcTspecValid == VOS_FALSE)
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Invoked with invalid TSPEC",
+                __FUNCTION__);
+      return;
+   }
+
+   // determine the service interval
+   if (pAc->wmmAcTspecInfo.min_service_interval)
+   {
+      service_interval = pAc->wmmAcTspecInfo.min_service_interval;
+   }
+   else if (pAc->wmmAcTspecInfo.max_service_interval)
+   {
+      service_interval = pAc->wmmAcTspecInfo.max_service_interval;
+   }
+   else
+   {
+      // no service interval is present in the TSPEC
+      // this is OK, there just won't be U-APSD
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: No service interval supplied",
+                __FUNCTION__);
+      return;
+   }
+
+   // determine the suspension interval & direction
+   suspension_interval = pAc->wmmAcTspecInfo.suspension_interval;
+   direction = pAc->wmmAcTspecInfo.ts_info.direction;
+
+   // if we have previously enabled U-APSD, have any params changed?
+   if ((pAc->wmmAcUapsdInfoValid) &&
+       (pAc->wmmAcUapsdServiceInterval == service_interval) &&
+       (pAc->wmmAcUapsdSuspensionInterval == suspension_interval) &&
+       (pAc->wmmAcUapsdDirection == direction))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: No change in U-APSD parameters",
+                __FUNCTION__);
+      return;
+   }
+
+   // are we in the appropriate power save modes?
+   if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_BEACON_MODE_POWER_SAVE))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: BMPS is not enabled",
+                __FUNCTION__);
+      return;
+   }
+
+   if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_UAPSD_MODE_POWER_SAVE))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: U-APSD is not enabled",
+                __FUNCTION__);
+      return;
+   }
+
+   // everything is in place to notify TL
+   status = WLANTL_EnableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                    (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                    acType,
+                                    pAc->wmmAcTspecInfo.ts_info.tid,
+                                    pAc->wmmAcTspecInfo.ts_info.up,
+                                    service_interval,
+                                    suspension_interval,
+                                    direction);
+
+   if ( !VOS_IS_STATUS_SUCCESS( status ) )
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                 "%s: Failed to enable U-APSD for AC=%d",
+                 __FUNCTION__, acType );
+      return;
+   }
+
+   // stash away the parameters that were used
+   pAc->wmmAcUapsdInfoValid = VOS_TRUE;
+   pAc->wmmAcUapsdServiceInterval = service_interval;
+   pAc->wmmAcUapsdSuspensionInterval = suspension_interval;
+   pAc->wmmAcUapsdDirection = direction;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: Enabled UAPSD in TL srv_int=%ld "
+             "susp_int=%ld dir=%d AC=%d",
+             __FUNCTION__,
+             service_interval,
+             suspension_interval,
+             direction,
+             acType);
+
+}
+
+/**
+  @brief hdd_wmm_disable_tl_uapsd() - function which decides whether
+  to disable UAPSD parameters in TL
+
+  @param pQosContext : [in] the pointer the QoS instance control block
+
+  @return
+  None
+*/
+static void hdd_wmm_disable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext)
+{
+   hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+   WLANTL_ACEnumType acType = pQosContext->acType;
+   hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+   VOS_STATUS status;
+
+
+   // have we previously enabled UAPSD?
+   if (pAc->wmmAcUapsdInfoValid == VOS_TRUE)
+   {
+      status = WLANTL_DisableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        acType);
+
+      if ( !VOS_IS_STATUS_SUCCESS( status ) )
+      {
+         VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                    "%s: Failed to disable U-APSD for AC=%d",
+                    __FUNCTION__, acType );
+      }
+      else
+      {
+         // TL no longer has valid UAPSD info
+         pAc->wmmAcUapsdInfoValid = VOS_FALSE;
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Disabled UAPSD in TL for AC=%d",
+                   __FUNCTION__,
+                   acType);
+      }
+   }
+}
+
+#endif
+
+/**
+  @brief hdd_wmm_free_context() - function which frees a QoS context
+
+  @param pQosContext : [in] the pointer the QoS instance control block
+
+  @return
+  None
+*/
+static void hdd_wmm_free_context (hdd_wmm_qos_context_t* pQosContext)
+{
+   hdd_adapter_t* pAdapter;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered, context %p",
+             __FUNCTION__, pQosContext);
+
+   if (unlikely((NULL == pQosContext) ||
+                (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
+   {
+      // must have been freed in another thread
+      return;
+   }
+
+   // get pointer to the adapter context
+   pAdapter = pQosContext->pAdapter;
+
+   // take the wmmLock since we're manipulating the context list
+   mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+
+   // make sure nobody thinks this is a valid context
+   pQosContext->magic = 0;
+
+   // unlink the context
+   list_del(&pQosContext->node);
+
+   // done manipulating the list
+   mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+   // reclaim memory
+   kfree(pQosContext);
+
+}
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+/**
+  @brief hdd_wmm_notify_app() - function which notifies an application
+                                changes in state of it flow
+
+  @param pQosContext : [in] the pointer the QoS instance control block
+
+  @return
+  None
+*/
+#define MAX_NOTIFY_LEN 50
+static void hdd_wmm_notify_app (hdd_wmm_qos_context_t* pQosContext)
+{
+   hdd_adapter_t* pAdapter;
+   union iwreq_data wrqu;
+   char buf[MAX_NOTIFY_LEN+1];
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered, context %p",
+             __FUNCTION__, pQosContext);
+
+   if (unlikely((NULL == pQosContext) ||
+                (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Invalid QoS Context",
+                __FUNCTION__);
+      return;
+   }
+
+
+   // create the event
+   memset(&wrqu, 0, sizeof(wrqu));
+   memset(buf, 0, sizeof(buf));
+
+   snprintf(buf, MAX_NOTIFY_LEN, "QCOM: TS change[%u: %u]",
+            (unsigned int)pQosContext->handle,
+            (unsigned int)pQosContext->lastStatus);
+
+   wrqu.data.pointer = buf;
+   wrqu.data.length = strlen(buf);
+
+   // get pointer to the adapter
+   pAdapter = pQosContext->pAdapter;
+
+   // send the event
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: Sending [%s]", __FUNCTION__, buf);
+   wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
+}
+
+
+/**
+  @brief hdd_wmm_is_access_allowed() - function which determines if access
+  is allowed for the given AC.  this is designed to be called during SME
+  callback processing since that is when access can be granted or removed
+
+  @param pAdapter    : [in] pointer to adapter context
+  @param pAc         : [in] pointer to the per-AC status
+
+  @return            : VOS_TRUE - access is allowed
+                     : VOS_FALSE - access is not allowed
+  None
+*/
+static v_BOOL_t hdd_wmm_is_access_allowed(hdd_adapter_t* pAdapter,
+                                          hdd_wmm_ac_status_t* pAc)
+{
+   // if we don't want QoS or the AP doesn't support QoS
+   // or we don't want to do implicit QoS
+   // or if AP doesn't require admission for this AC
+   // then we have access
+   if (!hdd_wmm_is_active(pAdapter) ||
+       !(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->bImplicitQosEnabled ||
+       !pAc->wmmAcAccessRequired)
+   {
+      return VOS_TRUE;
+   }
+
+   // if implicit QoS has already completed, successfully or not,
+   // then access is allowed
+   if (pAc->wmmAcAccessGranted || pAc->wmmAcAccessFailed)
+   {
+      return VOS_TRUE;
+   }
+
+   // admission is required and implicit QoS hasn't completed
+   // however explicit QoS may have completed and we'll have
+   // a Tspec
+   // if we don't have a Tspec then access is not allowed
+   if (!pAc->wmmAcTspecValid)
+   {
+      return VOS_FALSE;
+   }
+
+   // we have a Tspec -- does it allow upstream or bidirectional traffic?
+   // if it only allows downstream traffic then access is not allowed
+   if (pAc->wmmAcTspecInfo.ts_info.direction == SME_QOS_WMM_TS_DIR_DOWNLINK)
+   {
+      return VOS_FALSE;
+   }
+
+   // we meet all of the criteria for access
+   return VOS_TRUE;
+}
+
+#ifdef FEATURE_WLAN_CCX
+/**
+  @brief hdd_wmm_inactivity_timer_cb() - timer handler function which is
+  called for every inactivity interval per AC. This function gets the
+  current transmitted packets on the given AC, and checks if there where
+  any TX activity from the previous interval. If there was no traffic
+  then it would delete the TS that was negotiated on that AC.
+
+  @param pUserData   : [in] pointer to pQosContext
+
+  @return            : NONE
+*/
+void hdd_wmm_inactivity_timer_cb( v_PVOID_t pUserData )
+{
+    hdd_wmm_qos_context_t* pQosContext = (hdd_wmm_qos_context_t*)pUserData;
+    hdd_adapter_t* pAdapter;
+    hdd_wmm_ac_status_t *pAc;
+    hdd_wlan_wmm_status_e status;
+    VOS_STATUS vos_status;
+    v_U32_t currentTrafficCnt = 0;
+    WLANTL_ACEnumType acType = pQosContext->acType;
+
+    pAdapter = pQosContext->pAdapter;
+    pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+    // Get the Tx stats for this AC.
+    currentTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType];
+
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+            FL("WMM inactivity Timer for AC=%d, currentCnt=%d, prevCnt=%d\n"),
+            acType, (int)currentTrafficCnt, (int)pAc->wmmPrevTrafficCnt);
+    if (pAc->wmmPrevTrafficCnt == currentTrafficCnt)
+    {
+        // If there is no traffic activity, delete the TSPEC for this AC
+        status = hdd_wmm_delts(pAdapter, pQosContext->handle);
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+                FL("Deleted TS on AC %d, due to inactivity with status = %d!!!"),
+                acType, status);
+    }
+    else
+    {
+        pAc->wmmPrevTrafficCnt = currentTrafficCnt;
+        if (pAc->wmmInactivityTimer.state == VOS_TIMER_STATE_STOPPED)
+        {
+            // Restart the timer
+            vos_status = vos_timer_start(&pAc->wmmInactivityTimer, pAc->wmmInactivityTime);
+            if (!VOS_IS_STATUS_SUCCESS(vos_status))
+            {
+                VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                        FL("Restarting inactivity timer failed on AC %d"), acType);
+            }
+        }
+        else
+        {
+            VOS_ASSERT(vos_timer_getCurrentState(
+                        &pAc->wmmInactivityTimer) == VOS_TIMER_STATE_STOPPED);
+        }
+    }
+
+    return;
+}
+
+
+/**
+  @brief hdd_wmm_enable_inactivity_timer() - function to enable the
+  traffic inactivity timer for the given AC, if the inactivity_interval
+  specified in the ADDTS parameters is non-zero
+
+  @param pQosContext   : [in] pointer to pQosContext
+  @param inactivityTime: [in] value of the inactivity interval in millisecs
+
+  @return              : VOS_STATUS_E_FAILURE
+                         VOS_STATUS_SUCCESS
+*/
+VOS_STATUS hdd_wmm_enable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext, v_U32_t inactivityTime)
+{
+    VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
+    hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+    WLANTL_ACEnumType acType = pQosContext->acType;
+    hdd_wmm_ac_status_t *pAc;
+
+    pAdapter = pQosContext->pAdapter;
+    pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+
+    // If QoS-Tspec is successfully setup and if the inactivity timer is non-zero,
+    // a traffic inactivity timer needs to be started for the given AC
+    vos_status = vos_timer_init(
+            &pAc->wmmInactivityTimer,
+            VOS_TIMER_TYPE_SW,
+            hdd_wmm_inactivity_timer_cb,
+            (v_PVOID_t)pQosContext );
+    if ( !VOS_IS_STATUS_SUCCESS(vos_status))
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                FL("Initializing inactivity timer failed on AC %d"), acType);
+        return vos_status;
+    }
+
+    // Start the inactivity timer
+    vos_status = vos_timer_start(
+            &pAc->wmmInactivityTimer,
+            inactivityTime);
+    if ( !VOS_IS_STATUS_SUCCESS(vos_status))
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                FL("Starting inactivity timer failed on AC %d"), acType);
+        return vos_status;
+    }
+    pAc->wmmInactivityTime = inactivityTime;
+    // Initialize the current tx traffic count on this AC
+    pAc->wmmPrevTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType];
+
+    return vos_status;
+}
+
+/**
+  @brief hdd_wmm_enable_inactivity_timer() - function to disable the
+  traffic inactivity timer for the given AC. This would be called when
+  deleting the TS.
+
+  @param pQosContext   : [in] pointer to pQosContext
+
+  @return              : VOS_STATUS_E_FAILURE
+                         VOS_STATUS_SUCCESS
+*/
+VOS_STATUS hdd_wmm_disable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext)
+{
+    hdd_adapter_t* pAdapter = pQosContext->pAdapter;
+    WLANTL_ACEnumType acType = pQosContext->acType;
+    hdd_wmm_ac_status_t *pAc  = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+    VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
+
+    // Clear the timer and the counter
+    pAc->wmmInactivityTime = 0;
+    pAc->wmmPrevTrafficCnt = 0;
+    vos_timer_stop(&pAc->wmmInactivityTimer);
+    vos_status = vos_timer_destroy(&pAc->wmmInactivityTimer);
+
+    return vos_status;
+}
+#endif // FEATURE_WLAN_CCX
+
+/**
+  @brief hdd_wmm_sme_callback() - callback registered by HDD with SME for receiving
+  QoS notifications. Even though this function has a static scope it gets called
+  externally through some function pointer magic (so there is a need for
+  rigorous parameter checking)
+
+  @param hHal : [in] the HAL handle
+  @param HddCtx : [in] the HDD specified handle
+  @param pCurrentQosInfo : [in] the TSPEC params
+  @param SmeStatus : [in] the QoS related SME status
+
+  @return
+  eHAL_STATUS_SUCCESS if all good, eHAL_STATUS_FAILURE otherwise
+*/
+static eHalStatus hdd_wmm_sme_callback (tHalHandle hHal,
+                                        void * hddCtx,
+                                        sme_QosWmmTspecInfo* pCurrentQosInfo,
+                                        sme_QosStatusType smeStatus,
+                                        v_U32_t qosFlowId)
+{
+   hdd_wmm_qos_context_t* pQosContext = hddCtx;
+   hdd_adapter_t* pAdapter;
+   WLANTL_ACEnumType acType;
+   hdd_wmm_ac_status_t *pAc;
+   VOS_STATUS status;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered, context %p",
+             __FUNCTION__, pQosContext);
+
+   if (unlikely((NULL == pQosContext) ||
+                (HDD_WMM_CTX_MAGIC != pQosContext->magic)))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Invalid QoS Context",
+                __FUNCTION__);
+      return eHAL_STATUS_FAILURE;
+   }
+
+   pAdapter = pQosContext->pAdapter;
+   acType = pQosContext->acType;
+   pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: status %d flowid %d info %p",
+             __FUNCTION__, smeStatus, qosFlowId, pCurrentQosInfo);
+
+   switch (smeStatus)
+   {
+
+   case SME_QOS_STATUS_SETUP_SUCCESS_IND:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Setup is complete",
+                __FUNCTION__);
+
+      // there will always be a TSPEC returned with this status, even if
+      // a TSPEC is not exchanged OTA
+      if (pCurrentQosInfo)
+      {
+         pAc->wmmAcTspecValid = VOS_TRUE;
+         memcpy(&pAc->wmmAcTspecInfo,
+                pCurrentQosInfo,
+                sizeof(pAc->wmmAcTspecInfo));
+      }
+
+      if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Implicit Qos, notifying TL for TL AC %d",
+                   __FUNCTION__, acType);
+
+         // this was triggered by implicit QoS so we know packets are pending
+         // update state
+         pAc->wmmAcAccessAllowed = VOS_TRUE;
+         pAc->wmmAcAccessGranted = VOS_TRUE;
+         pAc->wmmAcAccessPending = VOS_FALSE;
+
+         // notify TL that packets are pending
+         status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        acType );
+
+         if ( !VOS_IS_STATUS_SUCCESS( status ) )
+         {
+            VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                       "%s: Failed to signal TL for AC=%d",
+                       __FUNCTION__, acType );
+         }
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+#ifdef FEATURE_WLAN_CCX
+      // Check if the inactivity interval is specified
+      if (pCurrentQosInfo->inactivity_interval) {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                 "%s: Inactivity timer value = %d for AC=%d\n",
+                 __FUNCTION__, pCurrentQosInfo->inactivity_interval, acType);
+         hdd_wmm_enable_inactivity_timer(pQosContext, pCurrentQosInfo->inactivity_interval);
+      }
+#endif // FEATURE_WLAN_CCX
+
+      // notify TL to enable trigger frames if necessary
+      hdd_wmm_enable_tl_uapsd(pQosContext);
+
+      break;
+
+   case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: Setup is complete (U-APSD set previously)",
+                __FUNCTION__);
+
+      if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Implicit Qos, notifying TL",
+                   __FUNCTION__);
+
+         // this was triggered by implicit QoS so we know packets are pending
+         // update state
+         pAc->wmmAcAccessAllowed = VOS_TRUE;
+         pAc->wmmAcAccessGranted = VOS_TRUE;
+         pAc->wmmAcAccessPending = VOS_FALSE;
+
+         // notify TL that packets are pending
+         status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        acType );
+
+         if ( !VOS_IS_STATUS_SUCCESS( status ) )
+         {
+            VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                       "%s: Failed to signal TL for AC=%d",
+                       __FUNCTION__, acType );
+         }
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      break;
+
+   case SME_QOS_STATUS_SETUP_FAILURE_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Setup failed",
+                __FUNCTION__);
+      // QoS setup failed
+
+      if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Implicit Qos, notifying TL",
+                   __FUNCTION__);
+
+         // we note the failure, but we also mark access as allowed so that
+         // the packets will flow.  Note that the MAC will "do the right thing"
+         pAc->wmmAcAccessPending = VOS_FALSE;
+         pAc->wmmAcAccessFailed = VOS_TRUE;
+         pAc->wmmAcAccessAllowed = VOS_TRUE;
+
+         // this was triggered by implicit QoS so we know packets are pending
+         status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        acType );
+
+         if ( !VOS_IS_STATUS_SUCCESS( status ) )
+         {
+            VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                       "%s: Failed to signal TL for AC=%d",
+                       __FUNCTION__, acType );
+         }
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      /* Setting up QoS Failed, QoS context can be released.
+       * SME is releasing this flow information and if HDD doen't release this context,
+       * next time if application uses the same handle to set-up QoS, HDD (as it has
+       * QoS context for this handle) will issue Modify QoS request to SME but SME will
+       * reject as no it has no information for this flow.
+       */
+      hdd_wmm_free_context(pQosContext);
+      break;
+
+   case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Setup Invalid Params, notify TL",
+                __FUNCTION__);
+      // QoS setup failed
+
+      if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Implicit Qos, notifying TL",
+                   __FUNCTION__);
+
+         // we note the failure, but we also mark access as allowed so that
+         // the packets will flow.  Note that the MAC will "do the right thing"
+         pAc->wmmAcAccessPending = VOS_FALSE;
+         pAc->wmmAcAccessFailed = VOS_TRUE;
+         pAc->wmmAcAccessAllowed = VOS_TRUE;
+
+         // this was triggered by implicit QoS so we know packets are pending
+         status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        acType );
+
+         if ( !VOS_IS_STATUS_SUCCESS( status ) )
+         {
+            VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                       "%s: Failed to signal TL for AC=%d",
+                       __FUNCTION__, acType );
+         }
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
+      VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                 "%s: Setup failed, not a QoS AP\n",
+                 __FUNCTION__);
+      if (!HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: Setup pending",
+                __FUNCTION__);
+      // not a callback status -- ignore if we get it
+      break;
+
+   case SME_QOS_STATUS_SETUP_MODIFIED_IND:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: Setup modified",
+                __FUNCTION__);
+      if (pCurrentQosInfo)
+      {
+         // update the TSPEC
+         pAc->wmmAcTspecValid = VOS_TRUE;
+         memcpy(&pAc->wmmAcTspecInfo,
+                pCurrentQosInfo,
+                sizeof(pAc->wmmAcTspecInfo));
+
+         if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+         {
+            VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                      "%s: Explicit Qos, notifying userspace",
+                      __FUNCTION__);
+
+            // this was triggered by an application
+            pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFIED;
+            hdd_wmm_notify_app(pQosContext);
+         }
+
+         // need to tell TL to update its UAPSD handling
+         hdd_wmm_enable_tl_uapsd(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+      if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Implicit Qos, notifying TL",
+                   __FUNCTION__);
+
+         // this was triggered by implicit QoS so we know packets are pending
+         pAc->wmmAcAccessPending = VOS_FALSE;
+         pAc->wmmAcAccessGranted = VOS_TRUE;
+         pAc->wmmAcAccessAllowed = VOS_TRUE;
+
+         // notify TL that packets are pending
+         status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        acType );
+
+         if ( !VOS_IS_STATUS_SUCCESS( status ) )
+         {
+            VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                       "%s: Failed to signal TL for AC=%d",
+                       __FUNCTION__, acType );
+         }
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
+      // nothing to do for now
+      break;
+
+   case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Setup successful but U-APSD failed",
+                __FUNCTION__);
+
+      if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Implicit Qos, notifying TL",
+                   __FUNCTION__);
+
+         // QoS setup was successful but setting U=APSD failed
+         // Since the OTA part of the request was successful, we don't mark
+         // this as a failure.
+         // the packets will flow.  Note that the MAC will "do the right thing"
+         pAc->wmmAcAccessGranted = VOS_TRUE;
+         pAc->wmmAcAccessAllowed = VOS_TRUE;
+         pAc->wmmAcAccessFailed = VOS_FALSE;
+         pAc->wmmAcAccessPending = VOS_FALSE;
+
+         // this was triggered by implicit QoS so we know packets are pending
+         status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        acType );
+
+         if ( !VOS_IS_STATUS_SUCCESS( status ) )
+         {
+            VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                       "%s: Failed to signal TL for AC=%d",
+                       __FUNCTION__, acType );
+         }
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_UAPSD_SET_FAILED;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      // Since U-APSD portion failed disabled trigger frame generation
+      hdd_wmm_disable_tl_uapsd(pQosContext);
+
+      break;
+
+   case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: Release is complete",
+                __FUNCTION__);
+
+      if (pCurrentQosInfo)
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: flows still active",
+                   __FUNCTION__);
+
+         // there is still at least one flow active for this AC
+         // so update the AC state
+         memcpy(&pAc->wmmAcTspecInfo,
+                pCurrentQosInfo,
+                sizeof(pAc->wmmAcTspecInfo));
+
+         // need to tell TL to update its UAPSD handling
+         hdd_wmm_enable_tl_uapsd(pQosContext);
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: last flow",
+                   __FUNCTION__);
+
+         // this is the last flow active for this AC so update the AC state
+         pAc->wmmAcTspecValid = VOS_FALSE;
+
+         // need to tell TL to update its UAPSD handling
+         hdd_wmm_disable_tl_uapsd(pQosContext);
+      }
+
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      // we are done with this flow
+      hdd_wmm_free_context(pQosContext);
+      break;
+
+   case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: Release failure",
+                __FUNCTION__);
+
+      // we don't need to update our state or TL since nothing has changed
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      break;
+
+   case SME_QOS_STATUS_RELEASE_QOS_LOST_IND:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: QOS Lost indication received",
+                __FUNCTION__);
+
+      // current TSPEC is no longer valid
+      pAc->wmmAcTspecValid = VOS_FALSE;
+
+      // need to tell TL to update its UAPSD handling
+      hdd_wmm_disable_tl_uapsd(pQosContext);
+
+      if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle)
+      {
+         // we no longer have implicit access granted
+         pAc->wmmAcAccessGranted = VOS_FALSE;
+         pAc->wmmAcAccessFailed = VOS_FALSE;
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                   "%s: Explicit Qos, notifying userspace",
+                   __FUNCTION__);
+
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_LOST;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      // we are done with this flow
+      hdd_wmm_free_context(pQosContext);
+      break;
+
+   case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Release pending",
+                __FUNCTION__);
+      // not a callback status -- ignore if we get it
+      break;
+
+   case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Release Invalid Params",
+                __FUNCTION__);
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Modification is complete, notify TL",
+                __FUNCTION__);
+
+      // there will always be a TSPEC returned with this status, even if
+      // a TSPEC is not exchanged OTA
+      if (pCurrentQosInfo)
+      {
+         pAc->wmmAcTspecValid = VOS_TRUE;
+         memcpy(&pAc->wmmAcTspecInfo,
+                pCurrentQosInfo,
+                sizeof(pAc->wmmAcTspecInfo));
+      }
+
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      // notify TL to enable trigger frames if necessary
+      hdd_wmm_enable_tl_uapsd(pQosContext);
+
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
+      // the flow modification failed so we'll leave in place
+      // whatever existed beforehand
+
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: modification pending",
+                __FUNCTION__);
+      // not a callback status -- ignore if we get it
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+      // the flow modification was successful but no QoS changes required
+
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
+      // invalid params -- notify the application
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
+         hdd_wmm_notify_app(pQosContext);
+      }
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_PENDING:
+      // nothing to do for now.  when APSD is established we'll have work to do
+      break;
+
+   case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED:
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Modify successful but U-APSD failed",
+                __FUNCTION__);
+
+      // QoS modification was successful but setting U=APSD failed.
+      // This will always be an explicit QoS instance, so all we can
+      // do is notify the application and let it clean up.
+      if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle)
+      {
+         // this was triggered by an application
+         pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_UAPSD_SET_FAILED;
+         hdd_wmm_notify_app(pQosContext);
+      }
+
+      // Since U-APSD portion failed disabled trigger frame generation
+      hdd_wmm_disable_tl_uapsd(pQosContext);
+
+      break;
+
+   case SME_QOS_STATUS_HANDING_OFF:
+      // no roaming so we won't see this
+      break;
+
+   case SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND:
+      // need to tell TL to stop trigger frame generation
+      hdd_wmm_disable_tl_uapsd(pQosContext);
+      break;
+
+   case SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND:
+      // need to tell TL to start sending trigger frames again
+      hdd_wmm_enable_tl_uapsd(pQosContext);
+      break;
+
+   default:
+      VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                 "%s: unexpected SME Status=%d\n",
+                 __FUNCTION__, smeStatus );
+      VOS_ASSERT(0);
+   }
+
+   // our access to the particular access category may have changed.
+   // some of the implicit QoS cases above may have already set this
+   // prior to invoking TL (so that we will properly service the
+   // Tx queues) but let's consistently handle all cases here
+   pAc->wmmAcAccessAllowed = hdd_wmm_is_access_allowed(pAdapter, pAc);
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: complete, access for TL AC %d is%sallowed",
+             __FUNCTION__,
+             acType,
+             pAc->wmmAcAccessAllowed ? " " : " not ");
+
+   return eHAL_STATUS_SUCCESS;
+}
+#endif
+
+/**============================================================================
+  @brief hdd_wmm_do_implicit_qos() - Function which will attempt to setup
+  QoS for any AC requiring it
+
+  @param work     : [in]  pointer to work structure
+
+  @return         : void
+  ===========================================================================*/
+static void hdd_wmm_do_implicit_qos(struct work_struct *work)
+{
+   hdd_wmm_qos_context_t* pQosContext =
+      container_of(work, hdd_wmm_qos_context_t, wmmAcSetupImplicitQos);
+   hdd_adapter_t* pAdapter;
+   WLANTL_ACEnumType acType;
+   hdd_wmm_ac_status_t *pAc;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+   VOS_STATUS status;
+   sme_QosStatusType smeStatus;
+#endif
+   sme_QosWmmTspecInfo qosInfo;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered, context %p",
+             __FUNCTION__, pQosContext);
+
+   if (unlikely(HDD_WMM_CTX_MAGIC != pQosContext->magic))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Invalid QoS Context",
+                __FUNCTION__);
+      return;
+   }
+
+   pAdapter = pQosContext->pAdapter;
+   acType = pQosContext->acType;
+   pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: pAdapter %p acType %d",
+             __FUNCTION__, pAdapter, acType);
+
+   if (!pAc->wmmAcAccessNeeded)
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: AC %d doesn't need service",
+                __FUNCTION__, acType);
+      pQosContext->magic = 0;
+      kfree(pQosContext);
+      return;
+   }
+
+   pAc->wmmAcAccessPending = VOS_TRUE;
+   pAc->wmmAcAccessNeeded = VOS_FALSE;
+
+   memset(&qosInfo, 0, sizeof(qosInfo));
+
+   switch (acType)
+   {
+   case WLANTL_AC_VO:
+      qosInfo.ts_info.up = SME_QOS_WMM_UP_VO;
+      qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x01;
+      qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVo;
+      qosInfo.ts_info.tid = 255;
+      qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVo;
+      qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVo;
+      qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv;
+      qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVo;
+      qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVo;
+      qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv;
+      break;
+   case WLANTL_AC_VI:
+      qosInfo.ts_info.up = SME_QOS_WMM_UP_VI;
+      qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x02;
+      qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVi;
+      qosInfo.ts_info.tid = 255;
+      qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVi;
+      qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVi;
+      qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv;
+      qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVi;
+      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;
+      qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x08;
+      qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBe;
+      qosInfo.ts_info.tid = 255;
+      qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBe;
+      qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBe;
+      qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv;
+      qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBe;
+      qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBe;
+      qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv;
+      break;
+   case WLANTL_AC_BK:
+      qosInfo.ts_info.up = SME_QOS_WMM_UP_BK;
+      qosInfo.ts_info.psb = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & 0x04;
+      qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBk;
+      qosInfo.ts_info.tid = 255;
+      qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBk;
+      qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBk;
+      qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv;
+      qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBk;
+      qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBk;
+      qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv;
+      break;
+   }
+#ifdef FEATURE_WLAN_CCX
+   qosInfo.inactivity_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraInactivityInterval;
+#endif
+   qosInfo.ts_info.burst_size_defn = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->burstSizeDefinition;
+
+   switch ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->tsInfoAckPolicy)
+   {
+     case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK:
+       qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
+       break;
+
+     case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK:
+       qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
+       break;
+
+     default:
+       // unknown
+       qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
+   }
+
+   if(qosInfo.ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)
+   {
+     if(!sme_QosIsTSInfoAckPolicyValid((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), &qosInfo, pAdapter->sessionId))
+     {
+       qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
+     }
+   }
+
+   mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+   list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
+   mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+   smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+                               pAdapter->sessionId,
+                               &qosInfo,
+                               hdd_wmm_sme_callback,
+                               pQosContext,
+                               qosInfo.ts_info.up,
+                               &pQosContext->qosFlowId);
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: sme_QosSetupReq returned %d flowid %d",
+             __FUNCTION__, smeStatus, pQosContext->qosFlowId);
+
+   // need to check the return values and act appropriately
+   switch (smeStatus)
+   {
+   case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
+   case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
+      // setup is pending, so no more work to do now.
+      // all further work will be done in hdd_wmm_sme_callback()
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Setup is pending, no further work",
+                __FUNCTION__);
+
+      break;
+
+
+   case SME_QOS_STATUS_SETUP_FAILURE_RSP:
+      // we can't tell the difference between when a request fails because
+      // AP rejected it versus when SME encountered an internal error
+
+      // in either case SME won't ever reference this context so
+      // free the record
+      hdd_wmm_free_context(pQosContext);
+
+      // fall through and start packets flowing
+   case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+      // no ACM in effect, no need to setup U-APSD
+   case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
+      // no ACM in effect, U-APSD is desired but was already setup
+
+      // for these cases everything is already setup so we can
+      // signal TL that it has work to do
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Setup is complete, notify TL",
+                __FUNCTION__);
+
+      pAc->wmmAcAccessAllowed = VOS_TRUE;
+      pAc->wmmAcAccessGranted = VOS_TRUE;
+      pAc->wmmAcAccessPending = VOS_FALSE;
+
+      status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                     (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                     acType );
+
+      if ( !VOS_IS_STATUS_SUCCESS( status ) )
+      {
+         VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                    "%s: Failed to signal TL for AC=%d",
+                    __FUNCTION__, acType );
+      }
+
+      break;
+
+
+   default:
+      VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                 "%s: unexpected SME Status=%d\n",
+                 __FUNCTION__, smeStatus );
+      VOS_ASSERT(0);
+   }
+#endif
+
+}
+
+/**============================================================================
+  @brief hdd_wmm_init() - Function which will initialize the WMM configuation
+  and status to an initial state.  The configuration can later be overwritten
+  via application APIs
+
+  @param pHddCtx : [in]  pointer to HDD context
+
+  @return         : VOS_STATUS_SUCCESS if succssful
+                  : other values if failure
+
+  ===========================================================================*/
+VOS_STATUS hdd_wmm_init ( hdd_context_t* pHddCtx )
+{
+   v_U8_t dscp;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered", __FUNCTION__);
+
+   // DSCP to User Priority Lookup Table
+   for (dscp = 0; dscp <= WLAN_HDD_MAX_DSCP; dscp++)
+   {
+      hddWmmDscpToUpMap[dscp] = SME_QOS_WMM_UP_BE;
+   }
+   hddWmmDscpToUpMap[8]  = SME_QOS_WMM_UP_BK;
+   hddWmmDscpToUpMap[16] = SME_QOS_WMM_UP_RESV;
+   hddWmmDscpToUpMap[24] = SME_QOS_WMM_UP_EE;
+   hddWmmDscpToUpMap[32] = SME_QOS_WMM_UP_CL;
+   hddWmmDscpToUpMap[40] = SME_QOS_WMM_UP_VI;
+   hddWmmDscpToUpMap[48] = SME_QOS_WMM_UP_VO;
+   hddWmmDscpToUpMap[56] = SME_QOS_WMM_UP_NC;
+
+   return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+  @brief hdd_wmm_adapter_init() - Function which will initialize the WMM configuation
+  and status to an initial state.  The configuration can later be overwritten
+  via application APIs
+
+  @param pAdapter : [in]  pointer to Adapter context
+
+  @return         : VOS_STATUS_SUCCESS if succssful
+                  : other values if failure
+
+  ===========================================================================*/
+VOS_STATUS hdd_wmm_adapter_init( hdd_adapter_t *pAdapter )
+{
+   hdd_wmm_ac_status_t *pAcStatus;
+   WLANTL_ACEnumType acType;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered", __FUNCTION__);
+
+   pAdapter->hddWmmStatus.wmmQap = VOS_FALSE;
+   INIT_LIST_HEAD(&pAdapter->hddWmmStatus.wmmContextList);
+   mutex_init(&pAdapter->hddWmmStatus.wmmLock);
+
+   for (acType = 0; acType < WLANTL_MAX_AC; acType++)
+   {
+      pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType];
+      pAcStatus->wmmAcAccessRequired = VOS_FALSE;
+      pAcStatus->wmmAcAccessNeeded = VOS_FALSE;
+      pAcStatus->wmmAcAccessPending = VOS_FALSE;
+      pAcStatus->wmmAcAccessFailed = VOS_FALSE;
+      pAcStatus->wmmAcAccessGranted = VOS_FALSE;
+      pAcStatus->wmmAcAccessAllowed = VOS_FALSE;
+      pAcStatus->wmmAcTspecValid = VOS_FALSE;
+      pAcStatus->wmmAcUapsdInfoValid = VOS_FALSE;
+   }
+
+   return VOS_STATUS_SUCCESS;
+}
+/**============================================================================
+  @brief hdd_wmm_close() - Function which will perform any necessary work to
+  to clean up the WMM functionality prior to the kernel module unload
+
+  @param pAdapter : [in]  pointer to adapter context
+
+  @return         : VOS_STATUS_SUCCESS if succssful
+                  : other values if failure
+
+  ===========================================================================*/
+VOS_STATUS hdd_wmm_adapter_close ( hdd_adapter_t* pAdapter )
+{
+   hdd_wmm_qos_context_t* pQosContext;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered", __FUNCTION__);
+
+   // free any context records that we still have linked
+   while (!list_empty(&pAdapter->hddWmmStatus.wmmContextList))
+   {
+      pQosContext = list_first_entry(&pAdapter->hddWmmStatus.wmmContextList,
+                                     hdd_wmm_qos_context_t, node);
+#ifdef FEATURE_WLAN_CCX
+      hdd_wmm_disable_inactivity_timer(pQosContext);
+#endif
+      hdd_wmm_free_context(pQosContext);
+   }
+
+   return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+  @brief hdd_wmm_classify_pkt() - Function which will classify an OS packet
+  into a WMM AC based on either 802.1Q or DSCP
+
+  @param pAdapter : [in]  pointer to adapter context
+  @param skb      : [in]  pointer to OS packet (sk_buff)
+  @param pAcType  : [out] pointer to WMM AC type of OS packet
+
+  @return         : None
+  ===========================================================================*/
+v_VOID_t hdd_wmm_classify_pkt ( hdd_adapter_t* pAdapter,
+                                struct sk_buff *skb,
+                                WLANTL_ACEnumType* pAcType,
+                                sme_QosWmmUpType *pUserPri)
+{
+   unsigned char * pPkt;
+   union generic_ethhdr *pHdr;
+   struct iphdr *pIpHdr;
+   unsigned char tos;
+   unsigned char dscp;
+   sme_QosWmmUpType userPri;
+   WLANTL_ACEnumType acType;
+
+   // this code is executed for every packet therefore
+   // all debug code is kept conditional
+
+#ifdef HDD_WMM_DEBUG
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered", __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+
+   pPkt = skb->data;
+   pHdr = (union generic_ethhdr *)pPkt;
+
+#ifdef HDD_WMM_DEBUG
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: proto/length is 0x%04x",
+             __FUNCTION__, pHdr->eth_II.h_proto);
+#endif // HDD_WMM_DEBUG
+
+   if (HDD_WMM_CLASSIFICATION_DSCP == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis)
+   {
+      if (pHdr->eth_II.h_proto == htons(ETH_P_IP))
+      {
+         // case 1: Ethernet II IP packet
+         pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_II)];
+         tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                   "%s: Ethernet II IP Packet, tos is %d",
+                   __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+
+      }
+      else if ((ntohs(pHdr->eth_II.h_proto) < WLAN_MIN_PROTO) &&
+               (pHdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) &&
+               (pHdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) &&
+               (pHdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) &&
+               (pHdr->eth_8023.h_proto == htons(ETH_P_IP)))
+      {
+         // case 2: 802.3 LLC/SNAP IP packet
+         pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023)];
+         tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                   "%s: 802.3 LLC/SNAP IP Packet, tos is %d",
+                   __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+      }
+      else if (pHdr->eth_II.h_proto == htons(ETH_P_8021Q))
+      {
+         // VLAN tagged
+
+         if (pHdr->eth_IIv.h_vlan_encapsulated_proto == htons(ETH_P_IP))
+         {
+            // case 3: Ethernet II vlan-tagged IP packet
+            pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_IIv)];
+            tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+            VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                      "%s: Ethernet II VLAN tagged IP Packet, tos is %d",
+                      __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+         }
+         else if ((ntohs(pHdr->eth_IIv.h_vlan_encapsulated_proto) < WLAN_MIN_PROTO) &&
+                  (pHdr->eth_8023v.h_snap.dsap == WLAN_SNAP_DSAP) &&
+                  (pHdr->eth_8023v.h_snap.ssap == WLAN_SNAP_SSAP) &&
+                  (pHdr->eth_8023v.h_snap.ctrl == WLAN_SNAP_CTRL) &&
+                  (pHdr->eth_8023v.h_proto == htons(ETH_P_IP)))
+         {
+            // case 4: 802.3 LLC/SNAP vlan-tagged IP packet
+            pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023v)];
+            tos = pIpHdr->tos;
+#ifdef HDD_WMM_DEBUG
+            VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                      "%s: 802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d",
+                      __FUNCTION__, tos);
+#endif // HDD_WMM_DEBUG
+         }
+         else
+         {
+            // default
+#ifdef HDD_WMM_DEBUG
+            VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
+                      "%s: VLAN tagged Unhandled Protocol, using default tos",
+                      __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+            tos = 0;
+         }
+      }
+      else
+      {
+          // default
+#ifdef HDD_WMM_DEBUG
+          VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
+                  "%s: Unhandled Protocol, using default tos",
+                  __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+          //Give the highest priority to 802.1x packet
+          if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X))
+              tos = 0xC0;
+          else
+              tos = 0;
+      }
+
+      dscp = (tos>>2) & 0x3f;
+      userPri = hddWmmDscpToUpMap[dscp];
+
+#ifdef HDD_WMM_DEBUG
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                "%s: tos is %d, dscp is %d, up is %d",
+                __FUNCTION__, tos, dscp, userPri);
+#endif // HDD_WMM_DEBUG
+
+   }
+   else if (HDD_WMM_CLASSIFICATION_802_1Q == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis)
+   {
+      if (pHdr->eth_IIv.h_vlan_proto == htons(ETH_P_8021Q))
+      {
+         // VLAN tagged
+         userPri = (ntohs(pHdr->eth_IIv.h_vlan_TCI)>>13) & 0x7;
+#ifdef HDD_WMM_DEBUG
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+                   "%s: Tagged frame, UP is %d",
+                   __FUNCTION__, userPri);
+#endif // HDD_WMM_DEBUG
+      }
+      else
+      {
+          // not VLAN tagged, use default
+#ifdef HDD_WMM_DEBUG
+          VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN,
+                  "%s: Untagged frame, using default UP",
+                  __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+          //Give the highest priority to 802.1x packet
+          if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X))
+              userPri = SME_QOS_WMM_UP_VO;
+          else
+              userPri = SME_QOS_WMM_UP_BE;
+      }
+   }
+   else
+   {
+      // default
+#ifdef HDD_WMM_DEBUG
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Unknown classification scheme, using default UP",
+                __FUNCTION__);
+#endif // HDD_WMM_DEBUG
+      userPri = SME_QOS_WMM_UP_BE;
+   }
+
+   acType = hddWmmUpToAcMap[userPri];
+
+#ifdef HDD_WMM_DEBUG
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: UP is %d, AC is %d",
+             __FUNCTION__, userPri, acType);
+#endif // HDD_WMM_DEBUG
+
+   *pUserPri = userPri;
+   *pAcType = acType;
+
+   return;
+}
+
+/**============================================================================
+  @brief hdd_hostapd_select_quueue() - Function which will classify the packet
+         according to linux qdisc expectation.
+
+
+  @param dev      : [in]  pointer to net_device structure
+  @param skb      : [in]  pointer to os packet
+
+  @return         : Qdisc queue index
+  ===========================================================================*/
+v_U16_t hdd_hostapd_select_queue(struct net_device * dev, struct sk_buff *skb)
+{
+   WLANTL_ACEnumType ac;
+   sme_QosWmmUpType up = SME_QOS_WMM_UP_BE;
+   v_USHORT_t queueIndex;
+   v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
+   hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
+   hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+   tpAniSirGlobal  pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_HAL, pHddCtx->pvosContext);
+#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
+   v_U8_t STAId;
+   v_U8_t *pSTAId = (v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
+
+   /*Get the Station ID*/
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+   if (eHAL_STATUS_SUCCESS != halTable_FindStaidByAddr(pMac, (tANI_U8 *)pDestMacAddress, &STAId))
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+            "%s: Failed to find right station", __FUNCTION__);
+      *pSTAId = HDD_WLAN_INVALID_STA_ID;
+      goto done;
+   }
+#else
+   if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &STAId))
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+            "%s: Failed to find right station", __FUNCTION__);
+      *pSTAId = HDD_WLAN_INVALID_STA_ID;
+      goto done;
+   }
+#endif //FEATURE_WLAN_NON_INTEGRATED_SOC
+
+   spin_lock_bh( &pAdapter->staInfo_lock );
+   if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[STAId].macAddrSTA, pDestMacAddress))
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Station MAC address does not matching", __FUNCTION__);
+
+      *pSTAId = HDD_WLAN_INVALID_STA_ID;
+      goto release_lock;
+   }
+   if (pAdapter->aStaInfo[STAId].isUsed && pAdapter->aStaInfo[STAId].isQosEnabled && (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->cfg_ini->WmmMode))
+   {
+      /* Get the user priority from IP header & corresponding AC */
+      hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
+   }
+   *pSTAId = STAId;
+
+release_lock:
+    spin_unlock_bh( &pAdapter->staInfo_lock );
+done:
+   skb->priority = up;
+   queueIndex = hddLinuxUpToAcMap[skb->priority];
+
+   return queueIndex;
+}
+
+/**============================================================================
+  @brief hdd_wmm_select_quueue() - Function which will classify the packet
+         according to linux qdisc expectation.
+
+
+  @param dev      : [in]  pointer to net_device structure
+  @param skb      : [in]  pointer to os packet
+
+  @return         : Qdisc queue index
+  ===========================================================================*/
+v_U16_t hdd_wmm_select_queue(struct net_device * dev, struct sk_buff *skb)
+{
+   WLANTL_ACEnumType ac;
+   sme_QosWmmUpType up = 0;
+   v_USHORT_t queueIndex;
+
+   hdd_adapter_t *pAdapter =  WLAN_HDD_GET_PRIV_PTR(dev);
+
+   // if we don't want QoS or the AP doesn't support Qos
+   // All traffic will get equal opportuniy to transmit data frames.
+   if( hdd_wmm_is_active(pAdapter) ) {
+      /* Get the user priority from IP header & corresponding AC */
+      hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up);
+   }
+
+   skb->priority = up;
+   queueIndex = hddLinuxUpToAcMap[skb->priority];
+
+   return queueIndex;
+}
+
+/**============================================================================
+  @brief hdd_wmm_acquire_access() - Function which will attempt to acquire
+  admittance for a WMM AC
+
+  @param pAdapter : [in]  pointer to adapter context
+  @param acType   : [in]  WMM AC type of OS packet
+  @param pGranted : [out] pointer to boolean flag when indicates if access
+                          has been granted or not
+
+  @return         : VOS_STATUS_SUCCESS if succssful
+                  : other values if failure
+  ===========================================================================*/
+VOS_STATUS hdd_wmm_acquire_access( hdd_adapter_t* pAdapter,
+                                   WLANTL_ACEnumType acType,
+                                   v_BOOL_t * pGranted )
+{
+   hdd_wmm_qos_context_t *pQosContext;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered for AC %d", __FUNCTION__, acType);
+
+   if (!hdd_wmm_is_active(pAdapter) || !(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->bImplicitQosEnabled)
+   {
+      // either we don't want QoS or the AP doesn't support QoS
+      // or we don't want to do implicit QoS
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: QoS not configured on both ends ", __FUNCTION__);
+
+      pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
+      *pGranted = VOS_TRUE;
+      return VOS_STATUS_SUCCESS;
+   }
+
+   // do we already have an implicit QoS request pending for this AC?
+   if ((pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded) ||
+       (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessPending))
+   {
+      // request already pending so we need to wait for that response
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Implicit QoS for TL AC %d already scheduled",
+                __FUNCTION__, acType);
+
+      *pGranted = VOS_FALSE;
+      return VOS_STATUS_SUCCESS;
+   }
+
+   // did we already fail to establish implicit QoS for this AC?
+   // (if so, access should have been granted when the failure was handled)
+   if (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessFailed)
+   {
+      // request previously failed
+      // allow access, but we'll be downgraded
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Implicit QoS for TL AC %d previously failed",
+                __FUNCTION__, acType);
+
+      pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
+      *pGranted = VOS_TRUE;
+      return VOS_STATUS_SUCCESS;
+   }
+
+   // we need to establish implicit QoS
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: Need to schedule implicit QoS for TL AC %d, pAdapter is %p",
+             __FUNCTION__, acType, pAdapter);
+
+   pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded = VOS_TRUE;
+
+   pQosContext = kmalloc(sizeof(*pQosContext), GFP_KERNEL);
+   if (NULL == pQosContext)
+   {
+      // no memory for QoS context.  Nothing we can do but let data flow
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Unable to allocate context", __FUNCTION__);
+      pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE;
+      *pGranted = VOS_TRUE;
+      return VOS_STATUS_SUCCESS;
+   }
+
+   pQosContext->acType = acType;
+   pQosContext->pAdapter = pAdapter;
+   pQosContext->qosFlowId = 0;
+   pQosContext->handle = HDD_WMM_HANDLE_IMPLICIT;
+   pQosContext->magic = HDD_WMM_CTX_MAGIC;
+   INIT_WORK(&pQosContext->wmmAcSetupImplicitQos,
+             hdd_wmm_do_implicit_qos);
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: Scheduling work for AC %d, context %p",
+             __FUNCTION__, acType, pQosContext);
+
+   schedule_work(&pQosContext->wmmAcSetupImplicitQos);
+
+   // caller will need to wait until the work takes place and
+   // TSPEC negotiation completes
+   *pGranted = VOS_FALSE;
+   return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+  @brief hdd_wmm_assoc() - Function which will handle the housekeeping
+  required by WMM when association takes place
+
+  @param pAdapter : [in]  pointer to adapter context
+  @param pRoamInfo: [in]  pointer to roam information
+  @param eBssType : [in]  type of BSS
+
+  @return         : VOS_STATUS_SUCCESS if succssful
+                  : other values if failure
+  ===========================================================================*/
+VOS_STATUS hdd_wmm_assoc( hdd_adapter_t* pAdapter,
+                          tCsrRoamInfo *pRoamInfo,
+                          eCsrRoamBssType eBssType )
+{
+   tANI_U8 uapsdMask;
+   VOS_STATUS status;
+
+   // when we associate we need to notify TL if it needs to enable
+   // UAPSD for any access categories
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered", __FUNCTION__);
+
+   if (pRoamInfo->fReassocReq)
+   {
+      // when we reassociate we should continue to use whatever
+      // parameters were previously established.  if we are
+      // reassociating due to a U-APSD change for a particular
+      // Access Category, then the change will be communicated
+      // to HDD via the QoS callback associated with the given
+      // flow, and U-APSD parameters will be updated there
+
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: Reassoc so no work, Exiting", __FUNCTION__);
+
+      return VOS_STATUS_SUCCESS;
+   }
+
+   // get the negotiated UAPSD Mask
+   uapsdMask = pRoamInfo->u.pConnectedProfile->modifyProfileFields.uapsd_mask;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: U-APSD mask is 0x%02x", __FUNCTION__, (int) uapsdMask);
+
+   if (uapsdMask & HDD_AC_VO)
+   {
+      status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        WLANTL_AC_VO,
+                                        7,
+                                        7,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv,
+                                        WLANTL_BI_DIR );
+
+      VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+   }
+
+   if (uapsdMask & HDD_AC_VI)
+   {
+      status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        WLANTL_AC_VI,
+                                        5,
+                                        5,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv,
+                                        WLANTL_BI_DIR );
+
+      VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+   }
+
+   if (uapsdMask & HDD_AC_BK)
+   {
+      status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        WLANTL_AC_BK,
+                                        2,
+                                        2,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv,
+                                        WLANTL_BI_DIR );
+
+      VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+   }
+
+   if (uapsdMask & HDD_AC_BE)
+   {
+      status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
+                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+                                        WLANTL_AC_BE,
+                                        3,
+                                        3,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv,
+                                        (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv,
+                                        WLANTL_BI_DIR );
+
+      VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ));
+   }
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Exiting", __FUNCTION__);
+
+   return VOS_STATUS_SUCCESS;
+}
+
+
+
+static const v_U8_t acmMaskBit[WLANTL_MAX_AC] =
+   {
+      0x4, /* WLANTL_AC_BK */
+      0x8, /* WLANTL_AC_BE */
+      0x2, /* WLANTL_AC_VI */
+      0x1  /* WLANTL_AC_VO */
+   };
+
+/**============================================================================
+  @brief hdd_wmm_connect() - Function which will handle the housekeeping
+  required by WMM when a connection is established
+
+  @param pAdapter : [in]  pointer to adapter context
+  @param pRoamInfo: [in]  pointer to roam information
+  @param eBssType : [in]  type of BSS
+
+  @return         : VOS_STATUS_SUCCESS if succssful
+                  : other values if failure
+  ===========================================================================*/
+VOS_STATUS hdd_wmm_connect( hdd_adapter_t* pAdapter,
+                            tCsrRoamInfo *pRoamInfo,
+                            eCsrRoamBssType eBssType )
+{
+   int ac;
+   v_BOOL_t qap;
+   v_BOOL_t qosConnection;
+   v_U8_t acmMask;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered", __FUNCTION__);
+
+   if ((eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType) &&
+       pRoamInfo &&
+       pRoamInfo->u.pConnectedProfile)
+   {
+      qap = pRoamInfo->u.pConnectedProfile->qap;
+      qosConnection = pRoamInfo->u.pConnectedProfile->qosConnection;
+      acmMask = pRoamInfo->u.pConnectedProfile->acm_mask;
+   }
+   else
+   {
+      qap = VOS_TRUE;
+      qosConnection = VOS_TRUE;
+      acmMask = 0x0;
+   }
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: qap is %d, qosConnection is %d, acmMask is 0x%x",
+             __FUNCTION__, qap, qosConnection, acmMask);
+
+   pAdapter->hddWmmStatus.wmmQap = qap;
+   pAdapter->hddWmmStatus.wmmQosConnection = qosConnection;
+
+   for (ac = 0; ac < WLANTL_MAX_AC; ac++)
+   {
+      if (qap &&
+          qosConnection &&
+          (acmMask & acmMaskBit[ac]))
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                   "%s: ac %d on",
+                   __FUNCTION__, ac);
+
+         // admission is required
+         pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_TRUE;
+         pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_FALSE;
+         pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessGranted = VOS_FALSE;
+      }
+      else
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                   "%s: ac %d off",
+                   __FUNCTION__, ac);
+         // admission is not required so access is allowed
+         pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_FALSE;
+         pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_TRUE;
+      }
+
+   }
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Exiting", __FUNCTION__);
+
+   return VOS_STATUS_SUCCESS;
+}
+
+/**============================================================================
+  @brief hdd_wmm_get_uapsd_mask() - Function which will calculate the
+  initial value of the UAPSD mask based upon the device configuration
+
+  @param pAdapter  : [in]  pointer to adapter context
+  @param pUapsdMask: [in]  pointer to where the UAPSD Mask is to be stored
+
+  @return         : VOS_STATUS_SUCCESS if succssful
+                  : other values if failure
+  ===========================================================================*/
+VOS_STATUS hdd_wmm_get_uapsd_mask( hdd_adapter_t* pAdapter,
+                                   tANI_U8 *pUapsdMask )
+{
+   tANI_U8 uapsdMask;
+
+   if (HDD_WMM_USER_MODE_NO_QOS == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
+   {
+      // no QOS then no UAPSD
+      uapsdMask = 0;
+   }
+   else
+   {
+      // start with the default mask
+      uapsdMask = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
+
+      // disable UAPSD for any ACs with a 0 Service Interval
+      if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv == 0 )
+      {
+         uapsdMask &= ~HDD_AC_VO;
+      }
+
+      if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv == 0 )
+      {
+         uapsdMask &= ~HDD_AC_VI;
+      }
+
+      if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv == 0 )
+      {
+         uapsdMask &= ~HDD_AC_BK;
+      }
+
+      if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv == 0 )
+      {
+         uapsdMask &= ~HDD_AC_BE;
+      }
+   }
+
+   // return calculated mask
+   *pUapsdMask = uapsdMask;
+   return VOS_STATUS_SUCCESS;
+}
+
+
+/**============================================================================
+  @brief hdd_wmm_is_active() - Function which will determine if WMM is
+  active on the current connection
+
+  @param pAdapter  : [in]  pointer to adapter context
+
+  @return         : VOS_TRUE if WMM is enabled
+                  : VOS_FALSE if WMM is not enabled
+  ===========================================================================*/
+v_BOOL_t hdd_wmm_is_active( hdd_adapter_t* pAdapter )
+{
+   if ((!pAdapter->hddWmmStatus.wmmQosConnection) ||
+       (!pAdapter->hddWmmStatus.wmmQap))
+   {
+      return VOS_FALSE;
+   }
+   else
+   {
+      return VOS_TRUE;
+   }
+}
+
+/**============================================================================
+  @brief hdd_wmm_addts() - Function which will add a traffic spec at the
+  request of an application
+
+  @param pAdapter  : [in]  pointer to adapter context
+  @param handle    : [in]  handle to uniquely identify a TS
+  @param pTspec    : [in]  pointer to the traffic spec
+
+  @return          : HDD_WLAN_WMM_STATUS_*
+  ===========================================================================*/
+hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter,
+                                     v_U32_t handle,
+                                     sme_QosWmmTspecInfo* pTspec )
+{
+   hdd_wmm_qos_context_t *pQosContext;
+   hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+   sme_QosStatusType smeStatus;
+#endif
+   v_BOOL_t found = VOS_FALSE;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered with handle 0x%x", __FUNCTION__, handle);
+
+   // see if a context already exists with the given handle
+   mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+   list_for_each_entry(pQosContext,
+                       &pAdapter->hddWmmStatus.wmmContextList,
+                       node)
+   {
+      if (pQosContext->handle == handle)
+      {
+         found = VOS_TRUE;
+         break;
+      }
+   }
+   mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+   if (found)
+   {
+      // record with that handle already exists
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Record already exists with handle 0x%x",
+                __FUNCTION__, handle);
+
+      /* Application is trying to modify some of the Tspec params. Allow it */
+      smeStatus = sme_QosModifyReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+                                  pTspec,
+                                  pQosContext->qosFlowId);
+
+      // need to check the return value and act appropriately
+      switch (smeStatus)
+      {
+        case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP:
+          status = HDD_WLAN_WMM_STATUS_MODIFY_PENDING;
+          break;
+        case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+          status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD;
+          break;
+        case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY:
+          status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING;
+          break;
+        case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP:
+          status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM;
+          break;
+        case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP:
+          status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
+          break;
+        case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
+          status = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
+          break;
+        default:
+          // we didn't get back one of the SME_QOS_STATUS_MODIFY_* status codes
+          VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                     "%s: unexpected SME Status=%d\n", smeStatus );
+          VOS_ASSERT(0);
+          return HDD_WLAN_WMM_STATUS_MODIFY_FAILED;
+      }
+
+      // we were successful, save the status
+      pQosContext->lastStatus = status;
+      return status;
+   }
+
+   pQosContext = kmalloc(sizeof(*pQosContext), GFP_KERNEL);
+   if (NULL == pQosContext)
+   {
+      // no memory for QoS context.  Nothing we can do
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                "%s: Unable to allocate QoS context", __FUNCTION__);
+      return HDD_WLAN_WMM_STATUS_INTERNAL_FAILURE;
+   }
+
+   // we assume the tspec has already been validated by the caller
+
+   pQosContext->handle = handle;
+   pQosContext->acType = hddWmmUpToAcMap[pTspec->ts_info.up];
+   pQosContext->pAdapter = pAdapter;
+   pQosContext->qosFlowId = 0;
+   pQosContext->magic = HDD_WMM_CTX_MAGIC;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: Setting up QoS, context %p",
+             __FUNCTION__, pQosContext);
+
+   mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+   list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList);
+   mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+   smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+                               pAdapter->sessionId,
+                               pTspec,
+                               hdd_wmm_sme_callback,
+                               pQosContext,
+                               pTspec->ts_info.up,
+                               &pQosContext->qosFlowId);
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO,
+             "%s: sme_QosSetupReq returned %d flowid %d",
+             __FUNCTION__, smeStatus, pQosContext->qosFlowId);
+
+   // need to check the return value and act appropriately
+   switch (smeStatus)
+   {
+   case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP:
+      status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
+      break;
+   case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP:
+      status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD;
+      break;
+   case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY:
+      status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING;
+      break;
+   case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING:
+      status = HDD_WLAN_WMM_STATUS_SETUP_PENDING;
+      break;
+   case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP:
+      hdd_wmm_free_context(pQosContext);
+      return HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
+   case SME_QOS_STATUS_SETUP_FAILURE_RSP:
+      // we can't tell the difference between when a request fails because
+      // AP rejected it versus when SME encounterd an internal error
+      hdd_wmm_free_context(pQosContext);
+      return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
+   case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP:
+      hdd_wmm_free_context(pQosContext);
+      return HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM;
+   default:
+      // we didn't get back one of the SME_QOS_STATUS_SETUP_* status codes
+      hdd_wmm_free_context(pQosContext);
+      VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                 "%s: unexpected SME Status=%d\n", smeStatus );
+      VOS_ASSERT(0);
+      return HDD_WLAN_WMM_STATUS_SETUP_FAILED;
+   }
+#endif
+
+   // we were successful, save the status
+   pQosContext->lastStatus = status;
+
+   return status;
+}
+
+/**============================================================================
+  @brief hdd_wmm_delts() - Function which will delete a traffic spec at the
+  request of an application
+
+  @param pAdapter  : [in]  pointer to adapter context
+  @param handle    : [in]  handle to uniquely identify a TS
+
+  @return          : HDD_WLAN_WMM_STATUS_*
+  ===========================================================================*/
+hdd_wlan_wmm_status_e hdd_wmm_delts( hdd_adapter_t* pAdapter,
+                                     v_U32_t handle )
+{
+   hdd_wmm_qos_context_t *pQosContext;
+   v_BOOL_t found = VOS_FALSE;
+   WLANTL_ACEnumType acType = 0;
+   v_U32_t qosFlowId = 0;
+   hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ;
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+   sme_QosStatusType smeStatus;
+#endif
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered with handle 0x%x", __FUNCTION__, handle);
+
+   // locate the context with the given handle
+   mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+   list_for_each_entry(pQosContext,
+                       &pAdapter->hddWmmStatus.wmmContextList,
+                       node)
+   {
+      if (pQosContext->handle == handle)
+      {
+         found = VOS_TRUE;
+         acType = pQosContext->acType;
+         qosFlowId = pQosContext->qosFlowId;
+         break;
+      }
+   }
+   mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+
+   if (VOS_FALSE == found)
+   {
+      // we didn't find the handle
+      VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                "%s: handle 0x%x not found", __FUNCTION__, handle);
+      return HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
+   }
+
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: found handle 0x%x, flow %d, AC %d, context %p",
+             __FUNCTION__, handle, qosFlowId, acType, pQosContext);
+
+#ifndef WLAN_MDM_CODE_REDUCTION_OPT
+   smeStatus = sme_QosReleaseReq( WLAN_HDD_GET_HAL_CTX(pAdapter), qosFlowId );
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: SME flow %d released, SME status %d",
+             __FUNCTION__, qosFlowId, smeStatus);
+
+   switch(smeStatus)
+   {
+   case SME_QOS_STATUS_RELEASE_SUCCESS_RSP:
+      // this flow is the only one on that AC, so go ahead and update
+      // our TSPEC state for the AC
+      pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcTspecValid = VOS_FALSE;
+
+      // need to tell TL to stop trigger timer, etc
+      hdd_wmm_disable_tl_uapsd(pQosContext);
+
+#ifdef FEATURE_WLAN_CCX
+      // disable the inactivity timer
+      hdd_wmm_disable_inactivity_timer(pQosContext);
+#endif
+      // we are done with this context
+      hdd_wmm_free_context(pQosContext);
+
+      // SME must not fire any more callbacks for this flow since the context
+      // is no longer valid
+
+      return HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS;
+
+   case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP:
+      // do nothing as we will get a response from SME
+      status = HDD_WLAN_WMM_STATUS_RELEASE_PENDING;
+      break;
+
+   case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP:
+      // nothing we can do with the existing flow except leave it
+      status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM;
+      break;
+
+   case SME_QOS_STATUS_RELEASE_FAILURE_RSP:
+      // nothing we can do with the existing flow except leave it
+      status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
+
+   default:
+      // we didn't get back one of the SME_QOS_STATUS_RELEASE_* status codes
+      VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR,
+                 "%s: unexpected SME Status=%d\n", smeStatus );
+      VOS_ASSERT(0);
+      status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED;
+   }
+
+#endif
+   pQosContext->lastStatus = status;
+   return status;
+}
+
+/**============================================================================
+  @brief hdd_wmm_checkts() - Function which will return the status of a traffic
+  spec at the request of an application
+
+  @param pAdapter  : [in]  pointer to adapter context
+  @param handle    : [in]  handle to uniquely identify a TS
+
+  @return          : HDD_WLAN_WMM_STATUS_*
+  ===========================================================================*/
+hdd_wlan_wmm_status_e hdd_wmm_checkts( hdd_adapter_t* pAdapter,
+                                       v_U32_t handle )
+{
+   hdd_wmm_qos_context_t *pQosContext;
+   hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_LOST;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+             "%s: Entered with handle 0x%x", __FUNCTION__, handle);
+
+   // locate the context with the given handle
+   mutex_lock(&pAdapter->hddWmmStatus.wmmLock);
+   list_for_each_entry(pQosContext,
+                       &pAdapter->hddWmmStatus.wmmContextList,
+                       node)
+   {
+      if (pQosContext->handle == handle)
+      {
+         VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW,
+                   "%s: found handle 0x%x, context %p",
+                   __FUNCTION__, handle, pQosContext);
+
+         status = pQosContext->lastStatus;
+         break;
+      }
+   }
+   mutex_unlock(&pAdapter->hddWmmStatus.wmmLock);
+   return status;
+}