wlan : wmm : Switch from UAPSD to legacy power save with DelTS

With the existing support, STA does not switch back from UAPSD to
legacy power when AP sends DelTSpec for a tid. And Exit UAPSD
doesnot happen when processing the DelTspec received from AP.
Changes made in address these issues.

Change-Id: I7975dbf72e4097aef9d3648af82959ab70f3f278
CRs-fixed: 550442
diff --git a/CORE/MAC/src/pe/include/limAdmitControl.h b/CORE/MAC/src/pe/include/limAdmitControl.h
index 3873058..24fe20e 100644
--- a/CORE/MAC/src/pe/include/limAdmitControl.h
+++ b/CORE/MAC/src/pe/include/limAdmitControl.h
@@ -112,7 +112,12 @@
 tSirRetStatus limAdmitControlInit(tpAniSirGlobal pMac);
 
 tSirRetStatus limSendHalMsgAddTs(tpAniSirGlobal pMac, tANI_U16 staIdx, tANI_U8 tspecIdx, tSirMacTspecIE tspecIE, tANI_U8 sessionId);
-tSirRetStatus limSendHalMsgDelTs(tpAniSirGlobal pMac,  tANI_U16 staIdx,  tANI_U8 tspecIdx,  tSirDeltsReqInfo delts, tANI_U8 sessionId);
+tSirRetStatus limSendHalMsgDelTs(tpAniSirGlobal pMac,
+                                 tANI_U16 staIdx,
+                                 tANI_U8 tspecIdx,
+                                 tSirDeltsReqInfo delts,
+                                 tANI_U8 sessionId,
+                                 tANI_U8 *bssId);
 void limProcessHalAddTsRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg);
 
 #endif
diff --git a/CORE/MAC/src/pe/lim/limAdmitControl.c b/CORE/MAC/src/pe/lim/limAdmitControl.c
index cac5573..584b5e8 100644
--- a/CORE/MAC/src/pe/lim/limAdmitControl.c
+++ b/CORE/MAC/src/pe/lim/limAdmitControl.c
@@ -1149,7 +1149,8 @@
   tANI_U16       staIdx,
   tANI_U8         tspecIdx,
   tSirDeltsReqInfo delts,
-  tANI_U8        sessionId)
+  tANI_U8        sessionId,
+  tANI_U8        *bssId)
 {
   tSirMsgQ msg;
   tpDelTsParams pDelTsParam;
@@ -1169,6 +1170,7 @@
   //filling message parameters.
   pDelTsParam->staIdx = staIdx;
   pDelTsParam->tspecIdx = tspecIdx;
+  vos_mem_copy(&pDelTsParam->bssId, bssId, sizeof(tSirMacAddr));
 
   PELOGW(limLog(pMac, LOGW, FL("calling wdaPostCtrlMsg()"));)
   MTRACE(macTraceMsgTx(pMac, sessionId, msg.type));
diff --git a/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
index 16ede0f..202237c 100644
--- a/CORE/MAC/src/pe/lim/limProcessActionFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
@@ -757,7 +757,7 @@
     if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA))
     {
     
-        if ((upToAc(tsinfo->traffic.userPrio) >= MAX_NUM_AC) || (! psessionEntry->gLimEdcaParams[upToAc(tsinfo->traffic.userPrio)].aci.acm))
+        if (upToAc(tsinfo->traffic.userPrio) >= MAX_NUM_AC)
         {
             limLog(pMac, LOGW, FL("DelTs with UP %d has no AC - ignoring request"),
                    tsinfo->traffic.userPrio);
@@ -765,6 +765,10 @@
         }
     }
 
+    if ((psessionEntry->limSystemRole != eLIM_AP_ROLE) &&
+        (psessionEntry->limSystemRole != eLIM_BT_AMP_AP_ROLE))
+        limSendSmeDeltsInd(pMac, &delts, aid,psessionEntry);
+
     // try to delete the TS
     if (eSIR_SUCCESS != limAdmitControlDeleteTS(pMac, pSta->assocId, tsinfo, &tsStatus, &tspecIdx))
     {
@@ -780,7 +784,12 @@
     else
     {
       //send message to HAL to delete TS
-      if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac, pSta->staIndex, tspecIdx, delts, psessionEntry->peSessionId))
+      if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac,
+                                            pSta->staIndex,
+                                            tspecIdx,
+                                            delts,
+                                            psessionEntry->peSessionId,
+                                            psessionEntry->bssId))
       {
         limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"),
                          tsinfo->traffic.userPrio);
@@ -840,8 +849,6 @@
         limLog(pMac, LOGE, FL("Self entry missing in Hash Table "));
 
     PELOG1(limLog(pMac, LOG1, FL("DeleteTS succeeded"));)
