blob: 5f2585fa7f7fb2366797d56a072d64633affc937 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**=========================================================================
23
24 \file sme_Qos.c
25
26 \brief implementation for SME QoS APIs
27
28 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
29
30 Qualcomm Confidential and Proprietary.
31
32 ========================================================================*/
33/* $Header$ */
34/*--------------------------------------------------------------------------
35 Include Files
36 ------------------------------------------------------------------------*/
37
38#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
39#include "halInternal.h" //Check if the below include of aniGobal.h is sufficient for Volans too.
40#endif
41
42#ifdef FEATURE_WLAN_INTEGRATED_SOC
43#include "aniGlobal.h"
44#endif
45
46#include "smeInside.h"
47#include "vos_diag_core_event.h"
48#include "vos_diag_core_log.h"
49
50#ifdef WLAN_FEATURE_VOWIFI_11R
51#include "smsDebug.h"
52#include "utilsParser.h"
53#endif
54#ifdef FEATURE_WLAN_CCX
55#include <csrCcx.h>
56#endif
57
58#ifndef WLAN_MDM_CODE_REDUCTION_OPT
59/* TODO : 6Mbps as Cisco APs seem to like only this value; analysis req. */
60#define SME_QOS_MIN_PHY_RATE 0x5B8D80
61#define SME_QOS_SURPLUS_BW_ALLOWANCE 0x2000 /* Ratio of 1.0 */
62/*---------------------------------------------------------------------------
63 Max values to bound tspec params against and avoid rollover
64---------------------------------------------------------------------------*/
65#define SME_QOS_32BIT_MAX 0xFFFFFFFF
66#define SME_QOS_16BIT_MAX 0xFFFF
67#define SME_QOS_16BIT_MSB 0x8000
68/*---------------------------------------------------------------------------
69 Adds y to x, but saturates at 32-bit max to avoid rollover
70---------------------------------------------------------------------------*/
71#define SME_QOS_BOUNDED_U32_ADD_Y_TO_X( _x, _y ) \
72 do \
73 { \
74 (_x) = ( (SME_QOS_32BIT_MAX-(_x))<(_y) ) ? \
75 (SME_QOS_32BIT_MAX) : (_x)+(_y); \
76 } while(0)
77/*---------------------------------------------------------------------------
78 As per WMM spec there could be max 2 TSPEC running on the same AC with
79 different direction. We will refer each TSPEC with an index
80---------------------------------------------------------------------------*/
81#define SME_QOS_TSPEC_INDEX_0 0
82#define SME_QOS_TSPEC_INDEX_1 1
83#define SME_QOS_TSPEC_INDEX_MAX 2
84#define SME_QOS_TSPEC_MASK_BIT_1_SET 1
85#define SME_QOS_TSPEC_MASK_BIT_2_SET 2
86#define SME_QOS_TSPEC_MASK_BIT_1_2_SET 3
87#define SME_QOS_TSPEC_MASK_CLEAR 0
88
89//which key to search on, in the flowlist (1 = flowID, 2 = AC, 4 = reason)
90#define SME_QOS_SEARCH_KEY_INDEX_1 1
91#define SME_QOS_SEARCH_KEY_INDEX_2 2
92#define SME_QOS_SEARCH_KEY_INDEX_3 4
93#define SME_QOS_SEARCH_KEY_INDEX_4 8 // ac + direction
94#define SME_QOS_SEARCH_KEY_INDEX_5 0x10 // ac + tspec_mask
95//special value for searching any Session Id
96#define SME_QOS_SEARCH_SESSION_ID_ANY CSR_ROAM_SESSION_MAX
97#define SME_QOS_ACCESS_POLICY_EDCA 1
98#define SME_QOS_MAX_TID 255
99#define SME_QOS_TSPEC_IE_LENGTH 61
100#define SME_QOS_TSPEC_IE_TYPE 2
101#define SME_QOS_MIN_FLOW_ID 1
102#define SME_QOS_MAX_FLOW_ID 0xFFFFFFFE
103#define SME_QOS_INVALID_FLOW_ID 0xFFFFFFFF
104// per the WMM Specification v1.2 Section 2.2.10
105// The Dialog Token field shall be set [...] to a non-zero value
106#define SME_QOS_MIN_DIALOG_TOKEN 1
107#define SME_QOS_MAX_DIALOG_TOKEN 0xFF
108/*--------------------------------------------------------------------------
109 Type declarations
110 ------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------
112 Enumeration of the various states in the QoS state m/c
113---------------------------------------------------------------------------*/
114typedef enum
115{
116 SME_QOS_CLOSED = 0,
117 SME_QOS_INIT,
118 SME_QOS_LINK_UP,
119 SME_QOS_REQUESTED,
120 SME_QOS_QOS_ON,
121 SME_QOS_HANDOFF,
122
123}sme_QosStates;
124/*---------------------------------------------------------------------------
125 Enumeration of the various QoS cmds
126---------------------------------------------------------------------------*/
127typedef enum
128{
129 SME_QOS_SETUP_REQ = 0,
130 SME_QOS_RELEASE_REQ,
131 SME_QOS_MODIFY_REQ,
132 SME_QOS_RESEND_REQ,
133 SME_QOS_CMD_MAX
134}sme_QosCmdType;
135/*---------------------------------------------------------------------------
136 Enumeration of the various QoS reason codes to be used in the Flow list
137---------------------------------------------------------------------------*/
138typedef enum
139{
140 SME_QOS_REASON_SETUP = 0,
141 SME_QOS_REASON_RELEASE,
142 SME_QOS_REASON_MODIFY,
143 SME_QOS_REASON_MODIFY_PENDING,
144 SME_QOS_REASON_REQ_SUCCESS,
145 SME_QOS_REASON_MAX
146}sme_QosReasonType;
147
148/*---------------------------------------------------------------------------
149 Table to map user priority passed in as an argument to appropriate Access
150 Category as specified in 802.11e/WMM
151---------------------------------------------------------------------------*/
152sme_QosEdcaAcType sme_QosUPtoACMap[SME_QOS_WMM_UP_MAX] =
153{
154 SME_QOS_EDCA_AC_BE, /* User Priority 0 */
155 SME_QOS_EDCA_AC_BK, /* User Priority 1 */
156 SME_QOS_EDCA_AC_BK, /* User Priority 2 */
157 SME_QOS_EDCA_AC_BE, /* User Priority 3 */
158 SME_QOS_EDCA_AC_VI, /* User Priority 4 */
159 SME_QOS_EDCA_AC_VI, /* User Priority 5 */
160 SME_QOS_EDCA_AC_VO, /* User Priority 6 */
161 SME_QOS_EDCA_AC_VO /* User Priority 7 */
162};
163
164/*---------------------------------------------------------------------------
165 Table to map access category (AC) to appropriate user priority as specified
166 in 802.11e/WMM
167 Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs
168 Mapping is done for consistency
169---------------------------------------------------------------------------*/
170sme_QosWmmUpType sme_QosACtoUPMap[SME_QOS_EDCA_AC_MAX] =
171{
172 SME_QOS_WMM_UP_BE, /* AC BE */
173 SME_QOS_WMM_UP_BK, /* AC BK */
174 SME_QOS_WMM_UP_VI, /* AC VI */
175 SME_QOS_WMM_UP_VO /* AC VO */
176};
177/*---------------------------------------------------------------------------
178DESCRIPTION
179 SME QoS module's FLOW Link List structure. This list can hold information per
180 flow/request, like TSPEC params requested, which AC it is running on
181---------------------------------------------------------------------------*/
182typedef struct sme_QosFlowInfoEntry_s
183{
184 tListElem link; /* list links */
185 v_U8_t sessionId;
186 v_U8_t tspec_mask;
187 sme_QosReasonType reason;
188 v_U32_t QosFlowID;
189 sme_QosEdcaAcType ac_type;
190 sme_QosWmmTspecInfo QoSInfo;
191 void * HDDcontext;
192 sme_QosCallback QoSCallback;
193 v_BOOL_t hoRenewal;//set to TRUE while re-negotiating flows after
194 //handoff, will set to FALSE once done with
195 //the process. Helps SME to decide if at all
196 //to notify HDD/LIS for flow renewal after HO
197} sme_QosFlowInfoEntry;
198/*---------------------------------------------------------------------------
199DESCRIPTION
200 SME QoS module's setup request cmd related information structure.
201---------------------------------------------------------------------------*/
202typedef struct sme_QosSetupCmdInfo_s
203{
204 v_U32_t QosFlowID;
205 sme_QosWmmTspecInfo QoSInfo;
206 void *HDDcontext;
207 sme_QosCallback QoSCallback;
208 sme_QosWmmUpType UPType;
209 v_BOOL_t hoRenewal;//set to TRUE while re-negotiating flows after
210 //handoff, will set to FALSE once done with
211 //the process. Helps SME to decide if at all
212 //to notify HDD/LIS for flow renewal after HO
213} sme_QosSetupCmdInfo;
214/*---------------------------------------------------------------------------
215DESCRIPTION
216 SME QoS module's modify cmd related information structure.
217---------------------------------------------------------------------------*/
218typedef struct sme_QosModifyCmdInfo_s
219{
220 v_U32_t QosFlowID;
221 sme_QosEdcaAcType ac;
222 sme_QosWmmTspecInfo QoSInfo;
223} sme_QosModifyCmdInfo;
224/*---------------------------------------------------------------------------
225DESCRIPTION
226 SME QoS module's resend cmd related information structure.
227---------------------------------------------------------------------------*/
228typedef struct sme_QosResendCmdInfo_s
229{
230 v_U8_t tspecMask;
231 sme_QosEdcaAcType ac;
232 sme_QosWmmTspecInfo QoSInfo;
233} sme_QosResendCmdInfo;
234/*---------------------------------------------------------------------------
235DESCRIPTION
236 SME QoS module's release cmd related information structure.
237---------------------------------------------------------------------------*/
238typedef struct sme_QosReleaseCmdInfo_s
239{
240 v_U32_t QosFlowID;
241} sme_QosReleaseCmdInfo;
242/*---------------------------------------------------------------------------
243DESCRIPTION
244 SME QoS module's buffered cmd related information structure.
245---------------------------------------------------------------------------*/
246typedef struct sme_QosCmdInfo_s
247{
248 sme_QosCmdType command;
249 tpAniSirGlobal pMac;
250 v_U8_t sessionId;
251 union
252 {
253 sme_QosSetupCmdInfo setupCmdInfo;
254 sme_QosModifyCmdInfo modifyCmdInfo;
255 sme_QosResendCmdInfo resendCmdInfo;
256 sme_QosReleaseCmdInfo releaseCmdInfo;
257 }u;
258} sme_QosCmdInfo;
259/*---------------------------------------------------------------------------
260DESCRIPTION
261 SME QoS module's buffered cmd List structure. This list can hold information
262 related to any pending cmd from HDD
263---------------------------------------------------------------------------*/
264typedef struct sme_QosCmdInfoEntry_s
265{
266 tListElem link; /* list links */
267 sme_QosCmdInfo cmdInfo;
268} sme_QosCmdInfoEntry;
269/*---------------------------------------------------------------------------
270DESCRIPTION
271 SME QoS module's Per AC information structure. This can hold information on
272 how many flows running on the AC, the current, previous states the AC is in
273---------------------------------------------------------------------------*/
274typedef struct sme_QosACInfo_s
275{
276 v_U8_t num_flows[SME_QOS_TSPEC_INDEX_MAX];
277 sme_QosStates curr_state;
278 sme_QosStates prev_state;
279 sme_QosWmmTspecInfo curr_QoSInfo[SME_QOS_TSPEC_INDEX_MAX];
280 sme_QosWmmTspecInfo requested_QoSInfo[SME_QOS_TSPEC_INDEX_MAX];
281 v_BOOL_t reassoc_pending;//reassoc requested for APSD
282 //As per WMM spec there could be max 2 TSPEC running on the same AC with
283 //different direction. We will refer each TSPEC with an index
284 v_U8_t tspec_mask_status; //status showing if both the indices are in use
285 v_U8_t tspec_pending;//tspec negotiation going on for which index
286 v_BOOL_t hoRenewal;//set to TRUE while re-negotiating flows after
287 //handoff, will set to FALSE once done with
288 //the process. Helps SME to decide if at all
289 //to notify HDD/LIS for flow renewal after HO
290#ifdef WLAN_FEATURE_VOWIFI_11R
291 v_U8_t ricIdentifier[SME_QOS_TSPEC_INDEX_MAX];
292 /* stores the ADD TS response for each AC. The ADD TS response is formed by
293 parsing the RIC received in the the reassoc response */
294 tSirAddtsRsp addTsRsp[SME_QOS_TSPEC_INDEX_MAX];
295#endif
296
297} sme_QosACInfo;
298/*---------------------------------------------------------------------------
299DESCRIPTION
300 SME QoS module's Per session information structure. This can hold information
301 on the state of the session
302---------------------------------------------------------------------------*/
303typedef struct sme_QosSessionInfo_s
304{
305 // what is this entry's session id
306 v_U8_t sessionId;
307 // is the session currently active
308 v_BOOL_t sessionActive;
309 // All AC info for this session
310 sme_QosACInfo ac_info[SME_QOS_EDCA_AC_MAX];
311 // Bitmask of the ACs with APSD on
312 // Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored
313 v_U8_t apsdMask;
314 // association information for this session
315 sme_QosAssocInfo assocInfo;
316 // ID assigned to our reassoc request
317 v_U32_t roamID;
318 // maintaining a powersave status in QoS module, to be fed back to PMC at
319 // times through the sme_QosPmcCheckRoutine
320 v_BOOL_t readyForPowerSave;
321 // are we in the process of handing off to a different AP
322 v_BOOL_t handoffRequested;
323 // following reassoc or AddTS has UAPSD already been requested from PMC
324 v_BOOL_t uapsdAlreadyRequested;
325 // commands that are being buffered for this session
326 tDblLinkList bufferedCommandList;
327
328#ifdef WLAN_FEATURE_VOWIFI_11R
329 v_BOOL_t ftHandoffInProgress;
330#endif
331
332} sme_QosSessionInfo;
333/*---------------------------------------------------------------------------
334DESCRIPTION
335 Search key union. We can use the flowID, ac type, or reason to find an entry
336 in the flow list
337---------------------------------------------------------------------------*/
338typedef union sme_QosSearchKey_s
339{
340 v_U32_t QosFlowID;
341 sme_QosEdcaAcType ac_type;
342 sme_QosReasonType reason;
343}sme_QosSearchKey;
344/*---------------------------------------------------------------------------
345DESCRIPTION
346 We can either use the flowID or the ac type to find an entry in the flow list.
347 The index is a bitmap telling us which key to use. Starting from LSB,
348 bit 0 - Flow ID
349 bit 1 - AC type
350---------------------------------------------------------------------------*/
351typedef struct sme_QosSearchInfo_s
352{
353 v_U8_t sessionId;
354 v_U8_t index;
355 sme_QosSearchKey key;
356 sme_QosWmmDirType direction;
357 v_U8_t tspec_mask;
358}sme_QosSearchInfo;
359/*---------------------------------------------------------------------------
360DESCRIPTION
361 SME QoS module's internal control block.
362---------------------------------------------------------------------------*/
363struct sme_QosCb_s
364{
365 //global Mac pointer
366 tpAniSirGlobal pMac;
367 //All Session Info
368 sme_QosSessionInfo sessionInfo[CSR_ROAM_SESSION_MAX];
369 //All FLOW info
370 tDblLinkList flow_list;
371 //default TSPEC params
372 sme_QosWmmTspecInfo def_QoSInfo[SME_QOS_EDCA_AC_MAX];
373 //counter for assigning Flow IDs
374 v_U32_t nextFlowId;
375 //counter for assigning Dialog Tokens
376 v_U8_t nextDialogToken;
377}sme_QosCb;
378typedef eHalStatus (*sme_QosProcessSearchEntry)(tpAniSirGlobal pMac, tListElem *pEntry);
379/*--------------------------------------------------------------------------
380 Internal function declarations
381 ------------------------------------------------------------------------*/
382sme_QosStatusType sme_QosInternalSetupReq(tpAniSirGlobal pMac,
383 v_U8_t sessionId,
384 sme_QosWmmTspecInfo * pQoSInfo,
385 sme_QosCallback QoSCallback,
386 void * HDDcontext,
387 sme_QosWmmUpType UPType,
388 v_U32_t QosFlowID,
389 v_BOOL_t buffered_cmd,
390 v_BOOL_t hoRenewal);
391sme_QosStatusType sme_QosInternalModifyReq(tpAniSirGlobal pMac,
392 sme_QosWmmTspecInfo * pQoSInfo,
393 v_U32_t QosFlowID,
394 v_BOOL_t buffered_cmd);
395sme_QosStatusType sme_QosInternalReleaseReq(tpAniSirGlobal pMac,
396 v_U32_t QosFlowID,
397 v_BOOL_t buffered_cmd);
398sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac,
399 v_U8_t sessionId,
400 sme_QosWmmTspecInfo *pTspec_Info,
401 sme_QosEdcaAcType ac);
402eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac,
403 v_U8_t sessionId,
404 sme_QosWmmTspecInfo * pTspec_Info,
405 sme_QosEdcaAcType ac);
406eHalStatus sme_QosDelTsReq(tpAniSirGlobal pMac,
407 v_U8_t sessionId,
408 sme_QosEdcaAcType ac,
409 v_U8_t tspec_mask);
410eHalStatus sme_QosProcessAddTsRsp(tpAniSirGlobal pMac, void *pMsgBuf);
411eHalStatus sme_QosProcessDelTsInd(tpAniSirGlobal pMac, void *pMsgBuf);
412eHalStatus sme_QosProcessDelTsRsp(tpAniSirGlobal pMac, void *pMsgBuf);
413eHalStatus sme_QosProcessAssocCompleteEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
414eHalStatus sme_QosProcessReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
415eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
416eHalStatus sme_QosProcessReassocFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
417eHalStatus sme_QosProcessDisconnectEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
418eHalStatus sme_QosProcessJoinReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
419eHalStatus sme_QosProcessHandoffAssocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
420eHalStatus sme_QosProcessHandoffSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
421eHalStatus sme_QosProcessHandoffFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
422#ifdef WLAN_FEATURE_VOWIFI_11R
423eHalStatus sme_QosProcessPreauthSuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
424eHalStatus sme_QosProcessSetKeySuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info);
425eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf);
426eHalStatus sme_QosFTAggrQosReq( tpAniSirGlobal pMac, v_U8_t sessionId );
427#endif
428eHalStatus sme_QosProcessAddTsSuccessRsp(tpAniSirGlobal pMac,
429 v_U8_t sessionId,
430 tSirAddtsRspInfo * pRsp);
431eHalStatus sme_QosProcessAddTsFailureRsp(tpAniSirGlobal pMac,
432 v_U8_t sessionId,
433 tSirAddtsRspInfo * pRsp);
434eHalStatus sme_QosAggregateParams(
435 sme_QosWmmTspecInfo * pInput_Tspec_Info,
436 sme_QosWmmTspecInfo * pCurrent_Tspec_Info,
437 sme_QosWmmTspecInfo * pUpdated_Tspec_Info);
438static eHalStatus sme_QosUpdateParams(v_U8_t sessionId,
439 sme_QosEdcaAcType ac,
440 v_U8_t tspec_mask,
441 sme_QosWmmTspecInfo * pTspec_Info);
442sme_QosWmmUpType sme_QosAcToUp(sme_QosEdcaAcType ac);
443sme_QosEdcaAcType sme_QosUpToAc(sme_QosWmmUpType up);
444v_BOOL_t sme_QosIsACM(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
445 sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes);
446tListElem *sme_QosFindInFlowList(sme_QosSearchInfo search_key);
447eHalStatus sme_QosFindAllInFlowList(tpAniSirGlobal pMac,
448 sme_QosSearchInfo search_key,
449 sme_QosProcessSearchEntry fnp);
450static void sme_QosStateTransition(v_U8_t sessionId,
451 sme_QosEdcaAcType ac,
452 sme_QosStates new_state);
453eHalStatus sme_QosBufferCmd(sme_QosCmdInfo *pcmd, v_BOOL_t insert_head);
454static eHalStatus sme_QosProcessBufferedCmd(v_U8_t sessionId);
455eHalStatus sme_QosSaveAssocInfo(sme_QosSessionInfo *pSession, sme_QosAssocInfo *pAssoc_info);
456eHalStatus sme_QosSetupFnp(tpAniSirGlobal pMac, tListElem *pEntry);
457eHalStatus sme_QosModificationNotifyFnp(tpAniSirGlobal pMac, tListElem *pEntry);
458eHalStatus sme_QosModifyFnp(tpAniSirGlobal pMac, tListElem *pEntry);
459eHalStatus sme_QosDelTsIndFnp(tpAniSirGlobal pMac, tListElem *pEntry);
460eHalStatus sme_QosReassocSuccessEvFnp(tpAniSirGlobal pMac, tListElem *pEntry);
461eHalStatus sme_QosAddTsFailureFnp(tpAniSirGlobal pMac, tListElem *pEntry);
462eHalStatus sme_QosAddTsSuccessFnp(tpAniSirGlobal pMac, tListElem *pEntry);
463static v_BOOL_t sme_QosIsRspPending(v_U8_t sessionId, sme_QosEdcaAcType ac);
464static v_BOOL_t sme_QosIsUapsdActive(void);
465void sme_QosPmcFullPowerCallback(void *callbackContext, eHalStatus status);
466void sme_QosPmcStartUapsdCallback(void *callbackContext, eHalStatus status);
467v_BOOL_t sme_QosPmcCheckRoutine(void *callbackContext);
468void sme_QosPmcDeviceStateUpdateInd(void *callbackContext, tPmcState pmcState);
469eHalStatus sme_QosProcessOutOfUapsdMode(tpAniSirGlobal pMac);
470eHalStatus sme_QosProcessIntoUapsdMode(tpAniSirGlobal pMac);
471static eHalStatus sme_QosBufferExistingFlows(tpAniSirGlobal pMac,
472 v_U8_t sessionId);
473static eHalStatus sme_QosDeleteExistingFlows(tpAniSirGlobal pMac,
474 v_U8_t sessionId);
475static void sme_QosCleanupCtrlBlkForHandoff(tpAniSirGlobal pMac,
476 v_U8_t sessionId);
477static eHalStatus sme_QosDeleteBufferedRequests(tpAniSirGlobal pMac,
478 v_U8_t sessionId);
479v_BOOL_t sme_QosValidateRequestedParams(tpAniSirGlobal pMac,
480 sme_QosWmmTspecInfo * pQoSInfo,
481 v_U8_t sessionId);
482
483extern eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme);
484extern eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme);
485static eHalStatus qosIssueCommand( tpAniSirGlobal pMac, v_U8_t sessionId,
486 eSmeCommandType cmdType, sme_QosWmmTspecInfo * pQoSInfo,
487 sme_QosEdcaAcType ac, v_U8_t tspec_mask );
488/*
489 sme_QosReRequestAddTS to re-send AddTS for the combined QoS request
490*/
491static sme_QosStatusType sme_QosReRequestAddTS(tpAniSirGlobal pMac,
492 v_U8_t sessionId,
493 sme_QosWmmTspecInfo * pQoSInfo,
494 sme_QosEdcaAcType ac,
495 v_U8_t tspecMask);
496static void sme_QosInitACs(tpAniSirGlobal pMac, v_U8_t sessionId);
497static eHalStatus sme_QosRequestReassoc(tpAniSirGlobal pMac, tANI_U8 sessionId,
498 tCsrRoamModifyProfileFields *pModFields,
499 v_BOOL_t fForce );
500static v_U32_t sme_QosAssignFlowId(void);
501static v_U8_t sme_QosAssignDialogToken(void);
502static eHalStatus sme_QosUpdateTspecMask(v_U8_t sessionId,
503 sme_QosSearchInfo search_key,
504 v_U8_t new_tspec_mask);
505/*--------------------------------------------------------------------------
506 External APIs definitions
507 ------------------------------------------------------------------------*/
508/* --------------------------------------------------------------------------
509 \brief sme_QosOpen() - This function must be called before any API call to
510 SME QoS module.
511 \param pMac - Pointer to the global MAC parameter structure.
512
513 \return eHalStatus
514----------------------------------------------------------------------------*/
515eHalStatus sme_QosOpen(tpAniSirGlobal pMac)
516{
517 sme_QosSessionInfo *pSession;
518 v_U8_t sessionId;
519 eHalStatus status;
520 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
521 "%s: %d: initializing SME-QoS module",
522 __FUNCTION__, __LINE__);
523 //init the control block
524 //(note that this will make all sessions invalid)
525 vos_mem_zero(&sme_QosCb, sizeof(sme_QosCb));
526 sme_QosCb.pMac = pMac;
527 sme_QosCb.nextFlowId = SME_QOS_MIN_FLOW_ID;
528 sme_QosCb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN;
529 //init flow list
530 status = csrLLOpen(pMac->hHdd, &sme_QosCb.flow_list);
531 if (!HAL_STATUS_SUCCESS(status))
532 {
533 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
534 "%s: %d: cannot initialize Flow List",
535 __FUNCTION__, __LINE__);
536 return eHAL_STATUS_FAILURE;
537 }
538
539 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
540 {
541 pSession = &sme_QosCb.sessionInfo[sessionId];
542 pSession->sessionId = sessionId;
543 // initialize the session's per-AC information
544 sme_QosInitACs(pMac, sessionId);
545 // initialize the session's buffered command list
546 status = csrLLOpen(pMac->hHdd, &pSession->bufferedCommandList);
547 if (!HAL_STATUS_SUCCESS(status))
548 {
549 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
550 "%s: %d: cannot initialize cmd list for session %d",
551 __FUNCTION__, __LINE__,
552 sessionId);
553 return eHAL_STATUS_FAILURE;
554 }
555 pSession->readyForPowerSave = VOS_TRUE;
556 }
557 //the routine registered here gets called by PMC whenever the device is about
558 //to enter one of the power save modes. PMC runs a poll with all the
559 //registered modules if device can enter powersave mode or remain full power
560 if(!HAL_STATUS_SUCCESS(
561 pmcRegisterPowerSaveCheck(pMac, sme_QosPmcCheckRoutine, pMac)))
562 {
563 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
564 "%s: %d: cannot register with pmcRegisterPowerSaveCheck()",
565 __FUNCTION__, __LINE__);
566 return eHAL_STATUS_FAILURE;
567 }
568 //the routine registered here gets called by PMC whenever there is a device
569 // state change. PMC might go to full power because of many reasons and this
570 // is the way for PMC to inform all the other registered modules so that
571 // everyone is in sync.
572 if(!HAL_STATUS_SUCCESS(
573 pmcRegisterDeviceStateUpdateInd(pMac, sme_QosPmcDeviceStateUpdateInd, pMac)))
574 {
575 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
576 "%s: %d: cannot register with pmcRegisterDeviceStateUpdateInd()",
577 __FUNCTION__, __LINE__);
578 return eHAL_STATUS_FAILURE;
579 }
580 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
581 "%s: %d: done initializing SME-QoS module",
582 __FUNCTION__, __LINE__);
583 return eHAL_STATUS_SUCCESS;
584}
585/* --------------------------------------------------------------------------
586 \brief sme_QosClose() - To close down SME QoS module. There should not be
587 any API call into this module after calling this function until another
588 call of sme_QosOpen.
589 \param pMac - Pointer to the global MAC parameter structure.
590
591 \return eHalStatus
592----------------------------------------------------------------------------*/
593eHalStatus sme_QosClose(tpAniSirGlobal pMac)
594{
595 sme_QosSessionInfo *pSession;
596 sme_QosEdcaAcType ac;
597 v_U8_t sessionId;
598 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
599 "%s: %d: closing down SME-QoS",
600 __FUNCTION__, __LINE__);
601 // deregister with PMC
602 if(!HAL_STATUS_SUCCESS(
603 pmcDeregisterDeviceStateUpdateInd(pMac, sme_QosPmcDeviceStateUpdateInd)))
604 {
605 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
606 "%s: %d: cannot deregister with pmcDeregisterDeviceStateUpdateInd()",
607 __FUNCTION__, __LINE__);
608 }
609 if(!HAL_STATUS_SUCCESS(
610 pmcDeregisterPowerSaveCheck(pMac, sme_QosPmcCheckRoutine)))
611 {
612 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
613 "%s: %d: cannot deregister with pmcDeregisterPowerSaveCheck()",
614 __FUNCTION__, __LINE__);
615 }
616 //cleanup control block
617 //close the flow list
618 csrLLClose(&sme_QosCb.flow_list);
619 // shut down all of the sessions
620 for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
621 {
622 pSession = &sme_QosCb.sessionInfo[sessionId];
623 if (pSession == NULL)
624 continue;
625
626 sme_QosInitACs(pMac, sessionId);
627 // this session doesn't require UAPSD
628 pSession->apsdMask = 0;
629
630 pSession->uapsdAlreadyRequested = VOS_FALSE;
631 pSession->handoffRequested = VOS_FALSE;
632 pSession->readyForPowerSave = VOS_TRUE;
633 pSession->roamID = 0;
634 //need to clean up buffered req
635 sme_QosDeleteBufferedRequests(pMac, sessionId);
636 //need to clean up flows
637 sme_QosDeleteExistingFlows(pMac, sessionId);
638
639 // Clean up the assoc info if already allocated
640 if (pSession->assocInfo.pBssDesc) {
641 vos_mem_free(pSession->assocInfo.pBssDesc);
642 pSession->assocInfo.pBssDesc = NULL;
643 }
644
645 // close the session's buffered command list
646 csrLLClose(&pSession->bufferedCommandList);
647 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
648 {
649 sme_QosStateTransition(sessionId, ac, SME_QOS_CLOSED);
650 }
651 pSession->sessionActive = VOS_FALSE;
652 pSession->readyForPowerSave = VOS_TRUE;
653 }
654 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
655 "%s: %d: closed down QoS",
656 __FUNCTION__, __LINE__);
657 return eHAL_STATUS_SUCCESS;
658}
659/*--------------------------------------------------------------------------
660 \brief sme_QosSetupReq() - The SME QoS API exposed to HDD to request for QoS
661 on a particular AC. This function should be called after a link has been
662 established, i.e. STA is associated with an AP etc. If the request involves
663 admission control on the requested AC, HDD needs to provide the necessary
664 Traffic Specification (TSPEC) parameters otherwise SME is going to use the
665 default params.
666
667 \param hHal - The handle returned by macOpen.
668 \param sessionId - sessionId returned by sme_OpenSession.
669 \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
670 related info as defined above, provided by HDD
671 \param QoSCallback - The callback which is registered per flow while
672 requesting for QoS. Used for any notification for the
673 flow (i.e. setup success/failure/release) which needs to
674 be sent to HDD
675 \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS
676 notification (through the callabck) to HDD
677 \param UPType - Useful only if HDD or any other upper layer module (BAP etc.)
678 looking for implicit QoS setup, in that
679 case, the pQoSInfo will be NULL & SME will know about the AC
680 (from the UP provided in this param) QoS is requested on
681 \param pQosFlowID - Identification per flow running on each AC generated by
682 SME.
683 It is only meaningful if the QoS setup for the flow is
684 successful
685
686 \return eHAL_STATUS_SUCCESS - Setup is successful.
687
688 Other status means Setup request failed
689 \sa
690
691 --------------------------------------------------------------------------*/
692sme_QosStatusType sme_QosSetupReq(tHalHandle hHal, tANI_U32 sessionId,
693 sme_QosWmmTspecInfo * pQoSInfo,
694 sme_QosCallback QoSCallback,
695 void * HDDcontext,
696 sme_QosWmmUpType UPType, v_U32_t * pQosFlowID)
697{
698 sme_QosSessionInfo *pSession;
699 eHalStatus lock_status = eHAL_STATUS_FAILURE;
700 tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
701 sme_QosStatusType status;
702 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
703 "%s: %d: QoS Setup requested by client on session %d",
704 __FUNCTION__, __LINE__,
705 sessionId);
706 lock_status = sme_AcquireGlobalLock( &pMac->sme );
707 if ( !HAL_STATUS_SUCCESS( lock_status ) )
708 {
709 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
710 "%s: %d: Unable to obtain lock",
711 __FUNCTION__, __LINE__);
712 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
713 }
714 //Make sure the session is valid
715 if (!CSR_IS_SESSION_VALID( pMac, sessionId ))
716 {
717 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
718 "%s: %d: Supplied Session ID %d is invalid",
719 __FUNCTION__, __LINE__,
720 sessionId);
721 status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
722 }
723 else
724 {
725 //Make sure the session is active
726 pSession = &sme_QosCb.sessionInfo[sessionId];
727 if (!pSession->sessionActive)
728 {
729 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
730 "%s: %d: Supplied Session ID %d is inactive",
731 __FUNCTION__, __LINE__,
732 sessionId);
733 status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
734 }
735 else
736 {
737 //Assign a Flow ID
738 *pQosFlowID = sme_QosAssignFlowId();
739 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
740 "%s: %d: QoS request on session %d assigned Flow ID %d",
741 __FUNCTION__, __LINE__,
742 sessionId, *pQosFlowID);
743 //Call the internal function for QoS setup,
744 // adding a layer of abstraction
745 status = sme_QosInternalSetupReq(pMac, (v_U8_t)sessionId, pQoSInfo,
746 QoSCallback, HDDcontext, UPType,
747 *pQosFlowID, VOS_FALSE, VOS_FALSE);
748 }
749 }
750 sme_ReleaseGlobalLock( &pMac->sme );
751 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
752 "%s: %d: QoS setup return status on session %d is %d",
753 __FUNCTION__, __LINE__,
754 sessionId, status);
755 return status;
756}
757
758/*--------------------------------------------------------------------------
759 \brief sme_QosModifyReq() - The SME QoS API exposed to HDD to request for
760 modification of certain QoS params on a flow running on a particular AC.
761 This function should be called after a link has been established, i.e. STA is
762 associated with an AP etc. & a QoS setup has been succesful for that flow.
763 If the request involves admission control on the requested AC, HDD needs to
764 provide the necessary Traffic Specification (TSPEC) parameters & SME might
765 start the renegotiation process through ADDTS.
766
767 \param hHal - The handle returned by macOpen.
768 \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
769 related info as defined above, provided by HDD
770 \param QosFlowID - Identification per flow running on each AC generated by
771 SME.
772 It is only meaningful if the QoS setup for the flow has
773 been successful already
774
775 \return SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful.
776
777 Other status means request failed
778 \sa
779
780 --------------------------------------------------------------------------*/
781sme_QosStatusType sme_QosModifyReq(tHalHandle hHal,
782 sme_QosWmmTspecInfo * pQoSInfo,
783 v_U32_t QosFlowID)
784{
785 eHalStatus lock_status = eHAL_STATUS_FAILURE;
786 tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
787 sme_QosStatusType status;
788 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
789 "%s: %d: QoS Modify requested by client for Flow %d",
790 __FUNCTION__, __LINE__,
791 QosFlowID);
792 lock_status = sme_AcquireGlobalLock( &pMac->sme );
793 if ( !HAL_STATUS_SUCCESS( lock_status ) )
794 {
795 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
796 "%s: %d: Unable to obtain lock",
797 __FUNCTION__, __LINE__);
798 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
799 }
800 //Call the internal function for QoS modify, adding a layer of abstraction
801 status = sme_QosInternalModifyReq(pMac, pQoSInfo, QosFlowID, VOS_FALSE);
802 sme_ReleaseGlobalLock( &pMac->sme );
803 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
804 "%s: %d: QoS Modify return status on Flow %d is %d",
805 __FUNCTION__, __LINE__,
806 QosFlowID, status);
807 return status;
808}
809/*--------------------------------------------------------------------------
810 \brief sme_QosReleaseReq() - The SME QoS API exposed to HDD to request for
811 releasing a QoS flow running on a particular AC. This function should be
812 called only if a QoS is set up with a valid FlowID. HDD sould invoke this
813 API only if an explicit request for QoS release has come from Application
814
815 \param hHal - The handle returned by macOpen.
816 \param QosFlowID - Identification per flow running on each AC generated by SME
817 It is only meaningful if the QoS setup for the flow is
818 successful
819
820 \return eHAL_STATUS_SUCCESS - Release is successful.
821
822 \sa
823
824 --------------------------------------------------------------------------*/
825sme_QosStatusType sme_QosReleaseReq(tHalHandle hHal, v_U32_t QosFlowID)
826{
827 eHalStatus lock_status = eHAL_STATUS_FAILURE;
828 tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
829 sme_QosStatusType status;
830 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
831 "%s: %d: QoS Release requested by client for Flow %d",
832 __FUNCTION__, __LINE__,
833 QosFlowID);
834 lock_status = sme_AcquireGlobalLock( &pMac->sme );
835 if ( !HAL_STATUS_SUCCESS( lock_status ) )
836 {
837 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
838 "%s: %d: Unable to obtain lock",
839 __FUNCTION__, __LINE__);
840 return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
841 }
842 //Call the internal function for QoS release, adding a layer of abstraction
843 status = sme_QosInternalReleaseReq(pMac, QosFlowID, VOS_FALSE);
844 sme_ReleaseGlobalLock( &pMac->sme );
845 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
846 "%s: %d: QoS Release return status on Flow %d is %d",
847 __FUNCTION__, __LINE__,
848 QosFlowID, status);
849 return status;
850}
851/*--------------------------------------------------------------------------
852 \brief sme_QosSetParams() - This function is used by HDD to provide the
853 default TSPEC params to SME.
854
855 \param pMac - Pointer to the global MAC parameter structure.
856 \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
857 related info per AC as defined above, provided by HDD
858
859 \return eHAL_STATUS_SUCCESS - Setparam is successful.
860
861 \sa
862
863 --------------------------------------------------------------------------*/
864eHalStatus sme_QosSetParams(tpAniSirGlobal pMac, sme_QosWmmTspecInfo * pQoSInfo)
865{
866 sme_QosEdcaAcType ac;
867 // find the AC
868 ac = sme_QosUpToAc(pQoSInfo->ts_info.up);
869 if(SME_QOS_EDCA_AC_MAX == ac)
870 {
871 //err msg
872 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
873 "%s: %d: Invalid AC %d (via UP %d)",
874 __FUNCTION__, __LINE__,
875 ac, pQoSInfo->ts_info.up );
876 return eHAL_STATUS_FAILURE;
877 }
878 //copy over the default params for this AC
879 sme_QosCb.def_QoSInfo[ac] = *pQoSInfo;
880 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
881 "%s: %d: QoS default params set for AC %d (via UP %d)",
882 __FUNCTION__, __LINE__,
883 ac, pQoSInfo->ts_info.up );
884 return eHAL_STATUS_SUCCESS;
885}
886
887void qosReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
888{
889 vos_mem_zero( &pCommand->u.qosCmd, sizeof( tGenericQosCmd ) );
890 smeReleaseCommand( pMac, pCommand );
891}
892
893/*--------------------------------------------------------------------------
894 \brief sme_QosMsgProcessor() - sme_ProcessMsg() calls this function for the
895 messages that are handled by SME QoS module.
896
897 \param pMac - Pointer to the global MAC parameter structure.
898 \param msg_type - the type of msg passed by PE as defined in wniApi.h
899 \param pMsgBuf - a pointer to a buffer that maps to various structures base
900 on the message type.
901 The beginning of the buffer can always map to tSirSmeRsp.
902
903 \return eHAL_STATUS_SUCCESS - Validation is successful.
904
905 \sa
906
907 --------------------------------------------------------------------------*/
908eHalStatus sme_QosMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type,
909 void *pMsgBuf)
910{
911 eHalStatus status = eHAL_STATUS_FAILURE;
912 tListElem *pEntry;
913 tSmeCmd *pCommand;
914 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
915 "%s: %d: msg = %d for QoS",
916 __FUNCTION__, __LINE__, msg_type);
917 //switch on the msg type & make the state transition accordingly
918 switch(msg_type)
919 {
920 case eWNI_SME_ADDTS_RSP:
921 pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
922 if( pEntry )
923 {
924 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
925 if( eSmeCommandAddTs == pCommand->command )
926 {
927 status = sme_QosProcessAddTsRsp(pMac, pMsgBuf);
928 if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
929 {
930 qosReleaseCommand( pMac, pCommand );
931 }
932 smeProcessPendingQueue( pMac );
933 }
934 }
935 break;
936 case eWNI_SME_DELTS_RSP:
937 pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
938 if( pEntry )
939 {
940 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
941 if( eSmeCommandDelTs == pCommand->command )
942 {
943 status = sme_QosProcessDelTsRsp(pMac, pMsgBuf);
944 if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
945 {
946 qosReleaseCommand( pMac, pCommand );
947 }
948 smeProcessPendingQueue( pMac );
949 }
950 }
951 break;
952 case eWNI_SME_DELTS_IND:
953 status = sme_QosProcessDelTsInd(pMac, pMsgBuf);
954 break;
955#ifdef WLAN_FEATURE_VOWIFI_11R
956 case eWNI_SME_FT_AGGR_QOS_RSP:
957 status = sme_QosProcessAggrQosRsp(pMac, pMsgBuf);
958 break;
959#endif
960
961 default:
962 //err msg
963 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
964 "%s: %d: unknown msg type = %d",
965 __FUNCTION__, __LINE__, msg_type);
966 break;
967 }
968 return status;
969}
970/*--------------------------------------------------------------------------
971 \brief sme_QosValidateParams() - The SME QoS API exposed to CSR to validate AP
972 capabilities regarding QoS support & any other QoS parameter validation.
973
974 \param pMac - Pointer to the global MAC parameter structure.
975 \param pBssDesc - Pointer to the BSS Descriptor information passed down by
976 CSR to PE while issuing the Join request
977
978 \return eHalStatus
979
980 \sa
981
982 --------------------------------------------------------------------------*/
983eHalStatus sme_QosValidateParams(tpAniSirGlobal pMac,
984 tSirBssDescription *pBssDesc)
985{
986 tDot11fBeaconIEs *pIes = NULL;
987 eHalStatus status = eHAL_STATUS_FAILURE;
988 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
989 "%s: %d: validation for QAP & APSD",
990 __FUNCTION__, __LINE__);
991 do
992 {
993 if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes)))
994 {
995 //err msg
996 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
997 "%s: %d: csrGetParsedBssDescriptionIEs() failed",
998 __FUNCTION__, __LINE__);
999 break;
1000 }
1001 //check if the AP is QAP & it supports APSD
1002 if( !CSR_IS_QOS_BSS(pIes) )
1003 {
1004 //err msg
1005 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1006 "%s: %d: AP doesn't support QoS",
1007 __FUNCTION__, __LINE__);
1008
1009 break;
1010 }
1011 if(!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) &&
1012 !(pIes->WMMInfoAp.uapsd))
1013 {
1014 //err msg
1015 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1016 "%s: %d: AP doesn't support APSD",
1017 __FUNCTION__, __LINE__);
1018 break;
1019 }
1020 status = eHAL_STATUS_SUCCESS;
1021 }while(0);
1022 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1023 "%s: %d: validated with status = %d",
1024 __FUNCTION__, __LINE__, status);
1025 if(pIes)
1026 {
1027 vos_mem_free(pIes);
1028 }
1029 return status;
1030}
1031/*--------------------------------------------------------------------------
1032 \brief sme_QosCsrEventInd() - The QoS sub-module in SME expects notifications
1033 from CSR when certain events occur as mentioned in sme_QosCsrEventIndType.
1034 \param pMac - Pointer to the global MAC parameter structure.
1035 \param ind - The event occurred of type sme_QosCsrEventIndType.
1036 \param pEvent_info - Information related to the event
1037
1038 \return eHalStatus
1039
1040 \sa
1041
1042 --------------------------------------------------------------------------*/
1043eHalStatus sme_QosCsrEventInd(tpAniSirGlobal pMac,
1044 v_U8_t sessionId,
1045 sme_QosCsrEventIndType ind,
1046 void *pEvent_info)
1047{
1048 eHalStatus status = eHAL_STATUS_FAILURE;
1049 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1050 "%s: %d: On Session %d Event %d received from CSR",
1051 __FUNCTION__, __LINE__,
1052 sessionId, ind );
1053 switch(ind)
1054 {
1055 case SME_QOS_CSR_ASSOC_COMPLETE:
1056 //expecting assoc info in pEvent_info
1057 status = sme_QosProcessAssocCompleteEv(pMac, sessionId, pEvent_info);
1058 break;
1059 case SME_QOS_CSR_REASSOC_REQ:
1060 //nothing expected in pEvent_info
1061 status = sme_QosProcessReassocReqEv(pMac, sessionId, pEvent_info);
1062 break;
1063 case SME_QOS_CSR_REASSOC_COMPLETE:
1064 //expecting assoc info in pEvent_info
1065 status = sme_QosProcessReassocSuccessEv(pMac, sessionId, pEvent_info);
1066 break;
1067 case SME_QOS_CSR_REASSOC_FAILURE:
1068 //nothing expected in pEvent_info
1069 status = sme_QosProcessReassocFailureEv(pMac, sessionId, pEvent_info);
1070 break;
1071 case SME_QOS_CSR_DISCONNECT_REQ:
1072 case SME_QOS_CSR_DISCONNECT_IND:
1073 //nothing expected in pEvent_info
1074 status = sme_QosProcessDisconnectEv(pMac, sessionId, pEvent_info);
1075 break;
1076 case SME_QOS_CSR_JOIN_REQ:
1077 //nothing expected in pEvent_info
1078 status = sme_QosProcessJoinReqEv(pMac, sessionId, pEvent_info);
1079 break;
1080 case SME_QOS_CSR_HANDOFF_ASSOC_REQ:
1081 //nothing expected in pEvent_info
1082 status = sme_QosProcessHandoffAssocReqEv(pMac, sessionId, pEvent_info);
1083 break;
1084 case SME_QOS_CSR_HANDOFF_COMPLETE:
1085 //nothing expected in pEvent_info
1086 status = sme_QosProcessHandoffSuccessEv(pMac, sessionId, pEvent_info);
1087 break;
1088 case SME_QOS_CSR_HANDOFF_FAILURE:
1089 //nothing expected in pEvent_info
1090 status = sme_QosProcessHandoffFailureEv(pMac, sessionId, pEvent_info);
1091 break;
1092#ifdef WLAN_FEATURE_VOWIFI_11R
1093 case SME_QOS_CSR_PREAUTH_SUCCESS_IND:
1094 status = sme_QosProcessPreauthSuccessInd(pMac, sessionId, pEvent_info);
1095 break;
Jeff Johnson43971f52012-07-17 12:26:56 -07001096#if defined(FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
Jeff Johnson295189b2012-06-20 16:38:30 -07001097 case SME_QOS_CSR_SET_KEY_SUCCESS_IND:
1098 status = sme_QosProcessSetKeySuccessInd(pMac, sessionId, pEvent_info);
1099 break;
1100#endif
1101#endif
1102 default:
1103 //Err msg
1104 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1105 "%s: %d: On Session %d Unknown Event %d received from CSR",
1106 __FUNCTION__, __LINE__,
1107 sessionId, ind );
1108 break;
1109 }
1110 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1111 "%s: %d: On Session %d processed Event %d with status %d",
1112 __FUNCTION__, __LINE__,
1113 sessionId, ind, status );
1114 return status;
1115}
1116/*--------------------------------------------------------------------------
1117 \brief sme_QosGetACMMask() - The QoS sub-module API to find out on which ACs
1118 AP mandates Admission Control (ACM = 1)
1119 (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored)
1120 \param pMac - Pointer to the global MAC parameter structure.
1121 \param pSirBssDesc - The event occurred of type sme_QosCsrEventIndType.
1122
1123 \return a bit mask indicating for which ACs AP has ACM set to 1
1124
1125 \sa
1126
1127 --------------------------------------------------------------------------*/
1128v_U8_t sme_QosGetACMMask(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes)
1129{
1130 sme_QosEdcaAcType ac;
1131 v_U8_t acm_mask = 0;
1132 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1133 "%s: %d: invoked",
1134 __FUNCTION__, __LINE__);
1135 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
1136 {
1137 if(sme_QosIsACM(pMac, pSirBssDesc, ac, pIes))
1138 {
1139 acm_mask = acm_mask | (1 << (SME_QOS_EDCA_AC_VO - ac));
1140 }
1141
1142 }
1143 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1144 "%s: %d: mask is %d",
1145 __FUNCTION__, __LINE__, acm_mask);
1146 return acm_mask;
1147}
1148/*--------------------------------------------------------------------------
1149 Internal function definitions
1150 ------------------------------------------------------------------------*/
1151/*--------------------------------------------------------------------------
1152 \brief sme_QosInternalSetupReq() - The SME QoS internal setup request handling
1153 function.
1154 If the request involves admission control on the requested AC, HDD needs to
1155 provide the necessary Traffic Specification (TSPEC) parameters otherwise SME
1156 is going to use the default params.
1157
1158 \param pMac - Pointer to the global MAC parameter structure.
1159 \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
1160 related info as defined above, provided by HDD
1161 \param QoSCallback - The callback which is registered per flow while
1162 requesting for QoS. Used for any notification for the
1163 flow (i.e. setup success/failure/release) which needs to
1164 be sent to HDD
1165 \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS
1166 notification (through the callabck) to HDD
1167 \param UPType - Useful only if HDD or any other upper layer module (BAP etc.)
1168 looking for implicit QoS setup, in that
1169 case, the pQoSInfo will be NULL & SME will know about the AC
1170 (from the UP provided in this param) QoS is requested on
1171 \param QosFlowID - Identification per flow running on each AC generated by
1172 SME.
1173 It is only meaningful if the QoS setup for the flow is
1174 successful
1175 \param buffered_cmd - tells us if the cmd was a buffered one or fresh from
1176 client
1177
1178 \return eHAL_STATUS_SUCCESS - Setup is successful.
1179
1180 Other status means Setup request failed
1181 \sa
1182
1183 --------------------------------------------------------------------------*/
1184sme_QosStatusType sme_QosInternalSetupReq(tpAniSirGlobal pMac,
1185 v_U8_t sessionId,
1186 sme_QosWmmTspecInfo * pQoSInfo,
1187 sme_QosCallback QoSCallback,
1188 void * HDDcontext,
1189 sme_QosWmmUpType UPType,
1190 v_U32_t QosFlowID,
1191 v_BOOL_t buffered_cmd,
1192 v_BOOL_t hoRenewal)
1193{
1194 sme_QosSessionInfo *pSession;
1195 sme_QosACInfo *pACInfo;
1196 sme_QosEdcaAcType ac;
1197 sme_QosWmmTspecInfo Tspec_Info;
1198 sme_QosStates new_state = SME_QOS_CLOSED;
1199 sme_QosFlowInfoEntry *pentry = NULL;
1200 sme_QosCmdInfo cmd;
1201 sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
1202 v_U8_t tmask = 0;
1203 v_U8_t new_tmask = 0;
1204 sme_QosSearchInfo search_key;
1205 v_BOOL_t bufferCommand;
1206 eHalStatus hstatus;
1207 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1208 "%s: %d: invoked on session %d for flow %d",
1209 __FUNCTION__, __LINE__,
1210 sessionId, QosFlowID);
1211 pSession = &sme_QosCb.sessionInfo[sessionId];
1212 // if caller sent an empty TSPEC, fill up with the default one
1213 if(!pQoSInfo)
1214 {
1215 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
1216 "%s: %d: caller sent an empty QoS param list, using defaults",
1217 __FUNCTION__, __LINE__);
1218 // find the AC with UPType passed in
1219 ac = sme_QosUpToAc(UPType);
1220 if(SME_QOS_EDCA_AC_MAX == ac)
1221 {
1222 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1223 "%s: %d: invalid AC %d from UP %d",
1224 __FUNCTION__, __LINE__,
1225 ac, UPType);
1226
1227 return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
1228 }
1229 Tspec_Info = sme_QosCb.def_QoSInfo[ac];
1230 }
1231 else
1232 {
1233 // find the AC
1234 ac = sme_QosUpToAc(pQoSInfo->ts_info.up);
1235 if(SME_QOS_EDCA_AC_MAX == ac)
1236 {
1237 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1238 "%s: %d: invalid AC %d from UP %d",
1239 __FUNCTION__, __LINE__,
1240 ac, pQoSInfo->ts_info.up);
1241
1242 return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
1243 }
1244 //validate QoS params
1245 if(!sme_QosValidateRequestedParams(pMac, pQoSInfo, sessionId))
1246 {
1247 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1248 "%s: %d: invalid params",
1249 __FUNCTION__, __LINE__);
1250 return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
1251 }
1252 Tspec_Info = *pQoSInfo;
1253 }
1254 pACInfo = &pSession->ac_info[ac];
1255 // need to vote off powersave for the duration of this request
1256 pSession->readyForPowerSave = VOS_FALSE;
1257 // assume we won't have to (re)buffer the command
1258 bufferCommand = VOS_FALSE;
1259 //check to consider the following flowing scenario
1260 //Addts request is pending on one AC, while APSD requested on another which
1261 //needs a reassoc. Will buffer a request if Addts is pending on any AC,
1262 //which will safegaurd the above scenario, & also won't confuse PE with back
1263 //to back Addts or Addts followed by Reassoc
1264 if(sme_QosIsRspPending(sessionId, ac))
1265 {
1266 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1267 "%s: %d: buffering the setup request for flow %d in state %d "
1268 "since another request is pending",
1269 __FUNCTION__, __LINE__,
1270 QosFlowID, pACInfo->curr_state );
1271 bufferCommand = VOS_TRUE;
1272 }
1273 else
1274 {
1275 // make sure we are in full power so that we can issue
1276 // an AddTS or reassoc if necessary
1277 hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback,
1278 pSession, eSME_REASON_OTHER);
1279 if( eHAL_STATUS_PMC_PENDING == hstatus )
1280 {
1281 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1282 "%s: %d: buffering the setup request for flow %d in state %d, "
1283 "waiting for full power",
1284 __FUNCTION__, __LINE__,
1285 QosFlowID, pACInfo->curr_state );
1286 bufferCommand = VOS_TRUE;
1287 }
1288 }
1289 if (bufferCommand)
1290 {
1291 // we need to buffer the command
1292 cmd.command = SME_QOS_SETUP_REQ;
1293 cmd.pMac = pMac;
1294 cmd.sessionId = sessionId;
1295 cmd.u.setupCmdInfo.HDDcontext = HDDcontext;
1296 cmd.u.setupCmdInfo.QoSInfo = Tspec_Info;
1297 cmd.u.setupCmdInfo.QoSCallback = QoSCallback;
1298 cmd.u.setupCmdInfo.UPType = UPType;
1299 cmd.u.setupCmdInfo.hoRenewal = hoRenewal;
1300 cmd.u.setupCmdInfo.QosFlowID = QosFlowID;
1301 hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
1302 if(!HAL_STATUS_SUCCESS(hstatus))
1303 {
1304 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1305 "%s: %d: couldn't buffer the setup request in state = %d",
1306 __FUNCTION__, __LINE__,
1307 pACInfo->curr_state );
1308 // unable to buffer the request
1309 // nothing is pending so vote powersave back on
1310 pSession->readyForPowerSave = VOS_TRUE;
1311 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1312 }
1313 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1314 "%s: %d: Buffered setup request for flow = %d",
1315 __FUNCTION__, __LINE__,
1316 QosFlowID);
1317 return SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
1318 }
1319
1320 //get into the state m/c to see if the request can be granted
1321 switch(pACInfo->curr_state)
1322 {
1323 case SME_QOS_LINK_UP:
1324 //call the internal qos setup logic to decide on if the
1325 // request is NOP, or need reassoc for APSD and/or need to send out ADDTS
1326 status = sme_QosSetup(pMac, sessionId, &Tspec_Info, ac);
1327 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1328 "%s: %d: On session %d with AC %d in state SME_QOS_LINK_UP "
1329 "sme_QosSetup returned with status %d",
1330 __FUNCTION__, __LINE__,
1331 sessionId, ac, status);
1332 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
1333 {
1334 // we aren't waiting for a response from the AP
1335 // so vote powersave back on
1336 pSession->readyForPowerSave = VOS_TRUE;
1337 }
1338 if((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)||
1339 (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
1340 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
1341 {
1342 // we received an expected "good" status
1343 //create an entry in the flow list
1344 pentry = vos_mem_malloc(sizeof(*pentry));
1345 if (!pentry)
1346 {
1347 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1348 "%s: %d: couldn't allocate memory for the new "
1349 "entry in the Flow List",
1350 __FUNCTION__, __LINE__);
1351 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1352 }
1353 pentry->ac_type = ac;
1354 pentry->HDDcontext = HDDcontext;
1355 pentry->QoSCallback = QoSCallback;
1356 pentry->hoRenewal = hoRenewal;
1357 pentry->QosFlowID = QosFlowID;
1358 pentry->sessionId = sessionId;
1359 // since we are in state SME_QOS_LINK_UP this must be the
1360 // first TSPEC on this AC, so use index 0 (mask bit 1)
1361 pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0] = Tspec_Info;
1362 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
1363 {
1364 if(pACInfo->tspec_mask_status &&
1365 !pACInfo->reassoc_pending)
1366 {
1367 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1368 "%s: %d: On session %d with AC %d in state "
1369 "SME_QOS_LINK_UP tspec_mask_status is %d "
1370 "but should not be set yet",
1371 __FUNCTION__, __LINE__,
1372 sessionId, ac, pACInfo->tspec_mask_status);
1373 //ASSERT
1374 VOS_ASSERT(0);
1375 vos_mem_free(pentry);
1376 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1377 }
1378 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET;
1379 if(!pACInfo->reassoc_pending)
1380 {
1381 // we didn't request for reassoc, it must be a tspec negotiation
1382 pACInfo->tspec_pending = 1;
1383 }
1384
1385 pentry->reason = SME_QOS_REASON_SETUP;
1386 new_state = SME_QOS_REQUESTED;
1387 }
1388 else
1389 {
1390 // SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP or
1391 // SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY
1392 pentry->reason = SME_QOS_REASON_REQ_SUCCESS;
1393 new_state = SME_QOS_QOS_ON;
1394 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET;
1395 pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] = Tspec_Info;
1396 if(buffered_cmd && !pentry->hoRenewal)
1397 {
1398 QoSCallback(pMac, HDDcontext,
1399 &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
1400 status,
1401 pentry->QosFlowID);
1402 }
1403 pentry->hoRenewal = VOS_FALSE;
1404 }
1405 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0]++;
1406
1407 //indicate on which index the flow entry belongs to & add it to the
1408 //Flow List at the end
1409 pentry->tspec_mask = pACInfo->tspec_mask_status;
1410 pentry->QoSInfo = Tspec_Info;
1411 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1412 "%s: %d: Creating entry on session %d at %p with flowID %d",
1413 __FUNCTION__, __LINE__,
1414 sessionId, pentry, QosFlowID);
1415 csrLLInsertTail(&sme_QosCb.flow_list, &pentry->link, VOS_TRUE);
1416 }
1417 else
1418 {
1419 // unexpected status returned by sme_QosSetup()
1420 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1421 "%s: %d: On session %d unexpected status %d "
1422 "returned by sme_QosSetup",
1423 __FUNCTION__, __LINE__,
1424 sessionId, status);
1425 new_state = pACInfo->curr_state;
1426 if(buffered_cmd && hoRenewal)
1427 {
1428 QoSCallback(pMac, HDDcontext,
1429 &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
1430 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
1431 QosFlowID);
1432 }
1433 }
1434 break;
1435 case SME_QOS_HANDOFF:
1436 case SME_QOS_REQUESTED:
1437 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1438 "%s: %d: Buffering setup request for flow %d in state = %d",
1439 __FUNCTION__, __LINE__,
1440 QosFlowID, pACInfo->curr_state );
1441 //buffer cmd
1442 cmd.command = SME_QOS_SETUP_REQ;
1443 cmd.pMac = pMac;
1444 cmd.sessionId = sessionId;
1445 cmd.u.setupCmdInfo.HDDcontext = HDDcontext;
1446 cmd.u.setupCmdInfo.QoSInfo = Tspec_Info;
1447 cmd.u.setupCmdInfo.QoSCallback = QoSCallback;
1448 cmd.u.setupCmdInfo.UPType = UPType;
1449 cmd.u.setupCmdInfo.hoRenewal = hoRenewal;
1450 cmd.u.setupCmdInfo.QosFlowID = QosFlowID;
1451 hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
1452 if(!HAL_STATUS_SUCCESS(hstatus))
1453 {
1454 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1455 "%s: %d: On session %d couldn't buffer the setup "
1456 "request for flow %d in state = %d",
1457 __FUNCTION__, __LINE__,
1458 sessionId, QosFlowID, pACInfo->curr_state );
1459 // unable to buffer the request
1460 // nothing is pending so vote powersave back on
1461 pSession->readyForPowerSave = VOS_TRUE;
1462 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1463 }
1464 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
1465 new_state = pACInfo->curr_state;
1466 break;
1467 case SME_QOS_QOS_ON:
1468
1469 //check if multiple flows running on the ac
1470 if((pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] > 0)||
1471 (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0))
1472 {
1473 //do we need to care about the case where APSD needed on ACM = 0 below?
1474 if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
1475 sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL))
1476 {
1477 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1478 "%s: %d: tspec_mask_status = %d for AC = %d",
1479 __FUNCTION__, __LINE__,
1480 pACInfo->tspec_mask_status, ac);
1481 if(!pACInfo->tspec_mask_status)
1482 {
1483 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1484 "%s: %d: tspec_mask_status can't be 0 for ac = %d in "
1485 "state = %d",
1486 __FUNCTION__, __LINE__,
1487 ac, pACInfo->curr_state);
1488 //ASSERT
1489 VOS_ASSERT(0);
1490 // unable to service the request
1491 // nothing is pending so vote powersave back on
1492 pSession->readyForPowerSave = VOS_TRUE;
1493 return status;
1494 }
1495 /* Flow aggregation */
1496 if(SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status)
1497 {
1498 /* Either of upstream, downstream or bidirectional flows are present */
1499 /* If either of new stream or current stream is for bidirecional, aggregate
1500 * the new stream with the current streams present and send out aggregated Tspec.*/
1501 if((Tspec_Info.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) ||
1502 (pACInfo->curr_QoSInfo[pACInfo->tspec_mask_status - 1].
1503 ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH))
1504 {
1505 // Aggregate the new stream with the current stream(s).
1506 tmask = pACInfo->tspec_mask_status;
1507 }
1508 /* None of new stream or current (aggregated) streams are for bidirectional.
1509 * Check if the new stream direction matches the current stream direction. */
1510 else if(pACInfo->curr_QoSInfo[pACInfo->tspec_mask_status - 1].
1511 ts_info.direction == Tspec_Info.ts_info.direction)
1512 {
1513 // Aggregate the new stream with the current stream(s).
1514 tmask = pACInfo->tspec_mask_status;
1515 }
1516 /* New stream is in different direction. */
1517 else
1518 {
1519 // No Aggregation. Mark the 2nd tpsec index also as active.
1520 tmask = SME_QOS_TSPEC_MASK_CLEAR;
1521 new_tmask = SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~pACInfo->tspec_mask_status;
1522 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_2_SET;
1523 }
1524 }
1525 else
1526 {
1527 /* Both uplink and downlink streams are present. */
1528 /* If new stream is bidirectional, aggregate new stream with all existing
1529 * upstreams and downstreams. Send out new aggregated tpsec. */
1530 if(Tspec_Info.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH)
1531 {
1532 // Only one tspec index (0) will be in use after this aggregation.
1533 tmask = SME_QOS_TSPEC_MASK_BIT_1_2_SET;
1534 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET;
1535 }
1536 /* New stream is also uni-directional
1537 * Find out the tsepc index with which it needs to be aggregated */
1538 else if(pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.direction !=
1539 Tspec_Info.ts_info.direction)
1540 {
1541 // Aggregate with 2nd tspec index
1542 tmask = SME_QOS_TSPEC_MASK_BIT_2_SET;
1543 }
1544 else
1545 {
1546 // Aggregate with 1st tspec index
1547 tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
1548 }
1549 }
1550 }
1551 else
1552 {
1553 //ACM = 0
1554 // We won't be sending a TSPEC to the AP but we still need
1555 // to aggregate to calculate trigger frame parameters
1556 tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
1557 }
1558 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1559 "%s: %d: tmask = %d, new_tmask = %d in state = %d",
1560 __FUNCTION__, __LINE__,
1561 tmask, new_tmask, pACInfo->curr_state );
1562 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1563 "%s: %d: tspec_mask_status = %d for AC = %d",
1564 __FUNCTION__, __LINE__,
1565 pACInfo->tspec_mask_status, ac);
1566 if(tmask)
1567 {
1568 // create the aggregate TSPEC
1569 if(tmask != SME_QOS_TSPEC_MASK_BIT_1_2_SET)
1570 {
1571 hstatus = sme_QosAggregateParams(&Tspec_Info,
1572 &pACInfo->curr_QoSInfo[tmask - 1],
1573 &pACInfo->requested_QoSInfo[tmask - 1]);
1574 }
1575 else
1576 {
1577 /* Aggregate the new bidirectional stream with the existing upstreams and
1578 * downstreams in tspec indices 0 and 1. */
1579 tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
1580
1581 if((hstatus = sme_QosAggregateParams(&Tspec_Info,
1582 &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
1583 &pACInfo->requested_QoSInfo[tmask - 1]))
1584 == eHAL_STATUS_SUCCESS)
1585 {
1586 hstatus = sme_QosAggregateParams(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
1587 &pACInfo->requested_QoSInfo[tmask - 1],
1588 NULL);
1589 }
1590 }
1591
1592 if(!HAL_STATUS_SUCCESS(hstatus))
1593 {
1594 //err msg
1595 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1596 "%s: %d: failed to aggregate params",
1597 __FUNCTION__, __LINE__);
1598 // unable to service the request
1599 // nothing is pending so vote powersave back on
1600 pSession->readyForPowerSave = VOS_TRUE;
1601 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1602 }
1603 }
1604 else
1605 {
1606 tmask = new_tmask;
1607 }
1608 }
1609 else
1610 {
1611 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1612 "%s: %d: no flows running for ac = %d while in state = %d",
1613 __FUNCTION__, __LINE__,
1614 ac, pACInfo->curr_state );
1615 //ASSERT
1616 VOS_ASSERT(0);
1617 // unable to service the request
1618 // nothing is pending so vote powersave back on
1619 pSession->readyForPowerSave = VOS_TRUE;
1620 return status;
1621 }
1622 //although aggregating, make sure to request on the correct UP
1623 pACInfo->requested_QoSInfo[tmask - 1].ts_info.up = Tspec_Info.ts_info.up;
1624 status = sme_QosSetup(pMac, sessionId,
1625 &pACInfo->requested_QoSInfo[tmask - 1], ac);
1626 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1627 "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
1628 "sme_QosSetup returned with status %d",
1629 __FUNCTION__, __LINE__,
1630 sessionId, ac, status);
1631 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
1632 {
1633 // we aren't waiting for a response from the AP
1634 // so vote powersave back on
1635 pSession->readyForPowerSave = VOS_TRUE;
1636 }
1637 if((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)||
1638 (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
1639 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
1640 {
1641 // we received an expected "good" status
1642 //create an entry in the flow list
1643 pentry = (sme_QosFlowInfoEntry *) vos_mem_malloc(sizeof(*pentry));
1644 if (!pentry)
1645 {
1646 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1647 "%s: %d: couldn't allocate memory for the new "
1648 "entry in the Flow List",
1649 __FUNCTION__, __LINE__);
1650 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1651 }
1652 pentry->ac_type = ac;
1653 pentry->HDDcontext = HDDcontext;
1654 pentry->QoSCallback = QoSCallback;
1655 pentry->hoRenewal = hoRenewal;
1656 pentry->QosFlowID = QosFlowID;
1657 pentry->sessionId = sessionId;
1658 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1659 "%s: %d: Creating flow %d",
1660 __FUNCTION__, __LINE__,
1661 QosFlowID);
1662 if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)||
1663 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
1664 {
1665 new_state = pACInfo->curr_state;
1666 pentry->reason = SME_QOS_REASON_REQ_SUCCESS;
1667 pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
1668 pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0];
1669 if(buffered_cmd && !pentry->hoRenewal)
1670 {
1671 QoSCallback(pMac, HDDcontext,
1672 &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
1673 status,
1674 pentry->QosFlowID);
1675 }
1676 if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)
1677 {
1678 // if we are not in handoff, then notify all flows on
1679 // this AC that the aggregate TSPEC may have changed
1680 if(!pentry->hoRenewal)
1681 {
1682 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
1683 search_key.key.ac_type = ac;
1684 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
1685 search_key.sessionId = sessionId;
1686 hstatus = sme_QosFindAllInFlowList(pMac, search_key,
1687 sme_QosSetupFnp);
1688 if(!HAL_STATUS_SUCCESS(hstatus))
1689 {
1690 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1691 "%s: %d: couldn't notify other "
1692 "entries on this AC =%d",
1693 __FUNCTION__, __LINE__, ac);
1694 }
1695 }
1696 }
1697 pentry->hoRenewal = VOS_FALSE;
1698 }
1699 else
1700 {
1701 // SME_QOS_STATUS_SETUP_REQ_PENDING_RSP
1702 new_state = SME_QOS_REQUESTED;
1703 pentry->reason = SME_QOS_REASON_SETUP;
1704 //Need this info when addts comes back from PE to know on
1705 //which index of the AC the request was from
1706 pACInfo->tspec_pending = tmask;
1707 }
1708 pACInfo->num_flows[tmask - 1]++;
1709 //indicate on which index the flow entry belongs to & add it to the
1710 //Flow List at the end
1711 pentry->tspec_mask = tmask;
1712 pentry->QoSInfo = Tspec_Info;
1713 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1714 "%s: %d: On session %d creating entry at %p with flowID %d",
1715 __FUNCTION__, __LINE__,
1716 sessionId, pentry, QosFlowID);
1717 csrLLInsertTail(&sme_QosCb.flow_list, &pentry->link, VOS_TRUE);
1718 }
1719 else
1720 {
1721 // unexpected status returned by sme_QosSetup()
1722 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1723 "%s: %d: On session %d unexpected status %d "
1724 "returned by sme_QosSetup",
1725 __FUNCTION__, __LINE__,
1726 sessionId, status);
1727 new_state = pACInfo->curr_state;
1728 }
1729 break;
1730 case SME_QOS_CLOSED:
1731 case SME_QOS_INIT:
1732 default:
1733 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1734 "%s: %d: setup requested in unexpected state = %d",
1735 __FUNCTION__, __LINE__,
1736 pACInfo->curr_state);
1737 // unable to service the request
1738 // nothing is pending so vote powersave back on
1739 pSession->readyForPowerSave = VOS_TRUE;
1740 VOS_ASSERT(0);
1741 new_state = pACInfo->curr_state;
1742 }
1743 /* if current state is same as previous no need for transistion,
1744 if we are doing reassoc & we are already in handoff state, no need to move
1745 to requested state. But make sure to set the previous state as requested
1746 state
1747 */
1748 if((new_state != pACInfo->curr_state)&&
1749 (!(pACInfo->reassoc_pending &&
1750 (SME_QOS_HANDOFF == pACInfo->curr_state))))
1751 {
1752 sme_QosStateTransition(sessionId, ac, new_state);
1753 }
1754
1755 if(pACInfo->reassoc_pending &&
1756 (SME_QOS_HANDOFF == pACInfo->curr_state))
1757 {
1758 pACInfo->prev_state = SME_QOS_REQUESTED;
1759 }
1760 if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
1761 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
1762 {
1763 (void)sme_QosProcessBufferedCmd(sessionId);
1764 }
1765 return status;
1766}
1767
1768/*--------------------------------------------------------------------------
1769 \brief sme_QosInternalModifyReq() - The SME QoS internal function to request
1770 for modification of certain QoS params on a flow running on a particular AC.
1771 If the request involves admission control on the requested AC, HDD needs to
1772 provide the necessary Traffic Specification (TSPEC) parameters & SME might
1773 start the renegotiation process through ADDTS.
1774
1775 \param pMac - Pointer to the global MAC parameter structure.
1776 \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
1777 related info as defined above, provided by HDD
1778 \param QosFlowID - Identification per flow running on each AC generated by
1779 SME.
1780 It is only meaningful if the QoS setup for the flow has
1781 been successful already
1782
1783 \return SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful.
1784
1785 Other status means request failed
1786 \sa
1787
1788 --------------------------------------------------------------------------*/
1789sme_QosStatusType sme_QosInternalModifyReq(tpAniSirGlobal pMac,
1790 sme_QosWmmTspecInfo * pQoSInfo,
1791 v_U32_t QosFlowID,
1792 v_BOOL_t buffered_cmd)
1793{
1794 tListElem *pEntry= NULL;
1795 sme_QosSessionInfo *pSession;
1796 sme_QosACInfo *pACInfo;
1797 sme_QosFlowInfoEntry *pNewEntry= NULL;
1798 sme_QosFlowInfoEntry *flow_info = NULL;
1799 sme_QosEdcaAcType ac;
1800 sme_QosStates new_state = SME_QOS_CLOSED;
1801 sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1802 sme_QosWmmTspecInfo Aggr_Tspec_Info;
1803 sme_QosSearchInfo search_key;
1804 sme_QosCmdInfo cmd;
1805 v_U8_t sessionId;
1806 v_BOOL_t bufferCommand;
1807 eHalStatus hstatus;
1808 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1809 "%s: %d: invoked for flow %d",
1810 __FUNCTION__, __LINE__,
1811 QosFlowID);
1812
1813 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
1814 //set the key type & the key to be searched in the Flow List
1815 search_key.key.QosFlowID = QosFlowID;
1816 search_key.index = SME_QOS_SEARCH_KEY_INDEX_1;
1817 search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY;
1818 //go through the link list to find out the details on the flow
1819 pEntry = sme_QosFindInFlowList(search_key);
1820 if(!pEntry)
1821 {
1822 //Err msg
1823 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1824 "%s: %d: no match found for flowID = %d",
1825 __FUNCTION__, __LINE__,
1826 QosFlowID);
1827 return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
1828 }
1829 // find the AC
1830 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
1831 ac = flow_info->ac_type;
1832
1833 sessionId = flow_info->sessionId;
1834 pSession = &sme_QosCb.sessionInfo[sessionId];
1835 pACInfo = &pSession->ac_info[ac];
1836
1837 //validate QoS params
1838 if(!sme_QosValidateRequestedParams(pMac, pQoSInfo, sessionId))
1839 {
1840 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1841 "%s: %d: invalid params",
1842 __FUNCTION__, __LINE__);
1843 return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
1844 }
1845 // For modify, make sure that direction, TID and UP are not being altered
1846 if((pQoSInfo->ts_info.direction != flow_info->QoSInfo.ts_info.direction) ||
1847 (pQoSInfo->ts_info.up != flow_info->QoSInfo.ts_info.up) ||
1848 (pQoSInfo->ts_info.tid != flow_info->QoSInfo.ts_info.tid))
1849 {
1850 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1851 "%s: %d: Modification of direction/tid/up is not allowed",
1852 __FUNCTION__, __LINE__);
1853
1854 return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
1855 }
1856 // need to vote off powersave for the duration of this request
1857 pSession->readyForPowerSave = VOS_FALSE;
1858 // assume we won't have to (re)buffer the command
1859 bufferCommand = VOS_FALSE;
1860 //check to consider the following flowing scenario
1861 //Addts request is pending on one AC, while APSD requested on another which
1862 //needs a reassoc. Will buffer a request if Addts is pending on any AC,
1863 //which will safegaurd the above scenario, & also won't confuse PE with back
1864 //to back Addts or Addts followed by Reassoc
1865 if(sme_QosIsRspPending(sessionId, ac))
1866 {
1867 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1868 "%s: %d: buffering the modify request for flow %d in state %d "
1869 "since another request is pending",
1870 __FUNCTION__, __LINE__,
1871 QosFlowID, pACInfo->curr_state );
1872 bufferCommand = VOS_TRUE;
1873 }
1874 else
1875 {
1876 // make sure we are in full power so that we can issue
1877 // an AddTS or reassoc if necessary
1878 hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback,
1879 pSession, eSME_REASON_OTHER);
1880 if( eHAL_STATUS_PMC_PENDING == hstatus )
1881 {
1882 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
1883 "%s: %d: buffering the modify request for flow %d in state %d, "
1884 "waiting for full power",
1885 __FUNCTION__, __LINE__,
1886 QosFlowID, pACInfo->curr_state );
1887 bufferCommand = VOS_TRUE;
1888 }
1889 }
1890 if (bufferCommand)
1891 {
1892 // we need to buffer the command
1893 cmd.command = SME_QOS_MODIFY_REQ;
1894 cmd.pMac = pMac;
1895 cmd.sessionId = sessionId;
1896 cmd.u.modifyCmdInfo.QosFlowID = QosFlowID;
1897 cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo;
1898 hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
1899 if(!HAL_STATUS_SUCCESS(hstatus))
1900 {
1901 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1902 "%s: %d: couldn't buffer the modify request in state = %d",
1903 __FUNCTION__, __LINE__,
1904 pACInfo->curr_state );
1905 // unable to buffer the request
1906 // nothing is pending so vote powersave back on
1907 pSession->readyForPowerSave = VOS_TRUE;
1908 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1909 }
1910 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1911 "%s: %d: Buffered modify request for flow = %d",
1912 __FUNCTION__, __LINE__,
1913 QosFlowID);
1914 return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
1915 }
1916 //get into the stat m/c to see if the request can be granted
1917 switch(pACInfo->curr_state)
1918 {
1919 case SME_QOS_QOS_ON:
1920 //save the new params adding a new (duplicate) entry in the Flow List
1921 //Once we have decided on OTA exchange needed or not we can delete the
1922 //original one from the List
1923 pNewEntry = (sme_QosFlowInfoEntry *) vos_mem_malloc(sizeof(*pNewEntry));
1924 if (!pNewEntry)
1925 {
1926 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
1927 "%s: %d: couldn't allocate memory for the new "
1928 "entry in the Flow List",
1929 __FUNCTION__, __LINE__);
1930 // unable to service the request
1931 // nothing is pending so vote powersave back on
1932 pSession->readyForPowerSave = VOS_TRUE;
1933 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1934 }
1935 pNewEntry->ac_type = ac;
1936 pNewEntry->sessionId = sessionId;
1937 pNewEntry->HDDcontext = flow_info->HDDcontext;
1938 pNewEntry->QoSCallback = flow_info->QoSCallback;
1939 pNewEntry->QosFlowID = flow_info->QosFlowID;
1940 pNewEntry->reason = SME_QOS_REASON_MODIFY_PENDING;
1941 //since it is a modify request, use the same index on which the flow
1942 //entry originally was running & add it to the Flow List at the end
1943 pNewEntry->tspec_mask = flow_info->tspec_mask;
1944 pNewEntry->QoSInfo = *pQoSInfo;
1945 //update the entry from Flow List which needed to be modified
1946 flow_info->reason = SME_QOS_REASON_MODIFY;
1947 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1948 "%s: %d: On session %d creating modified "
1949 "entry at %p with flowID %d",
1950 __FUNCTION__, __LINE__,
1951 sessionId, pNewEntry, pNewEntry->QosFlowID);
1952 //add the new entry under construction to the Flow List
1953 csrLLInsertTail(&sme_QosCb.flow_list, &pNewEntry->link, VOS_TRUE);
1954 //update TSPEC with the new param set
1955 hstatus = sme_QosUpdateParams(sessionId,
1956 ac, pNewEntry->tspec_mask,
1957 &Aggr_Tspec_Info);
1958 if(HAL_STATUS_SUCCESS(hstatus))
1959 {
1960 pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1] = Aggr_Tspec_Info;
1961 //if ACM, send out a new ADDTS
1962 status = sme_QosSetup(pMac, sessionId,
1963 &pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1],
1964 ac);
1965 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
1966 "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
1967 "sme_QosSetup returned with status %d",
1968 __FUNCTION__, __LINE__,
1969 sessionId, ac, status);
1970 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
1971 {
1972 // we aren't waiting for a response from the AP
1973 // so vote powersave back on
1974 pSession->readyForPowerSave = VOS_TRUE;
1975 }
1976 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
1977 {
1978 new_state = SME_QOS_REQUESTED;
1979 status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
1980 pACInfo->tspec_pending = pNewEntry->tspec_mask;
1981 }
1982 else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
1983 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
1984 {
1985 new_state = SME_QOS_QOS_ON;
1986
1987 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
1988 //delete the original entry in FLOW list which got modified
1989 search_key.key.ac_type = ac;
1990 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
1991 search_key.sessionId = sessionId;
1992 hstatus = sme_QosFindAllInFlowList(pMac, search_key,
1993 sme_QosModifyFnp);
1994 if(!HAL_STATUS_SUCCESS(hstatus))
1995 {
1996 status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1997 }
1998 if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP != status)
1999 {
2000 pACInfo->curr_QoSInfo[pNewEntry->tspec_mask -1] =
2001 pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1];
2002 if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)
2003 {
2004 status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY;
2005 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
2006 search_key.key.ac_type = ac;
2007 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
2008 search_key.sessionId = sessionId;
2009 hstatus = sme_QosFindAllInFlowList(pMac, search_key,
2010 sme_QosModificationNotifyFnp);
2011 if(!HAL_STATUS_SUCCESS(hstatus))
2012 {
2013 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2014 "%s: %d: couldn't notify other "
2015 "entries on this AC =%d",
2016 __FUNCTION__, __LINE__, ac);
2017 }
2018 }
2019 else if(SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)
2020 {
2021 status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP;
2022 }
2023 }
2024 if(buffered_cmd)
2025 {
2026 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
2027 &pACInfo->curr_QoSInfo[pNewEntry->tspec_mask -1],
2028 status,
2029 flow_info->QosFlowID);
2030 }
2031
2032 }
2033 else
2034 {
2035 // unexpected status returned by sme_QosSetup()
2036 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2037 "%s: %d: On session %d unexpected status %d "
2038 "returned by sme_QosSetup",
2039 __FUNCTION__, __LINE__,
2040 sessionId, status);
2041 new_state = SME_QOS_QOS_ON;
2042 }
2043 }
2044 else
2045 {
2046 //err msg
2047 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2048 "%s: %d: sme_QosUpdateParams() failed",
2049 __FUNCTION__, __LINE__);
2050 // unable to service the request
2051 // nothing is pending so vote powersave back on
2052 pSession->readyForPowerSave = VOS_TRUE;
2053 new_state = SME_QOS_LINK_UP;
2054 }
2055 /* if we are doing reassoc & we are already in handoff state, no need
2056 to move to requested state. But make sure to set the previous state
2057 as requested state
2058 */
2059 if(!(pACInfo->reassoc_pending &&
2060 (SME_QOS_HANDOFF == pACInfo->curr_state)))
2061 {
2062 sme_QosStateTransition(sessionId, ac, new_state);
2063 }
2064 else
2065 {
2066 pACInfo->prev_state = SME_QOS_REQUESTED;
2067 }
2068 break;
2069 case SME_QOS_HANDOFF:
2070 case SME_QOS_REQUESTED:
2071 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
2072 "%s: %d: Buffering modify request for flow %d in state = %d",
2073 __FUNCTION__, __LINE__,
2074 QosFlowID, pACInfo->curr_state );
2075 //buffer cmd
2076 cmd.command = SME_QOS_MODIFY_REQ;
2077 cmd.pMac = pMac;
2078 cmd.sessionId = sessionId;
2079 cmd.u.modifyCmdInfo.QosFlowID = QosFlowID;
2080 cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo;
2081 hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
2082 if(!HAL_STATUS_SUCCESS(hstatus))
2083 {
2084 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2085 "%s: %d: couldn't buffer the modify request in state = %d",
2086 __FUNCTION__, __LINE__,
2087 pACInfo->curr_state );
2088 // unable to buffer the request
2089 // nothing is pending so vote powersave back on
2090 pSession->readyForPowerSave = VOS_TRUE;
2091 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
2092 }
2093 status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
2094 break;
2095 case SME_QOS_CLOSED:
2096 case SME_QOS_INIT:
2097 case SME_QOS_LINK_UP:
2098 default:
2099 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2100 "%s: %d: modify requested in unexpected state = %d",
2101 __FUNCTION__, __LINE__,
2102 pACInfo->curr_state);
2103 // unable to service the request
2104 // nothing is pending so vote powersave back on
2105 pSession->readyForPowerSave = VOS_TRUE;
2106 break;
2107 }
2108 if((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
2109 (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY == status))
2110 {
2111 (void)sme_QosProcessBufferedCmd(sessionId);
2112 }
2113 return status;
2114}
2115/*--------------------------------------------------------------------------
2116 \brief sme_QosInternalReleaseReq() - The SME QoS internal function to request
2117 for releasing a QoS flow running on a particular AC.
2118
2119 \param pMac - Pointer to the global MAC parameter structure.
2120 \param QosFlowID - Identification per flow running on each AC generated by SME
2121 It is only meaningful if the QoS setup for the flow is
2122 successful
2123
2124 \return eHAL_STATUS_SUCCESS - Release is successful.
2125
2126 \sa
2127
2128 --------------------------------------------------------------------------*/
2129sme_QosStatusType sme_QosInternalReleaseReq(tpAniSirGlobal pMac,
2130 v_U32_t QosFlowID,
2131 v_BOOL_t buffered_cmd)
2132{
2133 tListElem *pEntry= NULL;
2134 sme_QosSessionInfo *pSession;
2135 sme_QosACInfo *pACInfo;
2136 sme_QosFlowInfoEntry *flow_info = NULL;
2137 sme_QosFlowInfoEntry *pDeletedFlow = NULL;
2138 sme_QosEdcaAcType ac;
2139 sme_QosStates new_state = SME_QOS_CLOSED;
2140 sme_QosStatusType status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2141 sme_QosWmmTspecInfo Aggr_Tspec_Info;
2142 sme_QosSearchInfo search_key;
2143 sme_QosCmdInfo cmd;
2144 tCsrRoamModifyProfileFields modifyProfileFields;
2145 v_BOOL_t deltsIssued = VOS_FALSE;
2146 v_U8_t sessionId;
2147 v_BOOL_t bufferCommand;
2148 eHalStatus hstatus;
2149 v_BOOL_t biDirectionalFlowsPresent = VOS_FALSE;
2150 v_BOOL_t uplinkFlowsPresent = VOS_FALSE;
2151 v_BOOL_t downlinkFlowsPresent = VOS_FALSE;
2152 tListElem *pResult= NULL;
2153 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2154 "%s: %d: invoked for flow %d",
2155 __FUNCTION__, __LINE__,
2156 QosFlowID);
2157
2158 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
2159 //set the key type & the key to be searched in the Flow List
2160 search_key.key.QosFlowID = QosFlowID;
2161 search_key.index = SME_QOS_SEARCH_KEY_INDEX_1;
2162 search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY;
2163 //go through the link list to find out the details on the flow
2164 pEntry = sme_QosFindInFlowList(search_key);
2165
2166 if(!pEntry)
2167 {
2168 //Err msg
2169 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2170 "%s: %d: no match found for flowID = %d",
2171 __FUNCTION__, __LINE__,
2172 QosFlowID);
2173 return SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP;
2174 }
2175 // find the AC
2176 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
2177 ac = flow_info->ac_type;
2178 sessionId = flow_info->sessionId;
2179 pSession = &sme_QosCb.sessionInfo[sessionId];
2180 pACInfo = &pSession->ac_info[ac];
2181 // need to vote off powersave for the duration of this request
2182 pSession->readyForPowerSave = VOS_FALSE;
2183 // assume we won't have to (re)buffer the command
2184 bufferCommand = VOS_FALSE;
2185 //check to consider the following flowing scenario
2186 //Addts request is pending on one AC, while APSD requested on another which
2187 //needs a reassoc. Will buffer a request if Addts is pending on any AC,
2188 //which will safegaurd the above scenario, & also won't confuse PE with back
2189 //to back Addts or Addts followed by Reassoc
2190 if(sme_QosIsRspPending(sessionId, ac))
2191 {
2192 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
2193 "%s: %d: buffering the release request for flow %d in state %d "
2194 "since another request is pending",
2195 __FUNCTION__, __LINE__,
2196 QosFlowID, pACInfo->curr_state );
2197 bufferCommand = VOS_TRUE;
2198 }
2199 else
2200 {
2201 // make sure we are in full power so that we can issue
2202 // a DelTS or reassoc if necessary
2203 hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback,
2204 pSession, eSME_REASON_OTHER);
2205 if( eHAL_STATUS_PMC_PENDING == hstatus )
2206 {
2207 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
2208 "%s: %d: buffering the release request for flow %d in state %d, "
2209 "waiting for full power",
2210 __FUNCTION__, __LINE__,
2211 QosFlowID, pACInfo->curr_state );
2212 bufferCommand = VOS_TRUE;
2213 }
2214 }
2215 if (bufferCommand)
2216 {
2217 // we need to buffer the command
2218 cmd.command = SME_QOS_RELEASE_REQ;
2219 cmd.pMac = pMac;
2220 cmd.sessionId = sessionId;
2221 cmd.u.releaseCmdInfo.QosFlowID = QosFlowID;
2222 hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
2223 if(!HAL_STATUS_SUCCESS(hstatus))
2224 {
2225 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2226 "%s: %d: couldn't buffer the release request in state = %d",
2227 __FUNCTION__, __LINE__,
2228 pACInfo->curr_state );
2229 // unable to buffer the request
2230 // nothing is pending so vote powersave back on
2231 pSession->readyForPowerSave = VOS_TRUE;
2232 return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2233 }
2234 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2235 "%s: %d: Buffered release request for flow = %d",
2236 __FUNCTION__, __LINE__,
2237 QosFlowID);
2238 return SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
2239 }
2240 //get into the stat m/c to see if the request can be granted
2241 switch(pACInfo->curr_state)
2242 {
2243 case SME_QOS_QOS_ON:
2244 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
2245 "%s: %d: tspec_mask_status = %d for AC = %d with "
2246 "entry tspec_mask = %d",
2247 __FUNCTION__, __LINE__,
2248 pACInfo->tspec_mask_status, ac, flow_info->tspec_mask);
2249
2250 //check if multiple flows running on the ac
2251 if(pACInfo->num_flows[flow_info->tspec_mask - 1] > 1)
2252 {
2253 //don't want to include the flow in the new TSPEC on which release
2254 //is requested
2255 flow_info->reason = SME_QOS_REASON_RELEASE;
2256
2257 /* Check if the flow being released is for bi-diretional.
2258 * Following flows may present in the system.
2259 * a) bi-directional flows
2260 * b) uplink flows
2261 * c) downlink flows.
2262 * If the flow being released is for bidirectional, splitting of existing
2263 * streams into two tspec indices is required in case ff (b), (c) are present
2264 * and not (a).
2265 * In case if split occurs, all upstreams are aggregated into tspec index 0,
2266 * downstreams are aggregaed into tspec index 1 and two tspec requests for
2267 * (aggregated) upstream(s) followed by (aggregated) downstream(s) is sent
2268 * to AP. */
2269 if(flow_info->QoSInfo.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH)
2270 {
2271 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
2272 //set the key type & the key to be searched in the Flow List
2273 search_key.key.ac_type = ac;
2274 search_key.index = SME_QOS_SEARCH_KEY_INDEX_4;
2275 search_key.sessionId = sessionId;
2276 search_key.direction = SME_QOS_WMM_TS_DIR_BOTH;
2277 pResult = sme_QosFindInFlowList(search_key);
2278 if(pResult)
2279 biDirectionalFlowsPresent = VOS_TRUE;
2280
2281 if(!biDirectionalFlowsPresent)
2282 {
2283 // The only existing bidirectional flow is being released
2284
2285 // Check if uplink flows exist
2286 search_key.direction = SME_QOS_WMM_TS_DIR_UPLINK;
2287 pResult = sme_QosFindInFlowList(search_key);
2288 if(pResult)
2289 uplinkFlowsPresent = VOS_TRUE;
2290
2291 // Check if downlink flows exist
2292 search_key.direction = SME_QOS_WMM_TS_DIR_DOWNLINK;
2293 pResult = sme_QosFindInFlowList(search_key);
2294 if(pResult)
2295 downlinkFlowsPresent = VOS_TRUE;
2296
2297 if(uplinkFlowsPresent && downlinkFlowsPresent)
2298 {
2299 // Need to split the uni-directional flows into SME_QOS_TSPEC_INDEX_0 and SME_QOS_TSPEC_INDEX_1
2300
2301 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
2302 // Mark all downstream flows as using tspec index 1
2303 search_key.key.ac_type = ac;
2304 search_key.index = SME_QOS_SEARCH_KEY_INDEX_4;
2305 search_key.sessionId = sessionId;
2306 search_key.direction = SME_QOS_WMM_TS_DIR_DOWNLINK;
2307 sme_QosUpdateTspecMask(sessionId, search_key, SME_QOS_TSPEC_MASK_BIT_2_SET);
2308
2309 // Aggregate all downstream flows
2310 hstatus = sme_QosUpdateParams(sessionId,
2311 ac, SME_QOS_TSPEC_MASK_BIT_2_SET,
2312 &Aggr_Tspec_Info);
2313
2314 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2315 "%s: %d: On session %d buffering the AddTS request "
2316 "for AC %d in state %d as Addts is pending "
2317 "on other Tspec index of this AC",
2318 __FUNCTION__, __LINE__,
2319 sessionId, ac, pACInfo->curr_state);
2320
2321 // Buffer the (aggregated) tspec request for downstream flows.
2322 // Please note that the (aggregated) tspec for upstream flows is sent
2323 // out by the susequent logic.
2324 cmd.command = SME_QOS_RESEND_REQ;
2325 cmd.pMac = pMac;
2326 cmd.sessionId = sessionId;
2327 cmd.u.resendCmdInfo.ac = ac;
2328 cmd.u.resendCmdInfo.tspecMask = SME_QOS_TSPEC_MASK_BIT_2_SET;
2329 cmd.u.resendCmdInfo.QoSInfo = Aggr_Tspec_Info;
2330 pACInfo->requested_QoSInfo[SME_QOS_TSPEC_MASK_BIT_2_SET - 1] = Aggr_Tspec_Info;
2331 if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE)))
2332 {
2333 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2334 "%s: %d: On session %d unable to buffer the AddTS "
2335 "request for AC %d TSPEC %d in state %d",
2336 __FUNCTION__, __LINE__,
2337 sessionId, ac, SME_QOS_TSPEC_MASK_BIT_2_SET, pACInfo->curr_state);
2338
2339 // unable to buffer the request
2340 // nothing is pending so vote powersave back on
2341 pSession->readyForPowerSave = VOS_TRUE;
2342
2343 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
2344 }
2345 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_2_SET;
2346
2347 }
2348 }
2349 }
2350
2351 /* In case of splitting of existing streams,
2352 * tspec_mask will be pointing to tspec index 0 and
2353 * aggregated tspec for upstream(s) is sent out here. */
2354 hstatus = sme_QosUpdateParams(sessionId,
2355 ac, flow_info->tspec_mask,
2356 &Aggr_Tspec_Info);
2357 if(HAL_STATUS_SUCCESS(hstatus))
2358 {
2359 pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1] = Aggr_Tspec_Info;
2360 //if ACM, send out a new ADDTS
2361 status = sme_QosSetup(pMac, sessionId,
2362 &pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1], ac);
2363 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2364 "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
2365 "sme_QosSetup returned with status %d",
2366 __FUNCTION__, __LINE__,
2367 sessionId, ac, status);
2368 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
2369 {
2370 // we aren't waiting for a response from the AP
2371 // so vote powersave back on
2372 pSession->readyForPowerSave = VOS_TRUE;
2373 }
2374 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
2375 {
2376 new_state = SME_QOS_REQUESTED;
2377 status = SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
2378 pACInfo->tspec_pending = flow_info->tspec_mask;
2379 }
2380 else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
2381 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status))
2382 {
2383 new_state = SME_QOS_QOS_ON;
2384 pACInfo->num_flows[flow_info->tspec_mask - 1]--;
2385 pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1] =
2386 pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1];
2387 //delete the entry from Flow List
2388 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2389 "%s: %d: Deleting entry at %p with flowID %d",
2390 __FUNCTION__, __LINE__,
2391 flow_info, QosFlowID);
2392 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
2393 pDeletedFlow = flow_info;
2394 if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)
2395 {
2396 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
2397 search_key.key.ac_type = ac;
2398 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
2399 search_key.sessionId = sessionId;
2400 hstatus = sme_QosFindAllInFlowList(pMac, search_key,
2401 sme_QosSetupFnp);
2402 if(!HAL_STATUS_SUCCESS(hstatus))
2403 {
2404 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2405 "%s: %d: couldn't notify other "
2406 "entries on this AC =%d",
2407 __FUNCTION__, __LINE__, ac);
2408 }
2409 }
2410 status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
2411 if(buffered_cmd)
2412 {
2413 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
2414 &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
2415 status,
2416 flow_info->QosFlowID);
2417 }
2418 }
2419 else
2420 {
2421 // unexpected status returned by sme_QosSetup()
2422 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2423 "%s: %d: On session %d unexpected status %d "
2424 "returned by sme_QosSetup",
2425 __FUNCTION__, __LINE__,
2426 sessionId, status);
2427 new_state = SME_QOS_LINK_UP;
2428 pACInfo->num_flows[flow_info->tspec_mask - 1]--;
2429 pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1] =
2430 pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1];
2431 //delete the entry from Flow List
2432 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2433 "%s: %d: On session %d deleting entry at "
2434 "%p with flowID %d",
2435 __FUNCTION__, __LINE__,
2436 sessionId, flow_info, QosFlowID);
2437 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
2438 pDeletedFlow = flow_info;
2439 if(buffered_cmd)
2440 {
2441 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
2442 &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
2443 status,
2444 flow_info->QosFlowID);
2445 }
2446 }
2447 }
2448 else
2449 {
2450 //err msg
2451 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2452 "%s: %d: sme_QosUpdateParams() failed",
2453 __FUNCTION__, __LINE__);
2454 // unable to service the request
2455 // nothing is pending so vote powersave back on
2456 pSession->readyForPowerSave = VOS_TRUE;
2457 new_state = SME_QOS_LINK_UP;
2458 if(buffered_cmd)
2459 {
2460 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
2461 &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
2462 status,
2463 flow_info->QosFlowID);
2464 }
2465 }
2466 }
2467 else
2468 {
2469 // this is the only flow aggregated in this TSPEC
2470 status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
2471#ifdef FEATURE_WLAN_CCX
2472 if (ac == SME_QOS_EDCA_AC_VO)
2473 {
2474 // Indicate to neighbor roam logic of the new required VO
2475 // ac bandwidth requirement.
2476 csrNeighborRoamIndicateVoiceBW( pMac, pACInfo->curr_QoSInfo[0].peak_data_rate, FALSE );
2477 }
2478#endif
2479 //check if delts needs to be sent
2480 if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
2481 sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL))
2482 {
2483 //check if other TSPEC for this AC is also in use
2484 if(SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status)
2485 {
2486 // this is the only TSPEC active on this AC
2487 // so indicate that we no longer require APSD
2488 pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2489 //Also update modifyProfileFields.uapsd_mask in CSR for consistency
2490 csrGetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
2491 modifyProfileFields.uapsd_mask = pSession->apsdMask;
2492 csrSetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
2493 if(!pSession->apsdMask)
2494 {
2495 // this session no longer needs UAPSD
2496 // do any sessions still require UAPSD?
2497 if (!sme_QosIsUapsdActive())
2498 {
2499 // No sessions require UAPSD so turn it off
2500 // (really don't care when PMC stops it)
2501 (void)pmcStopUapsd(pMac);
2502 }
2503 }
2504 }
2505 //send delts
2506 hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandDelTs,
2507 NULL, ac, flow_info->tspec_mask);
2508 if(!HAL_STATUS_SUCCESS(hstatus))
2509 {
2510 //err msg
2511 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2512 "%s: %d: sme_QosDelTsReq() failed",
2513 __FUNCTION__, __LINE__);
2514 status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2515 // we won't be waiting for a response from the AP
2516 // so vote powersave back on
2517 pSession->readyForPowerSave = VOS_TRUE;
2518 }
2519 else
2520 {
2521 pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET &
2522 (~flow_info->tspec_mask);
2523 deltsIssued = VOS_TRUE;
2524 }
2525 }
2526 else if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac)))
2527 {
2528 //reassoc logic
2529 csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
2530 modifyProfileFields.uapsd_mask |= pSession->apsdMask;
2531 modifyProfileFields.uapsd_mask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2532 pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2533 if(!pSession->apsdMask)
2534 {
2535 // this session no longer needs UAPSD
2536 // do any sessions still require UAPSD?
2537 if (!sme_QosIsUapsdActive())
2538 {
2539 // No sessions require UAPSD so turn it off
2540 // (really don't care when PMC stops it)
2541 (void)pmcStopUapsd(pMac);
2542 }
2543 }
2544 hstatus = sme_QosRequestReassoc(pMac, sessionId,
2545 &modifyProfileFields, VOS_FALSE);
2546 if(!HAL_STATUS_SUCCESS(hstatus))
2547 {
2548 //err msg
2549 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2550 "%s: %d: Reassoc failed",
2551 __FUNCTION__, __LINE__);
2552 status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2553 // we won't be waiting for a response from the AP
2554 // so vote powersave back on
2555 pSession->readyForPowerSave = VOS_TRUE;
2556 }
2557 else
2558 {
2559 pACInfo->reassoc_pending = VOS_FALSE;//no need to wait
2560 pACInfo->prev_state = SME_QOS_LINK_UP;
2561 pACInfo->tspec_pending = 0;
2562 }
2563 }
2564 else
2565 {
2566 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2567 "%s: %d: nothing to do for AC = %d",
2568 __FUNCTION__, __LINE__, ac);
2569 // we won't be waiting for a response from the AP
2570 // so vote powersave back on
2571 pSession->readyForPowerSave = VOS_TRUE;
2572 }
2573 if(buffered_cmd)
2574 {
2575 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
2576 NULL,
2577 status,
2578 flow_info->QosFlowID);
2579 }
2580 if(SME_QOS_STATUS_RELEASE_FAILURE_RSP == status)
2581 {
2582 break;
2583 }
2584
2585 if(((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->tspec_mask) > 0) &&
2586 ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->tspec_mask) <=
2587 SME_QOS_TSPEC_INDEX_MAX))
2588 {
2589 if(pACInfo->num_flows[(SME_QOS_TSPEC_MASK_BIT_1_2_SET &
2590 ~flow_info->tspec_mask) - 1] > 0)
2591 {
2592 new_state = SME_QOS_QOS_ON;
2593 }
2594 else
2595 {
2596 new_state = SME_QOS_LINK_UP;
2597 }
2598 }
2599 else
2600 {
2601 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2602 "%s: %d: Exceeded the array bounds of pACInfo->num_flows",
2603 __FUNCTION__, __LINE__);
2604 VOS_ASSERT (0);
2605 return SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP;
2606 }
2607
2608 if(VOS_FALSE == deltsIssued)
2609 {
2610 vos_mem_zero(&pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
2611 sizeof(sme_QosWmmTspecInfo));
2612 }
2613 vos_mem_zero(&pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1],
2614 sizeof(sme_QosWmmTspecInfo));
2615 pACInfo->num_flows[flow_info->tspec_mask - 1]--;
2616 //delete the entry from Flow List
2617 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2618 "%s: %d: On session %d deleting entry at %p with flowID %d",
2619 __FUNCTION__, __LINE__,
2620 sessionId, flow_info, QosFlowID);
2621 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
2622 pDeletedFlow = flow_info;
2623 }
2624 /* if we are doing reassoc & we are already in handoff state, no need
2625 to move to requested state. But make sure to set the previous state
2626 as requested state
2627 */
2628 if(SME_QOS_HANDOFF != pACInfo->curr_state)
2629 {
2630 sme_QosStateTransition(sessionId, ac, new_state);
2631 }
2632 if(pACInfo->reassoc_pending)
2633 {
2634 pACInfo->prev_state = SME_QOS_REQUESTED;
2635 }
2636 break;
2637 case SME_QOS_HANDOFF:
2638 case SME_QOS_REQUESTED:
2639 //buffer cmd
2640 cmd.command = SME_QOS_RELEASE_REQ;
2641 cmd.pMac = pMac;
2642 cmd.sessionId = sessionId;
2643 cmd.u.releaseCmdInfo.QosFlowID = QosFlowID;
2644 hstatus = sme_QosBufferCmd(&cmd, buffered_cmd);
2645 if(!HAL_STATUS_SUCCESS(hstatus))
2646 {
2647 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2648 "%s: %d: couldn't buffer the release request in state = %d",
2649 __FUNCTION__, __LINE__,
2650 pACInfo->curr_state );
2651 // unable to service the request
2652 // nothing is pending so vote powersave back on
2653 pSession->readyForPowerSave = VOS_TRUE;
2654 return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2655 }
2656 status = SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
2657 break;
2658 case SME_QOS_CLOSED:
2659 case SME_QOS_INIT:
2660 case SME_QOS_LINK_UP:
2661 default:
2662 //print error msg
2663 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2664 "%s: %d: release request in unexpected state = %d",
2665 __FUNCTION__, __LINE__,
2666 pACInfo->curr_state );
2667 //ASSERT
2668 VOS_ASSERT(0);
2669 // unable to service the request
2670 // nothing is pending so vote powersave back on
2671 pSession->readyForPowerSave = VOS_TRUE;
2672 break;
2673 }
2674 // if we deleted a flow, reclaim the memory
2675 if (pDeletedFlow)
2676 {
2677 vos_mem_free(pDeletedFlow);
2678 }
2679 if((SME_QOS_STATUS_RELEASE_SUCCESS_RSP == status))
2680 {
2681 (void)sme_QosProcessBufferedCmd(sessionId);
2682 }
2683 return status;
2684}
2685
2686/*--------------------------------------------------------------------------
2687 \brief sme_QosSetup() - The internal qos setup function which has the
2688 intelligence if the request is NOP, or for APSD and/or need to send out ADDTS.
2689 It also does the sanity check for QAP, AP supports APSD etc.
2690 \param pMac - Pointer to the global MAC parameter structure.
2691 \param sessionId - Session upon which setup is being performed
2692 \param pTspec_Info - Pointer to sme_QosWmmTspecInfo which contains the WMM
2693 TSPEC related info as defined above
2694 \param ac - Enumeration of the various EDCA Access Categories.
2695
2696 \return SME_QOS_STATUS_SETUP_SUCCESS_RSP if the setup is successful
2697 The logic used in the code might be confusing. Trying to cover all the cases
2698 here.
2699 AP supports App wants ACM = 1 Already set APSD Result
2700 | 0 | 0 | 0 | 0 | NO ACM NO APSD
2701 | 0 | 0 | 0 | 1 | NO ACM NO APSD/INVALID
2702 | 0 | 0 | 1 | 0 | ADDTS
2703 | 0 | 0 | 1 | 1 | ADDTS
2704 | 0 | 1 | 0 | 0 | FAILURE
2705 | 0 | 1 | 0 | 1 | INVALID
2706 | 0 | 1 | 1 | 0 | ADDTS
2707 | 0 | 1 | 1 | 1 | ADDTS
2708 | 1 | 0 | 0 | 0 | NO ACM NO APSD
2709 | 1 | 0 | 0 | 1 | NO ACM NO APSD
2710 | 1 | 0 | 1 | 0 | ADDTS
2711 | 1 | 0 | 1 | 1 | ADDTS
2712 | 1 | 1 | 0 | 0 | REASSOC
2713 | 1 | 1 | 0 | 1 | NOP: APSD SET ALREADY
2714 | 1 | 1 | 1 | 0 | ADDTS
2715 | 1 | 1 | 1 | 1 | ADDTS
2716
2717 \sa
2718
2719 --------------------------------------------------------------------------*/
2720sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac,
2721 v_U8_t sessionId,
2722 sme_QosWmmTspecInfo *pTspec_Info,
2723 sme_QosEdcaAcType ac)
2724{
2725 sme_QosSessionInfo *pSession;
2726 sme_QosACInfo *pACInfo;
2727 sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
2728 tDot11fBeaconIEs *pIes = NULL;
2729 tCsrRoamModifyProfileFields modifyProfileFields;
2730 eHalStatus hstatus;
2731 if( !CSR_IS_SESSION_VALID( pMac, sessionId ) )
2732 {
2733 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2734 "%s: %d: Session Id %d is invalid",
2735 __FUNCTION__, __LINE__,
2736 sessionId);
2737 return status;
2738 }
2739 pSession = &sme_QosCb.sessionInfo[sessionId];
2740 if( !pSession->sessionActive )
2741 {
2742 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2743 "%s: %d: Session %d is inactive",
2744 __FUNCTION__, __LINE__,
2745 sessionId);
2746 return status;
2747 }
2748 if(!pSession->assocInfo.pBssDesc)
2749 {
2750 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2751 "%s: %d: Session %d has an Invalid BSS Descriptor",
2752 __FUNCTION__, __LINE__,
2753 sessionId, ac);
2754 return status;
2755 }
2756 hstatus = csrGetParsedBssDescriptionIEs(pMac,
2757 pSession->assocInfo.pBssDesc,
2758 &pIes);
2759 if(!HAL_STATUS_SUCCESS(hstatus))
2760 {
2761 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2762 "%s: %d: On session %d unable to parse BSS IEs",
2763 __FUNCTION__, __LINE__,
2764 sessionId, ac);
2765 return status;
2766 }
2767
2768 /* success so pIes was allocated */
2769
2770 if( !CSR_IS_QOS_BSS(pIes) )
2771 {
2772 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2773 "%s: %d: On session %d AP doesn't support QoS",
2774 __FUNCTION__, __LINE__,
2775 sessionId);
2776 vos_mem_free(pIes);
2777 //notify HDD through the synchronous status msg
2778 return SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP;
2779 }
2780 if(pTspec_Info->max_service_interval || pTspec_Info->min_service_interval)
2781 {
2782 pTspec_Info->ts_info.psb = 1;
2783 }
2784 else
2785 {
2786 pTspec_Info->ts_info.psb = 0;
2787 }
2788
2789 pACInfo = &pSession->ac_info[ac];
2790 do
2791 {
2792 // is ACM enabled for this AC?
2793 if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
2794 sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL))
2795 {
2796 // ACM is enabled for this AC so we must send an AddTS
2797 if(pTspec_Info->ts_info.psb &&
2798 (!pMac->pmc.uapsdEnabled ))
2799 {
2800 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2801 "%s: %d: Request is looking for APSD but PMC doesn't "
2802 "have support for APSD",
2803 __FUNCTION__, __LINE__);
2804 break;
2805 }
2806 if(SME_QOS_MAX_TID == pTspec_Info->ts_info.tid)
2807 {
2808 //App didn't set TID, generate one
2809 pTspec_Info->ts_info.tid =
2810 (v_U8_t)(SME_QOS_WMM_UP_NC - pTspec_Info->ts_info.up);
2811 }
2812 //addts logic
2813 hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandAddTs,
2814 pTspec_Info, ac, 0);
2815 if(!HAL_STATUS_SUCCESS(hstatus))
2816 {
2817 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2818 "%s: %d: sme_QosAddTsReq() failed",
2819 __FUNCTION__, __LINE__);
2820 break;
2821 }
2822 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2823 "%s: %d: On session %d AddTS on AC %d is pending",
2824 __FUNCTION__, __LINE__,
2825 sessionId, ac);
2826 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
2827 break;
2828 }
2829 // ACM is not enabled for this AC
2830 // Is the application looking for APSD?
2831 if(0 == pTspec_Info->ts_info.psb)
2832 {
2833 //no, we don't need APSD
2834 //but check the case, if the setup is called as a result of a release
2835 // or modify which boils down to the fact that APSD was set on this AC
2836 // but no longer needed - so we need a reassoc for the above case to
2837 // let the AP know
2838 if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac)))
2839 {
2840 // APSD was formerly enabled on this AC but is no longer required
2841 // so we must reassociate
2842 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2843 "%s: %d: On session %d reassoc needed "
2844 "to disable APSD on AC %d",
2845 __FUNCTION__, __LINE__,
2846 sessionId, ac);
2847 csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
2848 modifyProfileFields.uapsd_mask |= pSession->apsdMask;
2849 modifyProfileFields.uapsd_mask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2850 hstatus = sme_QosRequestReassoc(pMac, sessionId,
2851 &modifyProfileFields, VOS_FALSE);
2852 if(!HAL_STATUS_SUCCESS(hstatus))
2853 {
2854 //err msg
2855 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2856 "%s: %d: Unable to request reassociation",
2857 __FUNCTION__, __LINE__);
2858 break;
2859 }
2860 else
2861 {
2862 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2863 "%s: %d: On session %d reassociation to enable "
2864 "APSD on AC %d is pending",
2865 __FUNCTION__, __LINE__,
2866 sessionId, ac);
2867 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
2868 pACInfo->reassoc_pending = VOS_TRUE;
2869 }
2870 }
2871 else
2872 {
2873 // we don't need APSD on this AC
2874 // and we don't currently have APSD on this AC
2875 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2876 "%s: %d: Request is not looking for APSD & Admission "
2877 "Control isn't mandatory for the AC",
2878 __FUNCTION__, __LINE__);
2879 //return success right away
2880 status = SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP;
2881 }
2882 break;
2883 }
2884 else if(!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) &&
2885 !(pIes->WMMInfoAp.uapsd))
2886 {
2887 // application is looking for APSD but AP doesn't support it
2888 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2889 "%s: %d: On session %d AP doesn't support APSD",
2890 __FUNCTION__, __LINE__,
2891 sessionId);
2892 break;
2893 }
2894 else if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac)))
2895 {
2896 // application is looking for APSD
2897 // and it is already enabled on this AC
2898 status = SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY;
2899 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2900 "%s: %d: Request is looking for APSD and it is already "
2901 "set for the AC",
2902 __FUNCTION__, __LINE__);
2903 break;
2904 }
2905 else
2906 {
2907 // application is looking for APSD
2908 // but it is not enabled on this AC
2909 // so we need to reassociate
2910 if(pMac->pmc.uapsdEnabled)
2911 {
2912 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2913 "%s: %d: On session %d reassoc needed "
2914 "to enable APSD on AC %d",
2915 __FUNCTION__, __LINE__,
2916 sessionId, ac);
2917 //reassoc logic
2918 // update the UAPSD mask to include the new
2919 // AC on which APSD is requested
2920 csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
2921 modifyProfileFields.uapsd_mask |= pSession->apsdMask;
2922 modifyProfileFields.uapsd_mask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
2923 hstatus = sme_QosRequestReassoc(pMac, sessionId,
2924 &modifyProfileFields, VOS_FALSE);
2925 if(!HAL_STATUS_SUCCESS(hstatus))
2926 {
2927 //err msg
2928 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2929 "%s: %d: Unable to request reassociation",
2930 __FUNCTION__, __LINE__);
2931 break;
2932 }
2933 else
2934 {
2935 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
2936 "%s: %d: On session %d reassociation to enable "
2937 "APSD on AC %d is pending",
2938 __FUNCTION__, __LINE__,
2939 sessionId, ac);
2940 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
2941 pACInfo->reassoc_pending = VOS_TRUE;
2942 }
2943 }
2944 else
2945 {
2946 //err msg: no support for APSD from PMC
2947 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2948 "%s: %d: no support for APSD or BMPS from PMC",
2949 __FUNCTION__, __LINE__);
2950 }
2951 }
2952 }while(0);
2953
2954 vos_mem_free(pIes);
2955 return status;
2956}
2957
Jeff Johnson43971f52012-07-17 12:26:56 -07002958#if defined(FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
Jeff Johnson295189b2012-06-20 16:38:30 -07002959/* This is a dummy function now. But the purpose of me adding this was to
2960 * delay the TSPEC processing till SET_KEY completes. This function can be
2961 * used to do any SME_QOS processing after the SET_KEY. As of now, it is
2962 * not required as we are ok with tspec getting programmed before set_key
2963 * as the roam timings are measured without tspec in reassoc!
2964 */
2965eHalStatus sme_QosProcessSetKeySuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
2966{
2967 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
Jeff Johnson43971f52012-07-17 12:26:56 -07002968 "########### Set Key Complete #############");
Jeff Johnson295189b2012-06-20 16:38:30 -07002969 return eHAL_STATUS_SUCCESS;
2970}
Jeff Johnson43971f52012-07-17 12:26:56 -07002971#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002972
Jeff Johnson43971f52012-07-17 12:26:56 -07002973#ifdef FEATURE_WLAN_CCX
Jeff Johnson295189b2012-06-20 16:38:30 -07002974/*--------------------------------------------------------------------------
2975 \brief sme_QosCCXSaveTspecResponse() - This function saves the TSPEC
2976 parameters that came along in the TSPEC IE in the reassoc response
2977
2978 \param pMac - Pointer to the global MAC parameter structure.
2979 \param sessionId - SME session ID
2980 \param pTspec - Pointer to the TSPEC IE from the reassoc rsp
2981 \param ac - Access Category for which this TSPEC rsp is received
2982 \param tspecIndex - flow/direction
2983
2984 \return eHAL_STATUS_SUCCESS - Release is successful.
2985 --------------------------------------------------------------------------*/
2986eHalStatus sme_QosCCXSaveTspecResponse(tpAniSirGlobal pMac, v_U8_t sessionId, tDot11fIEWMMTSPEC *pTspec, v_U8_t ac, v_U8_t tspecIndex)
2987{
2988 tpSirAddtsRsp pAddtsRsp = &sme_QosCb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex];
2989
2990 ac = sme_QosUPtoACMap[pTspec->user_priority];
2991
2992 vos_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp));
2993
2994 pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP;
2995 pAddtsRsp->length = sizeof(tSirAddtsRsp);
2996 pAddtsRsp->rc = eSIR_SUCCESS;
2997 pAddtsRsp->sessionId = sessionId;
2998 pAddtsRsp->rsp.dialogToken = 0;
2999 pAddtsRsp->rsp.status = eSIR_SUCCESS;
3000 pAddtsRsp->rsp.wmeTspecPresent = pTspec->present;
3001 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3002 "%s: Copy Tspec to local data structure ac=%d, tspecIdx=%d",
3003 __FUNCTION__, ac, tspecIndex);
3004
3005 if (pAddtsRsp->rsp.wmeTspecPresent)
3006 {
3007 //Copy TSPEC params received in assoc response to addts response
3008 ConvertWMMTSPEC(pMac, &pAddtsRsp->rsp.tspec, pTspec);
3009 }
3010
3011 return eHAL_STATUS_SUCCESS;
3012}
3013
3014/*--------------------------------------------------------------------------
3015 \brief sme_QosCCXProcessReassocTspecRsp() - This function processes the
3016 WMM TSPEC IE in the reassoc response. Reassoc triggered as part of
3017 CCX roaming to another CCX capable AP. If the TSPEC was added before
3018 reassoc, as part of Call Admission Control, the reasso req from the
3019 STA would carry the TSPEC parameters which were already negotiated
3020 with the older AP.
3021
3022 \param pMac - Pointer to the global MAC parameter structure.
3023 \param sessionId - SME session ID
3024 \param pEven_info - Pointer to the smeJoinRsp structure
3025
3026 \return eHAL_STATUS_SUCCESS - Release is successful.
3027 --------------------------------------------------------------------------*/
3028eHalStatus sme_QosCCXProcessReassocTspecRsp(tpAniSirGlobal pMac, v_U8_t sessionId, void* pEvent_info)
3029{
3030 sme_QosSessionInfo *pSession;
3031 sme_QosACInfo *pACInfo;
3032 tDot11fIEWMMTSPEC *pTspecIE = NULL;
3033 tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId );
3034 tCsrRoamConnectedInfo *pCsrConnectedInfo = &pCsrSession->connectedInfo;
3035 eHalStatus status = eHAL_STATUS_FAILURE;
3036 v_U8_t ac, numTspec, cnt;
3037 v_U8_t tspec_flow_index, tspec_mask_status;
3038 v_U32_t tspecIeLen;
3039
3040 pSession = &sme_QosCb.sessionInfo[sessionId];
3041
3042 // Get the TSPEC IEs which came along with the reassoc response
3043 // from the pbFrames pointer
3044 pTspecIE = (tDot11fIEWMMTSPEC *)(pCsrConnectedInfo->pbFrames + pCsrConnectedInfo->nBeaconLength +
3045 pCsrConnectedInfo->nAssocReqLength + pCsrConnectedInfo->nAssocRspLength + pCsrConnectedInfo->nRICRspLength);
3046
3047 // Get the number of tspecs Ies in the frame, the min length
3048 // should be atleast equal to the one TSPEC IE
3049 tspecIeLen = pCsrConnectedInfo->nTspecIeLength;
3050 if (tspecIeLen < sizeof(tDot11fIEWMMTSPEC)) {
3051 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3052 FL("CCX Tspec IE len %d less than min %d"),
3053 tspecIeLen, sizeof(tDot11fIEWMMTSPEC));
3054 return eHAL_STATUS_FAILURE;
3055 }
3056
3057 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
3058 "TspecLen = %d, pbFrames = %p, pTspecIE = %p\n",
3059 tspecIeLen, pCsrConnectedInfo->pbFrames, pTspecIE);
3060
3061 numTspec = (tspecIeLen)/sizeof(tDot11fIEWMMTSPEC);
3062 for(cnt=0; cnt<numTspec; cnt++) {
3063 ac = sme_QosUpToAc(pTspecIE->user_priority);
3064 pACInfo = &pSession->ac_info[ac];
3065 tspec_mask_status = pACInfo->tspec_mask_status;
3066 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
3067 FL("UP=%d, ac=%d, tspec_mask_status=%x"),
3068 pTspecIE->user_priority, ac, tspec_mask_status );
3069
3070 for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++) {
3071 if (tspec_mask_status & (1 << tspec_flow_index)) {
3072 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
3073 FL("Found Tspec entry flow = %d AC = %d"),tspec_flow_index, ac);
3074 sme_QosCCXSaveTspecResponse(pMac, sessionId, pTspecIE, ac, tspec_flow_index);
3075 } else {
3076 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
3077 FL("Not found Tspec entry flow = %d AC = %d"),tspec_flow_index, ac);
3078 }
3079 }
3080 // Increment the pointer to point it to the next TSPEC IE
3081 pTspecIE++;
3082 }
3083
3084 /* Send the Aggregated QoS request to HAL */
3085 status = sme_QosFTAggrQosReq(pMac,sessionId);
3086
3087 return status;
3088}
3089
3090/*--------------------------------------------------------------------------
3091 \brief sme_QosCopyTspecInfo() - This function copies the existing TSPEC
3092 parameters from the source structure to the destination structure.
3093
3094 \param pMac - Pointer to the global MAC parameter structure.
3095 \param pTspec_Info - source structure
3096 \param pTspec - destination structure
3097
3098 \return void
3099 --------------------------------------------------------------------------*/
3100static void sme_QosCopyTspecInfo(tpAniSirGlobal pMac, sme_QosWmmTspecInfo *pTspec_Info, tSirMacTspecIE* pTspec)
3101{
3102 /* As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
3103 * Interval, Service Start Time, Suspension Interval and Delay Bound are
3104 * all intended for HCCA operation and therefore must be set to zero*/
3105 pTspec->delayBound = pTspec_Info->delay_bound;
3106 pTspec->inactInterval = pTspec_Info->inactivity_interval;
3107 pTspec->length = SME_QOS_TSPEC_IE_LENGTH;
3108 pTspec->maxBurstSz = pTspec_Info->max_burst_size;
3109 pTspec->maxMsduSz = pTspec_Info->maximum_msdu_size;
3110 pTspec->maxSvcInterval = pTspec_Info->max_service_interval;
3111 pTspec->meanDataRate = pTspec_Info->mean_data_rate;
3112 pTspec->mediumTime = pTspec_Info->medium_time;
3113 pTspec->minDataRate = pTspec_Info->min_data_rate;
3114 pTspec->minPhyRate = pTspec_Info->min_phy_rate;
3115 pTspec->minSvcInterval = pTspec_Info->min_service_interval;
3116 pTspec->nomMsduSz = pTspec_Info->nominal_msdu_size;
3117 pTspec->peakDataRate = pTspec_Info->peak_data_rate;
3118 pTspec->surplusBw = pTspec_Info->surplus_bw_allowance;
3119 pTspec->suspendInterval = pTspec_Info->suspension_interval;
3120 pTspec->svcStartTime = pTspec_Info->svc_start_time;
3121 pTspec->tsinfo.traffic.direction = pTspec_Info->ts_info.direction;
3122
3123 //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
3124 if (pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac)) {
3125 pTspec->tsinfo.traffic.psb = pTspec_Info->ts_info.psb;
3126 } else {
3127 pTspec->tsinfo.traffic.psb = 0;
3128 pTspec_Info->ts_info.psb = 0;
3129 }
3130 pTspec->tsinfo.traffic.tsid = pTspec_Info->ts_info.tid;
3131 pTspec->tsinfo.traffic.userPrio = pTspec_Info->ts_info.up;
3132 pTspec->tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA;
3133 pTspec->tsinfo.traffic.burstSizeDefn = pTspec_Info->ts_info.burst_size_defn;
3134 pTspec->tsinfo.traffic.ackPolicy = pTspec_Info->ts_info.ack_policy;
3135 pTspec->type = SME_QOS_TSPEC_IE_TYPE;
3136
3137 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3138 "%s: %d: up = %d, tid = %d",
3139 __FUNCTION__, __LINE__,
3140 pTspec_Info->ts_info.up,
3141 pTspec_Info->ts_info.tid);
3142}
3143
3144/*--------------------------------------------------------------------------
3145 \brief sme_QosCCxRetrieveTspecInfo() - This function is called by CSR
3146 when try to create reassoc request message to PE - csrSendSmeReassocReqMsg
3147 This functions get the existing tspec parameters to be included
3148 in the reassoc request.
3149
3150 \param pMac - Pointer to the global MAC parameter structure.
3151 \param sessionId - SME session ID
3152 \param pTspecInfo - Pointer to the structure to carry back the TSPEC parameters
3153
3154 \return v_U8_t - number of existing negotiated TSPECs
3155 --------------------------------------------------------------------------*/
3156v_U8_t sme_QosCCxRetrieveTspecInfo(tpAniSirGlobal pMac, v_U8_t sessionId, tTspecInfo *pTspecInfo)
3157{
3158 sme_QosSessionInfo *pSession;
3159 sme_QosACInfo *pACInfo;
3160 v_U8_t tspec_mask_status = 0;
3161 v_U8_t tspec_pending_status = 0;
3162 v_U8_t ac, numTspecs = 0;
3163 tTspecInfo *pDstTspec = pTspecInfo;
3164
3165 //TODO: Check if TSPEC has already been established, if not return
3166
3167 pSession = &sme_QosCb.sessionInfo[sessionId];
3168
3169 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
3170 volatile v_U8_t tspec_index = 0;
3171
3172 pACInfo = &pSession->ac_info[ac];
3173 tspec_pending_status = pACInfo->tspec_pending;
3174 tspec_mask_status = pACInfo->tspec_mask_status;
3175
3176 do {
3177 if (tspec_mask_status & SME_QOS_TSPEC_MASK_BIT_1_SET) {
3178 /* If a tspec status is pending, take requested_QoSInfo for RIC request, else use curr_QoSInfo
3179 for the RIC request */
3180 if (tspec_pending_status & SME_QOS_TSPEC_MASK_BIT_1_SET) {
3181 sme_QosCopyTspecInfo(pMac, &pACInfo->requested_QoSInfo[tspec_index], &pDstTspec->tspec);
3182 } else {
3183 sme_QosCopyTspecInfo(pMac, &pACInfo->curr_QoSInfo[tspec_index], &pDstTspec->tspec);
3184 }
3185 pDstTspec->valid = TRUE;
3186 numTspecs++;
3187 pDstTspec++;
3188 }
3189 tspec_mask_status >>= 1;
3190 tspec_pending_status >>= 1;
3191 tspec_index++;
3192 } while (tspec_mask_status);
3193 }
3194
3195 return numTspecs;
3196}
3197
3198#endif
3199
3200#ifdef WLAN_FEATURE_VOWIFI_11R
3201
3202eHalStatus sme_QosCreateTspecRICIE(tpAniSirGlobal pMac, sme_QosWmmTspecInfo *pTspec_Info,
3203 v_U8_t *pRICBuffer, v_U32_t *pRICLength, v_U8_t *pRICIdentifier)
3204{
3205 tDot11fIERICDataDesc ricIE;
3206 tANI_U32 nStatus;
3207
3208 VOS_ASSERT(NULL != pRICBuffer);
3209 VOS_ASSERT(NULL != pRICLength);
3210 VOS_ASSERT(NULL != pRICIdentifier);
3211
3212 vos_mem_zero(&ricIE, sizeof(tDot11fIERICDataDesc));
3213
3214 ricIE.present = 1;
3215 ricIE.RICData.present = 1;
3216 ricIE.RICData.resourceDescCount = 1;
3217 ricIE.RICData.statusCode = 0;
3218 ricIE.RICData.Identifier = sme_QosAssignDialogToken();
3219#ifndef USE_80211_WMMTSPEC_FOR_RIC
3220 ricIE.TSPEC.present = 1;
3221 ricIE.TSPEC.delay_bound = pTspec_Info->delay_bound;
3222 ricIE.TSPEC.inactivity_int = pTspec_Info->inactivity_interval;
3223 ricIE.TSPEC.burst_size = pTspec_Info->max_burst_size;
3224 ricIE.TSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size;
3225 ricIE.TSPEC.max_service_int = pTspec_Info->max_service_interval;
3226 ricIE.TSPEC.mean_data_rate = pTspec_Info->mean_data_rate;
3227 ricIE.TSPEC.medium_time = pTspec_Info->medium_time;
3228 ricIE.TSPEC.min_data_rate = pTspec_Info->min_data_rate;
3229 ricIE.TSPEC.min_phy_rate = pTspec_Info->min_phy_rate;
3230 ricIE.TSPEC.min_service_int = pTspec_Info->min_service_interval;
3231 ricIE.TSPEC.size = pTspec_Info->nominal_msdu_size;
3232 ricIE.TSPEC.peak_data_rate = pTspec_Info->peak_data_rate;
3233 ricIE.TSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance;
3234 ricIE.TSPEC.suspension_int = pTspec_Info->suspension_interval;
3235 ricIE.TSPEC.service_start_time = pTspec_Info->svc_start_time;
3236 ricIE.TSPEC.direction = pTspec_Info->ts_info.direction;
3237 //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
3238 if( pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac) )
3239 {
3240 ricIE.TSPEC.psb = pTspec_Info->ts_info.psb;
3241 }
3242 else
3243 {
3244 ricIE.TSPEC.psb = 0;
3245 }
3246 ricIE.TSPEC.tsid = pTspec_Info->ts_info.tid;
3247 ricIE.TSPEC.user_priority = pTspec_Info->ts_info.up;
3248 ricIE.TSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA;
3249
3250 *pRICIdentifier = ricIE.RICData.Identifier;
3251
3252 nStatus = dot11fPackIeRICDataDesc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), pRICLength);
3253 if (DOT11F_FAILED(nStatus))
3254 {
3255 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3256 FL("Packing of RIC Data of length %d failed with status %d"),
3257 *pRICLength, nStatus);
3258 }
3259#else // WMM TSPEC
3260 /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
3261 Interval, Service Start Time, Suspension Interval and Delay Bound are
3262 all intended for HCCA operation and therefore must be set to zero*/
3263 ricIE.WMMTSPEC.present = 1;
3264 ricIE.WMMTSPEC.version = 1;
3265 ricIE.WMMTSPEC.delay_bound = pTspec_Info->delay_bound;
3266 ricIE.WMMTSPEC.inactivity_int = pTspec_Info->inactivity_interval;
3267 ricIE.WMMTSPEC.burst_size = pTspec_Info->max_burst_size;
3268 ricIE.WMMTSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size;
3269 ricIE.WMMTSPEC.max_service_int = pTspec_Info->max_service_interval;
3270 ricIE.WMMTSPEC.mean_data_rate = pTspec_Info->mean_data_rate;
3271 ricIE.WMMTSPEC.medium_time = pTspec_Info->medium_time;
3272 ricIE.WMMTSPEC.min_data_rate = pTspec_Info->min_data_rate;
3273 ricIE.WMMTSPEC.min_phy_rate = pTspec_Info->min_phy_rate;
3274 ricIE.WMMTSPEC.min_service_int = pTspec_Info->min_service_interval;
3275 ricIE.WMMTSPEC.size = pTspec_Info->nominal_msdu_size;
3276 ricIE.WMMTSPEC.peak_data_rate = pTspec_Info->peak_data_rate;
3277 ricIE.WMMTSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance;
3278 ricIE.WMMTSPEC.suspension_int = pTspec_Info->suspension_interval;
3279 ricIE.WMMTSPEC.service_start_time = pTspec_Info->svc_start_time;
3280 ricIE.WMMTSPEC.direction = pTspec_Info->ts_info.direction;
3281 //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
3282 if( pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac) )
3283 {
3284 ricIE.WMMTSPEC.psb = pTspec_Info->ts_info.psb;
3285 }
3286 else
3287 {
3288 ricIE.WMMTSPEC.psb = 0;
3289 }
3290 ricIE.WMMTSPEC.tsid = pTspec_Info->ts_info.tid;
3291 ricIE.WMMTSPEC.user_priority = pTspec_Info->ts_info.up;
3292 ricIE.WMMTSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA;
3293
3294
3295 nStatus = dot11fPackIeRICDataDesc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), pRICLength);
3296 if (DOT11F_FAILED(nStatus))
3297 {
3298 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3299 FL("Packing of RIC Data of length %d failed with status %d"),
3300 *pRICLength, nStatus);
3301 }
3302#endif /* 80211_TSPEC */
3303 *pRICIdentifier = ricIE.RICData.Identifier;
3304 return nStatus;
3305}
3306
3307eHalStatus sme_QosProcessFTReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
3308{
3309 sme_QosSessionInfo *pSession;
3310 sme_QosACInfo *pACInfo;
3311 v_U8_t ac, qos_requested = FALSE;
3312 v_U8_t tspec_flow_index;
3313 sme_QosFlowInfoEntry *flow_info = NULL;
3314 tListElem *pEntry= NULL;
3315
3316 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3317 FL("Invoked on session %d"), sessionId);
3318
3319 pSession = &sme_QosCb.sessionInfo[sessionId];
3320
3321 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
3322 {
3323 pACInfo = &pSession->ac_info[ac];
3324 qos_requested = FALSE;
3325
3326 for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++)
3327 {
3328 /* Only in the below case, copy the AC's curr QoS Info to requested QoS info */
3329 if ((pACInfo->ricIdentifier[tspec_flow_index] && !pACInfo->tspec_pending) ||
3330 (pACInfo->tspec_mask_status & (1<<tspec_flow_index)))
3331 {
3332 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3333 FL("Copying the currentQos to requestedQos for AC=%d, flow=%d\n"),
3334 ac, tspec_flow_index );
3335
3336 pACInfo->requested_QoSInfo[tspec_flow_index] = pACInfo->curr_QoSInfo[tspec_flow_index];
3337 vos_mem_zero(&pACInfo->curr_QoSInfo[tspec_flow_index], sizeof(sme_QosWmmTspecInfo));
3338 qos_requested = TRUE;
3339 }
3340 }
3341
3342 // Only if the tspec is required, transition the state to
3343 // SME_QOS_REQUESTED for this AC
3344 if (qos_requested)
3345 {
3346 switch(pACInfo->curr_state)
3347 {
3348 case SME_QOS_HANDOFF:
3349 sme_QosStateTransition(sessionId, ac, SME_QOS_REQUESTED);
3350 break;
3351 default:
3352 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3353 FL("FT Reassoc req event in unexpected state %d"), pACInfo->curr_state);
3354 VOS_ASSERT(0);
3355 }
3356 }
3357
3358 }
3359
3360 /* At this point of time, we are disconnected from the old AP, so it is safe
3361 * to reset all these session variables */
3362 pSession->apsdMask = 0;
3363 pSession->uapsdAlreadyRequested = 0;
3364 pSession->readyForPowerSave = 0;
3365
3366 /* Now change reason and HO renewal of all the flow in this session only */
3367 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
3368 if(!pEntry)
3369 {
3370 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
3371 "%s: %d: Flow List empty, nothing to update",
3372 __FUNCTION__, __LINE__);
3373 return eHAL_STATUS_FAILURE;
3374 }
3375
3376 do
3377 {
3378 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
3379 if(sessionId == flow_info->sessionId)
3380 {
3381 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3382 "%s: %d: Changing FlowID %d reason to SETUP and HO renewal to FALSE",
3383 __FUNCTION__, __LINE__,
3384 flow_info->QosFlowID);
3385 flow_info->reason = SME_QOS_REASON_SETUP;
3386 flow_info->hoRenewal = eANI_BOOLEAN_TRUE;
3387 }
3388 pEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
3389 } while( pEntry );
3390
3391 return eHAL_STATUS_SUCCESS;
3392}
3393
3394
3395eHalStatus sme_QosFTAggrQosReq( tpAniSirGlobal pMac, v_U8_t sessionId )
3396{
3397 tSirAggrQosReq *pMsg = NULL;
3398 sme_QosSessionInfo *pSession;
3399 eHalStatus status = eHAL_STATUS_FAILURE;
3400 int i, j = 0;
3401 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3402 "%s: %d: invoked on session %d", __FUNCTION__, __LINE__,
3403 sessionId);
3404
3405 pSession = &sme_QosCb.sessionInfo[sessionId];
3406
3407 pMsg = (tSirAggrQosReq *)vos_mem_malloc(sizeof(tSirAggrQosReq));
3408
3409 if (!pMsg)
3410 {
3411 //err msg
3412 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3413 "%s: %d: couldn't allocate memory for the msg buffer",
3414 __FUNCTION__, __LINE__);
3415
3416 return eHAL_STATUS_FAILURE;
3417 }
3418
3419 vos_mem_zero(pMsg, sizeof(tSirAggrQosReq));
3420
3421 pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_FT_AGGR_QOS_REQ);
3422 pMsg->length = sizeof(tSirAggrQosReq);
3423 pMsg->sessionId = sessionId;
3424 pMsg->timeout = 0;
3425 pMsg->rspReqd = VOS_TRUE;
3426 vos_mem_copy( &pMsg->bssId[ 0 ],
3427 &pSession->assocInfo.pBssDesc->bssId[ 0 ],
3428 sizeof(tCsrBssid) );
3429
3430 for( i = 0; i < SME_QOS_EDCA_AC_MAX; i++ )
3431 {
3432 for( j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++ )
3433 {
3434 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3435 FL("ac=%d, tspec_mask_staus=%x, tspec_index=%d\n"),
3436 i, pSession->ac_info[i].tspec_mask_status, j);
3437 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3438 FL("direction = %d\n"), pSession->ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic.direction);
3439 // Check if any flow is active on this AC
3440 if ((pSession->ac_info[i].tspec_mask_status) & (1 << j))
3441 {
3442 tANI_U8 direction = pSession->ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic.direction;
3443 if ((direction == SME_QOS_WMM_TS_DIR_UPLINK) ||
3444 (direction == SME_QOS_WMM_TS_DIR_BOTH))
3445 {
3446 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
3447 FL("Found tspec entry AC=%d, flow=%d, direction = %d\n"), i, j, direction);
3448 pMsg->aggrInfo.aggrAddTsInfo[i].dialogToken =
3449 sme_QosAssignDialogToken();
3450 pMsg->aggrInfo.aggrAddTsInfo[i].lleTspecPresent =
3451 pSession->ac_info[i].addTsRsp[j].rsp.lleTspecPresent;
3452 pMsg->aggrInfo.aggrAddTsInfo[i].numTclas =
3453 pSession->ac_info[i].addTsRsp[j].rsp.numTclas;
3454 vos_mem_copy( pMsg->aggrInfo.aggrAddTsInfo[i].tclasInfo,
3455 pSession->ac_info[i].addTsRsp[j].rsp.tclasInfo,
3456 SIR_MAC_TCLASIE_MAXNUM );
3457 pMsg->aggrInfo.aggrAddTsInfo[i].tclasProc =
3458 pSession->ac_info[i].addTsRsp[j].rsp.tclasProc;
3459 pMsg->aggrInfo.aggrAddTsInfo[i].tclasProcPresent =
3460 pSession->ac_info[i].addTsRsp[j].rsp.tclasProcPresent;
3461 pMsg->aggrInfo.aggrAddTsInfo[i].tspec =
3462 pSession->ac_info[i].addTsRsp[j].rsp.tspec;
3463 pMsg->aggrInfo.aggrAddTsInfo[i].wmeTspecPresent =
3464 pSession->ac_info[i].addTsRsp[j].rsp.wmeTspecPresent;
3465 pMsg->aggrInfo.aggrAddTsInfo[i].wsmTspecPresent =
3466 pSession->ac_info[i].addTsRsp[j].rsp.wsmTspecPresent;
3467 pMsg->aggrInfo.tspecIdx |= ( 1 << i );
3468
3469 // Mark the index for this AC as pending for response, which would be
3470 // used to validate the AddTS response from HAL->PE->SME
3471 pSession->ac_info[i].tspec_pending = (1<<j);
3472 }
3473 }
3474 }
3475 }
3476
3477 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3478 "Sending aggregated message to HAL 0x%x\n", pMsg->aggrInfo.tspecIdx);
3479
3480 if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg)))
3481 {
3482 status = eHAL_STATUS_SUCCESS;
3483 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3484 "%s: %d: sent down a AGGR QoS req to PE",
3485 __FUNCTION__, __LINE__);
3486 }
3487
3488 return status;
3489}
3490
3491eHalStatus sme_QosProcessFTRICResponse(tpAniSirGlobal pMac, v_U8_t sessionId, tDot11fIERICDataDesc *pRicDataDesc, v_U8_t ac, v_U8_t tspecIndex)
3492{
3493 tANI_U8 i = 0;
3494 tpSirAddtsRsp pAddtsRsp
3495 = &sme_QosCb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex];
3496
3497 vos_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp));
3498
3499 pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP;
3500 pAddtsRsp->length = sizeof(tSirAddtsRsp);
3501 pAddtsRsp->rc = pRicDataDesc->RICData.statusCode;
3502 pAddtsRsp->sessionId = sessionId;
3503 pAddtsRsp->rsp.dialogToken = pRicDataDesc->RICData.Identifier;
3504 pAddtsRsp->rsp.status = pRicDataDesc->RICData.statusCode;
3505 pAddtsRsp->rsp.wmeTspecPresent = pRicDataDesc->TSPEC.present;
3506 if (pAddtsRsp->rsp.wmeTspecPresent)
3507 {
3508 //Copy TSPEC params received in RIC response to addts response
3509 ConvertTSPEC(pMac, &pAddtsRsp->rsp.tspec, &pRicDataDesc->TSPEC);
3510 }
3511
3512 pAddtsRsp->rsp.numTclas = pRicDataDesc->num_TCLAS;
3513 if (pAddtsRsp->rsp.numTclas)
3514 {
3515 for (i = 0; i < pAddtsRsp->rsp.numTclas; i++)
3516 {
3517 //Copy TCLAS info per index to the addts response
3518 ConvertTCLAS(pMac, &pAddtsRsp->rsp.tclasInfo[i], &pRicDataDesc->TCLAS[i]);
3519 }
3520 }
3521
3522 pAddtsRsp->rsp.tclasProcPresent = pRicDataDesc->TCLASSPROC.present;
3523 if (pAddtsRsp->rsp.tclasProcPresent)
3524 pAddtsRsp->rsp.tclasProc = pRicDataDesc->TCLASSPROC.processing;
3525
3526
3527 pAddtsRsp->rsp.schedulePresent = pRicDataDesc->Schedule.present;
3528 if (pAddtsRsp->rsp.schedulePresent)
3529 {
3530 //Copy Schedule IE params to addts response
3531 ConvertSchedule(pMac, &pAddtsRsp->rsp.schedule, &pRicDataDesc->Schedule);
3532 }
3533
3534 //Need to check the below portion is a part of WMM TSPEC
3535 //Process Delay element
3536 if (pRicDataDesc->TSDelay.present)
3537 ConvertTSDelay(pMac, &pAddtsRsp->rsp.delay, &pRicDataDesc->TSDelay);
3538 //return sme_QosProcessAddTsRsp(pMac, &addtsRsp);
3539 return eHAL_STATUS_SUCCESS;
3540 }
3541eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf)
3542{
3543 tpSirAggrQosRsp pAggrRsp = (tpSirAggrQosRsp)pMsgBuf;
3544 tSirAddtsRsp addtsRsp;
3545 eHalStatus status = eHAL_STATUS_SUCCESS;
3546 int i, j = 0;
3547 tANI_U8 sessionId = pAggrRsp->sessionId;
3548
3549 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3550 FL("Received AGGR_QOS resp from LIM"));
3551
3552 /* Copy over the updated response information for TSPEC of all the ACs */
3553 for( i = 0; i < SIR_QOS_NUM_AC_MAX; i++ )
3554 {
3555 tANI_U8 tspec_mask_status = sme_QosCb.sessionInfo[sessionId].ac_info[i].tspec_mask_status;
3556 for( j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++ )
3557 {
3558 tANI_U8 direction = sme_QosCb.sessionInfo[sessionId].ac_info[i].
3559 addTsRsp[j].rsp.tspec.tsinfo.traffic.direction;
3560
3561 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3562 FL("Addts rsp from LIM AC=%d, flow=%d dir=%d, tspecIdx=%x\n"),
3563 i, j, direction, pAggrRsp->aggrInfo.tspecIdx);
3564 // Check if the direction is Uplink or bi-directional
3565 if( ((1<<i) & pAggrRsp->aggrInfo.tspecIdx) &&
3566 ((tspec_mask_status) & (1<<j)) &&
3567 ((direction == SME_QOS_WMM_TS_DIR_UPLINK) ||
3568 (direction == SME_QOS_WMM_TS_DIR_BOTH)))
3569 {
3570 addtsRsp = sme_QosCb.sessionInfo[sessionId].ac_info[i].addTsRsp[j];
3571 addtsRsp.rc = pAggrRsp->aggrInfo.aggrRsp[i].status;
3572 addtsRsp.rsp.status = pAggrRsp->aggrInfo.aggrRsp[i].status;
3573 addtsRsp.rsp.tspec = pAggrRsp->aggrInfo.aggrRsp[i].tspec;
3574
3575 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3576 FL("%s: Processing Addts rsp from LIM AC=%d, flow=%d\n"), i, j);
3577 /* post ADD TS response for each */
3578 if (sme_QosProcessAddTsRsp(pMac, &addtsRsp) != eHAL_STATUS_SUCCESS)
3579 {
3580 status = eHAL_STATUS_FAILURE;
3581 }
3582 }
3583 }
3584 }
3585 return status;
3586}
3587
3588
3589eHalStatus sme_QosProcessFTReassocRspEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
3590{
3591 sme_QosSessionInfo *pSession;
3592 sme_QosACInfo *pACInfo;
3593 v_U8_t ac;
3594 v_U8_t tspec_flow_index;
3595 tDot11fIERICDataDesc *pRicDataDesc = NULL;
3596 eHalStatus status = eHAL_STATUS_SUCCESS;
3597 tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId );
3598 tCsrRoamConnectedInfo *pCsrConnectedInfo = &pCsrSession->connectedInfo;
3599 tANI_U32 ricRspLen = pCsrConnectedInfo->nRICRspLength;
3600
3601 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3602 "%s: %d: invoked on session %d",
3603 __FUNCTION__, __LINE__,
3604 sessionId);
3605
3606 pSession = &sme_QosCb.sessionInfo[sessionId];
3607
3608 pRicDataDesc = (tDot11fIERICDataDesc *)pCsrConnectedInfo->pbFrames + pCsrConnectedInfo->nBeaconLength +
3609 pCsrConnectedInfo->nAssocReqLength + pCsrConnectedInfo->nAssocRspLength;
3610
3611 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
3612 {
3613 pACInfo = &pSession->ac_info[ac];
3614
3615 for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++)
3616 {
3617 /* Only in the below case, copy the AC's curr QoS Info to requested QoS info */
3618 if (pACInfo->ricIdentifier[tspec_flow_index])
3619 {
3620
3621 if (!ricRspLen)
3622 {
3623 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3624 FL("RIC Response not received for AC %d on TSPEC Index %d, RIC Req Identifier = %d"),
3625 ac, tspec_flow_index, pACInfo->ricIdentifier[tspec_flow_index]);
3626 VOS_ASSERT(0);
3627 }
3628 else
3629 {
3630 /* Now we got response for this identifier. Process it. */
3631 if (pRicDataDesc->present)
3632 {
3633 if (pRicDataDesc->RICData.present)
3634 {
3635 if (pRicDataDesc->RICData.Identifier != pACInfo->ricIdentifier[tspec_flow_index])
3636 {
3637 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3638 FL("RIC response order not same as request sent. Request ID = %d, Response ID = %d"),
3639 pACInfo->ricIdentifier[tspec_flow_index], pRicDataDesc->RICData.Identifier);
3640 VOS_ASSERT(0);
3641 }
3642 else
3643 {
3644 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3645 FL("Processing RIC Response for AC %d, TSPEC Flow index %d with RIC ID %d \n"),
3646 ac, tspec_flow_index, pRicDataDesc->RICData.Identifier);
3647 status = sme_QosProcessFTRICResponse(pMac, sessionId, pRicDataDesc, ac, tspec_flow_index);
3648 if (eHAL_STATUS_SUCCESS != status)
3649 {
3650 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3651 FL("Failed with status %d for AC %d in TSPEC Flow index = %d\n"),
3652 status, ac, tspec_flow_index);
3653 }
3654 }
3655 pRicDataDesc++;
3656 ricRspLen -= sizeof(tDot11fIERICDataDesc);
3657 }
3658 }
3659 }
3660 }
3661
3662 }
3663 }
3664
3665 if (ricRspLen)
3666 {
3667 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3668 FL("RIC Response still follows despite traversing through all ACs. Remaining len = %d\n"), ricRspLen);
3669 VOS_ASSERT(0);
3670 }
3671
3672 /* Send the Aggregated QoS request to HAL */
3673 status = sme_QosFTAggrQosReq(pMac,sessionId);
3674
3675 return status;
3676}
3677
3678#endif /* WLAN_FEATURE_VOWIFI_11R */
3679
3680
3681
3682/*--------------------------------------------------------------------------
3683 \brief sme_QosAddTsReq() - To send down the ADDTS request with TSPEC params
3684 to PE
3685
3686
3687 \param pMac - Pointer to the global MAC parameter structure.
3688 \param sessionId - Session upon which the TSPEC should be added
3689 \param pTspec_Info - Pointer to sme_QosWmmTspecInfo which contains the WMM
3690 TSPEC related info as defined above
3691 \param ac - Enumeration of the various EDCA Access Categories.
3692 \return eHalStatus
3693
3694 \sa
3695
3696 --------------------------------------------------------------------------*/
3697eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac,
3698 v_U8_t sessionId,
3699 sme_QosWmmTspecInfo * pTspec_Info,
3700 sme_QosEdcaAcType ac)
3701{
3702 tSirAddtsReq *pMsg = NULL;
3703 sme_QosSessionInfo *pSession;
3704 eHalStatus status = eHAL_STATUS_FAILURE;
3705#ifdef FEATURE_WLAN_CCX
3706 tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId );
3707#endif
3708#ifdef FEATURE_WLAN_DIAG_SUPPORT
3709 WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
3710#endif
3711 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3712 "%s: %d: invoked on session %d for AC %d",
3713 __FUNCTION__, __LINE__,
3714 sessionId, ac);
3715 pSession = &sme_QosCb.sessionInfo[sessionId];
3716 pMsg = (tSirAddtsReq *)vos_mem_malloc(sizeof(tSirAddtsReq));
3717 if (!pMsg)
3718 {
3719 //err msg
3720 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3721 "%s: %d: couldn't allocate memory for the msg buffer",
3722 __FUNCTION__, __LINE__);
3723 return eHAL_STATUS_FAILURE;
3724 }
3725 vos_mem_zero(pMsg, sizeof(tSirAddtsReq));
3726 pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_ADDTS_REQ);
3727 pMsg->length = sizeof(tSirAddtsReq);
3728 pMsg->sessionId = sessionId;
3729 pMsg->timeout = 0;
3730 pMsg->rspReqd = VOS_TRUE;
3731 pMsg->req.dialogToken = sme_QosAssignDialogToken();
3732 /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
3733 Interval, Service Start Time, Suspension Interval and Delay Bound are
3734 all intended for HCCA operation and therefore must be set to zero*/
3735 pMsg->req.tspec.delayBound = 0;
3736 pMsg->req.tspec.inactInterval = pTspec_Info->inactivity_interval;
3737 pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH;
3738 pMsg->req.tspec.maxBurstSz = pTspec_Info->max_burst_size;
3739 pMsg->req.tspec.maxMsduSz = pTspec_Info->maximum_msdu_size;
3740 pMsg->req.tspec.maxSvcInterval = pTspec_Info->max_service_interval;
3741 pMsg->req.tspec.meanDataRate = pTspec_Info->mean_data_rate;
3742 pMsg->req.tspec.mediumTime = pTspec_Info->medium_time;
3743 pMsg->req.tspec.minDataRate = pTspec_Info->min_data_rate;
3744 pMsg->req.tspec.minPhyRate = pTspec_Info->min_phy_rate;
3745 pMsg->req.tspec.minSvcInterval = pTspec_Info->min_service_interval;
3746 pMsg->req.tspec.nomMsduSz = pTspec_Info->nominal_msdu_size;
3747 pMsg->req.tspec.peakDataRate = pTspec_Info->peak_data_rate;
3748 pMsg->req.tspec.surplusBw = pTspec_Info->surplus_bw_allowance;
3749 pMsg->req.tspec.suspendInterval = pTspec_Info->suspension_interval;
3750 pMsg->req.tspec.svcStartTime = 0;
3751 pMsg->req.tspec.tsinfo.traffic.direction = pTspec_Info->ts_info.direction;
3752 //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup
3753 if( pTspec_Info->ts_info.psb
3754 && btcIsReadyForUapsd(pMac)
3755 )
3756 {
3757 pMsg->req.tspec.tsinfo.traffic.psb = pTspec_Info->ts_info.psb;
3758 }
3759 else
3760 {
3761 pMsg->req.tspec.tsinfo.traffic.psb = 0;
3762 pTspec_Info->ts_info.psb = 0;
3763 }
3764 pMsg->req.tspec.tsinfo.traffic.tsid = pTspec_Info->ts_info.tid;
3765 pMsg->req.tspec.tsinfo.traffic.userPrio = pTspec_Info->ts_info.up;
3766 pMsg->req.tspec.tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA;
3767 pMsg->req.tspec.tsinfo.traffic.burstSizeDefn = pTspec_Info->ts_info.burst_size_defn;
3768 pMsg->req.tspec.tsinfo.traffic.ackPolicy = pTspec_Info->ts_info.ack_policy;
3769 pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE;
3770 /*Fill the BSSID pMsg->req.bssId*/
3771 if (NULL == pSession->assocInfo.pBssDesc)
3772 {
3773 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3774 "%s: %d: BSS descriptor is NULL so we don't send requst to PE",
3775 __FUNCTION__, __LINE__);
3776 return eHAL_STATUS_FAILURE;
3777 }
3778 vos_mem_copy( &pMsg->bssId[ 0 ],
3779 &pSession->assocInfo.pBssDesc->bssId[ 0 ],
3780 sizeof(tCsrBssid) );
3781 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3782 "%s: %d: up = %d, tid = %d",
3783 __FUNCTION__, __LINE__,
3784 pTspec_Info->ts_info.up,
3785 pTspec_Info->ts_info.tid);
3786#ifdef FEATURE_WLAN_CCX
3787 if(pCsrSession->connectedProfile.isCCXAssoc)
3788 {
3789 pMsg->req.tsrsIE.tsid = pTspec_Info->ts_info.up;
3790 pMsg->req.tsrsPresent = 1;
3791 }
3792#endif
3793 if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg)))
3794 {
3795 status = eHAL_STATUS_SUCCESS;
3796 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3797 "%s: %d: sent down a ADDTS req to PE",
3798 __FUNCTION__, __LINE__);
3799 //event: EVENT_WLAN_QOS
3800#ifdef FEATURE_WLAN_DIAG_SUPPORT
3801 qos.eventId = SME_QOS_DIAG_ADDTS_REQ;
3802 qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED;
3803 WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
3804#endif //FEATURE_WLAN_DIAG_SUPPORT
3805 }
3806 return status;
3807}
3808/*--------------------------------------------------------------------------
3809 \brief sme_QosDelTsReq() - To send down the DELTS request with TSPEC params
3810 to PE
3811
3812
3813 \param pMac - Pointer to the global MAC parameter structure.
3814 \param sessionId - Session from which the TSPEC should be deleted
3815 \param ac - Enumeration of the various EDCA Access Categories.
3816 \param tspec_mask - on which tspec per AC, the delts is requested
3817
3818 \return eHalStatus
3819
3820 \sa
3821
3822 --------------------------------------------------------------------------*/
3823eHalStatus sme_QosDelTsReq(tpAniSirGlobal pMac,
3824 v_U8_t sessionId,
3825 sme_QosEdcaAcType ac,
3826 v_U8_t tspec_mask)
3827{
3828 sme_QosSessionInfo *pSession;
3829 sme_QosACInfo *pACInfo;
3830 tSirDeltsReq *pMsg;
3831 sme_QosWmmTspecInfo *pTspecInfo;
3832 eHalStatus status = eHAL_STATUS_FAILURE;
3833#ifdef FEATURE_WLAN_DIAG_SUPPORT
3834 WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
3835#endif
3836 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3837 "%s: %d: invoked on session %d for AC %d",
3838 __FUNCTION__, __LINE__,
3839 sessionId, ac);
3840 pMsg = (tSirDeltsReq *)vos_mem_malloc(sizeof(tSirDeltsReq));
3841 if (!pMsg)
3842 {
3843 //err msg
3844 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3845 "%s: %d: couldn't allocate memory for the msg buffer",
3846 __FUNCTION__, __LINE__);
3847 return eHAL_STATUS_FAILURE;
3848 }
3849 vos_mem_zero(pMsg, sizeof(tSirDeltsReq));
3850 // get pointer to the TSPEC being deleted
3851 pSession = &sme_QosCb.sessionInfo[sessionId];
3852 pACInfo = &pSession->ac_info[ac];
3853 pTspecInfo = &pACInfo->curr_QoSInfo[tspec_mask - 1];
3854 pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_DELTS_REQ);
3855 pMsg->length = sizeof(tSirDeltsReq);
3856 pMsg->sessionId = sessionId;
3857 pMsg->rspReqd = VOS_TRUE;
3858 pMsg->req.tspec.delayBound = pTspecInfo->delay_bound;
3859 pMsg->req.tspec.inactInterval = pTspecInfo->inactivity_interval;
3860 pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH;
3861 pMsg->req.tspec.maxBurstSz = pTspecInfo->max_burst_size;
3862 pMsg->req.tspec.maxMsduSz = pTspecInfo->maximum_msdu_size;
3863 pMsg->req.tspec.maxSvcInterval = pTspecInfo->max_service_interval;
3864 pMsg->req.tspec.meanDataRate = pTspecInfo->mean_data_rate;
3865 pMsg->req.tspec.mediumTime = pTspecInfo->medium_time;
3866 pMsg->req.tspec.minDataRate = pTspecInfo->min_data_rate;
3867 pMsg->req.tspec.minPhyRate = pTspecInfo->min_phy_rate;
3868 pMsg->req.tspec.minSvcInterval = pTspecInfo->min_service_interval;
3869 pMsg->req.tspec.nomMsduSz = pTspecInfo->nominal_msdu_size;
3870 pMsg->req.tspec.peakDataRate = pTspecInfo->peak_data_rate;
3871 pMsg->req.tspec.surplusBw = pTspecInfo->surplus_bw_allowance;
3872 pMsg->req.tspec.suspendInterval = pTspecInfo->suspension_interval;
3873 pMsg->req.tspec.svcStartTime = pTspecInfo->svc_start_time;
3874 pMsg->req.tspec.tsinfo.traffic.direction = pTspecInfo->ts_info.direction;
3875 pMsg->req.tspec.tsinfo.traffic.psb = pTspecInfo->ts_info.psb;
3876 pMsg->req.tspec.tsinfo.traffic.tsid = pTspecInfo->ts_info.tid;
3877 pMsg->req.tspec.tsinfo.traffic.userPrio = pTspecInfo->ts_info.up;
3878 pMsg->req.tspec.tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA;
3879 pMsg->req.tspec.tsinfo.traffic.burstSizeDefn = pTspecInfo->ts_info.burst_size_defn;
3880 pMsg->req.tspec.tsinfo.traffic.ackPolicy = pTspecInfo->ts_info.ack_policy;
3881 pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE;
3882 /*Fill the BSSID pMsg->req.bssId*/
3883 if (NULL == pSession->assocInfo.pBssDesc)
3884 {
3885 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3886 "%s: %d: BSS descriptor is NULL so we don't send request to PE",
3887 __FUNCTION__, __LINE__);
3888 return eHAL_STATUS_FAILURE;
3889 }
3890 vos_mem_copy( &pMsg->bssId[ 0 ],
3891 &pSession->assocInfo.pBssDesc->bssId[ 0 ],
3892 sizeof(tCsrBssid) );
3893
3894 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3895 "%s: %d: up = %d, tid = %d",
3896 __FUNCTION__, __LINE__,
3897 pTspecInfo->ts_info.up,
3898 pTspecInfo->ts_info.tid);
3899 vos_mem_zero(&pACInfo->curr_QoSInfo[tspec_mask - 1],
3900 sizeof(sme_QosWmmTspecInfo));
3901 if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg)))
3902 {
3903 status = eHAL_STATUS_SUCCESS;
3904 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3905 "%s: %d: sme_QosDelTsReq:Test: sent down a DELTS req to PE",
3906 __FUNCTION__, __LINE__);
3907 //event: EVENT_WLAN_QOS
3908#ifdef FEATURE_WLAN_DIAG_SUPPORT
3909 qos.eventId = SME_QOS_DIAG_DELTS;
3910 qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED;
3911 WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
3912#endif //FEATURE_WLAN_DIAG_SUPPORT
3913 }
3914
3915 return status;
3916}
3917
3918
3919/*--------------------------------------------------------------------------
3920 \brief sme_QosProcessAddTsRsp() - Function to process the
3921 eWNI_SME_ADDTS_RSP came from PE
3922
3923 \param pMac - Pointer to the global MAC parameter structure.
3924 \param pMsgBuf - Pointer to the msg buffer came from PE.
3925
3926 \return eHalStatus
3927
3928 \sa
3929
3930 --------------------------------------------------------------------------*/
3931eHalStatus sme_QosProcessAddTsRsp(tpAniSirGlobal pMac, void *pMsgBuf)
3932{
3933 tpSirAddtsRsp paddts_rsp = (tpSirAddtsRsp)pMsgBuf;
3934 sme_QosSessionInfo *pSession;
3935 v_U8_t sessionId = paddts_rsp->sessionId;
3936 eHalStatus status = eHAL_STATUS_FAILURE;
3937#ifdef WLAN_FEATURE_VOWIFI_11R
3938 sme_QosWmmUpType up = (sme_QosWmmUpType)paddts_rsp->rsp.tspec.tsinfo.traffic.userPrio;
3939 sme_QosACInfo *pACInfo;
3940 sme_QosEdcaAcType ac;
3941#endif
3942
3943 pSession = &sme_QosCb.sessionInfo[sessionId];
3944
3945#ifdef WLAN_FEATURE_VOWIFI_11R
3946 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3947 "%s: %d: invoked on session %d for UP %d",
3948 __FUNCTION__, __LINE__,
3949 sessionId, up);
3950
3951 ac = sme_QosUpToAc(up);
3952 if(SME_QOS_EDCA_AC_MAX == ac)
3953 {
3954 //err msg
3955 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3956 "%s: %d: invalid AC %d from UP %d",
3957 __FUNCTION__, __LINE__, ac, up);
3958
3959 return eHAL_STATUS_FAILURE;
3960 }
3961 pACInfo = &pSession->ac_info[ac];
3962 if (SME_QOS_HANDOFF == pACInfo->curr_state)
3963 {
3964 smsLog(pMac, LOG1, FL("ADDTS Response received for AC %d in HANDOFF State.. Dropping"), ac);
3965 pSession->readyForPowerSave = VOS_TRUE;
3966 return eHAL_STATUS_SUCCESS;
3967 }
3968#endif
3969
3970#ifdef FEATURE_WLAN_DIAG_SUPPORT
3971 WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
3972#endif
3973 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
3974 "%s: %d: Invoked on session %d with return code %d",
3975 __FUNCTION__, __LINE__,
3976 sessionId, paddts_rsp->rc);
3977 // our outstanding request has been serviced
3978 // we can go into powersave
3979 pSession->readyForPowerSave = VOS_TRUE;
3980 if(paddts_rsp->rc)
3981 {
3982 //event: EVENT_WLAN_QOS
3983#ifdef FEATURE_WLAN_DIAG_SUPPORT
3984 qos.eventId = SME_QOS_DIAG_ADDTS_RSP;
3985 qos.reasonCode = SME_QOS_DIAG_ADDTS_REFUSED;
3986 WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
3987#endif //FEATURE_WLAN_DIAG_SUPPORT
3988 status = sme_QosProcessAddTsFailureRsp(pMac, sessionId, &paddts_rsp->rsp);
3989 }
3990 else
3991 {
3992 status = sme_QosProcessAddTsSuccessRsp(pMac, sessionId, &paddts_rsp->rsp);
3993 }
3994 return status;
3995}
3996/*--------------------------------------------------------------------------
3997 \brief sme_QosProcessDelTsRsp() - Function to process the
3998 eWNI_SME_DELTS_RSP came from PE
3999
4000 \param pMac - Pointer to the global MAC parameter structure.
4001 \param pMsgBuf - Pointer to the msg buffer came from PE.
4002
4003 \return eHalStatus
4004
4005 \sa
4006
4007 --------------------------------------------------------------------------*/
4008eHalStatus sme_QosProcessDelTsRsp(tpAniSirGlobal pMac, void *pMsgBuf)
4009{
4010 tpSirDeltsRsp pDeltsRsp = (tpSirDeltsRsp)pMsgBuf;
4011 sme_QosSessionInfo *pSession;
4012 v_U8_t sessionId = pDeltsRsp->sessionId;
4013 // msg
4014 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4015 "%s: %d: Invoked on session %d with return code %d",
4016 __FUNCTION__, __LINE__,
4017 sessionId, pDeltsRsp->rc);
4018 pSession = &sme_QosCb.sessionInfo[sessionId];
4019 // our outstanding request has been serviced
4020 // we can go into powersave
4021 pSession->readyForPowerSave = VOS_TRUE;
4022 (void)sme_QosProcessBufferedCmd(sessionId);
4023 return eHAL_STATUS_SUCCESS;
4024}
4025/*--------------------------------------------------------------------------
4026 \brief sme_QosProcessDelTsInd() - Function to process the
4027 eWNI_SME_DELTS_IND came from PE
4028
4029 Since it's a DELTS indication from AP, will notify all the flows running on
4030 this AC about QoS release
4031 \param pMac - Pointer to the global MAC parameter structure.
4032 \param pMsgBuf - Pointer to the msg buffer came from PE.
4033
4034 \return eHalStatus
4035
4036 \sa
4037
4038 --------------------------------------------------------------------------*/
4039eHalStatus sme_QosProcessDelTsInd(tpAniSirGlobal pMac, void *pMsgBuf)
4040{
4041 tpSirDeltsRsp pdeltsind = (tpSirDeltsRsp)pMsgBuf;
4042 sme_QosSessionInfo *pSession;
4043 sme_QosACInfo *pACInfo;
4044 v_U8_t sessionId = pdeltsind->sessionId;
4045 sme_QosEdcaAcType ac;
4046 sme_QosSearchInfo search_key;
4047 sme_QosWmmUpType up = (sme_QosWmmUpType)pdeltsind->rsp.tspec.tsinfo.traffic.userPrio;
4048#ifdef FEATURE_WLAN_DIAG_SUPPORT
4049 WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
4050#endif
4051 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4052 "%s: %d: Invoked on session %d for UP %d",
4053 __FUNCTION__, __LINE__,
4054 sessionId, up);
4055 ac = sme_QosUpToAc(up);
4056 if(SME_QOS_EDCA_AC_MAX == ac)
4057 {
4058 //err msg
4059 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4060 "%s: %d: invalid AC %d from UP %d",
4061 __FUNCTION__, __LINE__,
4062 ac, up);
4063 return eHAL_STATUS_FAILURE;
4064 }
4065 pSession = &sme_QosCb.sessionInfo[sessionId];
4066 pACInfo = &pSession->ac_info[ac];
4067
4068 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
4069 //set the key type & the key to be searched in the Flow List
4070 search_key.key.ac_type = ac;
4071 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
4072 search_key.sessionId = sessionId;
4073 //find all Flows on the perticular AC & delete them, also send HDD indication
4074 // through the callback it registered per request
4075 if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosDelTsIndFnp)))
4076 {
4077 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4078 "%s: %d: no match found for ac = %d",
4079 __FUNCTION__, __LINE__,
4080 search_key.key.ac_type);
4081 //ASSERT
4082 VOS_ASSERT(0);
4083 return eHAL_STATUS_FAILURE;
4084 }
4085 //clean up the CB
4086 vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4087 sizeof(sme_QosWmmTspecInfo));
4088 vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4089 sizeof(sme_QosWmmTspecInfo));
4090 vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4091 sizeof(sme_QosWmmTspecInfo));
4092 vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4093 sizeof(sme_QosWmmTspecInfo));
4094 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
4095 pACInfo->tspec_pending = 0;
4096 //event: EVENT_WLAN_QOS
4097#ifdef FEATURE_WLAN_DIAG_SUPPORT
4098 qos.eventId = SME_QOS_DIAG_DELTS;
4099 qos.reasonCode = SME_QOS_DIAG_DELTS_IND_FROM_AP;
4100 WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
4101#endif //FEATURE_WLAN_DIAG_SUPPORT
4102
4103 sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP);
4104 (void)sme_QosProcessBufferedCmd(sessionId);
4105 return eHAL_STATUS_SUCCESS;
4106}
4107/*--------------------------------------------------------------------------
4108 \brief sme_QosProcessAssocCompleteEv() - Function to process the
4109 SME_QOS_CSR_ASSOC_COMPLETE event indication from CSR
4110 \param pEvent_info - Pointer to relevant info from CSR.
4111
4112 \return eHalStatus
4113
4114 \sa
4115
4116 --------------------------------------------------------------------------*/
4117eHalStatus sme_QosProcessAssocCompleteEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4118{
4119 sme_QosSessionInfo *pSession;
4120 sme_QosACInfo *pACInfo;
4121 eHalStatus status = eHAL_STATUS_FAILURE;
4122 sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_BE;
4123 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4124 "%s: %d: invoked on session %d",
4125 __FUNCTION__, __LINE__,
4126 sessionId);
4127 pSession = &sme_QosCb.sessionInfo[sessionId];
4128 if(((SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state)&&
4129 (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state)&&
4130 (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state)&&
4131 (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state)) ||
4132 (pSession->handoffRequested))
4133 {
4134 //get the association info
4135 if(!pEvent_info)
4136 {
4137 //err msg
4138 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4139 "%s: %d: pEvent_info is NULL",
4140 __FUNCTION__, __LINE__);
4141 return status;
4142 }
4143 if(!((sme_QosAssocInfo *)pEvent_info)->pBssDesc)
4144 {
4145 //err msg
4146 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4147 "%s: %d: pBssDesc is NULL",
4148 __FUNCTION__, __LINE__);
4149 return status;
4150 }
4151 if((pSession->assocInfo.pBssDesc) &&
4152 (csrIsBssidMatch(pMac, (tCsrBssid *)&pSession->assocInfo.pBssDesc->bssId,
4153 (tCsrBssid *) &(((sme_QosAssocInfo *)pEvent_info)->pBssDesc->bssId))))
4154 {
4155 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4156 "%s: %d: assoc with the same BSS, no update needed",
4157 __FUNCTION__, __LINE__);
4158 }
4159 else
4160 {
4161 status = sme_QosSaveAssocInfo(pSession, pEvent_info);
4162 }
4163 }
4164 else
4165 {
4166 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4167 "%s: %d: wrong state: BE %d, BK %d, VI %d, VO %d",
4168 __FUNCTION__, __LINE__,
4169 pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state,
4170 pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state,
4171 pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state,
4172 pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state);
4173 //ASSERT
4174 VOS_ASSERT(0);
4175 return status;
4176 }
4177 // the session is active
4178 pSession->sessionActive = VOS_TRUE;
4179 if(pSession->handoffRequested)
4180 {
4181 pSession->handoffRequested = VOS_FALSE;
4182 //renew all flows
4183 (void)sme_QosProcessBufferedCmd(sessionId);
4184 status = eHAL_STATUS_SUCCESS;
4185 }
4186 else
4187 {
4188 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4189 {
4190 pACInfo = &pSession->ac_info[ac];
4191 switch(pACInfo->curr_state)
4192 {
4193 case SME_QOS_INIT:
4194 sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP);
4195 break;
4196 case SME_QOS_LINK_UP:
4197 case SME_QOS_REQUESTED:
4198 case SME_QOS_QOS_ON:
4199 case SME_QOS_HANDOFF:
4200 case SME_QOS_CLOSED:
4201 default:
4202 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4203 "%s: %d: On session %d AC %d is in wrong state %d",
4204 __FUNCTION__, __LINE__,
4205 sessionId, ac, pACInfo->curr_state);
4206 //ASSERT
4207 VOS_ASSERT(0);
4208 break;
4209 }
4210 }
4211 }
4212 return status;
4213}
4214/*--------------------------------------------------------------------------
4215 \brief sme_QosProcessReassocReqEv() - Function to process the
4216 SME_QOS_CSR_REASSOC_REQ event indication from CSR
4217 \param pEvent_info - Pointer to relevant info from CSR.
4218
4219 \return eHalStatus
4220
4221 \sa
4222
4223 --------------------------------------------------------------------------*/
4224eHalStatus sme_QosProcessReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4225{
4226 sme_QosSessionInfo *pSession;
4227 sme_QosACInfo *pACInfo;
4228 sme_QosEdcaAcType ac;
4229 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4230 "%s: %d: invoked on session %d",
4231 __FUNCTION__, __LINE__,
4232 sessionId);
4233 pSession = &sme_QosCb.sessionInfo[sessionId];
4234
4235#ifdef WLAN_FEATURE_VOWIFI_11R
4236 if(pSession->ftHandoffInProgress)
4237 {
4238 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4239 "%s: %d: no need for state transition, should "
4240 "already be in handoff state",
4241 __FUNCTION__, __LINE__);
4242 VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
4243 VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
4244 VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
4245 VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
4246 sme_QosProcessFTReassocReqEv(pMac, sessionId, pEvent_info);
4247 return eHAL_STATUS_SUCCESS;
4248 }
4249#endif
4250
4251 if(pSession->handoffRequested)
4252 {
4253 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4254 "%s: %d: no need for state transition, should "
4255 "already be in handoff state",
4256 __FUNCTION__, __LINE__);
4257 VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
4258 VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
4259 VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
4260 VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
4261
4262 //buffer the existing flows to be renewed after handoff is done
4263 sme_QosBufferExistingFlows(pMac, sessionId);
4264 //clean up the control block partially for handoff
4265 sme_QosCleanupCtrlBlkForHandoff(pMac, sessionId);
4266 return eHAL_STATUS_SUCCESS;
4267 }
4268//TBH: Assuming both handoff algo & 11r willn't be enabled at the same time
4269#ifdef WLAN_FEATURE_VOWIFI_11R
4270 if(pSession->ftHandoffInProgress)
4271 {
4272 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4273 "%s: %d: no need for state transition, should "
4274 "already be in handoff state",
4275 __FUNCTION__, __LINE__);
4276 VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
4277 VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
4278 VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
4279 VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
4280
4281 sme_QosProcessFTReassocReqEv(pMac, sessionId, pEvent_info);
4282 return eHAL_STATUS_SUCCESS;
4283 }
4284#endif
4285
4286 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4287 {
4288 pACInfo = &pSession->ac_info[ac];
4289 switch(pACInfo->curr_state)
4290 {
4291 case SME_QOS_LINK_UP:
4292 case SME_QOS_REQUESTED:
4293 case SME_QOS_QOS_ON:
4294 sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
4295 break;
4296 case SME_QOS_HANDOFF:
4297 //This is normal because sme_QosRequestReassoc may already change the state
4298 break;
4299 case SME_QOS_CLOSED:
4300 case SME_QOS_INIT:
4301 default:
4302 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4303 "%s: %d: On session %d AC %d is in wrong state %d",
4304 __FUNCTION__, __LINE__,
4305 sessionId, ac, pACInfo->curr_state);
4306 //ASSERT
4307 VOS_ASSERT(0);
4308 break;
4309 }
4310 }
4311 return eHAL_STATUS_SUCCESS;
4312}
4313/*--------------------------------------------------------------------------
4314 \brief sme_QosProcessReassocSuccessEv() - Function to process the
4315 SME_QOS_CSR_REASSOC_COMPLETE event indication from CSR
4316 \param pEvent_info - Pointer to relevant info from CSR.
4317
4318 \return eHalStatus
4319
4320 \sa
4321
4322 --------------------------------------------------------------------------*/
4323eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4324{
4325 tpSirSmeJoinRsp pSmeJoinRsp = (tpSirSmeJoinRsp) pEvent_info;
4326 sme_QosSessionInfo *pSession;
4327 sme_QosACInfo *pACInfo;
4328 sme_QosEdcaAcType ac, ac_index;
4329 sme_QosSearchInfo search_key;
4330 sme_QosSearchInfo search_key1;
4331 eHalStatus status = eHAL_STATUS_FAILURE;
4332 tListElem *pEntry= NULL;
4333 sme_QosFlowInfoEntry *flow_info = NULL;
4334
4335 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4336 "%s: %d: invoked on session %d",
4337 __FUNCTION__, __LINE__,
4338 sessionId);
4339 pSession = &sme_QosCb.sessionInfo[sessionId];
4340 // our pending reassociation has completed
4341 // we can allow powersave
4342 pSession->readyForPowerSave = VOS_TRUE;
4343 //get the association info
4344 if(!pEvent_info)
4345 {
4346 //err msg
4347 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4348 "%s: %d: pEvent_info is NULL",
4349 __FUNCTION__, __LINE__);
4350 return status;
4351 }
4352 if(!((sme_QosAssocInfo *)pEvent_info)->pBssDesc)
4353 {
4354 //err msg
4355 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4356 "%s: %d: pBssDesc is NULL",
4357 __FUNCTION__, __LINE__);
4358 return status;
4359 }
4360 status = sme_QosSaveAssocInfo(pSession, pEvent_info);
4361 if(status)
4362 {
4363 //err msg
4364 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4365 "%s: %d: sme_QosSaveAssocInfo() failed",
4366 __FUNCTION__, __LINE__);
4367 }
4368//TBH: Assuming both handoff algo & 11r willn't be enabled at the same time
4369 if(pSession->handoffRequested)
4370 {
4371 pSession->handoffRequested = VOS_FALSE;
4372 //renew all flows
4373 (void)sme_QosProcessBufferedCmd(sessionId);
4374 return eHAL_STATUS_SUCCESS;
4375 }
4376#ifdef WLAN_FEATURE_VOWIFI_11R
4377 if (pSession->ftHandoffInProgress)
4378 {
4379 if (csrRoamIs11rAssoc(pMac)) {
4380 if (pSmeJoinRsp->parsedRicRspLen) {
4381 status = sme_QosProcessFTReassocRspEv(pMac, sessionId, pEvent_info);
4382 }
4383 }
4384#ifdef FEATURE_WLAN_CCX
4385 // If CCX association check for TSPEC IEs in the reassoc rsp frame
4386 if (csrRoamIsCCXAssoc(pMac)) {
4387 if (pSmeJoinRsp->tspecIeLen) {
4388 status = sme_QosCCXProcessReassocTspecRsp(pMac, sessionId, pEvent_info);
4389 }
4390 }
4391#endif
4392 pSession->ftHandoffInProgress = VOS_FALSE;
4393 pSession->handoffRequested = VOS_FALSE;
4394 return status;
4395 }
4396#endif
4397
4398 pSession->sessionActive = VOS_TRUE;
4399 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4400 {
4401 pACInfo = &pSession->ac_info[ac];
4402 switch(pACInfo->curr_state)
4403 {
4404 case SME_QOS_HANDOFF:
4405 // return to our previous state
4406 sme_QosStateTransition(sessionId, ac, pACInfo->prev_state);
4407 //for which ac APSD (hence the reassoc) is requested
4408 if(pACInfo->reassoc_pending)
4409 {
4410 //update the apsd mask in CB - make sure to take care of the case
4411 //where we are resetting the bit in apsd_mask
4412 if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb)
4413 {
4414 pSession->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
4415 }
4416 else
4417 {
4418 pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
4419 }
4420 pACInfo->reassoc_pending = VOS_FALSE;
4421 //during setup it gets set as addts & reassoc both gets a pending flag
4422 //pACInfo->tspec_pending = 0;
4423 sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON);
4424 // notify HDD with new Service Interval
4425 pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
4426 pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0];
4427 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
4428 //set the key type & the key to be searched in the Flow List
4429 search_key.key.ac_type = ac;
4430 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
4431 search_key.sessionId = sessionId;
4432 //notify PMC that reassoc is done for APSD on certain AC??
4433
4434 vos_mem_zero(&search_key1, sizeof(sme_QosSearchInfo));
4435 //set the hoRenewal field in control block if needed
4436 search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3;
4437 search_key1.key.reason = SME_QOS_REASON_SETUP;
4438 search_key1.sessionId = sessionId;
4439 for(ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX; ac_index++)
4440 {
4441 pEntry = sme_QosFindInFlowList(search_key1);
4442 if(pEntry)
4443 {
4444 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
4445 if(flow_info->ac_type == ac)
4446 {
4447 pACInfo->hoRenewal = flow_info->hoRenewal;
4448 break;
4449 }
4450 }
4451 }
4452 //notify HDD the success for the requested flow
4453 //notify all the other flows running on the AC that QoS got modified
4454 if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosReassocSuccessEvFnp)))
4455 {
4456 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4457 "%s: %d: no match found for ac = %d",
4458 __FUNCTION__, __LINE__,
4459 search_key.key.ac_type);
4460 //ASSERT
4461 VOS_ASSERT(0);
4462 return eHAL_STATUS_FAILURE;
4463 }
4464 pACInfo->hoRenewal = VOS_FALSE;
4465 vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4466 sizeof(sme_QosWmmTspecInfo));
4467 }
4468 status = eHAL_STATUS_SUCCESS;
4469 break;
4470 case SME_QOS_INIT:
4471 case SME_QOS_CLOSED:
4472 //NOP
4473 status = eHAL_STATUS_SUCCESS;
4474 break;
4475 case SME_QOS_LINK_UP:
4476 case SME_QOS_REQUESTED:
4477 case SME_QOS_QOS_ON:
4478 default:
4479 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4480 "%s: %d: On session %d AC %d is in wrong state %d",
4481 __FUNCTION__, __LINE__,
4482 sessionId, ac, pACInfo->curr_state);
4483 //ASSERT
4484 VOS_ASSERT(0);
4485 break;
4486 }
4487 }
4488 (void)sme_QosProcessBufferedCmd(sessionId);
4489 return status;
4490}
4491
4492/*--------------------------------------------------------------------------
4493 \brief sme_QosProcessReassocFailureEv() - Function to process the
4494 SME_QOS_CSR_REASSOC_FAILURE event indication from CSR
4495 \param pEvent_info - Pointer to relevant info from CSR.
4496
4497 \return eHalStatus
4498
4499 \sa
4500
4501 --------------------------------------------------------------------------*/
4502eHalStatus sme_QosProcessReassocFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4503{
4504 sme_QosSessionInfo *pSession;
4505 sme_QosACInfo *pACInfo;
4506 sme_QosEdcaAcType ac;
4507 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4508 "%s: %d: invoked on session %d",
4509 __FUNCTION__, __LINE__,
4510 sessionId);
4511 pSession = &sme_QosCb.sessionInfo[sessionId];
4512 // our pending reassociation has completed
4513 // we can allow powersave
4514 pSession->readyForPowerSave = VOS_TRUE;
4515 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4516 {
4517 pACInfo = &pSession->ac_info[ac];
4518 switch(pACInfo->curr_state)
4519 {
4520 case SME_QOS_HANDOFF:
4521 sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
4522 if(pACInfo->reassoc_pending)
4523 {
4524 pACInfo->reassoc_pending = VOS_FALSE;
4525 }
4526 vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4527 sizeof(sme_QosWmmTspecInfo));
4528 vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4529 sizeof(sme_QosWmmTspecInfo));
4530 vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4531 sizeof(sme_QosWmmTspecInfo));
4532 vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4533 sizeof(sme_QosWmmTspecInfo));
4534 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
4535 pACInfo->tspec_pending = 0;
4536 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0;
4537 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0;
4538 break;
4539 case SME_QOS_INIT:
4540 case SME_QOS_CLOSED:
4541 //NOP
4542 break;
4543 case SME_QOS_LINK_UP:
4544 case SME_QOS_REQUESTED:
4545 case SME_QOS_QOS_ON:
4546 default:
4547 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4548 "%s: %d: On session %d AC %d is in wrong state %d",
4549 __FUNCTION__, __LINE__,
4550 sessionId, ac, pACInfo->curr_state);
4551 //ASSERT
4552 VOS_ASSERT(0);
4553 break;
4554 }
4555 }
4556 //need to clean up flows
4557 sme_QosDeleteExistingFlows(pMac, sessionId);
4558 return eHAL_STATUS_SUCCESS;
4559}
4560/*--------------------------------------------------------------------------
4561 \brief sme_QosProcessHandoffAssocReqEv() - Function to process the
4562 SME_QOS_CSR_HANDOFF_ASSOC_REQ event indication from CSR
4563 \param pEvent_info - Pointer to relevant info from CSR.
4564
4565 \return eHalStatus
4566
4567 \sa
4568
4569 --------------------------------------------------------------------------*/
4570eHalStatus sme_QosProcessHandoffAssocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4571{
4572 sme_QosSessionInfo *pSession;
4573 sme_QosACInfo *pACInfo;
4574 v_U8_t ac;
4575 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4576 "%s: %d: invoked on session %d",
4577 __FUNCTION__, __LINE__,
4578 sessionId);
4579 pSession = &sme_QosCb.sessionInfo[sessionId];
4580 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4581 {
4582 pACInfo = &pSession->ac_info[ac];
4583 switch(pACInfo->curr_state)
4584 {
4585 case SME_QOS_LINK_UP:
4586 case SME_QOS_REQUESTED:
4587 case SME_QOS_QOS_ON:
4588 sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
4589 break;
4590 case SME_QOS_HANDOFF:
4591 //print error msg
4592#ifdef WLAN_FEATURE_VOWIFI_11R
4593 if(pSession->ftHandoffInProgress)
4594 {
4595 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4596 "%s: %d: SME_QOS_CSR_HANDOFF_ASSOC_REQ received in "
4597 "SME_QOS_HANDOFF state with FT in progress"
4598 , __FUNCTION__, __LINE__);
4599 break;
4600 }
4601#endif
4602
4603 case SME_QOS_CLOSED:
4604 case SME_QOS_INIT:
4605 default:
4606 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4607 "%s: %d: On session %d AC %d is in wrong state %d",
4608 __FUNCTION__, __LINE__,
4609 sessionId, ac, pACInfo->curr_state);
4610 //ASSERT
4611 VOS_ASSERT(0);
4612 break;
4613 }
4614 }
4615 // If FT handoff is in progress, legacy handoff need not be enabled
4616 if (!pSession->ftHandoffInProgress) {
4617 pSession->handoffRequested = VOS_TRUE;
4618 }
4619 // this session no longer needs UAPSD
4620 pSession->apsdMask = 0;
4621 // do any sessions still require UAPSD?
4622 if (!sme_QosIsUapsdActive())
4623 {
4624 // No sessions require UAPSD so turn it off
4625 // (really don't care when PMC stops it)
4626 (void)pmcStopUapsd(pMac);
4627 }
4628 pSession->uapsdAlreadyRequested = VOS_FALSE;
4629 return eHAL_STATUS_SUCCESS;
4630}
4631/*--------------------------------------------------------------------------
4632 \brief sme_QosProcessHandoffSuccessEv() - Function to process the
4633 SME_QOS_CSR_HANDOFF_COMPLETE event indication from CSR
4634 \param pEvent_info - Pointer to relevant info from CSR.
4635
4636 \return eHalStatus
4637
4638 \sa
4639
4640 --------------------------------------------------------------------------*/
4641eHalStatus sme_QosProcessHandoffSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4642{
4643 sme_QosSessionInfo *pSession;
4644 sme_QosACInfo *pACInfo;
4645 v_U8_t ac;
4646 eHalStatus status = eHAL_STATUS_FAILURE;
4647 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4648 "%s: %d: invoked on session %d",
4649 __FUNCTION__, __LINE__,
4650 sessionId);
4651 pSession = &sme_QosCb.sessionInfo[sessionId];
4652 //go back to original state before handoff
4653 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4654 {
4655 pACInfo = &pSession->ac_info[ac];
4656 switch(pACInfo->curr_state)
4657 {
4658 case SME_QOS_HANDOFF:
4659 sme_QosStateTransition(sessionId, ac, pACInfo->prev_state);
4660 //we will retry for the requested flow(s) with the new AP
4661 if(SME_QOS_REQUESTED == pACInfo->curr_state)
4662 {
4663 pACInfo->curr_state = SME_QOS_LINK_UP;
4664 }
4665 status = eHAL_STATUS_SUCCESS;
4666 break;
4667 // FT logic, has already moved it to QOS_REQUESTED state during the
4668 // reassoc request event, which would include the Qos (TSPEC) params
4669 // in the reassoc req frame
4670 case SME_QOS_REQUESTED:
4671 break;
4672 case SME_QOS_INIT:
4673 case SME_QOS_CLOSED:
4674 case SME_QOS_LINK_UP:
4675 case SME_QOS_QOS_ON:
4676 default:
4677#ifdef WLAN_FEATURE_VOWIFI_11R
4678/* In case of 11r - RIC, we request QoS and Hand-off at the same time hence the
4679 state may be SME_QOS_REQUESTED */
4680 if( pSession->ftHandoffInProgress )
4681 break;
4682#endif
4683 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4684 "%s: %d: On session %d AC %d is in wrong state %d",
4685 __FUNCTION__, __LINE__,
4686 sessionId, ac, pACInfo->curr_state);
4687 //ASSERT
4688 VOS_ASSERT(0);
4689 break;
4690 }
4691 }
4692 return status;
4693}
4694/*--------------------------------------------------------------------------
4695 \brief sme_QosProcessHandoffFailureEv() - Function to process the
4696 SME_QOS_CSR_HANDOFF_FAILURE event indication from CSR
4697 \param pEvent_info - Pointer to relevant info from CSR.
4698
4699 \return eHalStatus
4700
4701 \sa
4702
4703 --------------------------------------------------------------------------*/
4704eHalStatus sme_QosProcessHandoffFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4705{
4706 sme_QosSessionInfo *pSession;
4707 sme_QosACInfo *pACInfo;
4708 v_U8_t ac;
4709 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4710 "%s: %d: invoked on session %d",
4711 __FUNCTION__, __LINE__,
4712 sessionId);
4713 pSession = &sme_QosCb.sessionInfo[sessionId];
4714 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4715 {
4716 pACInfo = &pSession->ac_info[ac];
4717 switch(pACInfo->curr_state)
4718 {
4719 case SME_QOS_HANDOFF:
4720 sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
4721 //need to clean up flows: TODO
4722 vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4723 sizeof(sme_QosWmmTspecInfo));
4724 vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4725 sizeof(sme_QosWmmTspecInfo));
4726 vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4727 sizeof(sme_QosWmmTspecInfo));
4728 vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4729 sizeof(sme_QosWmmTspecInfo));
4730 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
4731 pACInfo->tspec_pending = 0;
4732 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0;
4733 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0;
4734 break;
4735 case SME_QOS_INIT:
4736 case SME_QOS_CLOSED:
4737 case SME_QOS_LINK_UP:
4738 case SME_QOS_REQUESTED:
4739 case SME_QOS_QOS_ON:
4740 default:
4741 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4742 "%s: %d: On session %d AC %d is in wrong state %d",
4743 __FUNCTION__, __LINE__,
4744 sessionId, ac, pACInfo->curr_state);
4745 //ASSERT
4746 VOS_ASSERT(0);
4747 break;
4748 }
4749 }
4750 //no longer in handoff
4751 pSession->handoffRequested = VOS_FALSE;
4752 //clean up the assoc info
4753 if(pSession->assocInfo.pBssDesc)
4754 {
4755 vos_mem_free(pSession->assocInfo.pBssDesc);
4756 pSession->assocInfo.pBssDesc = NULL;
4757 }
4758 return eHAL_STATUS_SUCCESS;
4759}
4760/*--------------------------------------------------------------------------
4761 \brief sme_QosProcessDisconnectEv() - Function to process the
4762 SME_QOS_CSR_DISCONNECT_REQ or SME_QOS_CSR_DISCONNECT_IND event indication
4763 from CSR
4764 \param pEvent_info - Pointer to relevant info from CSR.
4765
4766 \return eHalStatus
4767
4768 \sa
4769
4770 --------------------------------------------------------------------------*/
4771eHalStatus sme_QosProcessDisconnectEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4772{
4773 sme_QosSessionInfo *pSession;
4774 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4775 "%s: %d: invoked on session %d",
4776 __FUNCTION__, __LINE__,
4777 sessionId);
4778 pSession = &sme_QosCb.sessionInfo[sessionId];
4779 if((pSession->handoffRequested)
4780#ifdef WLAN_FEATURE_VOWIFI_11R
4781/* In case of 11r - RIC, we request QoS and Hand-off at the same time hence the
4782 state may be SME_QOS_REQUESTED */
4783 && !pSession->ftHandoffInProgress
4784#endif
4785 )
4786 {
4787 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4788 "%s: %d: no need for state transition, should "
4789 "already be in handoff state",
4790 __FUNCTION__, __LINE__);
4791 VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
4792 VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
4793 VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
4794 VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
4795 return eHAL_STATUS_SUCCESS;
4796 }
4797 sme_QosInitACs(pMac, sessionId);
4798 // this session doesn't require UAPSD
4799 pSession->apsdMask = 0;
4800 // do any sessions still require UAPSD?
4801 if (!sme_QosIsUapsdActive())
4802 {
4803 // No sessions require UAPSD so turn it off
4804 // (really don't care when PMC stops it)
4805 (void)pmcStopUapsd(pMac);
4806 }
4807 pSession->uapsdAlreadyRequested = VOS_FALSE;
4808 pSession->handoffRequested = VOS_FALSE;
4809 pSession->readyForPowerSave = VOS_TRUE;
4810 pSession->roamID = 0;
4811 //need to clean up buffered req
4812 sme_QosDeleteBufferedRequests(pMac, sessionId);
4813 //need to clean up flows
4814 sme_QosDeleteExistingFlows(pMac, sessionId);
4815 //clean up the assoc info
4816 if(pSession->assocInfo.pBssDesc)
4817 {
4818 vos_mem_free(pSession->assocInfo.pBssDesc);
4819 pSession->assocInfo.pBssDesc = NULL;
4820 }
4821 sme_QosCb.sessionInfo[sessionId].sessionActive = VOS_FALSE;
4822 return eHAL_STATUS_SUCCESS;
4823}
4824/*--------------------------------------------------------------------------
4825 \brief sme_QosProcessJoinReqEv() - Function to process the
4826 SME_QOS_CSR_JOIN_REQ event indication from CSR
4827 \param pEvent_info - Pointer to relevant info from CSR.
4828
4829 \return eHalStatus
4830
4831 \sa
4832
4833 --------------------------------------------------------------------------*/
4834eHalStatus sme_QosProcessJoinReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4835{
4836 sme_QosSessionInfo *pSession;
4837 sme_QosEdcaAcType ac;
4838 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4839 "%s: %d: invoked on session %d",
4840 __FUNCTION__, __LINE__,
4841 sessionId);
4842 pSession = &sme_QosCb.sessionInfo[sessionId];
4843 if(pSession->handoffRequested)
4844 {
4845 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4846 "%s: %d: no need for state transition, should "
4847 "already be in handoff state",
4848 __FUNCTION__, __LINE__);
4849 VOS_ASSERT(pSession->ac_info[0].curr_state == SME_QOS_HANDOFF);
4850 VOS_ASSERT(pSession->ac_info[1].curr_state == SME_QOS_HANDOFF);
4851 VOS_ASSERT(pSession->ac_info[2].curr_state == SME_QOS_HANDOFF);
4852 VOS_ASSERT(pSession->ac_info[3].curr_state == SME_QOS_HANDOFF);
4853 //buffer the existing flows to be renewed after handoff is done
4854 sme_QosBufferExistingFlows(pMac, sessionId);
4855 //clean up the control block partially for handoff
4856 sme_QosCleanupCtrlBlkForHandoff(pMac, sessionId);
4857 return eHAL_STATUS_SUCCESS;
4858 }
4859
4860 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4861 {
4862 sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
4863 }
4864 //clean up the assoc info if already set
4865 if(pSession->assocInfo.pBssDesc)
4866 {
4867 vos_mem_free(pSession->assocInfo.pBssDesc);
4868 pSession->assocInfo.pBssDesc = NULL;
4869 }
4870 return eHAL_STATUS_SUCCESS;
4871}
4872
4873#ifdef WLAN_FEATURE_VOWIFI_11R
4874/*--------------------------------------------------------------------------
4875 \brief sme_QosProcessPreauthSuccessInd() - Function to process the
4876 SME_QOS_CSR_PREAUTH_SUCCESS_IND event indication from CSR
4877
4878 \param pEvent_info - Pointer to relevant info from CSR.
4879
4880 \return eHalStatus
4881
4882 \sa
4883
4884 --------------------------------------------------------------------------*/
4885eHalStatus sme_QosProcessPreauthSuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info)
4886{
4887 sme_QosSessionInfo *pSession;
4888 sme_QosACInfo *pACInfo;
4889 v_U8_t ac;
4890 eHalStatus status = eHAL_STATUS_SUCCESS;
4891
4892 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
4893 "%s: %d: invoked on session %d",
4894 __FUNCTION__, __LINE__,
4895 sessionId);
4896
4897 pSession = &sme_QosCb.sessionInfo[sessionId];
4898
4899 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4900 {
4901 pACInfo = &pSession->ac_info[ac];
4902
4903 switch(pACInfo->curr_state)
4904 {
4905 case SME_QOS_LINK_UP:
4906 case SME_QOS_REQUESTED:
4907 case SME_QOS_QOS_ON:
4908 sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
4909 break;
4910 case SME_QOS_HANDOFF:
4911 //print error msg
4912 case SME_QOS_CLOSED:
4913 case SME_QOS_INIT:
4914 default:
4915 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
4916 "%s: %d: On session %d AC %d is in wrong state %d",
4917 __FUNCTION__, __LINE__,
4918 sessionId, ac, pACInfo->curr_state);
4919 //ASSERT
4920 VOS_ASSERT(0);
4921 break;
4922 }
4923 }
4924
4925 pSession->ftHandoffInProgress = VOS_TRUE;
4926
4927 // Check if its a 11R roaming before preparing the RIC IEs
4928 if (csrRoamIs11rAssoc(pMac))
4929 {
4930 v_U16_t ricOffset = 0;
4931 v_U32_t ricIELength = 0;
4932 v_U8_t *ricIE;
4933 v_U8_t tspec_mask_status = 0;
4934 v_U8_t tspec_pending_status = 0;
4935
4936 /* Any Block Ack info there, should have been already filled by PE and present in this buffer
4937 and the ric_ies_length should contain the length of the whole RIC IEs. Filling of TSPEC info
4938 should start from this length */
4939 ricIE = pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies;
4940 ricOffset = pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies_length;
4941
4942 /* Now we have to process the currentTspeInfo inside this session and create the RIC IEs */
4943 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
4944 {
4945 volatile v_U8_t tspec_index = 0;
4946
4947 pACInfo = &pSession->ac_info[ac];
4948 tspec_pending_status = pACInfo->tspec_pending;
4949 tspec_mask_status = pACInfo->tspec_mask_status;
4950 vos_mem_zero(pACInfo->ricIdentifier, SME_QOS_TSPEC_INDEX_MAX);
4951 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
4952 FL("AC %d ==> TSPEC status = %d, tspec pending = %d"),
4953 ac, tspec_mask_status, tspec_pending_status);
4954
4955 do
4956 {
4957 if (tspec_mask_status & 0x1)
4958 {
4959 /* If a tspec status is pending, take requested_QoSInfo for RIC request, else use curr_QoSInfo
4960 for the RIC request */
4961 if (tspec_pending_status & 0x1)
4962 {
4963 status = sme_QosCreateTspecRICIE(pMac, &pACInfo->requested_QoSInfo[tspec_index],
4964 ricIE + ricOffset, &ricIELength, &pACInfo->ricIdentifier[tspec_index]);
4965 }
4966 else
4967 {
4968 status = sme_QosCreateTspecRICIE(pMac, &pACInfo->curr_QoSInfo[tspec_index],
4969 ricIE + ricOffset, &ricIELength, &pACInfo->ricIdentifier[tspec_index]);
4970 }
4971 }
4972 ricOffset += ricIELength;
4973 pMac->ft.ftSmeContext.psavedFTPreAuthRsp->ric_ies_length += ricIELength;
4974
4975 tspec_mask_status >>= 1;
4976 tspec_pending_status >>= 1;
4977 tspec_index++;
4978 } while (tspec_mask_status);
4979 }
4980 }
4981 return status;
4982}
4983
4984#endif
4985
4986
4987/*--------------------------------------------------------------------------
4988 \brief sme_QosProcessAddTsFailureRsp() - Function to process the
4989 Addts request failure response came from PE
4990
4991 We will notify HDD only for the requested Flow, other Flows running on the AC
4992 stay intact
4993
4994 \param pMac - Pointer to the global MAC parameter structure.
4995 \param pRsp - Pointer to the addts response structure came from PE.
4996
4997 \return eHalStatus
4998
4999 \sa
5000
5001 --------------------------------------------------------------------------*/
5002eHalStatus sme_QosProcessAddTsFailureRsp(tpAniSirGlobal pMac,
5003 v_U8_t sessionId,
5004 tSirAddtsRspInfo * pRsp)
5005{
5006 sme_QosSessionInfo *pSession;
5007 sme_QosACInfo *pACInfo;
5008 sme_QosEdcaAcType ac;
5009 sme_QosSearchInfo search_key;
5010 v_U8_t tspec_pending;
5011 sme_QosWmmUpType up = (sme_QosWmmUpType)pRsp->tspec.tsinfo.traffic.userPrio;
5012 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5013 "%s: %d: invoked on session %d for UP %d",
5014 __FUNCTION__, __LINE__,
5015 sessionId, up);
5016 ac = sme_QosUpToAc(up);
5017 if(SME_QOS_EDCA_AC_MAX == ac)
5018 {
5019 //err msg
5020 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5021 "%s: %d: invalid AC %d from UP %d",
5022 __FUNCTION__, __LINE__, ac, up);
5023 return eHAL_STATUS_FAILURE;
5024 }
5025 pSession = &sme_QosCb.sessionInfo[sessionId];
5026 pACInfo = &pSession->ac_info[ac];
5027 // is there a TSPEC request pending on this AC?
5028 tspec_pending = pACInfo->tspec_pending;
5029 if(!tspec_pending)
5030 {
5031 //ASSERT
5032 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5033 "%s: %d: On session %d an AddTS is not pending on AC %d",
5034 __FUNCTION__, __LINE__,
5035 sessionId, ac);
5036 VOS_ASSERT(0);
5037 return eHAL_STATUS_FAILURE;
5038 }
5039
5040 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
5041 //set the key type & the key to be searched in the Flow List
5042 search_key.key.ac_type = ac;
5043 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
5044 search_key.sessionId = sessionId;
5045 if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosAddTsFailureFnp)))
5046 {
5047 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5048 "%s: %d: On session %d no match found for ac = %d",
5049 __FUNCTION__, __LINE__,
5050 sessionId, search_key.key.ac_type);
5051 //ASSERT
5052 VOS_ASSERT(0);
5053 return eHAL_STATUS_FAILURE;
5054 }
5055 vos_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1],
5056 sizeof(sme_QosWmmTspecInfo));
5057
5058 if((!pACInfo->num_flows[0])&&
5059 (!pACInfo->num_flows[1]))
5060 {
5061 pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET &
5062 (~pACInfo->tspec_pending);
5063 sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP);
5064 }
5065 else
5066 {
5067 sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON);
5068 }
5069 pACInfo->tspec_pending = 0;
5070
5071 (void)sme_QosProcessBufferedCmd(sessionId);
5072
5073 return eHAL_STATUS_SUCCESS;
5074}
5075
5076/*--------------------------------------------------------------------------
5077 \brief sme_QosUpdateTspecMask() - Utiltity function to update the tspec.
5078 Typical usage while aggregating unidirectional flows into a bi-directional
5079 flow on AC which is running multiple flows
5080
5081 \param sessionId - Session upon which the TSPEC is being updated
5082 \param ac - Enumeration of the various EDCA Access Categories.
5083 \param old_tspec_mask - on which tspec per AC, the update is requested
5084 \param new_tspec_mask - tspec to be set for this AC
5085
5086 \return eHalStatus
5087
5088 \sa
5089
5090 --------------------------------------------------------------------------*/
5091static eHalStatus sme_QosUpdateTspecMask(v_U8_t sessionId,
5092 sme_QosSearchInfo search_key,
5093 v_U8_t new_tspec_mask)
5094{
5095 tListElem *pEntry= NULL, *pNextEntry = NULL;
5096 sme_QosFlowInfoEntry *flow_info = NULL;
5097 sme_QosSessionInfo *pSession;
5098 sme_QosACInfo *pACInfo;
5099
5100 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5101 "%s: %d: invoked on session %d for AC %d TSPEC %d",
5102 __FUNCTION__, __LINE__,
5103 sessionId, search_key.key.ac_type, new_tspec_mask);
5104
5105 pSession = &sme_QosCb.sessionInfo[sessionId];
5106
5107 if (search_key.key.ac_type < SME_QOS_EDCA_AC_MAX)
5108 {
5109 pACInfo = &pSession->ac_info[search_key.key.ac_type];
5110 }
5111 else
5112 {
5113 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5114 "%s: %d: Exceeded the array bounds of pSession->ac_info",
5115 __FUNCTION__, __LINE__);
5116 VOS_ASSERT (0);
5117 return eHAL_STATUS_FAILURE;
5118 }
5119
5120 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
5121 if(!pEntry)
5122 {
5123 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5124 "%s: %d: Flow List empty, nothing to update",
5125 __FUNCTION__, __LINE__);
5126 return eHAL_STATUS_FAILURE;
5127 }
5128
5129 while( pEntry )
5130 {
5131 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
5132 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
5133
5134 if(search_key.sessionId == flow_info->sessionId)
5135 {
5136 if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_4)
5137 {
5138 if((search_key.key.ac_type == flow_info->ac_type) &&
5139 (search_key.direction == flow_info->QoSInfo.ts_info.direction))
5140 {
5141 //msg
5142 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5143 "%s: %d: Flow %d matches",
5144 __FUNCTION__, __LINE__,
5145 flow_info->QosFlowID);
5146 pACInfo->num_flows[flow_info->tspec_mask - 1]--;
5147 pACInfo->num_flows[new_tspec_mask - 1]++;
5148 flow_info->tspec_mask = new_tspec_mask;
5149 }
5150 }
5151 else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_5)
5152 {
5153 if((search_key.key.ac_type == flow_info->ac_type) &&
5154 (search_key.tspec_mask == flow_info->tspec_mask))
5155 {
5156 //msg
5157 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5158 "%s: %d: Flow %d matches",
5159 __FUNCTION__, __LINE__,
5160 flow_info->QosFlowID);
5161 pACInfo->num_flows[flow_info->tspec_mask - 1]--;
5162 pACInfo->num_flows[new_tspec_mask - 1]++;
5163 flow_info->tspec_mask = new_tspec_mask;
5164 }
5165 }
5166 }
5167
5168 pEntry = pNextEntry;
5169 }
5170
5171 return eHAL_STATUS_SUCCESS;
5172}
5173/*--------------------------------------------------------------------------
5174 \brief sme_QosProcessAddTsSuccessRsp() - Function to process the
5175 Addts request success response came from PE
5176
5177 We will notify HDD with addts success for the requested Flow, & for other
5178 Flows running on the AC we will send an addts modify status
5179
5180
5181 \param pMac - Pointer to the global MAC parameter structure.
5182 \param pRsp - Pointer to the addts response structure came from PE.
5183
5184 \return eHalStatus
5185
5186 \sa
5187
5188 --------------------------------------------------------------------------*/
5189eHalStatus sme_QosProcessAddTsSuccessRsp(tpAniSirGlobal pMac,
5190 v_U8_t sessionId,
5191 tSirAddtsRspInfo * pRsp)
5192{
5193 sme_QosSessionInfo *pSession;
5194 sme_QosACInfo *pACInfo;
5195 sme_QosEdcaAcType ac, ac_index;
5196 sme_QosSearchInfo search_key;
5197 sme_QosSearchInfo search_key1;
5198 v_U8_t tspec_pending;
5199 tListElem *pEntry= NULL;
5200 sme_QosFlowInfoEntry *flow_info = NULL;
5201 sme_QosWmmUpType up = (sme_QosWmmUpType)pRsp->tspec.tsinfo.traffic.userPrio;
5202#ifdef FEATURE_WLAN_DIAG_SUPPORT
5203 WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type);
5204 vos_log_qos_tspec_pkt_type *log_ptr = NULL;
5205#endif //FEATURE_WLAN_DIAG_SUPPORT
5206 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5207 "%s: %d: invoked on session %d for UP %d",
5208 __FUNCTION__, __LINE__,
5209 sessionId, up);
5210 pSession = &sme_QosCb.sessionInfo[sessionId];
5211 ac = sme_QosUpToAc(up);
5212 if(SME_QOS_EDCA_AC_MAX == ac)
5213 {
5214 //err msg
5215 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5216 "%s: %d: invalid AC %d from UP %d",
5217 __FUNCTION__, __LINE__, ac, up);
5218 return eHAL_STATUS_FAILURE;
5219 }
5220 pACInfo = &pSession->ac_info[ac];
5221 // is there a TSPEC request pending on this AC?
5222 tspec_pending = pACInfo->tspec_pending;
5223 if(!tspec_pending)
5224 {
5225 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5226 "%s: %d: On session %d an AddTS is not pending on AC %d",
5227 __FUNCTION__, __LINE__,
5228 sessionId, ac);
5229 //ASSERT
5230 VOS_ASSERT(0);
5231 return eHAL_STATUS_FAILURE;
5232 }
5233 //App is looking for APSD or the App which was looking for APSD has been
5234 //released, so STA re-negotiated with AP
5235 if(pACInfo->requested_QoSInfo[tspec_pending - 1].ts_info.psb)
5236 {
5237 //update the session's apsd mask
5238 pSession->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
5239 }
5240 else
5241 {
5242 if(((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) > 0) &&
5243 ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) <=
5244 SME_QOS_TSPEC_INDEX_MAX))
5245 {
5246 if(!pACInfo->requested_QoSInfo
5247 [(SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) - 1].ts_info.psb)
5248 {
5249 //update the session's apsd mask
5250 pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
5251 }
5252 }
5253 else
5254 {
5255 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5256 "%s: %d: Exceeded the array bounds of pACInfo->requested_QosInfo",
5257 __FUNCTION__, __LINE__);
5258 VOS_ASSERT (0);
5259 return eHAL_STATUS_FAILURE;
5260 }
5261 }
5262 pACInfo->curr_QoSInfo[tspec_pending - 1] =
5263 pACInfo->requested_QoSInfo[tspec_pending - 1];
5264 /* Check if the current flow is for bi-directional. If so, update the number of flows
5265 * to reflect that all flows are aggregated into tspec index 0. */
5266 if((pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1].ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) &&
5267 (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0))
5268 {
5269 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
5270 /* update tspec_mask for all the flows having SME_QOS_TSPEC_MASK_BIT_2_SET to SME_QOS_TSPEC_MASK_BIT_1_SET */
5271 search_key.key.ac_type = ac;
5272 search_key.index = SME_QOS_SEARCH_KEY_INDEX_5;
5273 search_key.sessionId = sessionId;
5274 search_key.tspec_mask = SME_QOS_TSPEC_MASK_BIT_2_SET;
5275 sme_QosUpdateTspecMask(sessionId, search_key, SME_QOS_TSPEC_MASK_BIT_1_SET);
5276 }
5277
5278 vos_mem_zero(&search_key1, sizeof(sme_QosSearchInfo));
5279 //set the horenewal field in control block if needed
5280 search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3;
5281 search_key1.key.reason = SME_QOS_REASON_SETUP;
5282 search_key1.sessionId = sessionId;
5283 for(ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX; ac_index++)
5284 {
5285 pEntry = sme_QosFindInFlowList(search_key1);
5286 if(pEntry)
5287 {
5288 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
5289 if(flow_info->ac_type == ac)
5290 {
5291 pACInfo->hoRenewal = flow_info->hoRenewal;
5292 break;
5293 }
5294 }
5295 }
5296 vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
5297 //set the key type & the key to be searched in the Flow List
5298 search_key.key.ac_type = ac;
5299 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
5300 search_key.sessionId = sessionId;
5301 //notify HDD the success for the requested flow
5302 //notify all the other flows running on the AC that QoS got modified
5303 if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosAddTsSuccessFnp)))
5304 {
5305 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5306 "%s: %d: On session %d no match found for ac %d",
5307 __FUNCTION__, __LINE__,
5308 sessionId, search_key.key.ac_type);
5309 //ASSERT
5310 VOS_ASSERT(0);
5311 return eHAL_STATUS_FAILURE;
5312 }
5313 pACInfo->hoRenewal = VOS_FALSE;
5314 vos_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1],
5315 sizeof(sme_QosWmmTspecInfo));
5316 //event: EVENT_WLAN_QOS
5317#ifdef FEATURE_WLAN_DIAG_SUPPORT
5318 qos.eventId = SME_QOS_DIAG_ADDTS_RSP;
5319 qos.reasonCode = SME_QOS_DIAG_ADDTS_ADMISSION_ACCEPTED;
5320 WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
5321 WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_qos_tspec_pkt_type, LOG_WLAN_QOS_TSPEC_C);
5322 if(log_ptr)
5323 {
5324 log_ptr->delay_bound = pACInfo->curr_QoSInfo[tspec_pending - 1].delay_bound;
5325 log_ptr->inactivity_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].inactivity_interval;
5326 log_ptr->max_burst_size = pACInfo->curr_QoSInfo[tspec_pending - 1].max_burst_size;
5327 log_ptr->max_service_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].max_service_interval;
5328 log_ptr->maximum_msdu_size = pACInfo->curr_QoSInfo[tspec_pending - 1].maximum_msdu_size;
5329 log_ptr->mean_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].mean_data_rate;
5330 log_ptr->medium_time = pACInfo->curr_QoSInfo[tspec_pending - 1].medium_time;
5331 log_ptr->min_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].min_data_rate;
5332 log_ptr->min_phy_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].min_phy_rate;
5333 log_ptr->min_service_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].min_service_interval;
5334 log_ptr->nominal_msdu_size = pACInfo->curr_QoSInfo[tspec_pending - 1].nominal_msdu_size;
5335 log_ptr->peak_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate;
5336 log_ptr->surplus_bw_allowance = pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance;
5337 log_ptr->suspension_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance;
5338 log_ptr->suspension_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].suspension_interval;
5339 log_ptr->svc_start_time = pACInfo->curr_QoSInfo[tspec_pending - 1].svc_start_time;
5340 log_ptr->tsinfo[0] = pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.direction << 5 |
5341 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.tid << 1;
5342 log_ptr->tsinfo[1] = pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.up << 11 |
5343 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.psb << 10;
5344 log_ptr->tsinfo[2] = 0;
5345 }
5346 WLAN_VOS_DIAG_LOG_REPORT(log_ptr);
5347#endif //FEATURE_WLAN_DIAG_SUPPORT
5348#ifdef FEATURE_WLAN_CCX
5349 if (ac == SME_QOS_EDCA_AC_VO)
5350 {
5351 // Indicate to neighbor roam logic of the new required VO
5352 // ac bandwidth requirement.
5353 csrNeighborRoamIndicateVoiceBW( pMac, pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate, TRUE );
5354 }
5355#endif
5356 pACInfo->tspec_pending = 0;
5357
5358 sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON);
5359
5360
5361 (void)sme_QosProcessBufferedCmd(sessionId);
5362 return eHAL_STATUS_SUCCESS;
5363
5364}
5365/*--------------------------------------------------------------------------
5366 \brief sme_QosAggregateParams() - Utiltity function to increament the TSPEC
5367 params per AC. Typical usage while using flow aggregation or deletion of flows
5368
5369 \param pInput_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains the
5370 WMM TSPEC related info with which pCurrent_Tspec_Info will be updated
5371 \param pCurrent_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains
5372 current the WMM TSPEC related info
5373
5374 \return eHalStatus
5375
5376 \sa
5377
5378 --------------------------------------------------------------------------*/
5379eHalStatus sme_QosAggregateParams(
5380 sme_QosWmmTspecInfo * pInput_Tspec_Info,
5381 sme_QosWmmTspecInfo * pCurrent_Tspec_Info,
5382 sme_QosWmmTspecInfo * pUpdated_Tspec_Info)
5383{
5384 sme_QosWmmTspecInfo TspecInfo;
5385 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5386 "%s: %d: invoked",
5387 __FUNCTION__, __LINE__);
5388 if(!pInput_Tspec_Info)
5389 {
5390 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5391 "%s: %d: input is NULL, nothing to aggregate",
5392 __FUNCTION__, __LINE__);
5393 return eHAL_STATUS_FAILURE;
5394 }
5395 if(!pCurrent_Tspec_Info)
5396 {
5397 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5398 "%s: %d: Current is NULL, can't aggregate",
5399 __FUNCTION__, __LINE__);
5400 return eHAL_STATUS_FAILURE;
5401 }
5402 vos_mem_copy(&TspecInfo, pCurrent_Tspec_Info,
5403 sizeof(sme_QosWmmTspecInfo));
5404 /*-------------------------------------------------------------------------
5405 APSD preference is only meaningful if service interval was set by app
5406 -------------------------------------------------------------------------*/
5407 if(pCurrent_Tspec_Info->min_service_interval && pInput_Tspec_Info->min_service_interval)
5408 {
5409 TspecInfo.min_service_interval = VOS_MIN(
5410 pCurrent_Tspec_Info->min_service_interval,
5411 pInput_Tspec_Info->min_service_interval);
5412 }
5413 else if(pInput_Tspec_Info->min_service_interval)
5414 {
5415 TspecInfo.min_service_interval = pInput_Tspec_Info->min_service_interval;
5416 }
5417 if(pCurrent_Tspec_Info->max_service_interval)
5418 {
5419 TspecInfo.max_service_interval = VOS_MIN(
5420 pCurrent_Tspec_Info->max_service_interval,
5421 pInput_Tspec_Info->max_service_interval);
5422 }
5423 else
5424 {
5425 TspecInfo.max_service_interval = pInput_Tspec_Info->max_service_interval;
5426 }
5427 /*-------------------------------------------------------------------------
5428 If directions don't match, it must necessarily be both uplink and
5429 downlink
5430 -------------------------------------------------------------------------*/
5431 if(pCurrent_Tspec_Info->ts_info.direction !=
5432 pInput_Tspec_Info->ts_info.direction)
5433 {
5434 TspecInfo.ts_info.direction = SME_QOS_WMM_TS_DIR_BOTH;
5435 }
5436 /*-------------------------------------------------------------------------
5437 Max MSDU size : these sizes are `maxed'
5438 -------------------------------------------------------------------------*/
5439 TspecInfo.maximum_msdu_size = VOS_MAX(pCurrent_Tspec_Info->maximum_msdu_size,
5440 pInput_Tspec_Info->maximum_msdu_size);
5441
5442 /*-------------------------------------------------------------------------
5443 Inactivity interval : these sizes are `maxed'
5444 -------------------------------------------------------------------------*/
5445 TspecInfo.inactivity_interval = VOS_MAX(pCurrent_Tspec_Info->inactivity_interval,
5446 pInput_Tspec_Info->inactivity_interval);
5447
5448 /*-------------------------------------------------------------------------
5449 Delay bounds: min of all values
5450 Check on 0: if 0, it means initial value since delay can never be 0!!
5451 -------------------------------------------------------------------------*/
5452 if(pCurrent_Tspec_Info->delay_bound)
5453 {
5454 TspecInfo.delay_bound = VOS_MIN(pCurrent_Tspec_Info->delay_bound,
5455 pInput_Tspec_Info->delay_bound);
5456 }
5457 else
5458 {
5459 TspecInfo.delay_bound = pInput_Tspec_Info->delay_bound;
5460 }
5461 TspecInfo.max_burst_size = VOS_MAX(pCurrent_Tspec_Info->max_burst_size,
5462 pInput_Tspec_Info->max_burst_size);
5463
5464 /*-------------------------------------------------------------------------
5465 Nominal MSDU size also has a fixed bit that needs to be `handled' before
5466 aggregation
5467 This can be handled only if previous size is the same as new or both have
5468 the fixed bit set
5469 These sizes are not added: but `maxed'
5470 -------------------------------------------------------------------------*/
5471 TspecInfo.nominal_msdu_size = VOS_MAX(
5472 pCurrent_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB,
5473 pInput_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB);
5474
5475 if( ((pCurrent_Tspec_Info->nominal_msdu_size == 0) ||
5476 (pCurrent_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB)) &&
5477 ((pInput_Tspec_Info->nominal_msdu_size == 0) ||
5478 (pInput_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB)))
5479 {
5480 TspecInfo.nominal_msdu_size |= SME_QOS_16BIT_MSB;
5481 }
5482
5483 /*-------------------------------------------------------------------------
5484 Data rates:
5485 Add up the rates for aggregation
5486 -------------------------------------------------------------------------*/
5487 SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.peak_data_rate,
5488 pInput_Tspec_Info->peak_data_rate );
5489 SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.min_data_rate,
5490 pInput_Tspec_Info->min_data_rate );
5491 /* mean data rate = peak data rate: aggregate to be flexible on apps */
5492 SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.mean_data_rate,
5493 pInput_Tspec_Info->mean_data_rate );
5494
5495 /*-------------------------------------------------------------------------
5496 Suspension interval : this is set to the inactivity interval since per
5497 spec it is less than or equal to inactivity interval
5498 This is not provided by app since we currently don't support the HCCA
5499 mode of operation
5500 Currently set it to 0 to avoid confusion: Cisco CCX needs ~0; spec
5501 requires inactivity interval to be > suspension interval: this could
5502 be tricky!
5503 -------------------------------------------------------------------------*/
5504 TspecInfo.suspension_interval = 0;
5505 /*-------------------------------------------------------------------------
5506 Remaining parameters do not come from app as they are very WLAN
5507 air interface specific
5508 Set meaningful values here
5509 -------------------------------------------------------------------------*/
5510 TspecInfo.medium_time = 0; /* per WMM spec */
5511 TspecInfo.min_phy_rate = SME_QOS_MIN_PHY_RATE;
5512 TspecInfo.svc_start_time = 0; /* arbitrary */
5513 TspecInfo.surplus_bw_allowance += pInput_Tspec_Info->surplus_bw_allowance;
5514 if(TspecInfo.surplus_bw_allowance > SME_QOS_SURPLUS_BW_ALLOWANCE)
5515 {
5516 TspecInfo.surplus_bw_allowance = SME_QOS_SURPLUS_BW_ALLOWANCE;
5517 }
5518 /* Set ack_policy to block ack even if one stream requests block ack policy */
5519 if((pInput_Tspec_Info->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK) ||
5520 (pCurrent_Tspec_Info->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK))
5521 {
5522 TspecInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
5523 }
5524
5525 if(pInput_Tspec_Info->ts_info.burst_size_defn || pCurrent_Tspec_Info->ts_info.burst_size_defn )
5526 {
5527 TspecInfo.ts_info.burst_size_defn = 1;
5528 }
5529 if(pUpdated_Tspec_Info)
5530 {
5531 vos_mem_copy(pUpdated_Tspec_Info, &TspecInfo,
5532 sizeof(sme_QosWmmTspecInfo));
5533 }
5534 else
5535 {
5536 vos_mem_copy(pCurrent_Tspec_Info, &TspecInfo,
5537 sizeof(sme_QosWmmTspecInfo));
5538 }
5539 return eHAL_STATUS_SUCCESS;
5540}
5541/*--------------------------------------------------------------------------
5542 \brief sme_QosUpdateParams() - Utiltity function to update the TSPEC
5543 params per AC. Typical usage while deleting flows on AC which is running
5544 multiple flows
5545
5546 \param sessionId - Session upon which the TSPEC is being updated
5547 \param ac - Enumeration of the various EDCA Access Categories.
5548 \param tspec_mask - on which tspec per AC, the update is requested
5549
5550 \return eHalStatus
5551
5552 \sa
5553
5554 --------------------------------------------------------------------------*/
5555static eHalStatus sme_QosUpdateParams(v_U8_t sessionId,
5556 sme_QosEdcaAcType ac,
5557 v_U8_t tspec_mask,
5558 sme_QosWmmTspecInfo * pTspec_Info)
5559{
5560 tListElem *pEntry= NULL, *pNextEntry = NULL;
5561 sme_QosSessionInfo *pSession;
5562 sme_QosACInfo *pACInfo;
5563 sme_QosFlowInfoEntry *flow_info = NULL;
5564 sme_QosWmmTspecInfo Tspec_Info;
5565 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5566 "%s: %d: invoked on session %d for AC %d TSPEC %d",
5567 __FUNCTION__, __LINE__,
5568 sessionId, ac, tspec_mask);
5569 if(!pTspec_Info)
5570 {
5571 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5572 "%s: %d: output is NULL, can't aggregate",
5573 __FUNCTION__, __LINE__);
5574 return eHAL_STATUS_FAILURE;
5575 }
5576 vos_mem_zero(&Tspec_Info, sizeof(sme_QosWmmTspecInfo));
5577 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
5578 if(!pEntry)
5579 {
5580 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5581 "%s: %d: Flow List empty, nothing to update",
5582 __FUNCTION__, __LINE__);
5583 return eHAL_STATUS_FAILURE;
5584 }
5585 pSession = &sme_QosCb.sessionInfo[sessionId];
5586 pACInfo = &pSession->ac_info[ac];
5587 //init the TS info field
5588 Tspec_Info.ts_info.up = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.up;
5589 Tspec_Info.ts_info.psb = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.psb;
5590 Tspec_Info.ts_info.tid = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.tid;
5591 while( pEntry )
5592 {
5593 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
5594 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
5595 if((sessionId == flow_info->sessionId) &&
5596 (ac == flow_info->ac_type) &&
5597 (tspec_mask == flow_info->tspec_mask))
5598 {
5599 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5600 "%s: %d: Flow %d matches",
5601 __FUNCTION__, __LINE__,
5602 flow_info->QosFlowID);
5603
5604 if((SME_QOS_REASON_RELEASE == flow_info->reason ) ||
5605 (SME_QOS_REASON_MODIFY == flow_info->reason))
5606 {
5607 //msg
5608 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5609 "%s: %d: Skipping Flow %d as it is marked "
5610 "for release/modify",
5611 __FUNCTION__, __LINE__,
5612 flow_info->QosFlowID);
5613 }
5614 else if(!HAL_STATUS_SUCCESS(sme_QosAggregateParams(&flow_info->QoSInfo,
5615 &Tspec_Info,
5616 NULL)))
5617 {
5618 //err msg
5619 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5620 "%s: %d: sme_QosAggregateParams() failed",
5621 __FUNCTION__, __LINE__);
5622 }
5623 }
5624 pEntry = pNextEntry;
5625 }
5626 // return the aggregate
5627 *pTspec_Info = Tspec_Info;
5628 return eHAL_STATUS_SUCCESS;
5629}
5630/*--------------------------------------------------------------------------
5631 \brief sme_QosAcToUp() - Utiltity function to map an AC to UP
5632 Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs
5633 Mapping is done for consistency
5634 \param ac - Enumeration of the various EDCA Access Categories.
5635 \return an User Priority
5636
5637 \sa
5638
5639 --------------------------------------------------------------------------*/
5640sme_QosWmmUpType sme_QosAcToUp(sme_QosEdcaAcType ac)
5641{
5642 sme_QosWmmUpType up = SME_QOS_WMM_UP_MAX;
5643 if(ac >= 0 && ac < SME_QOS_EDCA_AC_MAX)
5644 {
5645 up = sme_QosACtoUPMap[ac];
5646 }
5647 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
5648 "%s: %d: ac = %d up = %d returned",
5649 __FUNCTION__, __LINE__, ac, up);
5650 return up;
5651}
5652/*--------------------------------------------------------------------------
5653 \brief sme_QosUpToAc() - Utiltity function to map an UP to AC
5654 \param up - Enumeration of the various User priorities (UP).
5655 \return an Access Category
5656
5657 \sa
5658
5659 --------------------------------------------------------------------------*/
5660sme_QosEdcaAcType sme_QosUpToAc(sme_QosWmmUpType up)
5661{
5662 sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_MAX;
5663 if(up >= 0 && up < SME_QOS_WMM_UP_MAX)
5664 {
5665 ac = sme_QosUPtoACMap[up];
5666 }
5667 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
5668 "%s: %d: up = %d ac = %d returned",
5669 __FUNCTION__, __LINE__, up, ac);
5670 return ac;
5671}
5672/*--------------------------------------------------------------------------
5673 \brief sme_QosStateTransition() - The state transition function per AC. We
5674 save the previous state also.
5675 \param sessionId - Session upon which the state machine is running
5676 \param ac - Enumeration of the various EDCA Access Categories.
5677 \param new_state - The state FSM is moving to.
5678
5679 \return None
5680
5681 \sa
5682
5683 --------------------------------------------------------------------------*/
5684static void sme_QosStateTransition(v_U8_t sessionId,
5685 sme_QosEdcaAcType ac,
5686 sme_QosStates new_state)
5687{
5688 sme_QosSessionInfo *pSession;
5689 sme_QosACInfo *pACInfo;
5690 pSession = &sme_QosCb.sessionInfo[sessionId];
5691 pACInfo = &pSession->ac_info[ac];
5692 pACInfo->prev_state = pACInfo->curr_state;
5693 pACInfo->curr_state = new_state;
5694 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5695 "%s: %d: On session %d new state=%d, old state=%d, for AC=%d",
5696 __FUNCTION__, __LINE__,
5697 sessionId, pACInfo->curr_state, pACInfo->prev_state, ac );
5698}
5699/*--------------------------------------------------------------------------
5700 \brief sme_QosFindInFlowList() - Utility function to find an flow entry from
5701 the flow_list.
5702 \param search_key - We can either use the flowID or the ac type to find the
5703 entry in the flow list.
5704 A bitmap in sme_QosSearchInfo tells which key to use. Starting from LSB,
5705 bit 0 - Flow ID
5706 bit 1 - AC type
5707 \return the pointer to the entry in the link list
5708
5709 \sa
5710
5711 --------------------------------------------------------------------------*/
5712tListElem *sme_QosFindInFlowList(sme_QosSearchInfo search_key)
5713{
5714 tListElem *pEntry= NULL, *pNextEntry = NULL;
5715 sme_QosFlowInfoEntry *flow_info = NULL;
5716 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
5717 if(!pEntry)
5718 {
5719 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5720 "%s: %d: Flow List empty, can't search",
5721 __FUNCTION__, __LINE__);
5722 return NULL;
5723 }
5724 while( pEntry )
5725 {
5726 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
5727 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
5728 if((search_key.sessionId == flow_info->sessionId) ||
5729 (search_key.sessionId == SME_QOS_SEARCH_SESSION_ID_ANY))
5730 {
5731 if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_1)
5732 {
5733 if(search_key.key.QosFlowID == flow_info->QosFlowID)
5734 {
5735 //msg
5736 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5737 "%s: %d: match found on flowID, ending search",
5738 __FUNCTION__, __LINE__);
5739 break;
5740 }
5741 }
5742 else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_2)
5743 {
5744 if(search_key.key.ac_type == flow_info->ac_type)
5745 {
5746 //msg
5747 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5748 "%s: %d: match found on ac, ending search",
5749 __FUNCTION__, __LINE__);
5750 break;
5751 }
5752 }
5753 else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_3)
5754 {
5755 if(search_key.key.reason == flow_info->reason)
5756 {
5757 //msg
5758 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5759 "%s: %d: match found on reason, ending search",
5760 __FUNCTION__, __LINE__);
5761 break;
5762 }
5763 }
5764 else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_4)
5765 {
5766 if((search_key.key.ac_type == flow_info->ac_type) &&
5767 (search_key.direction == flow_info->QoSInfo.ts_info.direction))
5768 {
5769 //msg
5770 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5771 "%s: %d: match found on reason, ending search",
5772 __FUNCTION__, __LINE__);
5773
5774 break;
5775 }
5776 }
5777 }
5778 pEntry = pNextEntry;
5779 }
5780 return pEntry;
5781}
5782/*--------------------------------------------------------------------------
5783 \brief sme_QosFindAllInFlowList() - Utility function to find an flow entry
5784 from the flow_list & act on it.
5785 \param search_key - We can either use the flowID or the ac type to find the
5786 entry in the flow list.
5787 A bitmap in sme_QosSearchInfo tells which key to use. Starting from LSB,
5788 bit 0 - Flow ID
5789 bit 1 - AC type
5790 \param fnp - function pointer specifying the action type for the entry found
5791 \return eHalStatus
5792
5793 \sa
5794
5795 --------------------------------------------------------------------------*/
5796eHalStatus sme_QosFindAllInFlowList(tpAniSirGlobal pMac,
5797 sme_QosSearchInfo search_key,
5798 sme_QosProcessSearchEntry fnp)
5799{
5800 tListElem *pEntry= NULL, *pNextEntry = NULL;
5801 sme_QosSessionInfo *pSession;
5802 sme_QosFlowInfoEntry *flow_info = NULL;
5803 eHalStatus status = eHAL_STATUS_FAILURE;
5804 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
5805 if(!pEntry)
5806 {
5807 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5808 "%s: %d: Flow List empty, can't search",
5809 __FUNCTION__, __LINE__);
5810 return eHAL_STATUS_FAILURE;
5811 }
5812 while( pEntry )
5813 {
5814 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
5815 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
5816 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
5817 if((search_key.sessionId == flow_info->sessionId) ||
5818 (search_key.sessionId == SME_QOS_SEARCH_SESSION_ID_ANY))
5819 {
5820 if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_1)
5821 {
5822 if(search_key.key.QosFlowID == flow_info->QosFlowID)
5823 {
5824 //msg
5825 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5826 "%s: %d: match found on flowID, ending search",
5827 __FUNCTION__, __LINE__);
5828 status = fnp(pMac, pEntry);
5829 if(eHAL_STATUS_FAILURE == status)
5830 {
5831 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5832 "%s: %d: Failed to process entry",
5833 __FUNCTION__, __LINE__);
5834 break;
5835 }
5836 }
5837 }
5838 else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_2)
5839 {
5840 if(search_key.key.ac_type == flow_info->ac_type)
5841 {
5842 //msg
5843 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5844 "%s: %d: match found on ac, ending search",
5845 __FUNCTION__, __LINE__);
5846 flow_info->hoRenewal = pSession->ac_info[flow_info->ac_type].hoRenewal;
5847 status = fnp(pMac, pEntry);
5848 if(eHAL_STATUS_FAILURE == status)
5849 {
5850 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5851 "%s: %d: Failed to process entry",
5852 __FUNCTION__, __LINE__);
5853 break;
5854 }
5855 }
5856 }
5857 }
5858 pEntry = pNextEntry;
5859 }
5860 return status;
5861}
5862/*--------------------------------------------------------------------------
5863 \brief sme_QosIsACM() - Utility function to check if a particular AC
5864 mandates Admission Control.
5865 \param ac - Enumeration of the various EDCA Access Categories.
5866
5867 \return VOS_TRUE if the AC mandates Admission Control
5868
5869 \sa
5870
5871 --------------------------------------------------------------------------*/
5872v_BOOL_t sme_QosIsACM(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
5873 sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes)
5874{
5875 v_BOOL_t ret_val = VOS_FALSE;
5876 tDot11fBeaconIEs *pIesLocal;
5877 if(!pSirBssDesc)
5878 {
5879 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5880 "%s: %d: pSirBssDesc is NULL",
5881 __FUNCTION__, __LINE__);
5882 return VOS_FALSE;
5883 }
5884
5885 if (NULL != pIes)
5886 {
5887 /* IEs were provided so use them locally */
5888 pIesLocal = pIes;
5889 }
5890 else
5891 {
5892 /* IEs were not provided so parse them ourselves */
5893 if (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal)))
5894 {
5895 //err msg
5896 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5897 "%s: %d: csrGetParsedBssDescriptionIEs() failed",
5898 __FUNCTION__, __LINE__);
5899 return VOS_FALSE;
5900 }
5901
5902 /* if success then pIesLocal was allocated */
5903 }
5904
5905 if(CSR_IS_QOS_BSS(pIesLocal))
5906 {
5907 switch(ac)
5908 {
5909 case SME_QOS_EDCA_AC_BE:
5910 if(pIesLocal->WMMParams.acbe_acm) ret_val = VOS_TRUE;
5911 break;
5912 case SME_QOS_EDCA_AC_BK:
5913 if(pIesLocal->WMMParams.acbk_acm) ret_val = VOS_TRUE;
5914 break;
5915 case SME_QOS_EDCA_AC_VI:
5916 if(pIesLocal->WMMParams.acvi_acm) ret_val = VOS_TRUE;
5917 break;
5918 case SME_QOS_EDCA_AC_VO:
5919 if(pIesLocal->WMMParams.acvo_acm) ret_val = VOS_TRUE;
5920 break;
5921 default:
5922 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5923 "%s: %d: unknown AC = %d",
5924 __FUNCTION__, __LINE__, ac);
5925 //Assert
5926 VOS_ASSERT(0);
5927 break;
5928 }
5929 }//IS_QOS_BSS
5930 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
5931 "%s: %d: ACM = %d for AC = %d",
5932 __FUNCTION__, __LINE__, ret_val, ac );
5933 if (NULL == pIes)
5934 {
5935 /* IEs were allocated locally so free them */
5936 vos_mem_free(pIesLocal);
5937 }
5938 return ret_val;
5939}
5940/*--------------------------------------------------------------------------
5941 \brief sme_QosBufferExistingFlows() - Utility function to buffer the existing
5942 flows in flow_list, so that we can renew them after handoff is done.
5943
5944 \return eHalStatus
5945
5946 \sa
5947
5948 --------------------------------------------------------------------------*/
5949static eHalStatus sme_QosBufferExistingFlows(tpAniSirGlobal pMac,
5950 v_U8_t sessionId)
5951{
5952 tListElem *pEntry= NULL, *pNextEntry = NULL;
5953 sme_QosSessionInfo *pSession;
5954 sme_QosFlowInfoEntry *flow_info = NULL;
5955 sme_QosCmdInfo cmd;
5956 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
5957 if(!pEntry)
5958 {
5959 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5960 "%s: %d: Flow List empty, nothing to buffer",
5961 __FUNCTION__, __LINE__);
5962 return eHAL_STATUS_FAILURE;
5963 }
5964 while( pEntry )
5965 {
5966 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
5967 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
5968 if (flow_info->sessionId == sessionId)
5969 {
5970 if((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason )||
5971 (SME_QOS_REASON_SETUP == flow_info->reason ))
5972 {
5973 cmd.command = SME_QOS_SETUP_REQ;
5974 cmd.pMac = pMac;
5975 cmd.sessionId = sessionId;
5976 cmd.u.setupCmdInfo.HDDcontext = flow_info->HDDcontext;
5977 cmd.u.setupCmdInfo.QoSInfo = flow_info->QoSInfo;
5978 cmd.u.setupCmdInfo.QoSCallback = flow_info->QoSCallback;
5979 cmd.u.setupCmdInfo.UPType = SME_QOS_WMM_UP_MAX;//shouldn't be needed
5980 cmd.u.setupCmdInfo.QosFlowID = flow_info->QosFlowID;
5981 if(SME_QOS_REASON_SETUP == flow_info->reason )
5982 {
5983 cmd.u.setupCmdInfo.hoRenewal = VOS_FALSE;
5984 }
5985 else
5986 {
5987 cmd.u.setupCmdInfo.hoRenewal = VOS_TRUE;//TODO: might need this for modify
5988 }
5989 if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE)))
5990 {
5991 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
5992 "%s: %d: couldn't buffer the setup request for "
5993 "flow %d in handoff state",
5994 __FUNCTION__, __LINE__,
5995 flow_info->QosFlowID);
5996 }
5997 else
5998 {
5999 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6000 "%s: %d: buffered a setup request for "
6001 "flow %d in handoff state",
6002 __FUNCTION__, __LINE__,
6003 flow_info->QosFlowID);
6004 }
6005 }
6006 else if(SME_QOS_REASON_RELEASE == flow_info->reason )
6007 {
6008 cmd.command = SME_QOS_RELEASE_REQ;
6009 cmd.pMac = pMac;
6010 cmd.sessionId = sessionId;
6011 cmd.u.releaseCmdInfo.QosFlowID = flow_info->QosFlowID;
6012 if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE)))
6013 {
6014 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6015 "%s: %d: couldn't buffer the release request for "
6016 "flow %d in handoff state",
6017 __FUNCTION__, __LINE__,
6018 flow_info->QosFlowID);
6019 }
6020 else
6021 {
6022 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6023 "%s: %d: buffered a release request for "
6024 "flow %d in handoff state",
6025 __FUNCTION__, __LINE__,
6026 flow_info->QosFlowID);
6027 }
6028 }
6029 else if(SME_QOS_REASON_MODIFY_PENDING == flow_info->reason)
6030 {
6031 cmd.command = SME_QOS_MODIFY_REQ;
6032 cmd.pMac = pMac;
6033 cmd.sessionId = sessionId;
6034 cmd.u.modifyCmdInfo.QosFlowID = flow_info->QosFlowID;
6035 cmd.u.modifyCmdInfo.QoSInfo = flow_info->QoSInfo;
6036 if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE)))
6037 {
6038 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6039 "%s: %d: couldn't buffer the modify request for "
6040 "flow %d in handoff state",
6041 __FUNCTION__, __LINE__,
6042 flow_info->QosFlowID);
6043 }
6044 else
6045 {
6046 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6047 "%s: %d: buffered a modify request for "
6048 "flow %d in handoff state",
6049 __FUNCTION__, __LINE__,
6050 flow_info->QosFlowID);
6051 }
6052 }
6053 //delete the entry from Flow List
6054 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6055 "%s: %d: Deleting original entry at %p with flowID %d",
6056 __FUNCTION__, __LINE__,
6057 flow_info, flow_info->QosFlowID);
6058 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
6059 vos_mem_free(flow_info);
6060 }
6061 pEntry = pNextEntry;
6062 }
6063 pSession = &sme_QosCb.sessionInfo[sessionId];
6064 pSession->uapsdAlreadyRequested = VOS_FALSE;
6065 return eHAL_STATUS_SUCCESS;
6066}
6067/*--------------------------------------------------------------------------
6068 \brief sme_QosDeleteExistingFlows() - Utility function to Delete the existing
6069 flows in flow_list, if we lost connectivity.
6070
6071 \return eHalStatus
6072
6073 \sa
6074
6075 --------------------------------------------------------------------------*/
6076static eHalStatus sme_QosDeleteExistingFlows(tpAniSirGlobal pMac,
6077 v_U8_t sessionId)
6078{
6079 tListElem *pEntry= NULL, *pNextEntry = NULL;
6080 sme_QosFlowInfoEntry *flow_info = NULL;
6081 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_TRUE );
6082 if(!pEntry)
6083 {
6084 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6085 "%s: %d: Flow List empty, nothing to delete",
6086 __FUNCTION__, __LINE__);
6087 return eHAL_STATUS_FAILURE;
6088 }
6089 while( pEntry )
6090 {
6091 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_TRUE );
6092 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
6093 if (flow_info->sessionId == sessionId)
6094 {
6095 if((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason )||
6096 (SME_QOS_REASON_SETUP == flow_info->reason )||
6097 (SME_QOS_REASON_RELEASE == flow_info->reason )||
6098 (SME_QOS_REASON_MODIFY == flow_info->reason ))
6099 {
6100 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6101 NULL,
6102 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
6103 flow_info->QosFlowID);
6104 }
6105 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6106 "%s: %d: Deleting entry at %p with flowID %d",
6107 __FUNCTION__, __LINE__,
6108 flow_info, flow_info->QosFlowID);
6109 //delete the entry from Flow List
6110 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
6111 vos_mem_free(flow_info);
6112 }
6113 pEntry = pNextEntry;
6114 }
6115 return eHAL_STATUS_SUCCESS;
6116}
6117/*--------------------------------------------------------------------------
6118 \brief sme_QosBufferCmd() - Utility function to buffer a request (setup/modify/
6119 release) from client while processing another one on the same AC.
6120 \param pcmd - a pointer to the cmd structure to be saved inside the buffered
6121 cmd link list
6122
6123 \return eHalStatus
6124
6125 \sa
6126
6127 --------------------------------------------------------------------------*/
6128eHalStatus sme_QosBufferCmd(sme_QosCmdInfo *pcmd, v_BOOL_t insert_head)
6129{
6130 sme_QosSessionInfo *pSession;
6131 sme_QosCmdInfoEntry * pentry = NULL;
6132 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6133 "%s: %d: Invoked",
6134 __FUNCTION__, __LINE__);
6135 pentry = (sme_QosCmdInfoEntry *) vos_mem_malloc(sizeof(sme_QosCmdInfoEntry));
6136 if (!pentry)
6137 {
6138 //err msg
6139 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6140 "%s: %d: Memory allocation failure",
6141 __FUNCTION__, __LINE__);
6142 return eHAL_STATUS_FAILURE;
6143 }
6144 // copy the entire CmdInfo
6145 pentry->cmdInfo = *pcmd;
6146
6147 pSession = &sme_QosCb.sessionInfo[pcmd->sessionId];
6148 if(insert_head)
6149 {
6150 csrLLInsertHead(&pSession->bufferedCommandList, &pentry->link, VOS_TRUE);
6151 }
6152 else
6153 {
6154 csrLLInsertTail(&pSession->bufferedCommandList, &pentry->link, VOS_TRUE);
6155 }
6156 return eHAL_STATUS_SUCCESS;
6157}
6158/*--------------------------------------------------------------------------
6159 \brief sme_QosProcessBufferedCmd() - Utility function to process a buffered
6160 request (setup/modify/release) initially came from the client.
6161
6162 \return eHalStatus
6163
6164 \sa
6165
6166 --------------------------------------------------------------------------*/
6167static eHalStatus sme_QosProcessBufferedCmd(v_U8_t sessionId)
6168{
6169 sme_QosSessionInfo *pSession;
6170 sme_QosCmdInfoEntry *pcmd = NULL;
6171 tListElem *pEntry= NULL;
6172 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6173 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6174 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6175 "%s: %d: Invoked on session %d",
6176 __FUNCTION__, __LINE__,
6177 sessionId);
6178 pSession = &sme_QosCb.sessionInfo[sessionId];
6179 if(!csrLLIsListEmpty( &pSession->bufferedCommandList, VOS_FALSE ))
6180 {
6181 pEntry = csrLLRemoveHead( &pSession->bufferedCommandList, VOS_TRUE );
6182 if(!pEntry)
6183 {
6184 //Err msg
6185 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6186 "%s: %d: no more buffered commands on session %d",
6187 __FUNCTION__, __LINE__,
6188 sessionId);
6189 pSession->readyForPowerSave = VOS_TRUE;
6190 return eHAL_STATUS_FAILURE;
6191 }
6192 pcmd = GET_BASE_ADDR( pEntry, sme_QosCmdInfoEntry, link );
6193 switch(pcmd->cmdInfo.command)
6194 {
6195 case SME_QOS_SETUP_REQ:
6196 hdd_status = sme_QosInternalSetupReq(pcmd->cmdInfo.pMac,
6197 pcmd->cmdInfo.sessionId,
6198 &pcmd->cmdInfo.u.setupCmdInfo.QoSInfo,
6199 pcmd->cmdInfo.u.setupCmdInfo.QoSCallback,
6200 pcmd->cmdInfo.u.setupCmdInfo.HDDcontext,
6201 pcmd->cmdInfo.u.setupCmdInfo.UPType,
6202 pcmd->cmdInfo.u.setupCmdInfo.QosFlowID,
6203 VOS_TRUE,
6204 pcmd->cmdInfo.u.setupCmdInfo.hoRenewal);
6205 if(SME_QOS_STATUS_SETUP_FAILURE_RSP == hdd_status)
6206 {
6207 //Err msg
6208 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6209 "%s: %d: sme_QosInternalSetupReq failed on session %d",
6210 __FUNCTION__, __LINE__,
6211 sessionId);
6212 halStatus = eHAL_STATUS_FAILURE;
6213 }
6214 break;
6215 case SME_QOS_RELEASE_REQ:
6216 hdd_status = sme_QosInternalReleaseReq(pcmd->cmdInfo.pMac,
6217 pcmd->cmdInfo.u.releaseCmdInfo.QosFlowID,
6218 VOS_TRUE);
6219 if(SME_QOS_STATUS_RELEASE_FAILURE_RSP == hdd_status)
6220 {
6221 //Err msg
6222 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6223 "%s: %d: sme_QosInternalReleaseReq failed on session %d",
6224 __FUNCTION__, __LINE__,
6225 sessionId);
6226 halStatus = eHAL_STATUS_FAILURE;
6227 }
6228 break;
6229 case SME_QOS_MODIFY_REQ:
6230 hdd_status = sme_QosInternalModifyReq(pcmd->cmdInfo.pMac,
6231 &pcmd->cmdInfo.u.modifyCmdInfo.QoSInfo,
6232 pcmd->cmdInfo.u.modifyCmdInfo.QosFlowID,
6233 VOS_TRUE);
6234 if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == hdd_status)
6235 {
6236 //Err msg
6237 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6238 "%s: %d: sme_QosInternalModifyReq failed on session %d",
6239 __FUNCTION__, __LINE__,
6240 sessionId);
6241 halStatus = eHAL_STATUS_FAILURE;
6242 }
6243 break;
6244 case SME_QOS_RESEND_REQ:
6245 hdd_status = sme_QosReRequestAddTS(pcmd->cmdInfo.pMac,
6246 pcmd->cmdInfo.sessionId,
6247 &pcmd->cmdInfo.u.resendCmdInfo.QoSInfo,
6248 pcmd->cmdInfo.u.resendCmdInfo.ac,
6249 pcmd->cmdInfo.u.resendCmdInfo.tspecMask);
6250 if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == hdd_status)
6251 {
6252 //Err msg
6253 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6254 "%s: %d: sme_QosReRequestAddTS failed on session %d",
6255 __FUNCTION__, __LINE__,
6256 sessionId);
6257 halStatus = eHAL_STATUS_FAILURE;
6258 }
6259 break;
6260 default:
6261 //err msg
6262 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6263 "%s: %d: On session %d unknown cmd = %d",
6264 __FUNCTION__, __LINE__,
6265 sessionId, pcmd->cmdInfo.command);
6266 //ASSERT
6267 VOS_ASSERT(0);
6268 break;
6269 }
6270 // buffered command has been processed, reclaim the memory
6271 vos_mem_free(pcmd);
6272 }
6273 else
6274 {
6275 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6276 "%s: %d: cmd buffer empty",
6277 __FUNCTION__, __LINE__);
6278 pSession->readyForPowerSave = VOS_TRUE;
6279 }
6280 return halStatus;
6281}
6282/*--------------------------------------------------------------------------
6283 \brief sme_QosDeleteBufferedRequests() - Utility function to Delete the buffered
6284 requests in the buffered_cmd_list, if we lost connectivity.
6285
6286 \return eHalStatus
6287
6288 \sa
6289
6290 --------------------------------------------------------------------------*/
6291static eHalStatus sme_QosDeleteBufferedRequests(tpAniSirGlobal pMac,
6292 v_U8_t sessionId)
6293{
6294 sme_QosSessionInfo *pSession;
6295 sme_QosCmdInfoEntry *pcmd = NULL;
6296 tListElem *pEntry= NULL, *pNextEntry = NULL;
6297 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6298 "%s: %d: Invoked on session %d",
6299 __FUNCTION__, __LINE__, sessionId);
6300 pSession = &sme_QosCb.sessionInfo[sessionId];
6301 pEntry = csrLLPeekHead( &pSession->bufferedCommandList, VOS_TRUE );
6302 if(!pEntry)
6303 {
6304 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6305 "%s: %d: Buffered List empty, nothing to delete on session %d",
6306 __FUNCTION__, __LINE__,
6307 sessionId);
6308 return eHAL_STATUS_FAILURE;
6309 }
6310 while( pEntry )
6311 {
6312 pNextEntry = csrLLNext( &pSession->bufferedCommandList, pEntry, VOS_TRUE );
6313 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6314 "%s: %d: deleting entry from buffered List",
6315 __FUNCTION__, __LINE__);
6316 //delete the entry from Flow List
6317 csrLLRemoveEntry(&pSession->bufferedCommandList, pEntry, VOS_TRUE );
6318 // reclaim the memory
6319 pcmd = GET_BASE_ADDR( pEntry, sme_QosCmdInfoEntry, link );
6320 vos_mem_free(pcmd);
6321 pEntry = pNextEntry;
6322 }
6323 return eHAL_STATUS_SUCCESS;
6324}
6325/*--------------------------------------------------------------------------
6326 \brief sme_QosSaveAssocInfo() - Utility function to save the assoc info in the
6327 CB like BSS descritor of the AP, the profile that HDD sent down with the
6328 connect request, while CSR notifies for assoc/reassoc success.
6329 \param pAssoc_info - pointer to the assoc structure to store the BSS descritor
6330 of the AP, the profile that HDD sent down with the
6331 connect request
6332
6333 \return eHalStatus
6334
6335 \sa
6336
6337 --------------------------------------------------------------------------*/
6338eHalStatus sme_QosSaveAssocInfo(sme_QosSessionInfo *pSession, sme_QosAssocInfo *pAssoc_info)
6339{
6340 tSirBssDescription *pBssDesc = NULL;
6341 v_U32_t bssLen = 0;
6342 if(NULL == pAssoc_info)
6343 {
6344 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6345 "%s: %d: pAssoc_info is NULL",
6346 __FUNCTION__, __LINE__);
6347 return eHAL_STATUS_FAILURE;
6348 }
6349 //clean up the assoc info if already set
6350 if(pSession->assocInfo.pBssDesc)
6351 {
6352 vos_mem_free(pSession->assocInfo.pBssDesc);
6353 pSession->assocInfo.pBssDesc = NULL;
6354 }
6355 bssLen = pAssoc_info->pBssDesc->length +
6356 sizeof(pAssoc_info->pBssDesc->length);
6357 //save the bss Descriptor
6358 pBssDesc = (tSirBssDescription *)vos_mem_malloc(bssLen);
6359 if (!pBssDesc)
6360 {
6361 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6362 "%s: %d: couldn't allocate memory for the bss Descriptor",
6363 __FUNCTION__, __LINE__);
6364 return eHAL_STATUS_FAILURE;
6365 }
6366 vos_mem_copy(pBssDesc, pAssoc_info->pBssDesc, bssLen);
6367 pSession->assocInfo.pBssDesc = pBssDesc;
6368 //save the apsd info from assoc
6369 if(pAssoc_info->pProfile)
6370 {
6371 pSession->apsdMask |= pAssoc_info->pProfile->uapsd_mask;
6372 }
6373 // [TODO] Do we need to update the global APSD bitmap?
6374 return eHAL_STATUS_SUCCESS;
6375}
6376
6377/*--------------------------------------------------------------------------
6378 \brief sme_QosSetupFnp() - Utility function (pointer) to notify other entries
6379 in FLOW list on the same AC that qos params got modified
6380 \param pMac - Pointer to the global MAC parameter structure.
6381 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6382
6383 \return eHalStatus
6384
6385 \sa
6386
6387 --------------------------------------------------------------------------*/
6388eHalStatus sme_QosSetupFnp(tpAniSirGlobal pMac, tListElem *pEntry)
6389{
6390 sme_QosSessionInfo *pSession;
6391 sme_QosACInfo *pACInfo;
6392 sme_QosFlowInfoEntry *flow_info = NULL;
6393 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
6394 sme_QosEdcaAcType ac;
6395 if(!pEntry)
6396 {
6397 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6398 "%s: %d: Entry is NULL",
6399 __FUNCTION__, __LINE__);
6400 //ASSERT
6401 VOS_ASSERT(0);
6402 return eHAL_STATUS_FAILURE;
6403 }
6404 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
6405 ac = flow_info->ac_type;
6406 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
6407 pACInfo = &pSession->ac_info[ac];
6408 if(SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)
6409 {
6410 //notify HDD, only the other Flows running on the AC
6411 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6412 &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
6413 hdd_status,
6414 flow_info->QosFlowID);
6415 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6416 "%s: %d: Entry with flowID = %d getting notified",
6417 __FUNCTION__, __LINE__,
6418 flow_info->QosFlowID);
6419 }
6420 return eHAL_STATUS_SUCCESS;
6421}
6422/*--------------------------------------------------------------------------
6423 \brief sme_QosModificationNotifyFnp() - Utility function (pointer) to notify
6424 other entries in FLOW list on the same AC that qos params got modified
6425 \param pMac - Pointer to the global MAC parameter structure.
6426 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6427
6428 \return eHalStatus
6429
6430 \sa
6431
6432 --------------------------------------------------------------------------*/
6433eHalStatus sme_QosModificationNotifyFnp(tpAniSirGlobal pMac, tListElem *pEntry)
6434{
6435 sme_QosSessionInfo *pSession;
6436 sme_QosACInfo *pACInfo;
6437 sme_QosFlowInfoEntry *flow_info = NULL;
6438 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
6439 sme_QosEdcaAcType ac;
6440 if(!pEntry)
6441 {
6442 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6443 "%s: %d: Entry is NULL",
6444 __FUNCTION__, __LINE__);
6445 //ASSERT
6446 VOS_ASSERT(0);
6447 return eHAL_STATUS_FAILURE;
6448 }
6449 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
6450 ac = flow_info->ac_type;
6451 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
6452 pACInfo = &pSession->ac_info[ac];
6453 if(SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)
6454 {
6455 //notify HDD, only the other Flows running on the AC
6456 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6457 &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
6458 hdd_status,
6459 flow_info->QosFlowID);
6460 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6461 "%s: %d: Entry with flowID = %d getting notified",
6462 __FUNCTION__, __LINE__,
6463 flow_info->QosFlowID);
6464 }
6465 return eHAL_STATUS_SUCCESS;
6466}
6467/*--------------------------------------------------------------------------
6468 \brief sme_QosModifyFnp() - Utility function (pointer) to delete the origianl
6469 entry in FLOW list & add the modified one
6470 \param pMac - Pointer to the global MAC parameter structure.
6471 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6472
6473 \return eHalStatus
6474
6475 \sa
6476
6477 --------------------------------------------------------------------------*/
6478eHalStatus sme_QosModifyFnp(tpAniSirGlobal pMac, tListElem *pEntry)
6479{
6480 sme_QosFlowInfoEntry *flow_info = NULL;
6481 if(!pEntry)
6482 {
6483 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6484 "%s: %d: Entry is NULL",
6485 __FUNCTION__, __LINE__);
6486 VOS_ASSERT(0);
6487 return eHAL_STATUS_FAILURE;
6488 }
6489 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
6490 switch(flow_info->reason)
6491 {
6492 case SME_QOS_REASON_MODIFY_PENDING:
6493 //set the proper reason code for the new (with modified params) entry
6494 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6495 break;
6496 case SME_QOS_REASON_MODIFY:
6497 //delete the original entry from Flow List
6498 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6499 "%s: %d: Deleting original entry at %p with flowID %d",
6500 __FUNCTION__, __LINE__,
6501 flow_info, flow_info->QosFlowID);
6502 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
6503 // reclaim the memory
6504 vos_mem_free(flow_info);
6505 break;
6506 default:
6507 break;
6508 }
6509 return eHAL_STATUS_SUCCESS;
6510}
6511/*--------------------------------------------------------------------------
6512 \brief sme_QosDelTsIndFnp() - Utility function (pointer) to find all Flows on
6513 the perticular AC & delete them, also send HDD indication through the callback
6514 it registered per request
6515 \param pMac - Pointer to the global MAC parameter structure.
6516 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6517
6518 \return eHalStatus
6519
6520 \sa
6521
6522 --------------------------------------------------------------------------*/
6523eHalStatus sme_QosDelTsIndFnp(tpAniSirGlobal pMac, tListElem *pEntry)
6524{
6525 sme_QosSessionInfo *pSession;
6526 sme_QosACInfo *pACInfo;
6527 sme_QosFlowInfoEntry *flow_info = NULL;
6528 sme_QosEdcaAcType ac;
6529 if(!pEntry)
6530 {
6531 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6532 "%s: %d: Entry is NULL",
6533 __FUNCTION__, __LINE__);
6534 //ASSERT
6535 VOS_ASSERT(0);
6536 return eHAL_STATUS_FAILURE;
6537 }
6538 //delete the entry from Flow List
6539 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
6540 ac = flow_info->ac_type;
6541 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
6542 pACInfo = &pSession->ac_info[ac];
6543 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6544 &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1],
6545 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
6546 flow_info->QosFlowID);
6547 pACInfo->num_flows[flow_info->tspec_mask - 1]--;
6548 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6549 "%s: %d: Deleting entry at %p with flowID %d",
6550 __FUNCTION__, __LINE__,
6551 flow_info, flow_info->QosFlowID);
6552 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
6553 // reclaim the memory
6554 vos_mem_free(flow_info);
6555 return eHAL_STATUS_SUCCESS;
6556}
6557/*--------------------------------------------------------------------------
6558 \brief sme_QosReassocSuccessEvFnp() - Utility function (pointer) to notify HDD
6559 the success for the requested flow & notify all the other flows running on the
6560 same AC that QoS params got modified
6561 \param pMac - Pointer to the global MAC parameter structure.
6562 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6563
6564 \return eHalStatus
6565
6566 \sa
6567
6568 --------------------------------------------------------------------------*/
6569eHalStatus sme_QosReassocSuccessEvFnp(tpAniSirGlobal pMac, tListElem *pEntry)
6570{
6571 sme_QosSessionInfo *pSession;
6572 sme_QosACInfo *pACInfo;
6573 sme_QosFlowInfoEntry *flow_info = NULL;
6574 v_BOOL_t delete_entry = VOS_FALSE;
6575 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6576 sme_QosEdcaAcType ac;
6577 eHalStatus pmc_status = eHAL_STATUS_FAILURE;
6578 if(!pEntry)
6579 {
6580 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6581 "%s: %d: Entry is NULL",
6582 __FUNCTION__, __LINE__);
6583 //ASSERT
6584 VOS_ASSERT(0);
6585 return eHAL_STATUS_FAILURE;
6586 }
6587 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
6588 ac = flow_info->ac_type;
6589 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
6590 pACInfo = &pSession->ac_info[ac];
6591 switch(flow_info->reason)
6592 {
6593 case SME_QOS_REASON_SETUP:
6594 hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND;
6595 delete_entry = VOS_FALSE;
6596 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6597 //check for the case where we had to do reassoc to reset the apsd bit
6598 //for the ac - release or modify scenario
6599 if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb)
6600 {
6601 // notify PMC as App is looking for APSD. If we already requested
6602 // then we don't need to do anything.
6603 if(!pSession->uapsdAlreadyRequested)
6604 {
6605 // this is the first flow to detect we need PMC in UAPSD mode
6606
6607 pmc_status = pmcStartUapsd(pMac,
6608 sme_QosPmcStartUapsdCallback,
6609 pSession);
6610 // if PMC doesn't return success right away means it is yet to put
6611 // the module in BMPS state & later to UAPSD state
6612
6613 if(eHAL_STATUS_FAILURE == pmc_status)
6614 {
6615 hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED;
6616 //we need to always notify this case
6617 flow_info->hoRenewal = VOS_FALSE;
6618 }
6619 else if(eHAL_STATUS_PMC_PENDING == pmc_status)
6620 {
6621 // let other flows know PMC has been notified
6622 pSession->uapsdAlreadyRequested = VOS_TRUE;
6623 }
6624 // for any other pmc status we declare success
6625 }
6626 }
6627 break;
6628 case SME_QOS_REASON_RELEASE:
6629 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0]--;
6630 // fall through
6631 case SME_QOS_REASON_MODIFY:
6632 delete_entry = VOS_TRUE;
6633 break;
6634 case SME_QOS_REASON_MODIFY_PENDING:
6635 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND;
6636 delete_entry = VOS_FALSE;
6637 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6638 if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb)
6639 {
6640
6641 if(!pSession->uapsdAlreadyRequested)
6642 {
6643 // this is the first flow to detect we need PMC in UAPSD mode
6644 pmc_status = pmcStartUapsd(pMac,
6645 sme_QosPmcStartUapsdCallback,
6646 pSession);
6647
6648 // if PMC doesn't return success right away means it is yet to put
6649 // the module in BMPS state & later to UAPSD state
6650 if(eHAL_STATUS_FAILURE == pmc_status)
6651 {
6652 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED;
6653 // we need to always notify this case
6654 flow_info->hoRenewal = VOS_FALSE;
6655 }
6656 else if(eHAL_STATUS_PMC_PENDING == pmc_status)
6657 {
6658 pSession->uapsdAlreadyRequested = VOS_TRUE;
6659 }
6660 // for any other pmc status we declare success
6661 }
6662 }
6663 break;
6664 case SME_QOS_REASON_REQ_SUCCESS:
6665 hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
6666 // fall through
6667 default:
6668 delete_entry = VOS_FALSE;
6669 break;
6670 }
6671 if(!delete_entry)
6672 {
6673 if(!flow_info->hoRenewal)
6674 {
6675 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6676 &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
6677 hdd_status,
6678 flow_info->QosFlowID);
6679 }
6680 else
6681 {
6682 flow_info->hoRenewal = VOS_FALSE;
6683 }
6684 }
6685 else
6686 {
6687 //delete the entry from Flow List
6688 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6689 "%s: %d: Deleting entry at %p with flowID %d",
6690 __FUNCTION__, __LINE__,
6691 flow_info, flow_info->QosFlowID);
6692 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
6693 // reclaim the memory
6694 vos_mem_free(flow_info);
6695 }
6696
6697 return eHAL_STATUS_SUCCESS;
6698}
6699/*--------------------------------------------------------------------------
6700 \brief sme_QosAddTsFailureFnp() - Utility function (pointer),
6701 if the Addts request was for for an flow setup request, delete the entry from
6702 Flow list & notify HDD
6703 if the Addts request was for downgrading of QoS params because of an flow
6704 release requested on the AC, delete the entry from Flow list & notify HDD
6705 if the Addts request was for change of QoS params because of an flow
6706 modification requested on the AC, delete the new entry from Flow list & notify
6707 HDD
6708
6709 \param pMac - Pointer to the global MAC parameter structure.
6710 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6711
6712 \return eHalStatus
6713
6714 \sa
6715
6716 --------------------------------------------------------------------------*/
6717eHalStatus sme_QosAddTsFailureFnp(tpAniSirGlobal pMac, tListElem *pEntry)
6718{
6719 sme_QosSessionInfo *pSession;
6720 sme_QosACInfo *pACInfo;
6721 sme_QosFlowInfoEntry *flow_info = NULL;
6722 v_BOOL_t inform_hdd = VOS_FALSE;
6723 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6724 sme_QosEdcaAcType ac;
6725 if(!pEntry)
6726 {
6727 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6728 "%s: %d: Entry is NULL",
6729 __FUNCTION__, __LINE__);
6730 //ASSERT
6731 VOS_ASSERT(0);
6732 return eHAL_STATUS_FAILURE;
6733 }
6734 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
6735 ac = flow_info->ac_type;
6736 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
6737 pACInfo = &pSession->ac_info[ac];
6738 switch(flow_info->reason)
6739 {
6740 case SME_QOS_REASON_SETUP:
6741 hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6742 pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
6743 inform_hdd = VOS_TRUE;
6744 break;
6745 case SME_QOS_REASON_RELEASE:
6746 hdd_status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
6747 pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
6748 inform_hdd = VOS_TRUE;
6749 break;
6750 case SME_QOS_REASON_MODIFY_PENDING:
6751 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
6752 inform_hdd = VOS_TRUE;
6753 break;
6754 case SME_QOS_REASON_MODIFY:
6755 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6756 case SME_QOS_REASON_REQ_SUCCESS:
6757 default:
6758 inform_hdd = VOS_FALSE;
6759 break;
6760 }
6761 if(inform_hdd)
6762 {
6763 //notify HDD, only the requested Flow, other Flows running on the AC stay
6764 // intact
6765 if(!flow_info->hoRenewal)
6766 {
6767 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6768 &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1],
6769 hdd_status,
6770 flow_info->QosFlowID);
6771 }
6772 else
6773 {
6774 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6775 &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1],
6776 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
6777 flow_info->QosFlowID);
6778 }
6779 //delete the entry from Flow List
6780 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6781 "%s: %d: Deleting entry at %p with flowID %d",
6782 __FUNCTION__, __LINE__,
6783 flow_info, flow_info->QosFlowID);
6784 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
6785 // reclaim the memory
6786 vos_mem_free(flow_info);
6787 }
6788 return eHAL_STATUS_SUCCESS;
6789}
6790/*--------------------------------------------------------------------------
6791 \brief sme_QosAddTsSuccessFnp() - Utility function (pointer),
6792 if the Addts request was for for an flow setup request, notify HDD for success
6793 for the flow & notify all the other flows running on the same AC that QoS
6794 params got modified
6795 if the Addts request was for downgrading of QoS params because of an flow
6796 release requested on the AC, delete the entry from Flow list & notify HDD
6797 if the Addts request was for change of QoS params because of an flow
6798 modification requested on the AC, delete the old entry from Flow list & notify
6799 HDD for success for the flow & notify all the other flows running on the same
6800 AC that QoS params got modified
6801 \param pMac - Pointer to the global MAC parameter structure.
6802 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6803
6804 \return eHalStatus
6805
6806 \sa
6807
6808 --------------------------------------------------------------------------*/
6809eHalStatus sme_QosAddTsSuccessFnp(tpAniSirGlobal pMac, tListElem *pEntry)
6810{
6811 sme_QosSessionInfo *pSession;
6812 sme_QosACInfo *pACInfo;
6813 sme_QosFlowInfoEntry *flow_info = NULL;
6814 v_BOOL_t inform_hdd = VOS_FALSE;
6815 v_BOOL_t delete_entry = VOS_FALSE;
6816 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6817 sme_QosEdcaAcType ac;
6818 eHalStatus pmc_status = eHAL_STATUS_FAILURE;
6819 tCsrRoamModifyProfileFields modifyProfileFields;
6820
6821 if(!pEntry)
6822 {
6823 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
6824 "%s: %d: Entry is NULL",
6825 __FUNCTION__, __LINE__);
6826 //ASSERT
6827 VOS_ASSERT(0);
6828 return eHAL_STATUS_FAILURE;
6829 }
6830 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
6831 ac = flow_info->ac_type;
6832 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
6833 pACInfo = &pSession->ac_info[ac];
6834 if(flow_info->tspec_mask != pACInfo->tspec_pending)
6835 {
6836 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6837 "%s: %d: No need to notify the HDD, the ADDTS "
6838 "success is not for index = %d of the AC = %d",
6839 __FUNCTION__, __LINE__,
6840 flow_info->tspec_mask, ac);
6841 return eHAL_STATUS_SUCCESS;
6842 }
6843 switch(flow_info->reason)
6844 {
6845 case SME_QOS_REASON_SETUP:
6846 hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND;
6847 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6848 delete_entry = VOS_FALSE;
6849 inform_hdd = VOS_TRUE;
6850 // check if App is looking for APSD
6851 if(pACInfo->requested_QoSInfo[pACInfo->tspec_pending - 1].ts_info.psb)
6852 {
6853 // notify PMC as App is looking for APSD. If we already requested
6854 // then we don't need to do anything
6855 if(!pSession->uapsdAlreadyRequested)
6856 {
6857 // this is the first flow to detect we need PMC in UAPSD mode
6858 pmc_status = pmcStartUapsd(pMac,
6859 sme_QosPmcStartUapsdCallback,
6860 pSession);
6861 // if PMC doesn't return success right away means it is yet to put
6862 // the module in BMPS state & later to UAPSD state
6863 if(eHAL_STATUS_FAILURE == pmc_status)
6864 {
6865 hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED;
6866 // we need to always notify this case
6867 flow_info->hoRenewal = VOS_FALSE;
6868 }
6869 else if(eHAL_STATUS_PMC_PENDING == pmc_status)
6870 {
6871 // let other flows know PMC has been notified
6872 pSession->uapsdAlreadyRequested = VOS_TRUE;
6873 }
6874 // for any other pmc status we declare success
6875 }
6876 }
6877 break;
6878 case SME_QOS_REASON_RELEASE:
6879 pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
6880 hdd_status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
6881 inform_hdd = VOS_TRUE;
6882 delete_entry = VOS_TRUE;
6883 break;
6884 case SME_QOS_REASON_MODIFY:
6885 delete_entry = VOS_TRUE;
6886 inform_hdd = VOS_FALSE;
6887 break;
6888 case SME_QOS_REASON_MODIFY_PENDING:
6889 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND;
6890 delete_entry = VOS_FALSE;
6891 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6892 inform_hdd = VOS_TRUE;
6893 //notify PMC if App is looking for APSD
6894 if(pACInfo->requested_QoSInfo[pACInfo->tspec_pending - 1].ts_info.psb)
6895 {
6896 // notify PMC as App is looking for APSD. If we already requested
6897 // then we don't need to do anything.
6898 if(!pSession->uapsdAlreadyRequested)
6899 {
6900 // this is the first flow to detect we need PMC in UAPSD mode
6901 pmc_status = pmcStartUapsd(pMac,
6902 sme_QosPmcStartUapsdCallback,
6903 pSession);
6904 // if PMC doesn't return success right away means it is yet to put
6905 // the module in BMPS state & later to UAPSD state
6906 if(eHAL_STATUS_FAILURE == pmc_status)
6907 {
6908 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED;
6909 // we need to always notify this case
6910 flow_info->hoRenewal = VOS_FALSE;
6911 }
6912 else if(eHAL_STATUS_PMC_PENDING == pmc_status)
6913 {
6914 // let other flows know PMC has been notified
6915 pSession->uapsdAlreadyRequested = VOS_TRUE;
6916 }
6917 // for any other pmc status we declare success
6918 }
6919 }
6920 else
6921 {
6922 if((pACInfo->num_flows[flow_info->tspec_mask - 1] == 1) &&
6923 (SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status))
6924 {
6925 // this is the only TSPEC active on this AC
6926 // so indicate that we no longer require APSD
6927 pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
6928 //Also update modifyProfileFields.uapsd_mask in CSR for consistency
6929 csrGetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
6930 modifyProfileFields.uapsd_mask = pSession->apsdMask;
6931 csrSetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields);
6932 if(!pSession->apsdMask)
6933 {
6934 // this session no longer needs UAPSD
6935 // do any sessions still require UAPSD?
6936 if (!sme_QosIsUapsdActive())
6937 {
6938 // No sessions require UAPSD so turn it off
6939 // (really don't care when PMC stops it)
6940 (void)pmcStopUapsd(pMac);
6941 }
6942 }
6943 }
6944 }
6945 break;
6946 case SME_QOS_REASON_REQ_SUCCESS:
6947 hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
6948 inform_hdd = VOS_TRUE;
6949 default:
6950 delete_entry = VOS_FALSE;
6951 break;
6952 }
6953 if(inform_hdd)
6954 {
6955 if(!flow_info->hoRenewal)
6956 {
6957
6958 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6959 &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1],
6960 hdd_status,
6961 flow_info->QosFlowID);
6962 }
6963 else
6964 {
6965 flow_info->hoRenewal = VOS_FALSE;
6966 }
6967 }
6968 if(delete_entry)
6969 {
6970 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
6971 "%s: %d: Deleting entry at %p with flowID %d",
6972 __FUNCTION__, __LINE__,
6973 flow_info, flow_info->QosFlowID);
6974 //delete the entry from Flow List
6975 csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE );
6976 // reclaim the memory
6977 vos_mem_free(flow_info);
6978 }
6979
6980 return eHAL_STATUS_SUCCESS;
6981}
6982/*--------------------------------------------------------------------------
6983 \brief sme_QosIsRspPending() - Utility function to check if we are waiting
6984 for an AddTS or reassoc response on some AC other than the given AC
6985
6986 \param sessionId - Session we are interted in
6987 \param ac - Enumeration of the various EDCA Access Categories.
6988
6989 \return boolean
6990 TRUE - Response is pending on an AC
6991
6992 \sa
6993
6994 --------------------------------------------------------------------------*/
6995static v_BOOL_t sme_QosIsRspPending(v_U8_t sessionId, sme_QosEdcaAcType ac)
6996{
6997 sme_QosSessionInfo *pSession;
6998 sme_QosACInfo *pACInfo;
6999 sme_QosEdcaAcType acIndex;
7000 v_BOOL_t status = VOS_FALSE;
7001 pSession = &sme_QosCb.sessionInfo[sessionId];
7002 for(acIndex = SME_QOS_EDCA_AC_BE; acIndex < SME_QOS_EDCA_AC_MAX; acIndex++)
7003 {
7004 if(acIndex == ac)
7005 {
7006 continue;
7007 }
7008 pACInfo = &pSession->ac_info[acIndex];
7009 if((pACInfo->tspec_pending) || (pACInfo->reassoc_pending))
7010 {
7011 status = VOS_TRUE;
7012 break;
7013 }
7014 }
7015 return status;
7016}
7017/*--------------------------------------------------------------------------
7018 \brief sme_QosIsUapsdActive() - Function which can be called to determine
7019 if any sessions require PMC to be in U-APSD mode.
7020 \return boolean
7021
7022 Returns true if at least one session required PMC to be in U-APSD mode
7023 Returns false if no sessions require PMC to be in U-APSD mode
7024
7025 \sa
7026
7027 --------------------------------------------------------------------------*/
7028static v_BOOL_t sme_QosIsUapsdActive(void)
7029{
7030 sme_QosSessionInfo *pSession;
7031 v_U8_t sessionId;
7032 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
7033 {
7034 pSession = &sme_QosCb.sessionInfo[sessionId];
7035 if ((pSession->sessionActive) && (pSession->apsdMask))
7036 {
7037 return VOS_TRUE;
7038 }
7039 }
7040 // no active sessions have U-APSD active
7041 return VOS_FALSE;
7042}
7043/*--------------------------------------------------------------------------
7044 \brief sme_QosPmcFullPowerCallback() - Callback function registered with PMC
7045 to notify SME-QoS when it puts the chip into full power
7046
7047 \param callbackContext - The context passed to PMC during pmcRequestFullPower
7048 call.
7049 \param status - eHalStatus returned by PMC.
7050
7051 \return None
7052
7053 \sa
7054
7055 --------------------------------------------------------------------------*/
7056void sme_QosPmcFullPowerCallback(void *callbackContext, eHalStatus status)
7057{
7058 sme_QosSessionInfo *pSession = callbackContext;
7059 if(HAL_STATUS_SUCCESS(status))
7060 {
7061 (void)sme_QosProcessBufferedCmd(pSession->sessionId);
7062 }
7063 else
7064 {
7065 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7066 "%s: %d: PMC failed to put the chip in Full power",
7067 __FUNCTION__, __LINE__);
7068 //ASSERT
7069 VOS_ASSERT(0);
7070 }
7071}
7072
7073/*--------------------------------------------------------------------------
7074 \brief sme_QosPmcStartUAPSDCallback() - Callback function registered with PMC
7075 to notify SME-QoS when it puts the chip into UAPSD mode
7076
7077 \param callbackContext - The context passed to PMC during pmcStartUapsd call.
7078 \param status - eHalStatus returned by PMC.
7079
7080 \return None
7081
7082 \sa
7083
7084 --------------------------------------------------------------------------*/
7085void sme_QosPmcStartUapsdCallback(void *callbackContext, eHalStatus status)
7086{
7087 sme_QosSessionInfo *pSession = callbackContext;
7088 // NOTE WELL
7089 //
7090 // In the orignal QoS design the TL module was responsible for
7091 // the generation of trigger frames. When that design was in
7092 // use, we had to queue up any flows which were waiting for PMC
7093 // since we didn't want to notify HDD until PMC had changed to
7094 // UAPSD state. Otherwise HDD would provide TL with the trigger
7095 // frame parameters, and TL would start trigger frame generation
7096 // before PMC was ready. The flows were queued in various places
7097 // throughout this module, and they were dequeued here following
7098 // a successful transition to the UAPSD state by PMC.
7099 //
7100 // In the current QoS design the Firmware is responsible for the
7101 // generation of trigger frames, but the parameters are still
7102 // provided by TL via HDD. The Firmware will be notified of the
7103 // change to UAPSD state directly by PMC, at which time it will be
7104 // responsible for the generation of trigger frames. Therefore
7105 // where we used to queue up flows waiting for PMC to transition
7106 // to the UAPSD state, we now always transition directly to the
7107 // "success" state so that HDD will immediately provide the trigger
7108 // frame parameters to TL, who will in turn plumb them down to the
7109 // Firmware. That way the Firmware will have the trigger frame
7110 // parameters when it needs them
7111 // just note that there is no longer an outstanding request
7112 pSession->uapsdAlreadyRequested = VOS_FALSE;
7113}
7114/*--------------------------------------------------------------------------
7115 \brief sme_QosPmcCheckRoutine() - Function registered with PMC to check with
7116 SME-QoS whenever the device is about to enter one of the power
7117 save modes. PMC runs a poll with all the registered modules if device can
7118 enter powersave mode or remain in full power
7119
7120 \param callbackContext - The context passed to PMC during registration through
7121 pmcRegisterPowerSaveCheck.
7122 \return boolean
7123
7124 SME-QOS returns PMC true or false respectively if it wants to vote for
7125 entering power save or not
7126
7127 \sa
7128
7129 --------------------------------------------------------------------------*/
7130v_BOOL_t sme_QosPmcCheckRoutine(void *callbackContext)
7131{
7132 sme_QosSessionInfo *pSession;
7133 v_U8_t sessionId;
7134 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
7135 {
7136 pSession = &sme_QosCb.sessionInfo[sessionId];
7137 if ((pSession->sessionActive) &&
7138 (!pSession->readyForPowerSave))
7139 {
7140 return VOS_FALSE;
7141 }
7142 }
7143 // all active sessions have voted for powersave
7144 return VOS_TRUE;
7145}
7146/*--------------------------------------------------------------------------
7147 \brief sme_QosPmcDeviceStateUpdateInd() - Callback function registered with
7148 PMC to notify SME-QoS when it changes the power state
7149
7150 \param callbackContext - The context passed to PMC during registration
7151 through pmcRegisterDeviceStateUpdateInd.
7152 \param pmcState - Current power state that PMC moved into.
7153
7154 \return None
7155
7156 \sa
7157
7158 --------------------------------------------------------------------------*/
7159void sme_QosPmcDeviceStateUpdateInd(void *callbackContext, tPmcState pmcState)
7160{
7161 eHalStatus status = eHAL_STATUS_FAILURE;
7162 tpAniSirGlobal pMac = PMAC_STRUCT( callbackContext );
7163 //check all the entries in Flow list for non-zero service interval, which will
7164 //tell us if we need to notify HDD when PMC is out of UAPSD mode or going
7165 // back to UAPSD mode
7166 switch(pmcState)
7167 {
7168 case FULL_POWER:
7169 status = sme_QosProcessOutOfUapsdMode(pMac);
7170 break;
7171 case UAPSD:
7172 status = sme_QosProcessIntoUapsdMode(pMac);
7173 break;
7174 default:
7175 status = eHAL_STATUS_SUCCESS;
7176 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7177 "%s: %d: nothing to process in PMC state %d",
7178 __FUNCTION__, __LINE__,
7179 pmcState);
7180 }
7181 if(!HAL_STATUS_SUCCESS(status))
7182 {
Mohit Khanna23863762012-09-11 17:40:09 -07007183 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
Jeff Johnson295189b2012-06-20 16:38:30 -07007184 "%s: %d: ignoring Device(PMC) state change to %d",
7185 __FUNCTION__, __LINE__,
7186 pmcState);
7187 }
7188
7189}
7190/*--------------------------------------------------------------------------
7191 \brief sme_QosProcessOutOfUapsdMode() - Function to notify HDD when PMC
7192 notifies SME-QoS that it moved out of UAPSD mode to FULL power
7193
7194 \param pMac - Pointer to the global MAC parameter structure.
7195 \return eHalStatus
7196
7197 \sa
7198
7199 --------------------------------------------------------------------------*/
7200eHalStatus sme_QosProcessOutOfUapsdMode(tpAniSirGlobal pMac)
7201{
7202 sme_QosSessionInfo *pSession;
7203 tListElem *pEntry= NULL, *pNextEntry = NULL;
7204 sme_QosFlowInfoEntry *flow_info = NULL;
7205
7206 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
7207 if(!pEntry)
7208 {
Mohit Khanna23863762012-09-11 17:40:09 -07007209 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
Jeff Johnson295189b2012-06-20 16:38:30 -07007210 "%s: %d: Flow List empty, can't search",
7211 __FUNCTION__, __LINE__);
7212 return eHAL_STATUS_FAILURE;
7213 }
7214 while( pEntry )
7215 {
7216 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
7217 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
7218 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
7219 //only notify the flows which already successfully setup UAPSD
7220 if((flow_info->QoSInfo.max_service_interval ||
7221 flow_info->QoSInfo.min_service_interval) &&
7222 (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason))
7223 {
7224 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
7225 &pSession->ac_info[flow_info->ac_type].curr_QoSInfo[flow_info->tspec_mask - 1],
7226 SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND,
7227 flow_info->QosFlowID);
7228 }
7229 pEntry = pNextEntry;
7230 }
7231 return eHAL_STATUS_SUCCESS;
7232}
7233/*--------------------------------------------------------------------------
7234 \brief sme_QosProcessIntoUapsdMode() - Function to notify HDD when PMC
7235 notifies SME-QoS that it is moving into UAPSD mode
7236
7237 \param pMac - Pointer to the global MAC parameter structure.
7238 \return eHalStatus
7239
7240 \sa
7241
7242 --------------------------------------------------------------------------*/
7243eHalStatus sme_QosProcessIntoUapsdMode(tpAniSirGlobal pMac)
7244{
7245 sme_QosSessionInfo *pSession;
7246 tListElem *pEntry= NULL, *pNextEntry = NULL;
7247 sme_QosFlowInfoEntry *flow_info = NULL;
7248
7249 pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE );
7250 if(!pEntry)
7251 {
7252 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7253 "%s: %d: Flow List empty, can't search",
7254 __FUNCTION__, __LINE__);
7255 return eHAL_STATUS_FAILURE;
7256 }
7257 while( pEntry )
7258 {
7259 pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE );
7260 flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link );
7261 pSession = &sme_QosCb.sessionInfo[flow_info->sessionId];
7262 //only notify the flows which already successfully setup UAPSD
7263 if((flow_info->QoSInfo.max_service_interval ||
7264 flow_info->QoSInfo.min_service_interval) &&
7265 (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason))
7266 {
7267 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
7268 &pSession->ac_info[flow_info->ac_type].curr_QoSInfo[flow_info->tspec_mask - 1],
7269 SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND,
7270 flow_info->QosFlowID);
7271 }
7272 pEntry = pNextEntry;
7273 }
7274 return eHAL_STATUS_SUCCESS;
7275}
7276
7277void sme_QosCleanupCtrlBlkForHandoff(tpAniSirGlobal pMac, v_U8_t sessionId)
7278{
7279 sme_QosSessionInfo *pSession;
7280 sme_QosACInfo *pACInfo;
7281 sme_QosEdcaAcType ac;
7282 pSession = &sme_QosCb.sessionInfo[sessionId];
7283 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
7284 {
7285 pACInfo = &pSession->ac_info[ac];
7286 vos_mem_zero(pACInfo->curr_QoSInfo,
7287 sizeof(sme_QosWmmTspecInfo) * SME_QOS_TSPEC_INDEX_MAX);
7288 vos_mem_zero(pACInfo->requested_QoSInfo,
7289 sizeof(sme_QosWmmTspecInfo) * SME_QOS_TSPEC_INDEX_MAX);
7290 pACInfo->num_flows[0] = 0;
7291 pACInfo->num_flows[1] = 0;
7292 pACInfo->reassoc_pending = VOS_FALSE;
7293 pACInfo->tspec_mask_status = 0;
7294 pACInfo->tspec_pending = VOS_FALSE;
7295 pACInfo->hoRenewal = VOS_FALSE;
7296 pACInfo->prev_state = SME_QOS_LINK_UP;
7297 }
7298}
7299
7300/*--------------------------------------------------------------------------
7301 \brief sme_QosIsTSInfoAckPolicyValid() - The SME QoS API exposed to HDD to
7302 check if TS info ack policy field can be set to "HT-immediate block acknowledgement"
7303
7304 \param pMac - The handle returned by macOpen.
7305 \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
7306 related info, provided by HDD
7307 \param sessionId - sessionId returned by sme_OpenSession.
7308
7309 \return VOS_TRUE - Current Association is HT association and so TS info ack policy
7310 can be set to "HT-immediate block acknowledgement"
7311
7312 \sa
7313
7314 --------------------------------------------------------------------------*/
7315v_BOOL_t sme_QosIsTSInfoAckPolicyValid(tpAniSirGlobal pMac,
7316 sme_QosWmmTspecInfo * pQoSInfo,
7317 v_U8_t sessionId)
7318{
7319 tDot11fBeaconIEs *pIes = NULL;
7320 sme_QosSessionInfo *pSession;
7321 eHalStatus hstatus;
7322 if( !CSR_IS_SESSION_VALID( pMac, sessionId ) )
7323 {
7324 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7325 "%s: %d: Session Id %d is invalid",
7326 __FUNCTION__, __LINE__,
7327 sessionId);
7328 return VOS_FALSE;
7329 }
7330
7331 pSession = &sme_QosCb.sessionInfo[sessionId];
7332
7333 if( !pSession->sessionActive )
7334 {
7335 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7336 "%s: %d: Session %d is inactive",
7337 __FUNCTION__, __LINE__,
7338 sessionId);
7339 return VOS_FALSE;
7340 }
7341
7342 if(!pSession->assocInfo.pBssDesc)
7343 {
7344 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7345 "%s: %d: Session %d has an Invalid BSS Descriptor",
7346 __FUNCTION__, __LINE__,
7347 sessionId);
7348 return VOS_FALSE;
7349 }
7350
7351 hstatus = csrGetParsedBssDescriptionIEs(pMac,
7352 pSession->assocInfo.pBssDesc,
7353 &pIes);
7354 if(!HAL_STATUS_SUCCESS(hstatus))
7355 {
7356 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7357 "%s: %d: On session %d unable to parse BSS IEs",
7358 __FUNCTION__, __LINE__,
7359 sessionId);
7360 return VOS_FALSE;
7361 }
7362
7363 /* success means pIes was allocated */
7364
7365 if(!pIes->HTCaps.present &&
7366 pQoSInfo->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)
7367 {
7368 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7369 "%s: %d: On session %d HT Caps aren't present but application set ack policy to HT ",
7370 __FUNCTION__, __LINE__,
7371 sessionId);
7372
7373 vos_mem_free(pIes);
7374 return VOS_FALSE;
7375 }
7376
7377 vos_mem_free(pIes);
7378 return VOS_TRUE;
7379}
7380
7381v_BOOL_t sme_QosValidateRequestedParams(tpAniSirGlobal pMac,
7382 sme_QosWmmTspecInfo * pQoSInfo,
7383 v_U8_t sessionId)
7384{
7385 v_BOOL_t rc = VOS_FALSE;
7386
7387 do
7388 {
7389 if(SME_QOS_WMM_TS_DIR_RESV == pQoSInfo->ts_info.direction) break;
7390 if(!sme_QosIsTSInfoAckPolicyValid(pMac, pQoSInfo, sessionId)) break;
7391
7392 rc = VOS_TRUE;
7393 }while(0);
7394 return rc;
7395}
7396
7397static eHalStatus qosIssueCommand( tpAniSirGlobal pMac, v_U8_t sessionId,
7398 eSmeCommandType cmdType, sme_QosWmmTspecInfo * pQoSInfo,
7399 sme_QosEdcaAcType ac, v_U8_t tspec_mask )
7400{
7401 eHalStatus status = eHAL_STATUS_RESOURCES;
7402 tSmeCmd *pCommand = NULL;
7403 do
7404 {
7405 pCommand = smeGetCommandBuffer( pMac );
7406 if ( !pCommand )
7407 {
7408 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7409 "%s: %d: fail to get command buffer for command %d",
7410 __FUNCTION__, __LINE__, cmdType);
7411 break;
7412 }
7413 pCommand->command = cmdType;
7414 pCommand->sessionId = sessionId;
7415 switch ( cmdType )
7416 {
7417 case eSmeCommandAddTs:
7418 if( pQoSInfo )
7419 {
7420 status = eHAL_STATUS_SUCCESS;
7421 pCommand->u.qosCmd.tspecInfo = *pQoSInfo;
7422 pCommand->u.qosCmd.ac = ac;
7423 }
7424 else
7425 {
7426 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7427 "%s: %d: NULL pointer passed",
7428 __FUNCTION__, __LINE__);
7429 status = eHAL_STATUS_INVALID_PARAMETER;
7430 }
7431 break;
7432 case eSmeCommandDelTs:
7433 status = eHAL_STATUS_SUCCESS;
7434 pCommand->u.qosCmd.ac = ac;
7435 pCommand->u.qosCmd.tspec_mask = tspec_mask;
7436 break;
7437 default:
7438 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7439 "%s: %d: invalid command type %d",
7440 __FUNCTION__, __LINE__, cmdType );
7441 status = eHAL_STATUS_INVALID_PARAMETER;
7442 break;
7443 }
7444 } while( 0 );
7445 if( HAL_STATUS_SUCCESS( status ) && pCommand )
7446 {
7447 smePushCommand( pMac, pCommand, eANI_BOOLEAN_FALSE );
7448 }
7449 else if( pCommand )
7450 {
7451 qosReleaseCommand( pMac, pCommand );
7452 }
7453 return( status );
7454}
7455tANI_BOOLEAN qosProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
7456{
7457 eHalStatus status = eHAL_STATUS_SUCCESS;
7458 tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE;
7459 do
7460 {
7461 switch ( pCommand->command )
7462 {
7463 case eSmeCommandAddTs:
7464 status = sme_QosAddTsReq( pMac, (v_U8_t)pCommand->sessionId, &pCommand->u.qosCmd.tspecInfo, pCommand->u.qosCmd.ac);
7465 if( HAL_STATUS_SUCCESS( status ) )
7466 {
7467 fRemoveCmd = eANI_BOOLEAN_FALSE;
7468 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
7469 }
7470 break;
7471 case eSmeCommandDelTs:
7472 status = sme_QosDelTsReq( pMac, (v_U8_t)pCommand->sessionId, pCommand->u.qosCmd.ac, pCommand->u.qosCmd.tspec_mask );
7473 if( HAL_STATUS_SUCCESS( status ) )
7474 {
7475 fRemoveCmd = eANI_BOOLEAN_FALSE;
7476 }
7477 break;
7478 default:
7479 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7480 "%s: %d: invalid command type %d",
7481 __FUNCTION__, __LINE__, pCommand->command );
7482 break;
7483 }//switch
7484 } while(0);
7485 return( fRemoveCmd );
7486}
7487
7488/*
7489 sme_QosTriggerUapsdChange
7490 Invoked by BTC when UAPSD bypass is enabled or disabled
7491 We, in turn, must disable or enable UAPSD on all flows as appropriate
7492 That may require us to re-add TSPECs or to reassociate
7493*/
7494sme_QosStatusType sme_QosTriggerUapsdChange( tpAniSirGlobal pMac )
7495{
7496 sme_QosSessionInfo *pSession;
7497 sme_QosACInfo *pACInfo;
7498 v_U8_t ac, tspec1 = 0, tspec2 = 0;
7499 v_U8_t uapsd_mask;
7500 tDot11fBeaconIEs *pIesLocal;
7501 v_U8_t acm_mask;
7502 v_BOOL_t fIsUapsdNeeded;
7503 v_U8_t sessionId;
7504 v_BOOL_t addtsWhenACMNotSet = CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac);
7505 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7506 "%s: %d: Invoked",
7507 __FUNCTION__, __LINE__);
7508 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId)
7509 {
7510 pSession = &sme_QosCb.sessionInfo[sessionId];
7511 if( !pSession->sessionActive )
7512 {
7513 continue;
7514 }
7515 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7516 "%s: %d: Session %d is active",
7517 __FUNCTION__, __LINE__,
7518 sessionId);
7519 if( HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSession->assocInfo.pBssDesc, &pIesLocal)) )
7520 {
7521 // get the ACM mask
7522 acm_mask = sme_QosGetACMMask(pMac, pSession->assocInfo.pBssDesc, pIesLocal);
7523 vos_mem_free(pIesLocal);
7524 // get the uapsd mask for this session
7525 uapsd_mask = pSession->apsdMask;
7526 // unmask the bits with ACM on to avoid reassoc on them
7527 uapsd_mask &= ~acm_mask;
7528 // iterate through the ACs to determine if we need to re-add any TSPECs
7529 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
7530 {
7531 pACInfo = &pSession->ac_info[ac];
7532 // Does this AC have QoS active?
7533 if( SME_QOS_QOS_ON == pACInfo->curr_state )
7534 {
7535 // Yes, QoS is active on this AC
7536 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7537 "%s: %d: On session %d AC %d has QoS active",
7538 __FUNCTION__, __LINE__,
7539 sessionId, ac);
7540 // Does this AC require ACM?
7541 if(( acm_mask & (1 << (SME_QOS_EDCA_AC_VO - ac)) ) || addtsWhenACMNotSet )
7542 {
7543 // Yes, so we need to re-add any TSPECS
7544 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7545 "%s: %d: On session %d AC %d has ACM enabled",
7546 __FUNCTION__, __LINE__,
7547 sessionId, ac);
7548 // Are any TSPECs active?
7549 if( pACInfo->tspec_mask_status )
7550 {
7551 // Yes, at least 1 TSPEC is active. Are they both active?
7552 if( SME_QOS_TSPEC_MASK_BIT_1_2_SET == pACInfo->tspec_mask_status )
7553 {
7554 //both TSPECS are active
7555 tspec1 = SME_QOS_TSPEC_MASK_BIT_1_SET;
7556 tspec2 = SME_QOS_TSPEC_MASK_BIT_2_SET;
7557 }
7558 else
7559 {
7560 // only one TSPEC is active, get its mask
7561 tspec1 = SME_QOS_TSPEC_MASK_BIT_1_2_SET & pACInfo->tspec_mask_status;
7562 }
7563 // Does TSPEC 1 really require UAPSD?
7564 fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[tspec1 - 1].max_service_interval ||
7565 pACInfo->curr_QoSInfo[tspec1 - 1].min_service_interval);
7566 //double check whether we need to do anything
7567 if( fIsUapsdNeeded )
7568 {
7569 pACInfo->requested_QoSInfo[tspec1 - 1] =
7570 pACInfo->curr_QoSInfo[tspec1 - 1];
7571 sme_QosReRequestAddTS( pMac, sessionId,
7572 &pACInfo->requested_QoSInfo[tspec1 - 1],
7573 ac,
7574 tspec1 );
7575 }
7576 // Is TSPEC 2 active?
7577 if( tspec2 )
7578 {
7579 // Does TSPEC 2 really require UAPSD?
7580 fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[tspec2 - 1].max_service_interval ||
7581 pACInfo->curr_QoSInfo[tspec2 - 1].min_service_interval);
7582 if( fIsUapsdNeeded )
7583 {
7584 //No need to inform HDD
7585 //pACInfo->hoRenewal = VOS_TRUE;
7586 pACInfo->requested_QoSInfo[tspec2 - 1] =
7587 pACInfo->curr_QoSInfo[tspec2 - 1];
7588 sme_QosReRequestAddTS( pMac, sessionId,
7589 &pACInfo->requested_QoSInfo[tspec2 - 1],
7590 ac,
7591 tspec2);
7592 }
7593 }
7594 }
7595 else
7596 {
7597 // QoS is set, ACM is on, but no TSPECs -- inconsistent state
7598 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7599 "%s: %d: On session %d AC %d has QoS enabled and ACM is set, but no TSPEC",
7600 __FUNCTION__, __LINE__,
7601 sessionId, ac);
7602 VOS_ASSERT(0);
7603 }
7604 }
7605 else
7606 {
7607 //Since ACM bit is not set, there should be only one QoS information for both directions.
7608 fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[0].max_service_interval ||
7609 pACInfo->curr_QoSInfo[0].min_service_interval);
7610 if(fIsUapsdNeeded)
7611 {
7612 // we need UAPSD on this AC (and we may not currently have it)
7613 uapsd_mask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
7614 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7615 "%s: %d: On session %d AC %d has ACM disabled, uapsd mask now 0x%X",
7616 __FUNCTION__, __LINE__,
7617 sessionId, ac, uapsd_mask);
7618 }
7619 }
7620 }
7621 }
7622 // do we need to reassociate?
7623 if(uapsd_mask)
7624 {
7625 tCsrRoamModifyProfileFields modifyProfileFields;
7626 //we need to do a reassoc on these AC
7627 csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields);
7628 if( btcIsReadyForUapsd(pMac) )
7629 {
7630 modifyProfileFields.uapsd_mask = uapsd_mask;
7631 }
7632 else
7633 {
7634 modifyProfileFields.uapsd_mask = 0;
7635 }
7636 //Do we need to inform HDD?
7637 if(!HAL_STATUS_SUCCESS(sme_QosRequestReassoc(pMac, sessionId, &modifyProfileFields, VOS_TRUE)))
7638 {
7639 //err msg
7640 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7641 "%s: %d: On Session %d Reassoc failed",
7642 __FUNCTION__, __LINE__,
7643 sessionId);
7644 }
7645 }
7646 }
7647 else
7648 {
7649 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7650 "%s: %d: On Session %d failed to parse IEs",
7651 __FUNCTION__, __LINE__,
7652 sessionId);
7653 }
7654 }
7655 // return status is ignored by BTC
7656 return SME_QOS_STATUS_SETUP_SUCCESS_IND;
7657}
7658
7659/*
7660 sme_QosReRequestAddTS to re-send AddTS for the combined QoS request
7661*/
7662static sme_QosStatusType sme_QosReRequestAddTS(tpAniSirGlobal pMac,
7663 v_U8_t sessionId,
7664 sme_QosWmmTspecInfo * pQoSInfo,
7665 sme_QosEdcaAcType ac,
7666 v_U8_t tspecMask)
7667{
7668 sme_QosSessionInfo *pSession;
7669 sme_QosACInfo *pACInfo;
7670 sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
7671 sme_QosCmdInfo cmd;
7672 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7673 "%s: %d: Invoked on session %d for AC %d TSPEC %d",
7674 __FUNCTION__, __LINE__,
7675 sessionId, ac, tspecMask);
7676 pSession = &sme_QosCb.sessionInfo[sessionId];
7677 pACInfo = &pSession->ac_info[ac];
7678 // need to vote off powersave for the duration of this request
7679 pSession->readyForPowerSave = VOS_FALSE;
7680 //call PMC's request for power function
7681 // AND
7682 //another check is added considering the flowing scenario
7683 //Addts reqest is pending on one AC, while APSD requested on another which
7684 //needs a reassoc. Will buffer a request if Addts is pending on any AC,
7685 //which will safegaurd the above scenario, & also won't confuse PE with back
7686 //to back Addts or Addts followed by Reassoc
7687 if(sme_QosIsRspPending(sessionId, ac) ||
7688 ( eHAL_STATUS_PMC_PENDING == pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback, pSession, eSME_REASON_OTHER)))
7689 {
7690 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7691 "%s: %d: On session %d buffering the AddTS request "
7692 "for AC %d in state %d as Addts is pending "
7693 "on other AC or waiting for full power",
7694 __FUNCTION__, __LINE__,
7695 sessionId, ac, pACInfo->curr_state);
7696 //buffer cmd
7697 cmd.command = SME_QOS_RESEND_REQ;
7698 cmd.pMac = pMac;
7699 cmd.sessionId = sessionId;
7700 cmd.u.resendCmdInfo.ac = ac;
7701 cmd.u.resendCmdInfo.tspecMask = tspecMask;
7702 cmd.u.resendCmdInfo.QoSInfo = *pQoSInfo;
7703 if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE)))
7704 {
7705 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7706 "%s: %d: On session %d unable to buffer the AddTS "
7707 "request for AC %d TSPEC %d in state %d",
7708 __FUNCTION__, __LINE__,
7709 sessionId, ac, tspecMask, pACInfo->curr_state);
7710 // unable to buffer the request
7711 // nothing is pending so vote powersave back on
7712 pSession->readyForPowerSave = VOS_TRUE;
7713 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
7714 }
7715 return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
7716 }
7717 //get into the stat m/c to see if the request can be granted
7718 switch(pACInfo->curr_state)
7719 {
7720 case SME_QOS_QOS_ON:
7721 {
7722 //if ACM, send out a new ADDTS
7723 pACInfo->hoRenewal = VOS_TRUE;
7724 status = sme_QosSetup(pMac, sessionId, pQoSInfo, ac);
7725 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7726 "%s: %d: sme_QosSetup returned in SME_QOS_QOS_ON state on "
7727 "AC %d with status =%d",
7728 __FUNCTION__, __LINE__,
7729 ac, status);
7730 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status)
7731 {
7732 // we aren't waiting for a response from the AP
7733 // so vote powersave back on
7734 pSession->readyForPowerSave = VOS_TRUE;
7735 }
7736 if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)
7737 {
7738 status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
7739 pACInfo->tspec_pending = tspecMask;
7740 }
7741 else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
7742 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) ||
7743 (SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING == status))
7744 {
7745 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7746 "%s: %d: UAPSD is setup already status = %d "
7747 "returned by sme_QosSetup",
7748 __FUNCTION__, __LINE__,
7749 status);
7750 }
7751 else
7752 {
7753 //err msg
7754 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7755 "%s: %d: unexpected status = %d returned by sme_QosSetup",
7756 __FUNCTION__, __LINE__,
7757 status);
7758 }
7759 }
7760 break;
7761 case SME_QOS_HANDOFF:
7762 case SME_QOS_REQUESTED:
7763 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7764 "%s: %d: Re-Add request in state = %d buffer the request",
7765 __FUNCTION__, __LINE__,
7766 pACInfo->curr_state);
7767 cmd.command = SME_QOS_RESEND_REQ;
7768 cmd.pMac = pMac;
7769 cmd.sessionId = sessionId;
7770 cmd.u.resendCmdInfo.ac = ac;
7771 cmd.u.resendCmdInfo.tspecMask = tspecMask;
7772 cmd.u.resendCmdInfo.QoSInfo = *pQoSInfo;
7773 if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE)))
7774 {
7775 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7776 "%s: %d: couldn't buffer the readd request in state = %d",
7777 __FUNCTION__, __LINE__,
7778 pACInfo->curr_state );
7779 // unable to buffer the request
7780 // nothing is pending so vote powersave back on
7781 pSession->readyForPowerSave = VOS_TRUE;
7782 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
7783 }
7784 status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
7785 break;
7786 case SME_QOS_CLOSED:
7787 case SME_QOS_INIT:
7788 case SME_QOS_LINK_UP:
7789 default:
7790 //print error msg,
7791 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
7792 "%s: %d: ReAdd request in unexpected state = %d",
7793 __FUNCTION__, __LINE__,
7794 pACInfo->curr_state );
7795 // unable to service the request
7796 // nothing is pending so vote powersave back on
7797 pSession->readyForPowerSave = VOS_TRUE;
7798 // ASSERT?
7799 break;
7800 }
7801 if((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
7802 (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY == status))
7803 {
7804 (void)sme_QosProcessBufferedCmd(sessionId);
7805 }
7806 return (status);
7807}
7808
7809static void sme_QosInitACs(tpAniSirGlobal pMac, v_U8_t sessionId)
7810{
7811 sme_QosSessionInfo *pSession;
7812 sme_QosEdcaAcType ac;
7813 pSession = &sme_QosCb.sessionInfo[sessionId];
7814 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
7815 {
7816 vos_mem_zero(&pSession->ac_info[ac], sizeof(sme_QosACInfo));
7817 sme_QosStateTransition(sessionId, ac, SME_QOS_INIT);
7818 }
7819}
7820static eHalStatus sme_QosRequestReassoc(tpAniSirGlobal pMac, tANI_U8 sessionId,
7821 tCsrRoamModifyProfileFields *pModFields,
7822 v_BOOL_t fForce )
7823{
7824 sme_QosSessionInfo *pSession;
7825 sme_QosACInfo *pACInfo;
7826 eHalStatus status;
7827 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
7828 "%s: %d: Invoked on session %d with UAPSD mask 0x%X",
7829 __FUNCTION__, __LINE__,
7830 sessionId, pModFields->uapsd_mask);
7831 pSession = &sme_QosCb.sessionInfo[sessionId];
7832 status = csrReassoc(pMac, sessionId, pModFields, &pSession->roamID, fForce);
7833 if(HAL_STATUS_SUCCESS(status))
7834 {
7835 //Update the state to Handoff so subsequent requests are queued until
7836 // this one is finished
7837 sme_QosEdcaAcType ac;
7838 for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++)
7839 {
7840 pACInfo = &pSession->ac_info[ac];
7841 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
7842 "%s: %d: AC[%d] is in state [%d]",
7843 __FUNCTION__, __LINE__,
7844 ac, pACInfo->curr_state );
7845 // If it is already in HANDOFF state, don't do anything since we
7846 // MUST preserve the previous state and sme_QosStateTransition
7847 // will change the previous state
7848 if(SME_QOS_HANDOFF != pACInfo->curr_state)
7849 {
7850 sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF);
7851 }
7852 }
7853 }
7854 return status;
7855}
7856static v_U32_t sme_QosAssignFlowId(void)
7857{
7858 v_U32_t flowId;
7859 flowId = sme_QosCb.nextFlowId;
7860 if (SME_QOS_MAX_FLOW_ID == flowId)
7861 {
7862 // The Flow ID wrapped. This is obviously not a real life scenario
7863 // but handle it to keep the software test folks happy
7864 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
7865 "%s: %d: Software Test made the flow counter wrap, "
7866 "QoS may no longer be functional",
7867 __FUNCTION__, __LINE__);
7868 sme_QosCb.nextFlowId = SME_QOS_MIN_FLOW_ID;
7869 }
7870 else
7871 {
7872 sme_QosCb.nextFlowId++;
7873 }
7874 return flowId;
7875}
7876
7877static v_U8_t sme_QosAssignDialogToken(void)
7878{
7879 v_U8_t token;
7880 token = sme_QosCb.nextDialogToken;
7881 if (SME_QOS_MAX_DIALOG_TOKEN == token)
7882 {
7883 // wrap is ok
7884 sme_QosCb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN;
7885 }
7886 else
7887 {
7888 sme_QosCb.nextDialogToken++;
7889 }
7890 return token;
7891}
7892#endif /* WLAN_MDM_CODE_REDUCTION_OPT */