-    if((psessionEntry->limSystemRole != eLIM_AP_ROLE)&&(psessionEntry->limSystemRole != eLIM_BT_AMP_AP_ROLE))
-      limSendSmeDeltsInd(pMac, &delts, aid,psessionEntry);
 
 #ifdef FEATURE_WLAN_CCX
     limDeactivateAndChangeTimer(pMac,eLIM_TSM_TIMER);
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index d30647c..49d0ff8 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -5468,7 +5468,12 @@
            psessionEntry->gLimEdcaParams[upToAc(tsinfo->traffic.userPrio)].aci.acm)
       {
         //send message to HAL to delete TS
-        if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac, pSta->staIndex, tspecIdx, pDeltsReq->req, psessionEntry->peSessionId))
+        if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac,
+                                              pSta->staIndex,
+                                              tspecIdx,
+                                              pDeltsReq->req,
+                                              psessionEntry->peSessionId,
+                                              psessionEntry->bssId))
         {
           limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"),
                            tsinfo->traffic.userPrio);
diff --git a/CORE/MAC/src/pe/pmm/pmmApi.c b/CORE/MAC/src/pe/pmm/pmmApi.c
index ff8afd4..da3a559 100644
--- a/CORE/MAC/src/pe/pmm/pmmApi.c
+++ b/CORE/MAC/src/pe/pmm/pmmApi.c
@@ -2583,19 +2583,19 @@
         pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, uapsdTriggerMask);
         pUapsdParams->bssIdx = pSessionEntry->bssIdx;
 
-        PELOGE(pmmLog(pMac, LOGE, 
+        PELOGW(pmmLog(pMac, LOGW,
                       FL("UAPSD Mask:  static = 0x%x, DeliveryEnabled = 0x%x, TriggerEnabled = 0x%x "),
             pMac->lim.gUapsdPerAcBitmask,
             pMac->lim.gUapsdPerAcDeliveryEnableMask,
             pMac->lim.gUapsdPerAcTriggerEnableMask);)
 
-        PELOG1(pmmLog(pMac, LOG1, FL("Delivery Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "),
+        PELOGW(pmmLog(pMac, LOGW, FL("Delivery Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "),
             pUapsdParams->bkDeliveryEnabled, 
             pUapsdParams->beDeliveryEnabled, 
             pUapsdParams->viDeliveryEnabled, 
             pUapsdParams->voDeliveryEnabled);)
 
-        PELOG1(pmmLog(pMac, LOG1, FL("Trigger Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "),
+        PELOGW(pmmLog(pMac, LOGW, FL("Trigger Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "),
             pUapsdParams->bkTriggerEnabled, 
             pUapsdParams->beTriggerEnabled, 
             pUapsdParams->viTriggerEnabled, 
diff --git a/CORE/SME/src/QoS/sme_Qos.c b/CORE/SME/src/QoS/sme_Qos.c
index 8f0c02d..75f7d28 100644
--- a/CORE/SME/src/QoS/sme_Qos.c
+++ b/CORE/SME/src/QoS/sme_Qos.c
@@ -135,6 +135,14 @@
    
 }sme_QosStates;
 /*---------------------------------------------------------------------------
+   Enumeration of the various Release QoS trigger
+---------------------------------------------------------------------------*/
+typedef enum
+{
+   SME_QOS_RELEASE_DEFAULT = 0,
+   SME_QOS_RELEASE_BY_AP,
+}sme_QosRelTriggers;
+/*---------------------------------------------------------------------------
    Enumeration of the various QoS cmds 
 ---------------------------------------------------------------------------*/
 typedef enum
@@ -306,6 +314,7 @@
    parsing the RIC received in the the reassoc response */
    tSirAddtsRsp           addTsRsp[SME_QOS_TSPEC_INDEX_MAX];
 #endif
+   sme_QosRelTriggers     relTrig;
 
 } sme_QosACInfo;
 /*---------------------------------------------------------------------------
@@ -2516,24 +2525,34 @@
                   }
                }
             }
-            //send delts
-            hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandDelTs,
-                                      NULL, ac, flow_info->tspec_mask);
-            if(!HAL_STATUS_SUCCESS(hstatus))
+            if (SME_QOS_RELEASE_DEFAULT == pACInfo->relTrig)
             {
-               //err msg
-               VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, 
-                         "%s: %d: sme_QosDelTsReq() failed",
-                         __func__, __LINE__);
-               status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
-               // we won't be waiting for a response from the AP
-               // so vote powersave back on
-               pSession->readyForPowerSave = VOS_TRUE;
+               //send delts
+               hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandDelTs,
+                                         NULL, ac, flow_info->tspec_mask);
+               if(!HAL_STATUS_SUCCESS(hstatus))
+               {
+                  //err msg
+                  VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                            "%s: %d: sme_QosDelTsReq() failed",
+                            __func__, __LINE__);
+                  status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+                  // we won't be waiting for a response from the AP
+                  // so vote powersave back on
+                  pSession->readyForPowerSave = VOS_TRUE;
+               }
+               else
+               {
+                  pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET &
+                                                (~flow_info->tspec_mask);
+                  deltsIssued = VOS_TRUE;
+               }
             }
             else
             {
-               pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET & 
-                  (~flow_info->tspec_mask);
+               pSession->readyForPowerSave = VOS_TRUE;
+               pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET &
+                                              (~flow_info->tspec_mask);
                deltsIssued = VOS_TRUE;
             }
          }
@@ -2584,13 +2603,27 @@
             // so vote powersave back on
             pSession->readyForPowerSave = VOS_TRUE;
          }
-         if(buffered_cmd)
+
+         if (SME_QOS_RELEASE_BY_AP == pACInfo->relTrig)
          {
-            flow_info->QoSCallback(pMac, flow_info->HDDcontext, 
+            flow_info->QoSCallback(pMac, flow_info->HDDcontext,
+                          &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
+                          SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
+                          flow_info->QosFlowID);
+
+            VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
+                      "%s: %d: Deleting entry at %p with flowID %d",
+                      __func__, __LINE__,
+                      flow_info, flow_info->QosFlowID);
+         }
+         else if(buffered_cmd)
+         {
+            flow_info->QoSCallback(pMac, flow_info->HDDcontext,
                                    NULL,
                                    status,
                                    flow_info->QosFlowID);
          }
+
          if(SME_QOS_STATUS_RELEASE_FAILURE_RSP == status)
          {
             break;
@@ -2634,6 +2667,7 @@
                    sessionId, flow_info, QosFlowID);
          csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
          pDeletedFlow = flow_info;
+         pACInfo->relTrig = SME_QOS_RELEASE_DEFAULT;
       }
       /* if we are doing reassoc & we are already in handoff state, no need
          to move to requested state. But make sure to set the previous state
@@ -4126,26 +4160,14 @@
       VOS_ASSERT(0);
       return eHAL_STATUS_FAILURE;
    }
-   //clean up the CB
-   vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], 
-                sizeof(sme_QosWmmTspecInfo));
-   vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0], 
-                sizeof(sme_QosWmmTspecInfo));
-   vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1], 
-                sizeof(sme_QosWmmTspecInfo));
-   vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1], 
-                sizeof(sme_QosWmmTspecInfo));
-   pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
-   pACInfo->tspec_pending = 0;
-   //event: EVENT_WLAN_QOS
-#ifdef FEATURE_WLAN_DIAG_SUPPORT          
+
+//event: EVENT_WLAN_QOS
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
    qos.eventId = SME_QOS_DIAG_DELTS;
    qos.reasonCode = SME_QOS_DIAG_DELTS_IND_FROM_AP;
    WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
 #endif //FEATURE_WLAN_DIAG_SUPPORT
 
-   sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP);
-   (void)sme_QosProcessBufferedCmd(sessionId);
    return eHAL_STATUS_SUCCESS;
 }
 /*--------------------------------------------------------------------------
@@ -6628,6 +6650,9 @@
    sme_QosACInfo *pACInfo;
    sme_QosFlowInfoEntry *flow_info = NULL;
    sme_QosEdcaAcType ac;
+   eHalStatus lock_status = eHAL_STATUS_FAILURE;
+   sme_QosStatusType status;
+
    if(!pEntry)
    {
       VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, 
@@ -6642,18 +6667,24 @@
    ac = flow_info->ac_type;
    pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
    pACInfo = &pSession->ac_info[ac];
-   flow_info->QoSCallback(pMac, flow_info->HDDcontext, 
-                          &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
-                          SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
-                          flow_info->QosFlowID);
-   pACInfo->num_flows[flow_info->tspec_mask - 1]--;
+   pACInfo->relTrig = SME_QOS_RELEASE_BY_AP;
+
+   lock_status = sme_AcquireGlobalLock( &pMac->sme );
+   if ( !HAL_STATUS_SUCCESS( lock_status ) )
+   {
+      VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                "%s: %d: Unable to obtain lock",
+                __func__, __LINE__);
+      return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
+   }
+   //Call the internal function for QoS release, adding a layer of abstraction
+   status = sme_QosInternalReleaseReq(pMac, flow_info->QosFlowID, VOS_FALSE);
+   sme_ReleaseGlobalLock( &pMac->sme );
    VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, 
-             "%s: %d: Deleting entry at %p with flowID %d",
+             "%s: %d: QoS Release return status on Flow %d is %d",
              __func__, __LINE__,
-             flow_info, flow_info->QosFlowID);
-   csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
-   // reclaim the memory
-   vos_mem_free(flow_info);
+             flow_info->QosFlowID, status);
+
    return eHAL_STATUS_SUCCESS;
 }
 /*--------------------------------------------------------------------------