blob: 0e3d4ff0135857d858dceb1c762bc022f5eae4c2 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
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 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**=========================================================================
29
30 \file sme_qos.c
31
32 \brief implementation for SME QoS APIs
33
34 ========================================================================*/
35/* $Header$ */
36/*--------------------------------------------------------------------------
37 Include Files
38 ------------------------------------------------------------------------*/
39
40#include "ani_global.h"
41
42#include "sme_inside.h"
43#include "host_diag_core_event.h"
44#include "host_diag_core_log.h"
45
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080046#include "sms_debug.h"
47#include "utils_parser.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include "sme_power_save_api.h"
49
50#ifndef WLAN_MDM_CODE_REDUCTION_OPT
51/* TODO : 6Mbps as Cisco APs seem to like only this value; analysis req. */
52#define SME_QOS_MIN_PHY_RATE 0x5B8D80
53#define SME_QOS_SURPLUS_BW_ALLOWANCE 0x2000 /* Ratio of 1.0 */
54/*---------------------------------------------------------------------------
55 Max values to bound tspec params against and avoid rollover
56 ---------------------------------------------------------------------------*/
57#define SME_QOS_32BIT_MAX 0xFFFFFFFF
58#define SME_QOS_16BIT_MAX 0xFFFF
59#define SME_QOS_16BIT_MSB 0x8000
60/*---------------------------------------------------------------------------
61 Adds y to x, but saturates at 32-bit max to avoid rollover
62 ---------------------------------------------------------------------------*/
63#define SME_QOS_BOUNDED_U32_ADD_Y_TO_X(_x, _y) \
64 do { \
65 (_x) = ((SME_QOS_32BIT_MAX - (_x)) < (_y)) ? \
66 (SME_QOS_32BIT_MAX) : (_x) + (_y); \
67 } while (0)
68
69/*---------------------------------------------------------------------------
70 As per WMM spec there could be max 2 TSPEC running on the same AC with
71 different direction. We will refer each TSPEC with an index
72 ---------------------------------------------------------------------------*/
73#define SME_QOS_TSPEC_INDEX_0 0
74#define SME_QOS_TSPEC_INDEX_1 1
75#define SME_QOS_TSPEC_INDEX_MAX 2
76#define SME_QOS_TSPEC_MASK_BIT_1_SET 1
77#define SME_QOS_TSPEC_MASK_BIT_2_SET 2
78#define SME_QOS_TSPEC_MASK_BIT_1_2_SET 3
79#define SME_QOS_TSPEC_MASK_CLEAR 0
80
81/* which key to search on, in the flowlist (1 = flowID, 2 = AC, 4 = reason) */
82#define SME_QOS_SEARCH_KEY_INDEX_1 1
83#define SME_QOS_SEARCH_KEY_INDEX_2 2
84#define SME_QOS_SEARCH_KEY_INDEX_3 4
85#define SME_QOS_SEARCH_KEY_INDEX_4 8 /* ac + direction */
86#define SME_QOS_SEARCH_KEY_INDEX_5 0x10 /* ac + tspec_mask */
87/* special value for searching any Session Id */
88#define SME_QOS_SEARCH_SESSION_ID_ANY CSR_ROAM_SESSION_MAX
89#define SME_QOS_ACCESS_POLICY_EDCA 1
90#define SME_QOS_MAX_TID 255
91#define SME_QOS_TSPEC_IE_LENGTH 61
92#define SME_QOS_TSPEC_IE_TYPE 2
93#define SME_QOS_MIN_FLOW_ID 1
94#define SME_QOS_MAX_FLOW_ID 0xFFFFFFFE
95#define SME_QOS_INVALID_FLOW_ID 0xFFFFFFFF
96/* per the WMM Specification v1.2 Section 2.2.10 */
97/* The Dialog Token field shall be set [...] to a non-zero value */
98#define SME_QOS_MIN_DIALOG_TOKEN 1
99#define SME_QOS_MAX_DIALOG_TOKEN 0xFF
100/*--------------------------------------------------------------------------
101 Type declarations
102 ------------------------------------------------------------------------*/
103/*---------------------------------------------------------------------------
104 Enumeration of the various states in the QoS state m/c
105 ---------------------------------------------------------------------------*/
106typedef enum {
107 SME_QOS_CLOSED = 0,
108 SME_QOS_INIT,
109 SME_QOS_LINK_UP,
110 SME_QOS_REQUESTED,
111 SME_QOS_QOS_ON,
112 SME_QOS_HANDOFF,
113
114} sme_QosStates;
115/*---------------------------------------------------------------------------
116 Enumeration of the various Release QoS trigger
117 ---------------------------------------------------------------------------*/
118typedef enum {
119 SME_QOS_RELEASE_DEFAULT = 0,
120 SME_QOS_RELEASE_BY_AP,
121} sme_QosRelTriggers;
122/*---------------------------------------------------------------------------
123 Enumeration of the various QoS cmds
124 ---------------------------------------------------------------------------*/
125typedef enum {
126 SME_QOS_SETUP_REQ = 0,
127 SME_QOS_RELEASE_REQ,
128 SME_QOS_MODIFY_REQ,
129 SME_QOS_RESEND_REQ,
130 SME_QOS_CMD_MAX
131} sme_QosCmdType;
132/*---------------------------------------------------------------------------
133 Enumeration of the various QoS reason codes to be used in the Flow list
134 ---------------------------------------------------------------------------*/
135typedef enum {
136 SME_QOS_REASON_SETUP = 0,
137 SME_QOS_REASON_RELEASE,
138 SME_QOS_REASON_MODIFY,
139 SME_QOS_REASON_MODIFY_PENDING,
140 SME_QOS_REASON_REQ_SUCCESS,
141 SME_QOS_REASON_MAX
142} sme_QosReasonType;
143
144/*---------------------------------------------------------------------------
145 Table to map user priority passed in as an argument to appropriate Access
146 Category as specified in 802.11e/WMM
147 ---------------------------------------------------------------------------*/
148sme_QosEdcaAcType sme_qos_u_pto_ac_map[SME_QOS_WMM_UP_MAX] = {
149 SME_QOS_EDCA_AC_BE, /* User Priority 0 */
150 SME_QOS_EDCA_AC_BK, /* User Priority 1 */
151 SME_QOS_EDCA_AC_BK, /* User Priority 2 */
152 SME_QOS_EDCA_AC_BE, /* User Priority 3 */
153 SME_QOS_EDCA_AC_VI, /* User Priority 4 */
154 SME_QOS_EDCA_AC_VI, /* User Priority 5 */
155 SME_QOS_EDCA_AC_VO, /* User Priority 6 */
156 SME_QOS_EDCA_AC_VO /* User Priority 7 */
157};
158
159/*---------------------------------------------------------------------------
160 Table to map access category (AC) to appropriate user priority as specified
161 in 802.11e/WMM
162 Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs
163 Mapping is done for consistency
164 ---------------------------------------------------------------------------*/
165sme_QosWmmUpType sme_qos_a_cto_up_map[SME_QOS_EDCA_AC_MAX] = {
166 SME_QOS_WMM_UP_BE, /* AC BE */
167 SME_QOS_WMM_UP_BK, /* AC BK */
168 SME_QOS_WMM_UP_VI, /* AC VI */
169 SME_QOS_WMM_UP_VO /* AC VO */
170};
171
172/*---------------------------------------------------------------------------
173 DESCRIPTION
174 SME QoS module's FLOW Link List structure. This list can hold information per
175 flow/request, like TSPEC params requested, which AC it is running on
176 ---------------------------------------------------------------------------*/
177typedef struct sme_QosFlowInfoEntry_s {
178 tListElem link; /* list links */
179 uint8_t sessionId;
180 uint8_t tspec_mask;
181 sme_QosReasonType reason;
182 uint32_t QosFlowID;
183 sme_QosEdcaAcType ac_type;
184 sme_QosWmmTspecInfo QoSInfo;
185 void *HDDcontext;
186 sme_QosCallback QoSCallback;
187 bool hoRenewal; /* set to true while re-negotiating flows after */
188 /* handoff, will set to false once done with */
189 /* the process. Helps SME to decide if at all */
190 /* to notify HDD/LIS for flow renewal after HO */
191} sme_QosFlowInfoEntry;
192/*---------------------------------------------------------------------------
193 DESCRIPTION
194 SME QoS module's setup request cmd related information structure.
195 ---------------------------------------------------------------------------*/
196typedef struct sme_qos_setupCmdInfo_s {
197 uint32_t QosFlowID;
198 sme_QosWmmTspecInfo QoSInfo;
199 void *HDDcontext;
200 sme_QosCallback QoSCallback;
201 sme_QosWmmUpType UPType;
202 bool hoRenewal; /* set to true while re-negotiating flows after */
203 /* handoff, will set to false once done with */
204 /* the process. Helps SME to decide if at all */
205 /* to notify HDD/LIS for flow renewal after HO */
206} sme_qos_setupCmdInfo;
207/*---------------------------------------------------------------------------
208 DESCRIPTION
209 SME QoS module's modify cmd related information structure.
210 ---------------------------------------------------------------------------*/
211typedef struct sme_QosModifyCmdInfo_s {
212 uint32_t QosFlowID;
213 sme_QosEdcaAcType ac;
214 sme_QosWmmTspecInfo QoSInfo;
215} sme_QosModifyCmdInfo;
216/*---------------------------------------------------------------------------
217 DESCRIPTION
218 SME QoS module's resend cmd related information structure.
219 ---------------------------------------------------------------------------*/
220typedef struct sme_QosResendCmdInfo_s {
221 uint8_t tspecMask;
222 sme_QosEdcaAcType ac;
223 sme_QosWmmTspecInfo QoSInfo;
224} sme_QosResendCmdInfo;
225/*---------------------------------------------------------------------------
226 DESCRIPTION
227 SME QoS module's release cmd related information structure.
228 ---------------------------------------------------------------------------*/
229typedef struct sme_QosReleaseCmdInfo_s {
230 uint32_t QosFlowID;
231} sme_QosReleaseCmdInfo;
232/*---------------------------------------------------------------------------
233 DESCRIPTION
234 SME QoS module's buffered cmd related information structure.
235 ---------------------------------------------------------------------------*/
236typedef struct sme_QosCmdInfo_s {
237 sme_QosCmdType command;
238 tpAniSirGlobal pMac;
239 uint8_t sessionId;
240 union {
241 sme_qos_setupCmdInfo setupCmdInfo;
242 sme_QosModifyCmdInfo modifyCmdInfo;
243 sme_QosResendCmdInfo resendCmdInfo;
244 sme_QosReleaseCmdInfo releaseCmdInfo;
245 } u;
246} sme_QosCmdInfo;
247/*---------------------------------------------------------------------------
248 DESCRIPTION
249 SME QoS module's buffered cmd List structure. This list can hold information
250 related to any pending cmd from HDD
251 ---------------------------------------------------------------------------*/
252typedef struct sme_QosCmdInfoEntry_s {
253 tListElem link; /* list links */
254 sme_QosCmdInfo cmdInfo;
255} sme_QosCmdInfoEntry;
256/*---------------------------------------------------------------------------
257 DESCRIPTION
258 SME QoS module's Per AC information structure. This can hold information on
259 how many flows running on the AC, the current, previous states the AC is in
260 ---------------------------------------------------------------------------*/
261typedef struct sme_QosACInfo_s {
262 uint8_t num_flows[SME_QOS_TSPEC_INDEX_MAX];
263 sme_QosStates curr_state;
264 sme_QosStates prev_state;
265 sme_QosWmmTspecInfo curr_QoSInfo[SME_QOS_TSPEC_INDEX_MAX];
266 sme_QosWmmTspecInfo requested_QoSInfo[SME_QOS_TSPEC_INDEX_MAX];
Deepak Dhamdhereadd334b2016-01-09 23:40:33 -0800267 /* reassoc requested for APSD */
268 bool reassoc_pending;
269 /*
270 * As per WMM spec there could be max 2 TSPEC running on the same
271 * AC with different direction. We will refer each TSPEC with an index
272 */
273 /* status showing if both the indices are in use */
274 uint8_t tspec_mask_status;
275 /* tspec negotiation going on for which index */
276 uint8_t tspec_pending;
277 /* set to true while re-negotiating flows after */
278 bool hoRenewal;
279 /*
280 * handoff, will set to false once done with the process. Helps SME to
281 * decide if at all to notify HDD/LIS for flow renewal after HO
282 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800283 uint8_t ricIdentifier[SME_QOS_TSPEC_INDEX_MAX];
Deepak Dhamdhereadd334b2016-01-09 23:40:33 -0800284 /*
285 * stores the ADD TS response for each AC. The ADD TS response is
286 * formed by parsing the RIC received in the the reassoc response
287 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 tSirAddtsRsp addTsRsp[SME_QOS_TSPEC_INDEX_MAX];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 sme_QosRelTriggers relTrig;
290
291} sme_QosACInfo;
292/*---------------------------------------------------------------------------
293 DESCRIPTION
294 SME QoS module's Per session information structure. This can hold information
295 on the state of the session
296 ---------------------------------------------------------------------------*/
297typedef struct sme_QosSessionInfo_s {
298 /* what is this entry's session id */
299 uint8_t sessionId;
300 /* is the session currently active */
301 bool sessionActive;
302 /* All AC info for this session */
303 sme_QosACInfo ac_info[SME_QOS_EDCA_AC_MAX];
304 /* Bitmask of the ACs with APSD on */
305 /* Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored */
306 uint8_t apsdMask;
307 /* association information for this session */
308 sme_QosAssocInfo assocInfo;
309 /* ID assigned to our reassoc request */
310 uint32_t roamID;
311 /* maintaining a powersave status in QoS module, to be fed back to PMC at */
312 /* times through the sme_qos_pmc_check_routine */
313 bool readyForPowerSave;
314 /* are we in the process of handing off to a different AP */
315 bool handoffRequested;
316 /* following reassoc or AddTS has UAPSD already been requested from PMC */
317 bool uapsdAlreadyRequested;
318 /* commands that are being buffered for this session */
319 tDblLinkList bufferedCommandList;
320
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321 bool ftHandoffInProgress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322
323} sme_QosSessionInfo;
324/*---------------------------------------------------------------------------
325 DESCRIPTION
326 Search key union. We can use the flowID, ac type, or reason to find an entry
327 in the flow list
328 ---------------------------------------------------------------------------*/
329typedef union sme_QosSearchKey_s {
330 uint32_t QosFlowID;
331 sme_QosEdcaAcType ac_type;
332 sme_QosReasonType reason;
333} sme_QosSearchKey;
334/*---------------------------------------------------------------------------
335 DESCRIPTION
336 We can either use the flowID or the ac type to find an entry in the flow list.
337 The index is a bitmap telling us which key to use. Starting from LSB,
338 bit 0 - Flow ID
339 bit 1 - AC type
340 ---------------------------------------------------------------------------*/
341typedef struct sme_QosSearchInfo_s {
342 uint8_t sessionId;
343 uint8_t index;
344 sme_QosSearchKey key;
345 sme_QosWmmDirType direction;
346 uint8_t tspec_mask;
347} sme_QosSearchInfo;
348/*---------------------------------------------------------------------------
349 DESCRIPTION
350 SME QoS module's internal control block.
351 ---------------------------------------------------------------------------*/
352struct sme_qos_cb_s {
353 /* global Mac pointer */
354 tpAniSirGlobal pMac;
355 /* All Session Info */
356 sme_QosSessionInfo sessionInfo[CSR_ROAM_SESSION_MAX];
357 /* All FLOW info */
358 tDblLinkList flow_list;
359 /* default TSPEC params */
360 sme_QosWmmTspecInfo def_QoSInfo[SME_QOS_EDCA_AC_MAX];
361 /* counter for assigning Flow IDs */
362 uint32_t nextFlowId;
363 /* counter for assigning Dialog Tokens */
364 uint8_t nextDialogToken;
365} sme_qos_cb;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530366typedef QDF_STATUS (*sme_QosProcessSearchEntry)(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800367 tListElem *pEntry);
368
369sme_QosStatusType sme_qos_internal_setup_req(tpAniSirGlobal pMac,
370 uint8_t sessionId,
371 sme_QosWmmTspecInfo *pQoSInfo,
372 sme_QosCallback QoSCallback,
373 void *HDDcontext,
374 sme_QosWmmUpType UPType,
375 uint32_t QosFlowID,
376 bool buffered_cmd, bool hoRenewal);
377sme_QosStatusType sme_qos_internal_modify_req(tpAniSirGlobal pMac,
378 sme_QosWmmTspecInfo *pQoSInfo,
379 uint32_t QosFlowID,
380 bool buffered_cmd);
381sme_QosStatusType sme_qos_internal_release_req(tpAniSirGlobal pMac,
382 uint32_t QosFlowID,
383 bool buffered_cmd);
384sme_QosStatusType sme_qos_setup(tpAniSirGlobal pMac,
385 uint8_t sessionId,
386 sme_QosWmmTspecInfo *pTspec_Info,
387 sme_QosEdcaAcType ac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530388QDF_STATUS sme_qos_add_ts_req(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800389 uint8_t sessionId,
390 sme_QosWmmTspecInfo *pTspec_Info,
391 sme_QosEdcaAcType ac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530392QDF_STATUS sme_qos_del_ts_req(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 uint8_t sessionId,
394 sme_QosEdcaAcType ac, uint8_t tspec_mask);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530395QDF_STATUS sme_qos_process_add_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf);
396QDF_STATUS sme_qos_process_del_ts_ind(tpAniSirGlobal pMac, void *pMsgBuf);
397QDF_STATUS sme_qos_process_del_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf);
398QDF_STATUS sme_qos_process_assoc_complete_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800399 void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530400QDF_STATUS sme_qos_process_reassoc_req_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530402QDF_STATUS sme_qos_process_reassoc_success_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800403 uint8_t sessionId, void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530404QDF_STATUS sme_qos_process_reassoc_failure_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405 uint8_t sessionId, void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530406QDF_STATUS sme_qos_process_disconnect_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800407 void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530408QDF_STATUS sme_qos_process_join_req_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800409 void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530410QDF_STATUS sme_qos_process_handoff_assoc_req_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 uint8_t sessionId,
412 void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530413QDF_STATUS sme_qos_process_handoff_success_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800414 uint8_t sessionId, void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530415QDF_STATUS sme_qos_process_handoff_failure_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800416 uint8_t sessionId, void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530417QDF_STATUS sme_qos_process_preauth_success_ind(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 uint8_t sessionId,
419 void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530420QDF_STATUS sme_qos_process_set_key_success_ind(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 uint8_t sessionId, void *pEvent_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530422QDF_STATUS sme_qos_process_aggr_qos_rsp(tpAniSirGlobal pMac, void *pMsgBuf);
423QDF_STATUS sme_qos_ft_aggr_qos_req(tpAniSirGlobal pMac, uint8_t sessionId);
424QDF_STATUS sme_qos_process_add_ts_success_rsp(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425 uint8_t sessionId,
426 tSirAddtsRspInfo *pRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530427QDF_STATUS sme_qos_process_add_ts_failure_rsp(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 uint8_t sessionId,
429 tSirAddtsRspInfo *pRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530430QDF_STATUS sme_qos_aggregate_params(sme_QosWmmTspecInfo *pInput_Tspec_Info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431 sme_QosWmmTspecInfo *pCurrent_Tspec_Info,
432 sme_QosWmmTspecInfo *pUpdated_Tspec_Info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530433static QDF_STATUS sme_qos_update_params(uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800434 sme_QosEdcaAcType ac,
435 uint8_t tspec_mask,
436 sme_QosWmmTspecInfo *pTspec_Info);
437sme_QosWmmUpType sme_qos_ac_to_up(sme_QosEdcaAcType ac);
438sme_QosEdcaAcType sme_qos_up_to_ac(sme_QosWmmUpType up);
439bool sme_qos_is_acm(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
440 sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes);
441tListElem *sme_qos_find_in_flow_list(sme_QosSearchInfo search_key);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530442QDF_STATUS sme_qos_find_all_in_flow_list(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 sme_QosSearchInfo search_key,
444 sme_QosProcessSearchEntry fnp);
445static void sme_qos_state_transition(uint8_t sessionId,
446 sme_QosEdcaAcType ac,
447 sme_QosStates new_state);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530448QDF_STATUS sme_qos_buffer_cmd(sme_QosCmdInfo *pcmd, bool insert_head);
449static QDF_STATUS sme_qos_process_buffered_cmd(uint8_t sessionId);
450QDF_STATUS sme_qos_save_assoc_info(sme_QosSessionInfo *pSession,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800451 sme_QosAssocInfo *pAssoc_info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530452QDF_STATUS sme_qos_setup_fnp(tpAniSirGlobal pMac, tListElem *pEntry);
453QDF_STATUS sme_qos_modification_notify_fnp(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 tListElem *pEntry);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530455QDF_STATUS sme_qos_modify_fnp(tpAniSirGlobal pMac, tListElem *pEntry);
456QDF_STATUS sme_qos_del_ts_ind_fnp(tpAniSirGlobal pMac, tListElem *pEntry);
457QDF_STATUS sme_qos_reassoc_success_ev_fnp(tpAniSirGlobal pMac, tListElem *pEntry);
458QDF_STATUS sme_qos_add_ts_failure_fnp(tpAniSirGlobal pMac, tListElem *pEntry);
459QDF_STATUS sme_qos_add_ts_success_fnp(tpAniSirGlobal pMac, tListElem *pEntry);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460static bool sme_qos_is_rsp_pending(uint8_t sessionId, sme_QosEdcaAcType ac);
461static bool sme_qos_is_uapsd_active(void);
462
463void sme_qos_pmc_offload_start_uapsd_callback(void *callbackContext,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530464 uint32_t sessionId, QDF_STATUS status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465bool sme_qos_pmc_offload_check_routine(void *callbackContext, uint32_t sessionId);
466
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530467static QDF_STATUS sme_qos_buffer_existing_flows(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800468 uint8_t sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530469static QDF_STATUS sme_qos_delete_existing_flows(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800470 uint8_t sessionId);
471static void sme_qos_cleanup_ctrl_blk_for_handoff(tpAniSirGlobal pMac,
472 uint8_t sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530473static QDF_STATUS sme_qos_delete_buffered_requests(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 uint8_t sessionId);
475bool sme_qos_validate_requested_params(tpAniSirGlobal pMac,
476 sme_QosWmmTspecInfo *pQoSInfo,
477 uint8_t sessionId);
478
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530479extern QDF_STATUS sme_acquire_global_lock(tSmeStruct *psSme);
480extern QDF_STATUS sme_release_global_lock(tSmeStruct *psSme);
481static QDF_STATUS qos_issue_command(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482 eSmeCommandType cmdType,
483 sme_QosWmmTspecInfo *pQoSInfo,
484 sme_QosEdcaAcType ac, uint8_t tspec_mask);
485/*
486 sme_qos_re_request_add_ts to re-send AddTS for the combined QoS request
487 */
488static sme_QosStatusType sme_qos_re_request_add_ts(tpAniSirGlobal pMac,
489 uint8_t sessionId,
490 sme_QosWmmTspecInfo *pQoSInfo,
491 sme_QosEdcaAcType ac,
492 uint8_t tspecMask);
493static void sme_qos_init_a_cs(tpAniSirGlobal pMac, uint8_t sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530494static QDF_STATUS sme_qos_request_reassoc(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 tCsrRoamModifyProfileFields *
496 pModFields, bool fForce);
497static uint32_t sme_qos_assign_flow_id(void);
498static uint8_t sme_qos_assign_dialog_token(void);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530499static QDF_STATUS sme_qos_update_tspec_mask(uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 sme_QosSearchInfo search_key,
501 uint8_t new_tspec_mask);
502
503/* External APIs definitions */
504
505/**
506 * sme_qos_open() - called to initialize SME QoS module.
507 * @pMac: global MAC context
508 *
509 * This function must be called before any API call to
510 * SME QoS module.
511 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530512 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800513 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530514QDF_STATUS sme_qos_open(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515{
516 sme_QosSessionInfo *pSession;
517 uint8_t sessionId;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530518 QDF_STATUS status;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530519 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 "%s: %d: initializing SME-QoS module", __func__, __LINE__);
521 /* init the control block */
522 /* (note that this will make all sessions invalid) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530523 qdf_mem_zero(&sme_qos_cb, sizeof(sme_qos_cb));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524 sme_qos_cb.pMac = pMac;
525 sme_qos_cb.nextFlowId = SME_QOS_MIN_FLOW_ID;
526 sme_qos_cb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN;
527 /* init flow list */
528 status = csr_ll_open(pMac->hHdd, &sme_qos_cb.flow_list);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530529 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530530 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800531 "%s: %d: cannot initialize Flow List",
532 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530533 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534 }
535
536 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) {
537 pSession = &sme_qos_cb.sessionInfo[sessionId];
538 pSession->sessionId = sessionId;
539 /* initialize the session's per-AC information */
540 sme_qos_init_a_cs(pMac, sessionId);
541 /* initialize the session's buffered command list */
542 status = csr_ll_open(pMac->hHdd, &pSession->bufferedCommandList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530543 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530544 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545 "%s: %d: cannot initialize cmd list for session %d",
546 __func__, __LINE__, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530547 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 }
549 pSession->readyForPowerSave = true;
550 }
551
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530552 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 "%s: %d: done initializing SME-QoS module",
554 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530555 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556}
557
558/* --------------------------------------------------------------------------
559 \brief sme_qos_close() - To close down SME QoS module. There should not be
560 any API call into this module after calling this function until another
561 call of sme_qos_open.
562 \param pMac - Pointer to the global MAC parameter structure.
563
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530564 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565 ----------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530566QDF_STATUS sme_qos_close(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567{
568 sme_QosSessionInfo *pSession;
569 sme_QosEdcaAcType ac;
570 uint8_t sessionId;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530571 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 "%s: %d: closing down SME-QoS", __func__, __LINE__);
573
574 /* cleanup control block */
575 /* close the flow list */
576 csr_ll_close(&sme_qos_cb.flow_list);
577 /* shut down all of the sessions */
578 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) {
579 pSession = &sme_qos_cb.sessionInfo[sessionId];
580 if (pSession == NULL)
581 continue;
582
583 sme_qos_init_a_cs(pMac, sessionId);
584 /* this session doesn't require UAPSD */
585 pSession->apsdMask = 0;
586
587 pSession->uapsdAlreadyRequested = false;
588 pSession->handoffRequested = false;
589 pSession->readyForPowerSave = true;
590 pSession->roamID = 0;
591 /* need to clean up buffered req */
592 sme_qos_delete_buffered_requests(pMac, sessionId);
593 /* need to clean up flows */
594 sme_qos_delete_existing_flows(pMac, sessionId);
595
596 /* Clean up the assoc info if already allocated */
597 if (pSession->assocInfo.pBssDesc) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530598 qdf_mem_free(pSession->assocInfo.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599 pSession->assocInfo.pBssDesc = NULL;
600 }
601 /* close the session's buffered command list */
602 csr_ll_close(&pSession->bufferedCommandList);
603 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
604 sme_qos_state_transition(sessionId, ac, SME_QOS_CLOSED);
605 }
606 pSession->sessionActive = false;
607 pSession->readyForPowerSave = true;
608 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530609 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 "%s: %d: closed down QoS", __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530611 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612}
613
614/**
615 * sme_qos_setup_req() - The SME QoS API exposed to HDD to request for QoS
616 * on a particular AC.
617 * @hHal: The handle returned by mac_open.
618 * @sessionId: sessionId returned by sme_open_session.
619 * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
620 * related info as defined above, provided by HDD
621 * @QoSCallback: The callback which is registered per flow while
622 * requesting for QoS. Used for any notification for the
623 * flow (i.e. setup success/failure/release) which needs to
624 * be sent to HDD
625 * @HDDcontext: A cookie passed by HDD to be used by SME during any QoS
626 * notification (through the callabck) to HDD
627 * @UPType: Useful only if HDD or any other upper layer module (BAP etc.)
628 * looking for implicit QoS setup, in that
629 * case, the pQoSInfo will be NULL & SME will know about the AC
630 * (from the UP provided in this param) QoS is requested on
631 * @pQosFlowID: Identification per flow running on each AC generated by
632 * SME. It is only meaningful if the QoS setup for the flow is
633 * successful
634 * This function should be called after a link has been
635 * established, i.e. STA is associated with an AP etc. If the request involves
636 * admission control on the requested AC, HDD needs to provide the necessary
637 * Traffic Specification (TSPEC) parameters otherwise SME is going to use the
638 * default params.
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530639 * Return: QDF_STATUS_SUCCESS - Setup is successful.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640 * Other status means Setup request failed
641 */
642sme_QosStatusType sme_qos_setup_req(tHalHandle hHal, uint32_t sessionId,
643 sme_QosWmmTspecInfo *pQoSInfo,
644 sme_QosCallback QoSCallback,
645 void *HDDcontext,
646 sme_QosWmmUpType UPType,
647 uint32_t *pQosFlowID)
648{
649 sme_QosSessionInfo *pSession;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530650 QDF_STATUS lock_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
652 sme_QosStatusType status;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530653 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 "%s: %d: QoS Setup requested by client on session %d",
655 __func__, __LINE__, sessionId);
656 lock_status = sme_acquire_global_lock(&pMac->sme);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530657 if (!QDF_IS_STATUS_SUCCESS(lock_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530658 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659 "%s: %d: Unable to obtain lock", __func__, __LINE__);
660 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
661 }
662 /* Make sure the session is valid */
663 if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530664 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 "%s: %d: Supplied Session ID %d is invalid",
666 __func__, __LINE__, sessionId);
667 status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
668 } else {
669 /* Make sure the session is active */
670 pSession = &sme_qos_cb.sessionInfo[sessionId];
671 if (!pSession->sessionActive) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530672 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800673 "%s: %d: Supplied Session ID %d is inactive",
674 __func__, __LINE__, sessionId);
675 status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
676 } else {
677 /* Assign a Flow ID */
678 *pQosFlowID = sme_qos_assign_flow_id();
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530679 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 "%s: %d: QoS request on session %d assigned Flow ID %d",
681 __func__, __LINE__, sessionId, *pQosFlowID);
682 /* Call the internal function for QoS setup, */
683 /* adding a layer of abstraction */
684 status =
685 sme_qos_internal_setup_req(pMac, (uint8_t) sessionId,
686 pQoSInfo, QoSCallback,
687 HDDcontext, UPType,
688 *pQosFlowID, false,
689 false);
690 }
691 }
692 sme_release_global_lock(&pMac->sme);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530693 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 "%s: %d: QoS setup return status on session %d is %d",
695 __func__, __LINE__, sessionId, status);
696 return status;
697}
698
699/**
700 * sme_qos_modify_req() - The SME QoS API exposed to HDD to request for
701 * modification of certain QoS params on a flow running on a particular AC.
702 * @hHal: The handle returned by mac_open.
703 * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
704 * related info as defined above, provided by HDD
705 * @QosFlowID: Identification per flow running on each AC generated by
706 * SME. It is only meaningful if the QoS setup for the flow has
707 * been successful already
708 *
709 * This function should be called after a link has been established,
710 * i.e. STA is associated with an AP etc. & a QoS setup has been succesful for
711 * that flow. If the request involves admission control on the requested AC,
712 * HDD needs to provide the necessary Traffic Specification (TSPEC) parameters &
713 * SME might start the renegotiation process through ADDTS.
714 *
715 * Return: SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful.
716 * Other status means request failed
717 */
718sme_QosStatusType sme_qos_modify_req(tHalHandle hHal,
719 sme_QosWmmTspecInfo *pQoSInfo,
720 uint32_t QosFlowID)
721{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530722 QDF_STATUS lock_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800723 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
724 sme_QosStatusType status;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530725 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 "%s: %d: QoS Modify requested by client for Flow %d",
727 __func__, __LINE__, QosFlowID);
728 lock_status = sme_acquire_global_lock(&pMac->sme);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530729 if (!QDF_IS_STATUS_SUCCESS(lock_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530730 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731 "%s: %d: Unable to obtain lock", __func__, __LINE__);
732 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
733 }
734 /* Call the internal function for QoS modify, adding a layer of abstraction */
735 status = sme_qos_internal_modify_req(pMac, pQoSInfo, QosFlowID, false);
736 sme_release_global_lock(&pMac->sme);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530737 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738 "%s: %d: QoS Modify return status on Flow %d is %d",
739 __func__, __LINE__, QosFlowID, status);
740 return status;
741}
742
743/**
744 * sme_qos_release_req() - The SME QoS API exposed to HDD to request for
745 * releasing a QoS flow running on a particular AC.
746 *
747 * @hHal: The handle returned by mac_open.
748 * @QosFlowID: Identification per flow running on each AC generated by SME
749 * It is only meaningful if the QoS setup for the flow is successful
750 *
751 * This function should be called only if a QoS is set up with a valid FlowID.
752 * HDD sould invoke this API only if an explicit request for QoS release has
753 * come from Application
754 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530755 * Return: QDF_STATUS_SUCCESS - Release is successful.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800756 */
757sme_QosStatusType sme_qos_release_req(tHalHandle hHal, uint32_t QosFlowID)
758{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530759 QDF_STATUS lock_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
761 sme_QosStatusType status;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530762 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763 "%s: %d: QoS Release requested by client for Flow %d",
764 __func__, __LINE__, QosFlowID);
765 lock_status = sme_acquire_global_lock(&pMac->sme);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766 if (!QDF_IS_STATUS_SUCCESS(lock_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530767 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768 "%s: %d: Unable to obtain lock", __func__, __LINE__);
769 return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
770 }
771 /* Call the internal function for QoS release, adding a layer of abstraction */
772 status = sme_qos_internal_release_req(pMac, QosFlowID, false);
773 sme_release_global_lock(&pMac->sme);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530774 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 "%s: %d: QoS Release return status on Flow %d is %d",
776 __func__, __LINE__, QosFlowID, status);
777 return status;
778}
779
780void qos_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand)
781{
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530782 qdf_mem_zero(&pCommand->u.qosCmd, sizeof(tGenericQosCmd));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 sme_release_command(pMac, pCommand);
784}
785
786/**
787 * sme_qos_msg_processor() - Processes QOS messages
788 * @mac_ctx: Pointer to the global MAC parameter structure.
789 * @msg_type: the type of msg passed by PE as defined in wni_api.h
790 * @msg: a pointer to a buffer that maps to various structures bases.
791 *
792 * sme_process_msg() calls this function for the messages that
793 * are handled by SME QoS module.
794 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530795 * Return: QDF_STATUS enumeration.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530797QDF_STATUS sme_qos_msg_processor(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798 uint16_t msg_type, void *msg)
799{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530800 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800801 tListElem *entry = NULL;
802 tSmeCmd *command;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530803 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 FL(" msg = %d for QoS"), msg_type);
805 /* switch on the msg type & make the state transition accordingly */
806 switch (msg_type) {
807 case eWNI_SME_ADDTS_RSP:
808 entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList,
809 LL_ACCESS_LOCK);
810 if (NULL == entry)
811 break;
812 command = GET_BASE_ADDR(entry, tSmeCmd, Link);
813 if (eSmeCommandAddTs == command->command) {
814 status = sme_qos_process_add_ts_rsp(mac_ctx, msg);
815 if (csr_ll_remove_entry
816 (&mac_ctx->sme.smeCmdActiveList, entry,
817 LL_ACCESS_LOCK)) {
818 qos_release_command(mac_ctx, command);
819 }
820 sme_process_pending_queue(mac_ctx);
821 }
822 break;
823 case eWNI_SME_DELTS_RSP:
824 entry =
825 csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList,
826 LL_ACCESS_LOCK);
827 if (NULL == entry)
828 break;
829 command = GET_BASE_ADDR(entry, tSmeCmd, Link);
830 if (eSmeCommandDelTs == command->command) {
831 status = sme_qos_process_del_ts_rsp(mac_ctx, msg);
832 if (csr_ll_remove_entry
833 (&mac_ctx->sme.smeCmdActiveList, entry,
834 LL_ACCESS_LOCK)) {
835 qos_release_command(mac_ctx, command);
836 }
837 sme_process_pending_queue(mac_ctx);
838 }
839 break;
840 case eWNI_SME_DELTS_IND:
841 status = sme_qos_process_del_ts_ind(mac_ctx, msg);
842 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843 case eWNI_SME_FT_AGGR_QOS_RSP:
844 status = sme_qos_process_aggr_qos_rsp(mac_ctx, msg);
845 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 default:
847 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530848 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 FL("unknown msg type = %d"),
850 msg_type);
851 break;
852 }
853 return status;
854}
855
856/**
857 * sme_qos_validate_params() - validate SME QOS parameters.
858 * @pMac: Pointer to the global MAC parameter structure.
859 * @pBssDesc: Pointer to the BSS Descriptor information passed down by
860 * CSR to PE while issuing the Join request
861 *
862 * The SME QoS API exposed to CSR to validate AP
863 * capabilities regarding QoS support & any other QoS parameter validation.
864 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530865 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530867QDF_STATUS sme_qos_validate_params(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868 tSirBssDescription *pBssDesc)
869{
870 tDot11fBeaconIEs *pIes = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530871 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530872 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 "%s: %d: validation for QAP & APSD", __func__, __LINE__);
874 do {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530875 if (!QDF_IS_STATUS_SUCCESS(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876 csr_get_parsed_bss_description_ies(
877 pMac, pBssDesc, &pIes))) {
878 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530879 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800880 "%s: %d: csr_get_parsed_bss_description_ies() failed",
881 __func__, __LINE__);
882 break;
883 }
884 /* check if the AP is QAP & it supports APSD */
885 if (!CSR_IS_QOS_BSS(pIes)) {
886 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530887 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 "%s: %d: AP doesn't support QoS",
889 __func__, __LINE__);
890
891 break;
892 }
893 if (!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) &&
894 !(pIes->WMMInfoAp.uapsd)) {
895 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530896 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800897 "%s: %d: AP doesn't support APSD",
898 __func__, __LINE__);
899 break;
900 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530901 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 } while (0);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530903 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 "%s: %d: validated with status = %d",
905 __func__, __LINE__, status);
906 if (pIes) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530907 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908 }
909 return status;
910}
911
912/*--------------------------------------------------------------------------
913 \brief sme_qos_csr_event_ind() - The QoS sub-module in SME expects notifications
914 from CSR when certain events occur as mentioned in sme_qos_csr_event_indType.
915 \param pMac - Pointer to the global MAC parameter structure.
916 \param ind - The event occurred of type sme_qos_csr_event_indType.
917 \param pEvent_info - Information related to the event
918
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530919 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920
921 \sa
922
923 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530924QDF_STATUS sme_qos_csr_event_ind(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925 uint8_t sessionId,
926 sme_qos_csr_event_indType ind, void *pEvent_info)
927{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530928 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530929 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800930 "%s: %d: On Session %d Event %d received from CSR",
931 __func__, __LINE__, sessionId, ind);
932 switch (ind) {
933 case SME_QOS_CSR_ASSOC_COMPLETE:
934 /* expecting assoc info in pEvent_info */
935 status =
936 sme_qos_process_assoc_complete_ev(pMac, sessionId, pEvent_info);
937 break;
938 case SME_QOS_CSR_REASSOC_REQ:
939 /* nothing expected in pEvent_info */
940 status =
941 sme_qos_process_reassoc_req_ev(pMac, sessionId, pEvent_info);
942 break;
943 case SME_QOS_CSR_REASSOC_COMPLETE:
944 /* expecting assoc info in pEvent_info */
945 status =
946 sme_qos_process_reassoc_success_ev(pMac, sessionId,
947 pEvent_info);
948 break;
949 case SME_QOS_CSR_REASSOC_FAILURE:
950 /* nothing expected in pEvent_info */
951 status =
952 sme_qos_process_reassoc_failure_ev(pMac, sessionId,
953 pEvent_info);
954 break;
955 case SME_QOS_CSR_DISCONNECT_REQ:
956 case SME_QOS_CSR_DISCONNECT_IND:
957 /* nothing expected in pEvent_info */
958 status =
959 sme_qos_process_disconnect_ev(pMac, sessionId, pEvent_info);
960 break;
961 case SME_QOS_CSR_JOIN_REQ:
962 /* nothing expected in pEvent_info */
963 status = sme_qos_process_join_req_ev(pMac, sessionId, pEvent_info);
964 break;
965 case SME_QOS_CSR_HANDOFF_ASSOC_REQ:
966 /* nothing expected in pEvent_info */
967 status =
968 sme_qos_process_handoff_assoc_req_ev(pMac, sessionId,
969 pEvent_info);
970 break;
971 case SME_QOS_CSR_HANDOFF_COMPLETE:
972 /* nothing expected in pEvent_info */
973 status =
974 sme_qos_process_handoff_success_ev(pMac, sessionId,
975 pEvent_info);
976 break;
977 case SME_QOS_CSR_HANDOFF_FAILURE:
978 /* nothing expected in pEvent_info */
979 status =
980 sme_qos_process_handoff_failure_ev(pMac, sessionId,
981 pEvent_info);
982 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800983 case SME_QOS_CSR_PREAUTH_SUCCESS_IND:
984 status =
985 sme_qos_process_preauth_success_ind(pMac, sessionId,
986 pEvent_info);
987 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988 case SME_QOS_CSR_SET_KEY_SUCCESS_IND:
989 status =
990 sme_qos_process_set_key_success_ind(pMac, sessionId,
991 pEvent_info);
992 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993 default:
994 /* Err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530995 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996 "%s: %d: On Session %d Unknown Event %d received from CSR",
997 __func__, __LINE__, sessionId, ind);
998 break;
999 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301000 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001 "%s: %d: On Session %d processed Event %d with status %d",
1002 __func__, __LINE__, sessionId, ind, status);
1003 return status;
1004}
1005
1006/*--------------------------------------------------------------------------
1007 \brief sme_qos_get_acm_mask() - The QoS sub-module API to find out on which ACs
1008 AP mandates Admission Control (ACM = 1)
1009 (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored)
1010 \param pMac - Pointer to the global MAC parameter structure.
1011 \param pSirBssDesc - The event occurred of type sme_qos_csr_event_indType.
1012
1013 \return a bit mask indicating for which ACs AP has ACM set to 1
1014
1015 \sa
1016
1017 --------------------------------------------------------------------------*/
1018uint8_t sme_qos_get_acm_mask(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
1019 tDot11fBeaconIEs *pIes)
1020{
1021 sme_QosEdcaAcType ac;
1022 uint8_t acm_mask = 0;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301023 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001024 "%s: %d: invoked", __func__, __LINE__);
1025 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
1026 if (sme_qos_is_acm(pMac, pSirBssDesc, ac, pIes)) {
1027 acm_mask = acm_mask | (1 << (SME_QOS_EDCA_AC_VO - ac));
1028 }
1029
1030 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301031 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001032 "%s: %d: mask is %d", __func__, __LINE__, acm_mask);
1033 return acm_mask;
1034}
1035
1036/* Internal function definitions */
1037
1038/**
1039 * sme_qos_internal_setup_req() - The SME QoS internal setup request handling
1040 * function.
1041 *
1042 * @pMac: Pointer to the global MAC parameter structure.
1043 * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
1044 * related info as defined above, provided by HDD
1045 * @QoSCallback: The callback which is registered per flow while
1046 * requesting for QoS. Used for any notification for the
1047 * flow (i.e. setup success/failure/release) which needs to
1048 * be sent to HDD
1049 * @HDDcontext: A cookie passed by HDD to be used by SME during any QoS
1050 * notification (through the callabck) to HDD
1051 * @UPType: Useful only if HDD or any other upper layer module (BAP etc.)
1052 * looking for implicit QoS setup, in that
1053 * case, the pQoSInfo will be NULL & SME will know about the AC
1054 * (from the UP provided in this param) QoS is requested on
1055 * @QosFlowID: Identification per flow running on each AC generated by
1056 * SME. It is only meaningful if the QoS setup for the flow is
1057 * successful
1058 * @buffered_cmd: tells us if the cmd was a buffered one or fresh from
1059 * client
1060 *
1061 * If the request involves admission control on the requested AC, HDD needs to
1062 * provide the necessary Traffic Specification (TSPEC) parameters otherwise SME
1063 * is going to use the default params.
1064 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301065 * Return: QDF_STATUS_SUCCESS - Setup is successful.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 * Other status means Setup request failed
1067 */
1068sme_QosStatusType sme_qos_internal_setup_req(tpAniSirGlobal pMac,
1069 uint8_t sessionId,
1070 sme_QosWmmTspecInfo *pQoSInfo,
1071 sme_QosCallback QoSCallback,
1072 void *HDDcontext,
1073 sme_QosWmmUpType UPType,
1074 uint32_t QosFlowID,
1075 bool buffered_cmd, bool hoRenewal)
1076{
1077 sme_QosSessionInfo *pSession;
1078 sme_QosACInfo *pACInfo;
1079 sme_QosEdcaAcType ac;
1080 sme_QosWmmTspecInfo Tspec_Info;
1081 sme_QosStates new_state = SME_QOS_CLOSED;
1082 sme_QosFlowInfoEntry *pentry = NULL;
1083 sme_QosCmdInfo cmd;
1084 sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
1085 uint8_t tmask = 0;
1086 uint8_t new_tmask = 0;
1087 sme_QosSearchInfo search_key;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301088 QDF_STATUS hstatus;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301089 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001090 "%s: %d: invoked on session %d for flow %d",
1091 __func__, __LINE__, sessionId, QosFlowID);
1092 pSession = &sme_qos_cb.sessionInfo[sessionId];
1093 /* if caller sent an empty TSPEC, fill up with the default one */
1094 if (!pQoSInfo) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301095 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001096 "%s: %d: caller sent an empty QoS param list, using defaults",
1097 __func__, __LINE__);
1098 /* find the AC with UPType passed in */
1099 ac = sme_qos_up_to_ac(UPType);
1100 if (SME_QOS_EDCA_AC_MAX == ac) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301101 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102 "%s: %d: invalid AC %d from UP %d",
1103 __func__, __LINE__, ac, UPType);
1104
1105 return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
1106 }
1107 Tspec_Info = sme_qos_cb.def_QoSInfo[ac];
1108 } else {
1109 /* find the AC */
1110 ac = sme_qos_up_to_ac(pQoSInfo->ts_info.up);
1111 if (SME_QOS_EDCA_AC_MAX == ac) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301112 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001113 "%s: %d: invalid AC %d from UP %d",
1114 __func__, __LINE__, ac, pQoSInfo->ts_info.up);
1115
1116 return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
1117 }
1118 /* validate QoS params */
1119 if (!sme_qos_validate_requested_params(pMac, pQoSInfo, sessionId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301120 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 "%s: %d: invalid params", __func__, __LINE__);
1122 return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP;
1123 }
1124 Tspec_Info = *pQoSInfo;
1125 }
1126 pACInfo = &pSession->ac_info[ac];
1127 /* need to vote off powersave for the duration of this request */
1128 pSession->readyForPowerSave = false;
1129 /* check to consider the following flowing scenario.
1130 * Addts request is pending on one AC, while APSD requested on another
1131 * which needs a reassoc. Will buffer a request if Addts is pending
1132 * on any AC, which will safegaurd the above scenario, & also won't
1133 * confuse PE with back to back Addts or Addts followed by Reassoc
1134 */
1135 if (sme_qos_is_rsp_pending(sessionId, ac)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301136 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 "%s: %d: buffering the setup request for flow %d in state %d "
1138 "since another request is pending",
1139 __func__, __LINE__, QosFlowID, pACInfo->curr_state);
1140 /* we need to buffer the command */
1141 cmd.command = SME_QOS_SETUP_REQ;
1142 cmd.pMac = pMac;
1143 cmd.sessionId = sessionId;
1144 cmd.u.setupCmdInfo.HDDcontext = HDDcontext;
1145 cmd.u.setupCmdInfo.QoSInfo = Tspec_Info;
1146 cmd.u.setupCmdInfo.QoSCallback = QoSCallback;
1147 cmd.u.setupCmdInfo.UPType = UPType;
1148 cmd.u.setupCmdInfo.hoRenewal = hoRenewal;
1149 cmd.u.setupCmdInfo.QosFlowID = QosFlowID;
1150 hstatus = sme_qos_buffer_cmd(&cmd, buffered_cmd);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301151 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301152 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153 "%s: %d: couldn't buffer the setup request in state = %d",
1154 __func__, __LINE__, pACInfo->curr_state);
1155 /* unable to buffer the request */
1156 /* nothing is pending so vote powersave back on */
1157 pSession->readyForPowerSave = true;
1158 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1159 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301160 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 "%s: %d: Buffered setup request for flow = %d",
1162 __func__, __LINE__, QosFlowID);
1163 return SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
1164 }
1165 /* get into the state m/c to see if the request can be granted */
1166 switch (pACInfo->curr_state) {
1167 case SME_QOS_LINK_UP:
1168 /* call the internal qos setup logic to decide on if the */
1169 /* request is NOP, or need reassoc for APSD and/or need to send out ADDTS */
1170 status = sme_qos_setup(pMac, sessionId, &Tspec_Info, ac);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301171 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001172 "%s: %d: On session %d with AC %d in state SME_QOS_LINK_UP "
1173 "sme_qos_setup returned with status %d",
1174 __func__, __LINE__, sessionId, ac, status);
1175 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) {
1176 /* we aren't waiting for a response from the AP */
1177 /* so vote powersave back on */
1178 pSession->readyForPowerSave = true;
1179 }
1180 if ((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) ||
1181 (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)
1182 || (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY ==
1183 status)) {
1184 /* we received an expected "good" status */
1185 /* create an entry in the flow list */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301186 pentry = qdf_mem_malloc(sizeof(*pentry));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001187 if (!pentry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301188 QDF_TRACE(QDF_MODULE_ID_SME,
1189 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001190 "%s: %d: couldn't allocate memory for the new "
1191 "entry in the Flow List", __func__,
1192 __LINE__);
1193 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1194 }
1195 pentry->ac_type = ac;
1196 pentry->HDDcontext = HDDcontext;
1197 pentry->QoSCallback = QoSCallback;
1198 pentry->hoRenewal = hoRenewal;
1199 pentry->QosFlowID = QosFlowID;
1200 pentry->sessionId = sessionId;
1201 /* since we are in state SME_QOS_LINK_UP this must be the */
1202 /* first TSPEC on this AC, so use index 0 (mask bit 1) */
1203 pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
1204 Tspec_Info;
1205 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) {
1206 if (pACInfo->tspec_mask_status &&
1207 !pACInfo->reassoc_pending) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301208 QDF_TRACE(QDF_MODULE_ID_SME,
1209 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210 "%s: %d: On session %d with AC %d in state "
1211 "SME_QOS_LINK_UP tspec_mask_status is %d "
1212 "but should not be set yet",
1213 __func__, __LINE__, sessionId,
1214 ac,
1215 pACInfo->tspec_mask_status);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301216 QDF_ASSERT(0);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301217 qdf_mem_free(pentry);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1219 }
1220 pACInfo->tspec_mask_status =
1221 SME_QOS_TSPEC_MASK_BIT_1_SET;
1222 if (!pACInfo->reassoc_pending) {
1223 /* we didn't request for reassoc, it must be a tspec negotiation */
1224 pACInfo->tspec_pending = 1;
1225 }
1226
1227 pentry->reason = SME_QOS_REASON_SETUP;
1228 new_state = SME_QOS_REQUESTED;
1229 } else {
1230 /* SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP or */
1231 /* SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY */
1232 pentry->reason = SME_QOS_REASON_REQ_SUCCESS;
1233 new_state = SME_QOS_QOS_ON;
1234 pACInfo->tspec_mask_status =
1235 SME_QOS_TSPEC_MASK_BIT_1_SET;
1236 pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
1237 Tspec_Info;
1238 if (buffered_cmd && !pentry->hoRenewal) {
1239 QoSCallback(pMac, HDDcontext,
1240 &pACInfo->
1241 curr_QoSInfo
1242 [SME_QOS_TSPEC_INDEX_0],
1243 status, pentry->QosFlowID);
1244 }
1245 pentry->hoRenewal = false;
1246 }
1247 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0]++;
1248
1249 /* indicate on which index the flow entry belongs to & add it to the */
1250 /* Flow List at the end */
1251 pentry->tspec_mask = pACInfo->tspec_mask_status;
1252 pentry->QoSInfo = Tspec_Info;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301253 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 "%s: %d: Creating entry on session %d at %p with flowID %d",
1255 __func__, __LINE__,
1256 sessionId, pentry, QosFlowID);
1257 csr_ll_insert_tail(&sme_qos_cb.flow_list, &pentry->link,
1258 true);
1259 } else {
1260 /* unexpected status returned by sme_qos_setup() */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301261 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001262 "%s: %d: On session %d unexpected status %d "
1263 "returned by sme_qos_setup",
1264 __func__, __LINE__, sessionId, status);
1265 new_state = pACInfo->curr_state;
1266 if (buffered_cmd && hoRenewal) {
1267 QoSCallback(pMac, HDDcontext,
1268 &pACInfo->
1269 curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
1270 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
1271 QosFlowID);
1272 }
1273 }
1274 break;
1275 case SME_QOS_HANDOFF:
1276 case SME_QOS_REQUESTED:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301277 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001278 "%s: %d: Buffering setup request for flow %d in state = %d",
1279 __func__, __LINE__, QosFlowID, pACInfo->curr_state);
1280 /* buffer cmd */
1281 cmd.command = SME_QOS_SETUP_REQ;
1282 cmd.pMac = pMac;
1283 cmd.sessionId = sessionId;
1284 cmd.u.setupCmdInfo.HDDcontext = HDDcontext;
1285 cmd.u.setupCmdInfo.QoSInfo = Tspec_Info;
1286 cmd.u.setupCmdInfo.QoSCallback = QoSCallback;
1287 cmd.u.setupCmdInfo.UPType = UPType;
1288 cmd.u.setupCmdInfo.hoRenewal = hoRenewal;
1289 cmd.u.setupCmdInfo.QosFlowID = QosFlowID;
1290 hstatus = sme_qos_buffer_cmd(&cmd, buffered_cmd);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301291 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301292 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 "%s: %d: On session %d couldn't buffer the setup "
1294 "request for flow %d in state = %d",
1295 __func__, __LINE__,
1296 sessionId, QosFlowID, pACInfo->curr_state);
1297 /* unable to buffer the request */
1298 /* nothing is pending so vote powersave back on */
1299 pSession->readyForPowerSave = true;
1300 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1301 }
1302 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
1303 new_state = pACInfo->curr_state;
1304 break;
1305 case SME_QOS_QOS_ON:
1306
1307 /* check if multiple flows running on the ac */
1308 if ((pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] > 0) ||
1309 (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0)) {
1310 /* do we need to care about the case where APSD needed on ACM = 0 below? */
1311 if (CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
1312 sme_qos_is_acm(pMac, pSession->assocInfo.pBssDesc, ac,
1313 NULL)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301314 QDF_TRACE(QDF_MODULE_ID_SME,
1315 QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316 "%s: %d: tspec_mask_status = %d for AC = %d",
1317 __func__, __LINE__,
1318 pACInfo->tspec_mask_status, ac);
1319 if (!pACInfo->tspec_mask_status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301320 QDF_TRACE(QDF_MODULE_ID_SME,
1321 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322 "%s: %d: tspec_mask_status can't be 0 for ac = %d in "
1323 "state = %d", __func__,
1324 __LINE__, ac,
1325 pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301326 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 /* unable to service the request */
1328 /* nothing is pending so vote powersave back on */
1329 pSession->readyForPowerSave = true;
1330 return status;
1331 }
1332 /* Flow aggregation */
1333 if (((pACInfo->tspec_mask_status > 0) &&
1334 (pACInfo->tspec_mask_status <=
1335 SME_QOS_TSPEC_INDEX_MAX))) {
1336 /* Either of upstream, downstream or bidirectional flows are present */
1337 /* If either of new stream or current stream is for bidirecional, aggregate
1338 * the new stream with the current streams present and send out aggregated Tspec.*/
1339 if ((Tspec_Info.ts_info.direction ==
1340 SME_QOS_WMM_TS_DIR_BOTH)
1341 || (pACInfo->
1342 curr_QoSInfo[pACInfo->
1343 tspec_mask_status -
1344 1].ts_info.
1345 direction ==
1346 SME_QOS_WMM_TS_DIR_BOTH)) {
1347 /* Aggregate the new stream with the current stream(s). */
1348 tmask =
1349 pACInfo->tspec_mask_status;
1350 }
1351 /* None of new stream or current (aggregated) streams are for bidirectional.
1352 * Check if the new stream direction matches the current stream direction. */
1353 else if (pACInfo->
1354 curr_QoSInfo[pACInfo->
1355 tspec_mask_status
1356 -
1357 1].ts_info.
1358 direction ==
1359 Tspec_Info.ts_info.direction) {
1360 /* Aggregate the new stream with the current stream(s). */
1361 tmask =
1362 pACInfo->tspec_mask_status;
1363 }
1364 /* New stream is in different direction. */
1365 else {
1366 /* No Aggregation. Mark the 2nd tpsec index also as active. */
1367 tmask =
1368 SME_QOS_TSPEC_MASK_CLEAR;
1369 new_tmask =
1370 SME_QOS_TSPEC_MASK_BIT_1_2_SET
1371 & ~pACInfo->
1372 tspec_mask_status;
1373 pACInfo->tspec_mask_status =
1374 SME_QOS_TSPEC_MASK_BIT_1_2_SET;
1375 }
1376 } else if (SME_QOS_TSPEC_MASK_BIT_1_2_SET ==
1377 pACInfo->tspec_mask_status) {
1378 /* Both uplink and downlink streams are present. */
1379 /* If new stream is bidirectional, aggregate new stream with all existing
1380 * upstreams and downstreams. Send out new aggregated tpsec. */
1381 if (Tspec_Info.ts_info.direction ==
1382 SME_QOS_WMM_TS_DIR_BOTH) {
1383 /* Only one tspec index (0) will be in use after this aggregation. */
1384 tmask =
1385 SME_QOS_TSPEC_MASK_BIT_1_2_SET;
1386 pACInfo->tspec_mask_status =
1387 SME_QOS_TSPEC_MASK_BIT_1_SET;
1388 }
1389 /* New stream is also uni-directional
1390 * Find out the tsepc index with which it needs to be aggregated */
1391 else if (pACInfo->
1392 curr_QoSInfo
1393 [SME_QOS_TSPEC_INDEX_0].
1394 ts_info.direction !=
1395 Tspec_Info.ts_info.direction) {
1396 /* Aggregate with 2nd tspec index */
1397 tmask =
1398 SME_QOS_TSPEC_MASK_BIT_2_SET;
1399 } else {
1400 /* Aggregate with 1st tspec index */
1401 tmask =
1402 SME_QOS_TSPEC_MASK_BIT_1_SET;
1403 }
1404 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301405 QDF_TRACE(QDF_MODULE_ID_SME,
1406 QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001407 "%s: %d: wrong tmask = %d",
1408 __func__, __LINE__,
1409 pACInfo->tspec_mask_status);
1410 }
1411 } else {
1412 /* ACM = 0 */
1413 /* We won't be sending a TSPEC to the AP but we still need */
1414 /* to aggregate to calculate trigger frame parameters */
1415 tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
1416 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301417 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418 "%s: %d: tmask = %d, new_tmask = %d in state = %d",
1419 __func__, __LINE__,
1420 tmask, new_tmask, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301421 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422 "%s: %d: tspec_mask_status = %d for AC = %d",
1423 __func__, __LINE__,
1424 pACInfo->tspec_mask_status, ac);
1425 if (tmask) {
1426 /* create the aggregate TSPEC */
1427 if (tmask != SME_QOS_TSPEC_MASK_BIT_1_2_SET) {
1428 hstatus =
1429 sme_qos_aggregate_params(&Tspec_Info,
1430 &pACInfo->
1431 curr_QoSInfo
1432 [tmask - 1],
1433 &pACInfo->
1434 requested_QoSInfo
1435 [tmask - 1]);
1436 } else {
1437 /* Aggregate the new bidirectional stream with the existing upstreams and
1438 * downstreams in tspec indices 0 and 1. */
1439 tmask = SME_QOS_TSPEC_MASK_BIT_1_SET;
1440
1441 hstatus = sme_qos_aggregate_params(
1442 &Tspec_Info, &pACInfo->
1443 curr_QoSInfo
1444 [SME_QOS_TSPEC_INDEX_0],
1445 &pACInfo->
1446 requested_QoSInfo
1447 [tmask - 1]);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301448 if (hstatus == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449 hstatus =
1450 sme_qos_aggregate_params
1451 (&pACInfo->
1452 curr_QoSInfo
1453 [SME_QOS_TSPEC_INDEX_1],
1454 &pACInfo->
1455 requested_QoSInfo[tmask -
1456 1],
1457 NULL);
1458 }
1459 }
1460
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301461 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301463 QDF_TRACE(QDF_MODULE_ID_SME,
1464 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 "%s: %d: failed to aggregate params",
1466 __func__, __LINE__);
1467 /* unable to service the request */
1468 /* nothing is pending so vote powersave back on */
1469 pSession->readyForPowerSave = true;
1470 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1471 }
1472 } else {
1473 if (!
1474 (new_tmask > 0
1475 && new_tmask <= SME_QOS_TSPEC_INDEX_MAX)) {
1476 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1477 }
1478 tmask = new_tmask;
1479 pACInfo->requested_QoSInfo[tmask - 1] =
1480 Tspec_Info;
1481 }
1482 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301483 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001484 "%s: %d: no flows running for ac = %d while in state = %d",
1485 __func__, __LINE__, ac, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301486 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001487 /* unable to service the request */
1488 /* nothing is pending so vote powersave back on */
1489 pSession->readyForPowerSave = true;
1490 return status;
1491 }
1492 /* although aggregating, make sure to request on the correct UP,TID,PSB and direction */
1493 pACInfo->requested_QoSInfo[tmask - 1].ts_info.up =
1494 Tspec_Info.ts_info.up;
1495 pACInfo->requested_QoSInfo[tmask - 1].ts_info.tid =
1496 Tspec_Info.ts_info.tid;
1497 pACInfo->requested_QoSInfo[tmask - 1].ts_info.direction =
1498 Tspec_Info.ts_info.direction;
1499 pACInfo->requested_QoSInfo[tmask - 1].ts_info.psb =
1500 Tspec_Info.ts_info.psb;
1501 status =
1502 sme_qos_setup(pMac, sessionId,
1503 &pACInfo->requested_QoSInfo[tmask - 1], ac);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301504 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505 "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
1506 "sme_qos_setup returned with status %d", __func__,
1507 __LINE__, sessionId, ac, status);
1508 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) {
1509 /* we aren't waiting for a response from the AP */
1510 /* so vote powersave back on */
1511 pSession->readyForPowerSave = true;
1512 }
1513 if ((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) ||
1514 (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)
1515 || (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY ==
1516 status)) {
1517 /* we received an expected "good" status */
1518 /* create an entry in the flow list */
1519 pentry =
1520 (sme_QosFlowInfoEntry *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301521 qdf_mem_malloc(sizeof(*pentry));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522 if (!pentry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301523 QDF_TRACE(QDF_MODULE_ID_SME,
1524 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001525 "%s: %d: couldn't allocate memory for the new "
1526 "entry in the Flow List", __func__,
1527 __LINE__);
1528 return SME_QOS_STATUS_SETUP_FAILURE_RSP;
1529 }
1530 pentry->ac_type = ac;
1531 pentry->HDDcontext = HDDcontext;
1532 pentry->QoSCallback = QoSCallback;
1533 pentry->hoRenewal = hoRenewal;
1534 pentry->QosFlowID = QosFlowID;
1535 pentry->sessionId = sessionId;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301536 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537 "%s: %d: Creating flow %d",
1538 __func__, __LINE__, QosFlowID);
1539 if ((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP ==
1540 status)
1541 || (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY ==
1542 status)) {
1543 new_state = pACInfo->curr_state;
1544 pentry->reason = SME_QOS_REASON_REQ_SUCCESS;
1545 pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
1546 pACInfo->
1547 requested_QoSInfo[SME_QOS_TSPEC_INDEX_0];
1548 if (buffered_cmd && !pentry->hoRenewal) {
1549 QoSCallback(pMac, HDDcontext,
1550 &pACInfo->
1551 curr_QoSInfo
1552 [SME_QOS_TSPEC_INDEX_0],
1553 status, pentry->QosFlowID);
1554 }
1555 if (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) {
1556 /* if we are not in handoff, then notify all flows on */
1557 /* this AC that the aggregate TSPEC may have changed */
1558 if (!pentry->hoRenewal) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301559 qdf_mem_zero(&search_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001560 sizeof
1561 (sme_QosSearchInfo));
1562 search_key.key.ac_type = ac;
1563 search_key.index =
1564 SME_QOS_SEARCH_KEY_INDEX_2;
1565 search_key.sessionId =
1566 sessionId;
1567 hstatus =
1568 sme_qos_find_all_in_flow_list
1569 (pMac, search_key,
1570 sme_qos_setup_fnp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301571 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572 (hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301573 QDF_TRACE
Anurag Chouhan6d760662016-02-20 16:05:43 +05301574 (QDF_MODULE_ID_SME,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301575 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001576 "%s: %d: couldn't notify other "
1577 "entries on this AC =%d",
1578 __func__, __LINE__,
1579 ac);
1580 }
1581 }
1582 }
1583 pentry->hoRenewal = false;
1584 } else {
1585 /* SME_QOS_STATUS_SETUP_REQ_PENDING_RSP */
1586 new_state = SME_QOS_REQUESTED;
1587 pentry->reason = SME_QOS_REASON_SETUP;
1588 /* Need this info when addts comes back from PE to know on */
1589 /* which index of the AC the request was from */
1590 pACInfo->tspec_pending = tmask;
1591 }
1592 pACInfo->num_flows[tmask - 1]++;
1593 /* indicate on which index the flow entry belongs to & add it to the */
1594 /* Flow List at the end */
1595 pentry->tspec_mask = tmask;
1596 pentry->QoSInfo = Tspec_Info;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301597 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598 "%s: %d: On session %d creating entry at %p with flowID %d",
1599 __func__, __LINE__,
1600 sessionId, pentry, QosFlowID);
1601 csr_ll_insert_tail(&sme_qos_cb.flow_list, &pentry->link,
1602 true);
1603 } else {
1604 /* unexpected status returned by sme_qos_setup() */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301605 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606 "%s: %d: On session %d unexpected status %d "
1607 "returned by sme_qos_setup",
1608 __func__, __LINE__, sessionId, status);
1609 new_state = pACInfo->curr_state;
1610 }
1611 break;
1612 case SME_QOS_CLOSED:
1613 case SME_QOS_INIT:
1614 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301615 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001616 "%s: %d: setup requested in unexpected state = %d",
1617 __func__, __LINE__, pACInfo->curr_state);
1618 /* unable to service the request */
1619 /* nothing is pending so vote powersave back on */
1620 pSession->readyForPowerSave = true;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301621 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001622 new_state = pACInfo->curr_state;
1623 }
1624 /* if current state is same as previous no need for transistion,
1625 if we are doing reassoc & we are already in handoff state, no need to move
1626 to requested state. But make sure to set the previous state as requested
1627 state
1628 */
1629 if ((new_state != pACInfo->curr_state) &&
1630 (!(pACInfo->reassoc_pending &&
1631 (SME_QOS_HANDOFF == pACInfo->curr_state)))) {
1632 sme_qos_state_transition(sessionId, ac, new_state);
1633 }
1634
1635 if (pACInfo->reassoc_pending &&
1636 (SME_QOS_HANDOFF == pACInfo->curr_state)) {
1637 pACInfo->prev_state = SME_QOS_REQUESTED;
1638 }
1639 if ((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) ||
1640 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) {
1641 (void)sme_qos_process_buffered_cmd(sessionId);
1642 }
1643 return status;
1644}
1645
1646/**
1647 * sme_qos_internal_modify_req() - The SME QoS internal function to request
1648 * for modification of certain QoS params on a flow running on a particular AC.
1649 * @pMac: Pointer to the global MAC parameter structure.
1650 * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
1651 * related info as defined above, provided by HDD
1652 * @QosFlowID: Identification per flow running on each AC generated by
1653 * SME. It is only meaningful if the QoS setup for the flow has
1654 * been successful already
1655 *
1656 * If the request involves admission control on the requested AC, HDD needs to
1657 * provide the necessary Traffic Specification (TSPEC) parameters & SME might
1658 * start the renegotiation process through ADDTS.
1659 *
1660 * Return: SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful.
1661 * Other status means request failed
1662 */
1663sme_QosStatusType sme_qos_internal_modify_req(tpAniSirGlobal pMac,
1664 sme_QosWmmTspecInfo *pQoSInfo,
1665 uint32_t QosFlowID,
1666 bool buffered_cmd)
1667{
1668 tListElem *pEntry = NULL;
1669 sme_QosSessionInfo *pSession;
1670 sme_QosACInfo *pACInfo;
1671 sme_QosFlowInfoEntry *pNewEntry = NULL;
1672 sme_QosFlowInfoEntry *flow_info = NULL;
1673 sme_QosEdcaAcType ac;
1674 sme_QosStates new_state = SME_QOS_CLOSED;
1675 sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1676 sme_QosWmmTspecInfo Aggr_Tspec_Info;
1677 sme_QosSearchInfo search_key;
1678 sme_QosCmdInfo cmd;
1679 uint8_t sessionId;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301680 QDF_STATUS hstatus;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301681 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001682 "%s: %d: invoked for flow %d", __func__, __LINE__, QosFlowID);
1683
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301684 qdf_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 /* set the key type & the key to be searched in the Flow List */
1686 search_key.key.QosFlowID = QosFlowID;
1687 search_key.index = SME_QOS_SEARCH_KEY_INDEX_1;
1688 search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY;
1689 /* go through the link list to find out the details on the flow */
1690 pEntry = sme_qos_find_in_flow_list(search_key);
1691 if (!pEntry) {
1692 /* Err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301693 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001694 "%s: %d: no match found for flowID = %d",
1695 __func__, __LINE__, QosFlowID);
1696 return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
1697 }
1698 /* find the AC */
1699 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
1700 ac = flow_info->ac_type;
1701
1702 sessionId = flow_info->sessionId;
1703 pSession = &sme_qos_cb.sessionInfo[sessionId];
1704 pACInfo = &pSession->ac_info[ac];
1705
1706 /* validate QoS params */
1707 if (!sme_qos_validate_requested_params(pMac, pQoSInfo, sessionId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301708 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001709 "%s: %d: invalid params", __func__, __LINE__);
1710 return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
1711 }
1712 /* For modify, make sure that direction, TID and UP are not being altered */
1713 if ((pQoSInfo->ts_info.direction !=
1714 flow_info->QoSInfo.ts_info.direction)
1715 || (pQoSInfo->ts_info.up != flow_info->QoSInfo.ts_info.up)
1716 || (pQoSInfo->ts_info.tid != flow_info->QoSInfo.ts_info.tid)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301717 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 "%s: %d: Modification of direction/tid/up is not allowed",
1719 __func__, __LINE__);
1720
1721 return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP;
1722 }
1723
1724 /* should not be same as previous ioctl parameters */
1725 if ((pQoSInfo->nominal_msdu_size ==
1726 flow_info->QoSInfo.nominal_msdu_size) &&
1727 (pQoSInfo->maximum_msdu_size ==
1728 flow_info->QoSInfo.maximum_msdu_size) &&
1729 (pQoSInfo->min_data_rate ==
1730 flow_info->QoSInfo.min_data_rate) &&
1731 (pQoSInfo->mean_data_rate ==
1732 flow_info->QoSInfo.mean_data_rate) &&
1733 (pQoSInfo->peak_data_rate ==
1734 flow_info->QoSInfo.peak_data_rate) &&
1735 (pQoSInfo->min_service_interval ==
1736 flow_info->QoSInfo.min_service_interval) &&
1737 (pQoSInfo->max_service_interval ==
1738 flow_info->QoSInfo.max_service_interval) &&
1739 (pQoSInfo->inactivity_interval ==
1740 flow_info->QoSInfo.inactivity_interval) &&
1741 (pQoSInfo->suspension_interval ==
1742 flow_info->QoSInfo.suspension_interval) &&
1743 (pQoSInfo->surplus_bw_allowance ==
1744 flow_info->QoSInfo.surplus_bw_allowance)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301745 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001746 "%s: %d: the addts parameters are same as last request,"
1747 "dropping the current request", __func__, __LINE__);
1748
1749 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1750 }
1751
1752 /* need to vote off powersave for the duration of this request */
1753 pSession->readyForPowerSave = false;
1754 /* check to consider the following flowing scenario.
1755 * Addts request is pending on one AC, while APSD requested on another
1756 * which needs a reassoc. Will buffer a request if Addts is pending on
1757 * any AC, which will safegaurd the above scenario, & also won't
1758 * confuse PE with back to back Addts or Addts followed by Reassoc
1759 */
1760 if (sme_qos_is_rsp_pending(sessionId, ac)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301761 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 "%s: %d: buffering the modify request for flow %d in state %d "
1763 "since another request is pending",
1764 __func__, __LINE__, QosFlowID, pACInfo->curr_state);
1765 /* we need to buffer the command */
1766 cmd.command = SME_QOS_MODIFY_REQ;
1767 cmd.pMac = pMac;
1768 cmd.sessionId = sessionId;
1769 cmd.u.modifyCmdInfo.QosFlowID = QosFlowID;
1770 cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo;
1771 hstatus = sme_qos_buffer_cmd(&cmd, buffered_cmd);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301772 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301773 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 "%s: %d: couldn't buffer the modify request in state = %d",
1775 __func__, __LINE__, pACInfo->curr_state);
1776 /* unable to buffer the request */
1777 /* nothing is pending so vote powersave back on */
1778 pSession->readyForPowerSave = true;
1779 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1780 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301781 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 "%s: %d: Buffered modify request for flow = %d",
1783 __func__, __LINE__, QosFlowID);
1784 return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
1785 }
1786 /* get into the stat m/c to see if the request can be granted */
1787 switch (pACInfo->curr_state) {
1788 case SME_QOS_QOS_ON:
1789 /* save the new params adding a new (duplicate) entry in the Flow List */
1790 /* Once we have decided on OTA exchange needed or not we can delete the */
1791 /* original one from the List */
1792 pNewEntry =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301793 (sme_QosFlowInfoEntry *) qdf_mem_malloc(sizeof(*pNewEntry));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794 if (!pNewEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301795 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001796 "%s: %d: couldn't allocate memory for the new "
1797 "entry in the Flow List", __func__, __LINE__);
1798 /* unable to service the request */
1799 /* nothing is pending so vote powersave back on */
1800 pSession->readyForPowerSave = true;
1801 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1802 }
1803 pNewEntry->ac_type = ac;
1804 pNewEntry->sessionId = sessionId;
1805 pNewEntry->HDDcontext = flow_info->HDDcontext;
1806 pNewEntry->QoSCallback = flow_info->QoSCallback;
1807 pNewEntry->QosFlowID = flow_info->QosFlowID;
1808 pNewEntry->reason = SME_QOS_REASON_MODIFY_PENDING;
1809 /* since it is a modify request, use the same index on which the flow */
1810 /* entry originally was running & add it to the Flow List at the end */
1811 pNewEntry->tspec_mask = flow_info->tspec_mask;
1812 pNewEntry->QoSInfo = *pQoSInfo;
1813 /* update the entry from Flow List which needed to be modified */
1814 flow_info->reason = SME_QOS_REASON_MODIFY;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301815 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 "%s: %d: On session %d creating modified "
1817 "entry at %p with flowID %d",
1818 __func__, __LINE__,
1819 sessionId, pNewEntry, pNewEntry->QosFlowID);
1820 /* add the new entry under construction to the Flow List */
1821 csr_ll_insert_tail(&sme_qos_cb.flow_list, &pNewEntry->link,
1822 true);
1823 /* update TSPEC with the new param set */
1824 hstatus = sme_qos_update_params(sessionId,
1825 ac, pNewEntry->tspec_mask,
1826 &Aggr_Tspec_Info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301827 if (QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001828 pACInfo->requested_QoSInfo[pNewEntry->tspec_mask - 1] =
1829 Aggr_Tspec_Info;
1830 /* if ACM, send out a new ADDTS */
1831 status = sme_qos_setup(pMac, sessionId,
1832 &pACInfo->
1833 requested_QoSInfo[pNewEntry->
1834 tspec_mask - 1],
1835 ac);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301836 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001837 "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
1838 "sme_qos_setup returned with status %d",
1839 __func__, __LINE__, sessionId, ac, status);
1840 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) {
1841 /* we aren't waiting for a response from the AP */
1842 /* so vote powersave back on */
1843 pSession->readyForPowerSave = true;
1844 }
1845 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) {
1846 new_state = SME_QOS_REQUESTED;
1847 status =
1848 SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
1849 pACInfo->tspec_pending = pNewEntry->tspec_mask;
1850 } else
1851 if ((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP
1852 == status)
1853 ||
1854 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY
1855 == status)) {
1856 new_state = SME_QOS_QOS_ON;
1857
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301858 qdf_mem_zero(&search_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859 sizeof(sme_QosSearchInfo));
1860 /* delete the original entry in FLOW list which got modified */
1861 search_key.key.ac_type = ac;
1862 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
1863 search_key.sessionId = sessionId;
1864 hstatus =
1865 sme_qos_find_all_in_flow_list(pMac, search_key,
1866 sme_qos_modify_fnp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301867 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 status =
1869 SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1870 }
1871 if (SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP !=
1872 status) {
1873 pACInfo->curr_QoSInfo[pNewEntry->
1874 tspec_mask - 1] =
1875 pACInfo->
1876 requested_QoSInfo[pNewEntry->
1877 tspec_mask - 1];
1878 if (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) {
1879 status =
1880 SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301881 qdf_mem_zero(&search_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 sizeof
1883 (sme_QosSearchInfo));
1884 search_key.key.ac_type = ac;
1885 search_key.index =
1886 SME_QOS_SEARCH_KEY_INDEX_2;
1887 search_key.sessionId =
1888 sessionId;
1889 hstatus =
1890 sme_qos_find_all_in_flow_list
1891 (pMac, search_key,
1892 sme_qos_modification_notify_fnp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301893 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 (hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301895 QDF_TRACE
Anurag Chouhan6d760662016-02-20 16:05:43 +05301896 (QDF_MODULE_ID_SME,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301897 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 "%s: %d: couldn't notify other "
1899 "entries on this AC =%d",
1900 __func__, __LINE__,
1901 ac);
1902 }
1903 } else
1904 if
1905 (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP
1906 == status) {
1907 status =
1908 SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP;
1909 }
1910 }
1911 if (buffered_cmd) {
1912 flow_info->QoSCallback(pMac,
1913 flow_info->
1914 HDDcontext,
1915 &pACInfo->
1916 curr_QoSInfo
1917 [pNewEntry->
1918 tspec_mask - 1],
1919 status,
1920 flow_info->
1921 QosFlowID);
1922 }
1923
1924 } else {
1925 /* unexpected status returned by sme_qos_setup() */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301926 QDF_TRACE(QDF_MODULE_ID_SME,
1927 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928 "%s: %d: On session %d unexpected status %d "
1929 "returned by sme_qos_setup", __func__,
1930 __LINE__, sessionId, status);
1931 new_state = SME_QOS_QOS_ON;
1932 }
1933 } else {
1934 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301935 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 "%s: %d: sme_qos_update_params() failed",
1937 __func__, __LINE__);
1938 /* unable to service the request */
1939 /* nothing is pending so vote powersave back on */
1940 pSession->readyForPowerSave = true;
1941 new_state = SME_QOS_LINK_UP;
1942 }
1943 /* if we are doing reassoc & we are already in handoff state, no need
1944 to move to requested state. But make sure to set the previous state
1945 as requested state
1946 */
1947 if (!(pACInfo->reassoc_pending &&
1948 (SME_QOS_HANDOFF == pACInfo->curr_state))) {
1949 sme_qos_state_transition(sessionId, ac, new_state);
1950 } else {
1951 pACInfo->prev_state = SME_QOS_REQUESTED;
1952 }
1953 break;
1954 case SME_QOS_HANDOFF:
1955 case SME_QOS_REQUESTED:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301956 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 "%s: %d: Buffering modify request for flow %d in state = %d",
1958 __func__, __LINE__, QosFlowID, pACInfo->curr_state);
1959 /* buffer cmd */
1960 cmd.command = SME_QOS_MODIFY_REQ;
1961 cmd.pMac = pMac;
1962 cmd.sessionId = sessionId;
1963 cmd.u.modifyCmdInfo.QosFlowID = QosFlowID;
1964 cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo;
1965 hstatus = sme_qos_buffer_cmd(&cmd, buffered_cmd);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301966 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301967 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 "%s: %d: couldn't buffer the modify request in state = %d",
1969 __func__, __LINE__, pACInfo->curr_state);
1970 /* unable to buffer the request */
1971 /* nothing is pending so vote powersave back on */
1972 pSession->readyForPowerSave = true;
1973 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
1974 }
1975 status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
1976 break;
1977 case SME_QOS_CLOSED:
1978 case SME_QOS_INIT:
1979 case SME_QOS_LINK_UP:
1980 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301981 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 "%s: %d: modify requested in unexpected state = %d",
1983 __func__, __LINE__, pACInfo->curr_state);
1984 /* unable to service the request */
1985 /* nothing is pending so vote powersave back on */
1986 pSession->readyForPowerSave = true;
1987 break;
1988 }
1989 if ((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)
1990 || (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY ==
1991 status)) {
1992 (void)sme_qos_process_buffered_cmd(sessionId);
1993 }
1994 return status;
1995}
1996
1997/**
1998 * sme_qos_internal_release_req() - release QOS flow on a particular AC
1999 * @pMac: Pointer to the global MAC parameter structure.
2000 * @QosFlowID: Identification per flow running on each AC generated by SME
2001 * It is only meaningful if the QoS setup for the flow is successful
2002 *
2003 * The SME QoS internal function to request
2004 * for releasing a QoS flow running on a particular AC.
2005
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302006 * Return: QDF_STATUS_SUCCESS - Release is successful.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 */
2008sme_QosStatusType sme_qos_internal_release_req(tpAniSirGlobal pMac,
2009 uint32_t QosFlowID,
2010 bool buffered_cmd)
2011{
2012 tListElem *pEntry = NULL;
2013 sme_QosSessionInfo *pSession;
2014 sme_QosACInfo *pACInfo;
2015 sme_QosFlowInfoEntry *flow_info = NULL;
2016 sme_QosFlowInfoEntry *pDeletedFlow = NULL;
2017 sme_QosEdcaAcType ac;
2018 sme_QosStates new_state = SME_QOS_CLOSED;
2019 sme_QosStatusType status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2020 sme_QosWmmTspecInfo Aggr_Tspec_Info;
2021 sme_QosSearchInfo search_key;
2022 sme_QosCmdInfo cmd;
2023 tCsrRoamModifyProfileFields modifyProfileFields;
2024 bool deltsIssued = false;
2025 uint8_t sessionId;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302026 QDF_STATUS hstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002027 bool biDirectionalFlowsPresent = false;
2028 bool uplinkFlowsPresent = false;
2029 bool downlinkFlowsPresent = false;
2030 tListElem *pResult = NULL;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302031 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 "%s: %d: invoked for flow %d", __func__, __LINE__, QosFlowID);
2033
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302034 qdf_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035 /* set the key type & the key to be searched in the Flow List */
2036 search_key.key.QosFlowID = QosFlowID;
2037 search_key.index = SME_QOS_SEARCH_KEY_INDEX_1;
2038 search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY;
2039 /* go through the link list to find out the details on the flow */
2040 pEntry = sme_qos_find_in_flow_list(search_key);
2041
2042 if (!pEntry) {
2043 /* Err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302044 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 "%s: %d: no match found for flowID = %d",
2046 __func__, __LINE__, QosFlowID);
2047 return SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP;
2048 }
2049 /* find the AC */
2050 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
2051 ac = flow_info->ac_type;
2052 sessionId = flow_info->sessionId;
2053 pSession = &sme_qos_cb.sessionInfo[sessionId];
2054 pACInfo = &pSession->ac_info[ac];
2055 /* need to vote off powersave for the duration of this request */
2056 pSession->readyForPowerSave = false;
2057 /* check to consider the following flowing scenario.
2058 * Addts request is pending on one AC, while APSD requested on another
2059 * which needs a reassoc. Will buffer a request if Addts is pending on
2060 * any AC, which will safegaurd the above scenario, & also won't
2061 * confuse PE with back to back Addts or Addts followed by Reassoc
2062 */
2063 if (sme_qos_is_rsp_pending(sessionId, ac)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302064 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002065 "%s: %d: buffering the release request for flow %d in state %d "
2066 "since another request is pending",
2067 __func__, __LINE__, QosFlowID, pACInfo->curr_state);
2068 /* we need to buffer the command */
2069 cmd.command = SME_QOS_RELEASE_REQ;
2070 cmd.pMac = pMac;
2071 cmd.sessionId = sessionId;
2072 cmd.u.releaseCmdInfo.QosFlowID = QosFlowID;
2073 hstatus = sme_qos_buffer_cmd(&cmd, buffered_cmd);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302074 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302075 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 "%s: %d: couldn't buffer the release request in state = %d",
2077 __func__, __LINE__, pACInfo->curr_state);
2078 /* unable to buffer the request */
2079 /* nothing is pending so vote powersave back on */
2080 pSession->readyForPowerSave = true;
2081 return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2082 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302083 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 "%s: %d: Buffered release request for flow = %d",
2085 __func__, __LINE__, QosFlowID);
2086 return SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
2087 }
2088 /* get into the stat m/c to see if the request can be granted */
2089 switch (pACInfo->curr_state) {
2090 case SME_QOS_QOS_ON:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302091 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 "%s: %d: tspec_mask_status = %d for AC = %d with "
2093 "entry tspec_mask = %d",
2094 __func__, __LINE__,
2095 pACInfo->tspec_mask_status, ac,
2096 flow_info->tspec_mask);
2097
2098 /* check if multiple flows running on the ac */
2099 if (pACInfo->num_flows[flow_info->tspec_mask - 1] > 1) {
2100 /* don't want to include the flow in the new TSPEC on which release */
2101 /* is requested */
2102 flow_info->reason = SME_QOS_REASON_RELEASE;
2103
2104 /* Check if the flow being released is for bi-diretional.
2105 * Following flows may present in the system.
2106 * a) bi-directional flows
2107 * b) uplink flows
2108 * c) downlink flows.
2109 * If the flow being released is for bidirectional, splitting of existing
2110 * streams into two tspec indices is required in case ff (b), (c) are present
2111 * and not (a).
2112 * In case if split occurs, all upstreams are aggregated into tspec index 0,
2113 * downstreams are aggregaed into tspec index 1 and two tspec requests for
2114 * (aggregated) upstream(s) followed by (aggregated) downstream(s) is sent
2115 * to AP. */
2116 if (flow_info->QoSInfo.ts_info.direction ==
2117 SME_QOS_WMM_TS_DIR_BOTH) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302118 qdf_mem_zero(&search_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 sizeof(sme_QosSearchInfo));
2120 /* set the key type & the key to be searched in the Flow List */
2121 search_key.key.ac_type = ac;
2122 search_key.index = SME_QOS_SEARCH_KEY_INDEX_4;
2123 search_key.sessionId = sessionId;
2124 search_key.direction = SME_QOS_WMM_TS_DIR_BOTH;
2125 pResult = sme_qos_find_in_flow_list(search_key);
2126 if (pResult)
2127 biDirectionalFlowsPresent = true;
2128
2129 if (!biDirectionalFlowsPresent) {
2130 /* The only existing bidirectional flow is being released */
2131
2132 /* Check if uplink flows exist */
2133 search_key.direction =
2134 SME_QOS_WMM_TS_DIR_UPLINK;
2135 pResult =
2136 sme_qos_find_in_flow_list(search_key);
2137 if (pResult)
2138 uplinkFlowsPresent = true;
2139
2140 /* Check if downlink flows exist */
2141 search_key.direction =
2142 SME_QOS_WMM_TS_DIR_DOWNLINK;
2143 pResult =
2144 sme_qos_find_in_flow_list(search_key);
2145 if (pResult)
2146 downlinkFlowsPresent = true;
2147
2148 if (uplinkFlowsPresent
2149 && downlinkFlowsPresent) {
2150 /* Need to split the uni-directional flows into SME_QOS_TSPEC_INDEX_0 and SME_QOS_TSPEC_INDEX_1 */
2151
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302152 qdf_mem_zero(&search_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002153 sizeof
2154 (sme_QosSearchInfo));
2155 /* Mark all downstream flows as using tspec index 1 */
2156 search_key.key.ac_type = ac;
2157 search_key.index =
2158 SME_QOS_SEARCH_KEY_INDEX_4;
2159 search_key.sessionId =
2160 sessionId;
2161 search_key.direction =
2162 SME_QOS_WMM_TS_DIR_DOWNLINK;
2163 sme_qos_update_tspec_mask
2164 (sessionId, search_key,
2165 SME_QOS_TSPEC_MASK_BIT_2_SET);
2166
2167 /* Aggregate all downstream flows */
2168 hstatus =
2169 sme_qos_update_params
2170 (sessionId, ac,
2171 SME_QOS_TSPEC_MASK_BIT_2_SET,
2172 &Aggr_Tspec_Info);
2173
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302174 QDF_TRACE(QDF_MODULE_ID_SME,
2175 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 "%s: %d: On session %d buffering the AddTS request "
2177 "for AC %d in state %d as Addts is pending "
2178 "on other Tspec index of this AC",
2179 __func__, __LINE__,
2180 sessionId, ac,
2181 pACInfo->curr_state);
2182
2183 /* Buffer the (aggregated) tspec request for downstream flows. */
2184 /* Please note that the (aggregated) tspec for upstream flows is sent */
2185 /* out by the susequent logic. */
2186 cmd.command =
2187 SME_QOS_RESEND_REQ;
2188 cmd.pMac = pMac;
2189 cmd.sessionId = sessionId;
2190 cmd.u.resendCmdInfo.ac = ac;
2191 cmd.u.resendCmdInfo.tspecMask =
2192 SME_QOS_TSPEC_MASK_BIT_2_SET;
2193 cmd.u.resendCmdInfo.QoSInfo =
2194 Aggr_Tspec_Info;
2195 pACInfo->
2196 requested_QoSInfo
2197 [SME_QOS_TSPEC_MASK_BIT_2_SET
2198 - 1] = Aggr_Tspec_Info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302199 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200 (sme_qos_buffer_cmd
2201 (&cmd, false))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302202 QDF_TRACE
Anurag Chouhan6d760662016-02-20 16:05:43 +05302203 (QDF_MODULE_ID_SME,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302204 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002205 "%s: %d: On session %d unable to buffer the AddTS "
2206 "request for AC %d TSPEC %d in state %d",
2207 __func__, __LINE__,
2208 sessionId, ac,
2209 SME_QOS_TSPEC_MASK_BIT_2_SET,
2210 pACInfo->
2211 curr_state);
2212
2213 /* unable to buffer the request */
2214 /* nothing is pending so vote powersave back on */
2215 pSession->
2216 readyForPowerSave =
2217 true;
2218
2219 return
2220 SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
2221 }
2222 pACInfo->tspec_mask_status =
2223 SME_QOS_TSPEC_MASK_BIT_1_2_SET;
2224
2225 }
2226 }
2227 }
2228
2229 /* In case of splitting of existing streams,
2230 * tspec_mask will be pointing to tspec index 0 and
2231 * aggregated tspec for upstream(s) is sent out here. */
2232 hstatus = sme_qos_update_params(sessionId,
2233 ac, flow_info->tspec_mask,
2234 &Aggr_Tspec_Info);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302235 if (QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236 pACInfo->requested_QoSInfo[flow_info->
2237 tspec_mask - 1] =
2238 Aggr_Tspec_Info;
2239 /* if ACM, send out a new ADDTS */
2240 status = sme_qos_setup(pMac, sessionId,
2241 &pACInfo->
2242 requested_QoSInfo
2243 [flow_info->tspec_mask -
2244 1], ac);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302245 QDF_TRACE(QDF_MODULE_ID_SME,
2246 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON "
2248 "sme_qos_setup returned with status %d",
2249 __func__, __LINE__, sessionId, ac,
2250 status);
2251 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP !=
2252 status) {
2253 /* we aren't waiting for a response from the AP */
2254 /* so vote powersave back on */
2255 pSession->readyForPowerSave = true;
2256 }
2257 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP ==
2258 status) {
2259 new_state = SME_QOS_REQUESTED;
2260 status =
2261 SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
2262 pACInfo->tspec_pending =
2263 flow_info->tspec_mask;
2264 } else
2265 if ((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) {
2266 new_state = SME_QOS_QOS_ON;
2267 pACInfo->num_flows[flow_info->
2268 tspec_mask - 1]--;
2269 pACInfo->curr_QoSInfo[flow_info->
2270 tspec_mask - 1] =
2271 pACInfo->
2272 requested_QoSInfo[flow_info->
2273 tspec_mask - 1];
2274 /* delete the entry from Flow List */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302275 QDF_TRACE(QDF_MODULE_ID_SME,
2276 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 "%s: %d: Deleting entry at %p with flowID %d",
2278 __func__, __LINE__, flow_info,
2279 QosFlowID);
2280 csr_ll_remove_entry(&sme_qos_cb.flow_list,
2281 pEntry, true);
2282 pDeletedFlow = flow_info;
2283 if (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302284 qdf_mem_zero(&search_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 sizeof
2286 (sme_QosSearchInfo));
2287 search_key.key.ac_type = ac;
2288 search_key.index =
2289 SME_QOS_SEARCH_KEY_INDEX_2;
2290 search_key.sessionId =
2291 sessionId;
2292 hstatus =
2293 sme_qos_find_all_in_flow_list
2294 (pMac, search_key,
2295 sme_qos_setup_fnp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302296 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 (hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302298 QDF_TRACE
Anurag Chouhan6d760662016-02-20 16:05:43 +05302299 (QDF_MODULE_ID_SME,
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302300 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 "%s: %d: couldn't notify other "
2302 "entries on this AC =%d",
2303 __func__, __LINE__,
2304 ac);
2305 }
2306 }
2307 status =
2308 SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
2309 if (buffered_cmd) {
2310 flow_info->QoSCallback(pMac,
2311 flow_info->
2312 HDDcontext,
2313 &pACInfo->
2314 curr_QoSInfo
2315 [flow_info->
2316 tspec_mask
2317 - 1],
2318 status,
2319 flow_info->
2320 QosFlowID);
2321 }
2322 } else {
2323 /* unexpected status returned by sme_qos_setup() */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302324 QDF_TRACE(QDF_MODULE_ID_SME,
2325 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 "%s: %d: On session %d unexpected status %d "
2327 "returned by sme_qos_setup",
2328 __func__, __LINE__, sessionId,
2329 status);
2330 new_state = SME_QOS_LINK_UP;
2331 pACInfo->num_flows[flow_info->
2332 tspec_mask - 1]--;
2333 pACInfo->curr_QoSInfo[flow_info->
2334 tspec_mask - 1] =
2335 pACInfo->
2336 requested_QoSInfo[flow_info->
2337 tspec_mask - 1];
2338 /* delete the entry from Flow List */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302339 QDF_TRACE(QDF_MODULE_ID_SME,
2340 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341 "%s: %d: On session %d deleting entry at "
2342 "%p with flowID %d", __func__,
2343 __LINE__, sessionId,
2344 flow_info, QosFlowID);
2345 csr_ll_remove_entry(&sme_qos_cb.flow_list,
2346 pEntry, true);
2347 pDeletedFlow = flow_info;
2348 if (buffered_cmd) {
2349 flow_info->QoSCallback(pMac,
2350 flow_info->
2351 HDDcontext,
2352 &pACInfo->
2353 curr_QoSInfo
2354 [flow_info->
2355 tspec_mask
2356 - 1],
2357 status,
2358 flow_info->
2359 QosFlowID);
2360 }
2361 }
2362 } else {
2363 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302364 QDF_TRACE(QDF_MODULE_ID_SME,
2365 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366 "%s: %d: sme_qos_update_params() failed",
2367 __func__, __LINE__);
2368 /* unable to service the request */
2369 /* nothing is pending so vote powersave back on */
2370 pSession->readyForPowerSave = true;
2371 new_state = SME_QOS_LINK_UP;
2372 if (buffered_cmd) {
2373 flow_info->QoSCallback(pMac,
2374 flow_info->
2375 HDDcontext,
2376 &pACInfo->
2377 curr_QoSInfo
2378 [flow_info->
2379 tspec_mask - 1],
2380 status,
2381 flow_info->
2382 QosFlowID);
2383 }
2384 }
2385 } else {
2386 /* this is the only flow aggregated in this TSPEC */
2387 status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
2388 /* check if delts needs to be sent */
2389 if (CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
2390 sme_qos_is_acm(pMac, pSession->assocInfo.pBssDesc, ac,
2391 NULL)) {
2392 /* check if other TSPEC for this AC is also in use */
2393 if (SME_QOS_TSPEC_MASK_BIT_1_2_SET !=
2394 pACInfo->tspec_mask_status) {
2395 /* this is the only TSPEC active on this AC */
2396 /* so indicate that we no longer require APSD */
2397 pSession->apsdMask &=
2398 ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2399 /* Also update modifyProfileFields.uapsd_mask in CSR for consistency */
2400 csr_get_modify_profile_fields(pMac,
2401 flow_info->
2402 sessionId,
2403 &modifyProfileFields);
2404 modifyProfileFields.uapsd_mask =
2405 pSession->apsdMask;
2406 csr_set_modify_profile_fields(pMac,
2407 flow_info->
2408 sessionId,
2409 &modifyProfileFields);
2410 if (!pSession->apsdMask) {
2411 /* this session no longer needs UAPSD */
2412 /* do any sessions still require UAPSD? */
2413 if (!sme_qos_is_uapsd_active()) {
2414 /* No sessions require UAPSD so turn it off */
2415 /* (really don't care when PMC stops it) */
2416 sme_ps_uapsd_disable(
2417 pMac, sessionId);
2418 }
2419 }
2420 }
2421 if (SME_QOS_RELEASE_DEFAULT == pACInfo->relTrig) {
2422 /* send delts */
2423 hstatus =
2424 qos_issue_command(pMac, sessionId,
2425 eSmeCommandDelTs,
2426 NULL, ac,
2427 flow_info->
2428 tspec_mask);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302429 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002430 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302431 QDF_TRACE(QDF_MODULE_ID_SME,
2432 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 "%s: %d: sme_qos_del_ts_req() failed",
2434 __func__, __LINE__);
2435 status =
2436 SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2437 /* we won't be waiting for a response from the AP */
2438 /* so vote powersave back on */
2439 pSession->readyForPowerSave =
2440 true;
2441 } else {
2442 pACInfo->tspec_mask_status &=
2443 SME_QOS_TSPEC_MASK_BIT_1_2_SET
2444 & (~flow_info->tspec_mask);
2445 deltsIssued = true;
2446 }
2447 } else {
2448 pSession->readyForPowerSave = true;
2449 pACInfo->tspec_mask_status &=
2450 SME_QOS_TSPEC_MASK_BIT_1_2_SET &
2451 (~flow_info->tspec_mask);
2452 deltsIssued = true;
2453 }
2454 } else if (pSession->apsdMask &
2455 (1 << (SME_QOS_EDCA_AC_VO - ac))) {
2456 /* reassoc logic */
2457 csr_get_modify_profile_fields(pMac, sessionId,
2458 &modifyProfileFields);
2459 modifyProfileFields.uapsd_mask |=
2460 pSession->apsdMask;
2461 modifyProfileFields.uapsd_mask &=
2462 ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2463 pSession->apsdMask &=
2464 ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2465 if (!pSession->apsdMask) {
2466 /* this session no longer needs UAPSD */
2467 /* do any sessions still require UAPSD? */
2468 if (!sme_qos_is_uapsd_active()) {
2469 /* No sessions require UAPSD so turn it off */
2470 /* (really don't care when PMC stops it) */
2471 sme_ps_uapsd_disable(
2472 pMac, sessionId);
2473 }
2474 }
2475 hstatus = sme_qos_request_reassoc(pMac, sessionId,
2476 &modifyProfileFields,
2477 false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302478 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302480 QDF_TRACE(QDF_MODULE_ID_SME,
2481 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 "%s: %d: Reassoc failed",
2483 __func__, __LINE__);
2484 status =
2485 SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2486 /* we won't be waiting for a response from the AP */
2487 /* so vote powersave back on */
2488 pSession->readyForPowerSave = true;
2489 } else {
2490 pACInfo->reassoc_pending = false; /* no need to wait */
2491 pACInfo->prev_state = SME_QOS_LINK_UP;
2492 pACInfo->tspec_pending = 0;
2493 }
2494 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302495 QDF_TRACE(QDF_MODULE_ID_SME,
2496 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 "%s: %d: nothing to do for AC = %d",
2498 __func__, __LINE__, ac);
2499 /* we won't be waiting for a response from the AP */
2500 /* so vote powersave back on */
2501 pSession->readyForPowerSave = true;
2502 }
2503
2504 if (SME_QOS_RELEASE_BY_AP == pACInfo->relTrig) {
2505 flow_info->QoSCallback(pMac,
2506 flow_info->HDDcontext,
2507 &pACInfo->
2508 curr_QoSInfo[flow_info->
2509 tspec_mask -
2510 1],
2511 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
2512 flow_info->QosFlowID);
2513
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302514 QDF_TRACE(QDF_MODULE_ID_SME,
2515 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 "%s: %d: Deleting entry at %p with flowID %d",
2517 __func__, __LINE__, flow_info,
2518 flow_info->QosFlowID);
2519 } else if (buffered_cmd) {
2520 flow_info->QoSCallback(pMac,
2521 flow_info->HDDcontext,
2522 NULL, status,
2523 flow_info->QosFlowID);
2524 }
2525
2526 if (SME_QOS_STATUS_RELEASE_FAILURE_RSP == status) {
2527 break;
2528 }
2529
2530 if (((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->
2531 tspec_mask) > 0)
2532 &&
2533 ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->
2534 tspec_mask) <= SME_QOS_TSPEC_INDEX_MAX)) {
2535 if (pACInfo->
2536 num_flows[(SME_QOS_TSPEC_MASK_BIT_1_2_SET &
2537 ~flow_info->tspec_mask) - 1] >
2538 0) {
2539 new_state = SME_QOS_QOS_ON;
2540 } else {
2541 new_state = SME_QOS_LINK_UP;
2542 }
2543 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302544 QDF_TRACE(QDF_MODULE_ID_SME,
2545 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 "%s: %d: Exceeded the array bounds of pACInfo->num_flows",
2547 __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302548 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 return
2550 SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP;
2551 }
2552
2553 if (false == deltsIssued) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302554 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555 curr_QoSInfo[flow_info->
2556 tspec_mask - 1],
2557 sizeof(sme_QosWmmTspecInfo));
2558 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302559 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 requested_QoSInfo[flow_info->tspec_mask -
2561 1],
2562 sizeof(sme_QosWmmTspecInfo));
2563 pACInfo->num_flows[flow_info->tspec_mask - 1]--;
2564 /* delete the entry from Flow List */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302565 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 "%s: %d: On session %d deleting entry at %p with flowID %d",
2567 __func__, __LINE__,
2568 sessionId, flow_info, QosFlowID);
2569 csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry,
2570 true);
2571 pDeletedFlow = flow_info;
2572 pACInfo->relTrig = SME_QOS_RELEASE_DEFAULT;
2573 }
2574 /* if we are doing reassoc & we are already in handoff state, no need
2575 to move to requested state. But make sure to set the previous state
2576 as requested state
2577 */
2578 if (SME_QOS_HANDOFF != pACInfo->curr_state) {
2579 sme_qos_state_transition(sessionId, ac, new_state);
2580 }
2581 if (pACInfo->reassoc_pending) {
2582 pACInfo->prev_state = SME_QOS_REQUESTED;
2583 }
2584 break;
2585 case SME_QOS_HANDOFF:
2586 case SME_QOS_REQUESTED:
2587 /* buffer cmd */
2588 cmd.command = SME_QOS_RELEASE_REQ;
2589 cmd.pMac = pMac;
2590 cmd.sessionId = sessionId;
2591 cmd.u.releaseCmdInfo.QosFlowID = QosFlowID;
2592 hstatus = sme_qos_buffer_cmd(&cmd, buffered_cmd);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302593 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302594 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 "%s: %d: couldn't buffer the release request in state = %d",
2596 __func__, __LINE__, pACInfo->curr_state);
2597 /* unable to service the request */
2598 /* nothing is pending so vote powersave back on */
2599 pSession->readyForPowerSave = true;
2600 return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
2601 }
2602 status = SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP;
2603 break;
2604 case SME_QOS_CLOSED:
2605 case SME_QOS_INIT:
2606 case SME_QOS_LINK_UP:
2607 default:
2608 /* print error msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302609 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002610 "%s: %d: release request in unexpected state = %d",
2611 __func__, __LINE__, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302612 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 /* unable to service the request */
2614 /* nothing is pending so vote powersave back on */
2615 pSession->readyForPowerSave = true;
2616 break;
2617 }
2618 /* if we deleted a flow, reclaim the memory */
2619 if (pDeletedFlow) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302620 qdf_mem_free(pDeletedFlow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002621 }
2622 if ((SME_QOS_STATUS_RELEASE_SUCCESS_RSP == status)) {
2623 (void)sme_qos_process_buffered_cmd(sessionId);
2624 }
2625 return status;
2626}
2627
2628/**
2629 * sme_qos_setup() - internal SME QOS setup function.
2630 * @pMac: Pointer to the global MAC parameter structure.
2631 * @sessionId: Session upon which setup is being performed
2632 * @pTspec_Info: Pointer to sme_QosWmmTspecInfo which contains the WMM
2633 * TSPEC related info as defined above
2634 * @ac: Enumeration of the various EDCA Access Categories.
2635 *
2636 * The internal qos setup function which has the intelligence
2637 * if the request is NOP, or for APSD and/or need to send out ADDTS.
2638 * It also does the sanity check for QAP, AP supports APSD etc.
2639 * The logic used in the code might be confusing.
2640 *
2641 * Trying to cover all the cases here.
2642 * AP supports App wants ACM = 1 Already set APSD Result
2643 * | 0 | 0 | 0 | 0 | NO ACM NO APSD
2644 * | 0 | 0 | 0 | 1 | NO ACM NO APSD/INVALID
2645 * | 0 | 0 | 1 | 0 | ADDTS
2646 * | 0 | 0 | 1 | 1 | ADDTS
2647 * | 0 | 1 | 0 | 0 | FAILURE
2648 * | 0 | 1 | 0 | 1 | INVALID
2649 * | 0 | 1 | 1 | 0 | ADDTS
2650 * | 0 | 1 | 1 | 1 | ADDTS
2651 * | 1 | 0 | 0 | 0 | NO ACM NO APSD
2652 * | 1 | 0 | 0 | 1 | NO ACM NO APSD
2653 * | 1 | 0 | 1 | 0 | ADDTS
2654 * | 1 | 0 | 1 | 1 | ADDTS
2655 * | 1 | 1 | 0 | 0 | REASSOC
2656 * | 1 | 1 | 0 | 1 | NOP: APSD SET ALREADY
2657 * | 1 | 1 | 1 | 0 | ADDTS
2658 * | 1 | 1 | 1 | 1 | ADDTS
2659 *
2660 * Return: SME_QOS_STATUS_SETUP_SUCCESS_RSP if the setup is successful'
2661 */
2662sme_QosStatusType sme_qos_setup(tpAniSirGlobal pMac,
2663 uint8_t sessionId,
2664 sme_QosWmmTspecInfo *pTspec_Info,
2665 sme_QosEdcaAcType ac)
2666{
2667 sme_QosSessionInfo *pSession;
2668 sme_QosACInfo *pACInfo;
2669 sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
2670 tDot11fBeaconIEs *pIes = NULL;
2671 tCsrRoamModifyProfileFields modifyProfileFields;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302672 QDF_STATUS hstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302674 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 "%s: %d: Session Id %d is invalid",
2676 __func__, __LINE__, sessionId);
2677 return status;
2678 }
2679 pSession = &sme_qos_cb.sessionInfo[sessionId];
2680 if (!pSession->sessionActive) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302681 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 "%s: %d: Session %d is inactive",
2683 __func__, __LINE__, sessionId);
2684 return status;
2685 }
2686 if (!pSession->assocInfo.pBssDesc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302687 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 "%s: %d: Session %d has an Invalid BSS Descriptor",
2689 __func__, __LINE__, sessionId);
2690 return status;
2691 }
2692 hstatus = csr_get_parsed_bss_description_ies(pMac,
2693 pSession->assocInfo.pBssDesc,
2694 &pIes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302695 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302696 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697 "%s: %d: On session %d unable to parse BSS IEs",
2698 __func__, __LINE__, sessionId);
2699 return status;
2700 }
2701
2702 /* success so pIes was allocated */
2703
2704 if (!CSR_IS_QOS_BSS(pIes)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302705 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 "%s: %d: On session %d AP doesn't support QoS",
2707 __func__, __LINE__, sessionId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302708 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 /* notify HDD through the synchronous status msg */
2710 return SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP;
2711 }
2712
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302713 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 "%s: %d: UAPSD/PSB set %d: ", __func__, __LINE__,
2715 pTspec_Info->ts_info.psb);
2716
2717 pACInfo = &pSession->ac_info[ac];
2718 do {
2719 /* is ACM enabled for this AC? */
2720 if (CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) ||
2721 sme_qos_is_acm(pMac, pSession->assocInfo.pBssDesc,
2722 ac, NULL)) {
2723 /* ACM is enabled for this AC so we must send an AddTS */
2724 if (pTspec_Info->ts_info.psb &&
2725 !(pIes->WMMParams.
2726 qosInfo & SME_QOS_AP_SUPPORTS_APSD)
2727 && !(pIes->WMMInfoAp.uapsd)) {
2728 /* application is looking for APSD but AP doesn't support it */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302729 QDF_TRACE(QDF_MODULE_ID_SME,
2730 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 "%s: %d: On session %d AP doesn't support APSD",
2732 __func__, __LINE__, sessionId);
2733 break;
2734 }
2735
2736 if (SME_QOS_MAX_TID == pTspec_Info->ts_info.tid) {
2737 /* App didn't set TID, generate one */
2738 pTspec_Info->ts_info.tid =
2739 (uint8_t) (SME_QOS_WMM_UP_NC -
2740 pTspec_Info->ts_info.up);
2741 }
2742 /* addts logic */
2743 hstatus =
2744 qos_issue_command(pMac, sessionId, eSmeCommandAddTs,
2745 pTspec_Info, ac, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302746 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302747 QDF_TRACE(QDF_MODULE_ID_SME,
2748 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749 "%s: %d: sme_qos_add_ts_req() failed",
2750 __func__, __LINE__);
2751 break;
2752 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302753 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754 "%s: %d: On session %d AddTS on AC %d is pending",
2755 __func__, __LINE__, sessionId, ac);
2756 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
2757 break;
2758 }
2759 /* ACM is not enabled for this AC */
2760 /* Is the application looking for APSD? */
2761 if (0 == pTspec_Info->ts_info.psb) {
2762 /* no, we don't need APSD */
2763 /* but check the case, if the setup is called as a result of a release */
2764 /* or modify which boils down to the fact that APSD was set on this AC */
2765 /* but no longer needed - so we need a reassoc for the above case to */
2766 /* let the AP know */
2767 if (pSession->
2768 apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac))) {
2769 /* APSD was formerly enabled on this AC but is no longer required */
2770 /* so we must reassociate */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302771 QDF_TRACE(QDF_MODULE_ID_SME,
2772 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 "%s: %d: On session %d reassoc needed "
2774 "to disable APSD on AC %d", __func__,
2775 __LINE__, sessionId, ac);
2776 csr_get_modify_profile_fields(pMac, sessionId,
2777 &modifyProfileFields);
2778 modifyProfileFields.uapsd_mask |=
2779 pSession->apsdMask;
2780 modifyProfileFields.uapsd_mask &=
2781 ~(1 << (SME_QOS_EDCA_AC_VO - ac));
2782 hstatus =
2783 sme_qos_request_reassoc(pMac, sessionId,
2784 &modifyProfileFields,
2785 false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302786 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302788 QDF_TRACE(QDF_MODULE_ID_SME,
2789 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002790 "%s: %d: Unable to request reassociation",
2791 __func__, __LINE__);
2792 break;
2793 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302794 QDF_TRACE(QDF_MODULE_ID_SME,
2795 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 "%s: %d: On session %d reassociation to enable "
2797 "APSD on AC %d is pending",
2798 __func__, __LINE__, sessionId,
2799 ac);
2800 status =
2801 SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
2802 pACInfo->reassoc_pending = true;
2803 }
2804 } else {
2805 /* we don't need APSD on this AC */
2806 /* and we don't currently have APSD on this AC */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302807 QDF_TRACE(QDF_MODULE_ID_SME,
2808 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 "%s: %d: Request is not looking for APSD & Admission "
2810 "Control isn't mandatory for the AC",
2811 __func__, __LINE__);
2812 /* return success right away */
2813 status =
2814 SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP;
2815 }
2816 break;
2817 } else if (!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD)
2818 && !(pIes->WMMInfoAp.uapsd)) {
2819 /* application is looking for APSD but AP doesn't support it */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302820 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 "%s: %d: On session %d AP doesn't support APSD",
2822 __func__, __LINE__, sessionId);
2823 break;
2824 } else if (pSession->
2825 apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac))) {
2826 /* application is looking for APSD */
2827 /* and it is already enabled on this AC */
2828 status = SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302829 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 "%s: %d: Request is looking for APSD and it is already "
2831 "set for the AC", __func__, __LINE__);
2832 break;
2833 } else {
2834 /* application is looking for APSD */
2835 /* but it is not enabled on this AC */
2836 /* so we need to reassociate */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302837 QDF_TRACE(QDF_MODULE_ID_SME,
2838 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 FL("On session %d reassoc needed to enable APSD on AC %d"),
2840 sessionId, ac);
2841 /* reassoc logic */
2842 /* update the UAPSD mask to include the new */
2843 /* AC on which APSD is requested */
2844 csr_get_modify_profile_fields(pMac, sessionId,
2845 &modifyProfileFields);
2846 modifyProfileFields.uapsd_mask |=
2847 pSession->apsdMask;
2848 modifyProfileFields.uapsd_mask |=
2849 1 << (SME_QOS_EDCA_AC_VO - ac);
2850 hstatus =
2851 sme_qos_request_reassoc(pMac, sessionId,
2852 &modifyProfileFields,
2853 false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302854 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002855 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302856 QDF_TRACE(QDF_MODULE_ID_SME,
2857 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002858 "%s: %d: Unable to request reassociation",
2859 __func__, __LINE__);
2860 break;
2861 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302862 QDF_TRACE(QDF_MODULE_ID_SME,
2863 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002864 FL("On session %d reassociation to enable APSD on AC %d is pending"),
2865 sessionId, ac);
2866 status =
2867 SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
2868 pACInfo->reassoc_pending = true;
2869 }
2870 }
2871 } while (0);
2872
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302873 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874 return status;
2875}
2876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877/* This is a dummy function now. But the purpose of me adding this was to
2878 * delay the TSPEC processing till SET_KEY completes. This function can be
2879 * used to do any SME_QOS processing after the SET_KEY. As of now, it is
2880 * not required as we are ok with tspec getting programmed before set_key
2881 * as the roam timings are measured without tspec in reassoc!
2882 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302883QDF_STATUS sme_qos_process_set_key_success_ind(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 uint8_t sessionId, void *pEvent_info)
2885{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302886 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 "########### Set Key Complete #############");
2888 (void)sme_qos_process_buffered_cmd(sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302889 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002890}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891
2892#ifdef FEATURE_WLAN_ESE
2893/**
2894 * sme_qos_ese_save_tspec_response() - save TSPEC parameters.
2895 * @pMac: Pointer to the global MAC parameter structure.
2896 * @sessionId: SME session ID
2897 * @pTspec: Pointer to the TSPEC IE from the reassoc rsp
2898 * @ac: Access Category for which this TSPEC rsp is received
2899 * @tspecIndex: flow/direction
2900 *
2901 * This function saves the TSPEC parameters that came along in the TSPEC IE
2902 * in the reassoc response
2903 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302904 * Return: QDF_STATUS_SUCCESS - Release is successful.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302906QDF_STATUS sme_qos_ese_save_tspec_response(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 tDot11fIEWMMTSPEC *pTspec, uint8_t ac,
2908 uint8_t tspecIndex)
2909{
2910 tpSirAddtsRsp pAddtsRsp =
2911 &sme_qos_cb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex];
2912
2913 ac = sme_qos_u_pto_ac_map[pTspec->user_priority];
2914
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302915 qdf_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916
2917 pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP;
2918 pAddtsRsp->length = sizeof(tSirAddtsRsp);
2919 pAddtsRsp->rc = eSIR_SUCCESS;
2920 pAddtsRsp->sessionId = sessionId;
2921 pAddtsRsp->rsp.dialogToken = 0;
2922 pAddtsRsp->rsp.status = eSIR_SUCCESS;
2923 pAddtsRsp->rsp.wmeTspecPresent = pTspec->present;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302924 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 "%s: Copy Tspec to local data structure ac=%d, tspecIdx=%d",
2926 __func__, ac, tspecIndex);
2927
2928 if (pAddtsRsp->rsp.wmeTspecPresent) {
2929 /* Copy TSPEC params received in assoc response to addts response */
2930 convert_wmmtspec(pMac, &pAddtsRsp->rsp.tspec, pTspec);
2931 }
2932
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302933 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934}
2935
2936/**
2937 * sme_qos_ese_process_reassoc_tspec_rsp() - process ese reassoc tspec response
2938 * @pMac: Pointer to the global MAC parameter structure.
2939 * @sessionId: SME session ID
2940 * @pEven_info: Pointer to the smeJoinRsp structure
2941 *
2942 * This function processes the WMM TSPEC IE in the reassoc response.
2943 * Reassoc triggered as part of ESE roaming to another ESE capable AP.
2944 * If the TSPEC was added before reassoc, as part of Call Admission Control,
2945 * the reasso req from the STA would carry the TSPEC parameters which were
2946 * already negotiated with the older AP.
2947 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302948 * Return: QDF_STATUS_SUCCESS - Release is successful.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302950QDF_STATUS sme_qos_ese_process_reassoc_tspec_rsp(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951 uint8_t sessionId,
2952 void *pEvent_info)
2953{
2954 sme_QosSessionInfo *pSession;
2955 sme_QosACInfo *pACInfo;
2956 tDot11fIEWMMTSPEC *pTspecIE = NULL;
2957 tCsrRoamSession *pCsrSession = NULL;
2958 tCsrRoamConnectedInfo *pCsrConnectedInfo = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302959 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 uint8_t ac, numTspec, cnt;
2961 uint8_t tspec_flow_index, tspec_mask_status;
2962 uint32_t tspecIeLen;
2963
2964 pCsrSession = CSR_GET_SESSION(pMac, sessionId);
2965 if (NULL == pCsrSession) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302966 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 FL("session %d not found"), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302968 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 }
2970 pCsrConnectedInfo = &pCsrSession->connectedInfo;
2971 pSession = &sme_qos_cb.sessionInfo[sessionId];
2972
2973 /* Get the TSPEC IEs which came along with the reassoc response */
2974 /* from the pbFrames pointer */
2975 pTspecIE =
2976 (tDot11fIEWMMTSPEC *) (pCsrConnectedInfo->pbFrames +
2977 pCsrConnectedInfo->nBeaconLength +
2978 pCsrConnectedInfo->nAssocReqLength +
2979 pCsrConnectedInfo->nAssocRspLength +
2980 pCsrConnectedInfo->nRICRspLength);
2981
2982 /* Get the number of tspecs Ies in the frame, the min length */
2983 /* should be atleast equal to the one TSPEC IE */
2984 tspecIeLen = pCsrConnectedInfo->nTspecIeLength;
2985 if (tspecIeLen < sizeof(tDot11fIEWMMTSPEC)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302986 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 FL("ESE Tspec IE len %d less than min %zu"),
2988 tspecIeLen, sizeof(tDot11fIEWMMTSPEC));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302989 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 }
2991
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302992 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002993 "TspecLen = %d, pbFrames = %p, pTspecIE = %p",
2994 tspecIeLen, pCsrConnectedInfo->pbFrames, pTspecIE);
2995
2996 numTspec = (tspecIeLen) / sizeof(tDot11fIEWMMTSPEC);
2997 for (cnt = 0; cnt < numTspec; cnt++) {
2998 ac = sme_qos_up_to_ac(pTspecIE->user_priority);
2999 if (ac >= SME_QOS_EDCA_AC_MAX) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303000 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 FL("ac %d more than it`s max value"), ac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303002 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003003 }
3004 pACInfo = &pSession->ac_info[ac];
3005 tspec_mask_status = pACInfo->tspec_mask_status;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303006 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 FL("UP=%d, ac=%d, tspec_mask_status=%x"),
3008 pTspecIE->user_priority, ac, tspec_mask_status);
3009
3010 for (tspec_flow_index = 0;
3011 tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX;
3012 tspec_flow_index++) {
3013 if (tspec_mask_status & (1 << tspec_flow_index)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303014 QDF_TRACE(QDF_MODULE_ID_SME,
3015 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 FL
3017 ("Found Tspec entry flow = %d AC = %d"),
3018 tspec_flow_index, ac);
3019 sme_qos_ese_save_tspec_response(pMac, sessionId,
3020 pTspecIE, ac,
3021 tspec_flow_index);
3022 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303023 QDF_TRACE(QDF_MODULE_ID_SME,
3024 QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025 FL
3026 ("Not found Tspec entry flow = %d AC = %d"),
3027 tspec_flow_index, ac);
3028 }
3029 }
3030 /* Increment the pointer to point it to the next TSPEC IE */
3031 pTspecIE++;
3032 }
3033
3034 /* Send the Aggregated QoS request to HAL */
3035 status = sme_qos_ft_aggr_qos_req(pMac, sessionId);
3036
3037 return status;
3038}
3039
3040/**
3041 * sme_qos_copy_tspec_info() - copy tspec info.
3042 * @pMac: Pointer to the global MAC parameter structure.
3043 * @pTspec_Info: source structure
3044 * @pTspec: destination structure
3045 *
3046 * This function copies the existing TSPEC parameters from the source structure
3047 * to the destination structure.
3048 *
3049 * Return: None
3050 */
3051static void sme_qos_copy_tspec_info(tpAniSirGlobal pMac,
3052 sme_QosWmmTspecInfo *pTspec_Info,
3053 tSirMacTspecIE *pTspec)
3054{
3055 /* As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
3056 * Interval, Service Start Time, Suspension Interval and Delay Bound are
3057 * all intended for HCCA operation and therefore must be set to zero*/
3058 pTspec->delayBound = pTspec_Info->delay_bound;
3059 pTspec->inactInterval = pTspec_Info->inactivity_interval;
3060 pTspec->length = SME_QOS_TSPEC_IE_LENGTH;
3061 pTspec->maxBurstSz = pTspec_Info->max_burst_size;
3062 pTspec->maxMsduSz = pTspec_Info->maximum_msdu_size;
3063 pTspec->maxSvcInterval = pTspec_Info->max_service_interval;
3064 pTspec->meanDataRate = pTspec_Info->mean_data_rate;
3065 pTspec->mediumTime = pTspec_Info->medium_time;
3066 pTspec->minDataRate = pTspec_Info->min_data_rate;
3067 pTspec->minPhyRate = pTspec_Info->min_phy_rate;
3068 pTspec->minSvcInterval = pTspec_Info->min_service_interval;
3069 pTspec->nomMsduSz = pTspec_Info->nominal_msdu_size;
3070 pTspec->peakDataRate = pTspec_Info->peak_data_rate;
3071 pTspec->surplusBw = pTspec_Info->surplus_bw_allowance;
3072 pTspec->suspendInterval = pTspec_Info->suspension_interval;
3073 pTspec->svcStartTime = pTspec_Info->svc_start_time;
3074 pTspec->tsinfo.traffic.direction = pTspec_Info->ts_info.direction;
3075
3076 /* Make sure UAPSD is allowed */
3077 if (pTspec_Info->ts_info.psb) {
3078 pTspec->tsinfo.traffic.psb = pTspec_Info->ts_info.psb;
3079 } else {
3080 pTspec->tsinfo.traffic.psb = 0;
3081 pTspec_Info->ts_info.psb = 0;
3082 }
3083 pTspec->tsinfo.traffic.tsid = pTspec_Info->ts_info.tid;
3084 pTspec->tsinfo.traffic.userPrio = pTspec_Info->ts_info.up;
3085 pTspec->tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA;
3086 pTspec->tsinfo.traffic.burstSizeDefn =
3087 pTspec_Info->ts_info.burst_size_defn;
3088 pTspec->tsinfo.traffic.ackPolicy = pTspec_Info->ts_info.ack_policy;
3089 pTspec->type = SME_QOS_TSPEC_IE_TYPE;
3090
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303091 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 "%s: %d: up = %d, tid = %d",
3093 __func__, __LINE__,
3094 pTspec_Info->ts_info.up, pTspec_Info->ts_info.tid);
3095}
3096
3097/**
3098 * sme_qos_ese_retrieve_tspec_info() - retrieve tspec info.
3099 * @pMac: Pointer to the global MAC parameter structure.
3100 * @sessionId: SME session ID
3101 * @pTspecInfo: Pointer to the structure to carry back the TSPEC parameters
3102 *
3103 * This function is called by CSR when try to create reassoc request message to
3104 * PE - csrSendSmeReassocReqMsg. This functions get the existing tspec
3105 * parameters to be included in the reassoc request.
3106 *
3107 * Return: uint8_t - number of existing negotiated TSPECs
3108 */
3109uint8_t sme_qos_ese_retrieve_tspec_info(tpAniSirGlobal mac_ctx,
3110 uint8_t session_id, tTspecInfo *tspec_info)
3111{
3112 sme_QosSessionInfo *session;
3113 sme_QosACInfo *ac_info;
3114 uint8_t ac, num_tspec = 0;
3115 tTspecInfo *dst_tspec = tspec_info;
3116 uint8_t tspec_mask;
3117 uint8_t tspec_pending;
3118
3119 /*
3120 * TODO: Check if TSPEC has already been established
3121 * if not return
3122 */
3123 session = &sme_qos_cb.sessionInfo[session_id];
3124 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
3125 volatile uint8_t index = 0;
3126 ac_info = &session->ac_info[ac];
3127 tspec_pending = ac_info->tspec_pending;
3128 tspec_mask = ac_info->tspec_mask_status;
3129 do {
3130 /*
3131 * If a tspec status is pending, take
3132 * requested_QoSInfo for RIC request,
3133 * else use curr_QoSInfo for the
3134 * RIC request
3135 */
3136 if ((tspec_mask & SME_QOS_TSPEC_MASK_BIT_1_SET)
3137 && (tspec_pending &
3138 SME_QOS_TSPEC_MASK_BIT_1_SET)){
3139 sme_qos_copy_tspec_info(mac_ctx,
3140 &ac_info->requested_QoSInfo[index],
3141 &dst_tspec->tspec);
3142 dst_tspec->valid = true;
3143 num_tspec++;
3144 dst_tspec++;
3145 } else if ((tspec_mask & SME_QOS_TSPEC_MASK_BIT_1_SET)
3146 && !(tspec_pending &
3147 SME_QOS_TSPEC_MASK_BIT_1_SET)){
3148 sme_qos_copy_tspec_info(mac_ctx,
3149 &ac_info->curr_QoSInfo[index],
3150 &dst_tspec->tspec);
3151 dst_tspec->valid = true;
3152 num_tspec++;
3153 dst_tspec++;
3154 }
3155 tspec_mask >>= 1;
3156 tspec_pending >>= 1;
3157 index++;
3158 } while (tspec_mask);
3159 }
3160 return num_tspec;
3161}
3162
3163#endif
3164
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303166QDF_STATUS sme_qos_create_tspec_ricie(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 sme_QosWmmTspecInfo *pTspec_Info,
3168 uint8_t *pRICBuffer, uint32_t *pRICLength,
3169 uint8_t *pRICIdentifier)
3170{
3171 tDot11fIERICDataDesc ricIE;
3172 uint32_t nStatus;
3173
3174 if (pRICBuffer == NULL || pRICIdentifier == NULL || pRICLength == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303175 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303176 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177 }
3178
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303179 qdf_mem_zero(&ricIE, sizeof(tDot11fIERICDataDesc));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180
3181 ricIE.present = 1;
3182 ricIE.RICData.present = 1;
3183 ricIE.RICData.resourceDescCount = 1;
3184 ricIE.RICData.statusCode = 0;
3185 ricIE.RICData.Identifier = sme_qos_assign_dialog_token();
3186#ifndef USE_80211_WMMTSPEC_FOR_RIC
3187 ricIE.TSPEC.present = 1;
3188 ricIE.TSPEC.delay_bound = pTspec_Info->delay_bound;
3189 ricIE.TSPEC.inactivity_int = pTspec_Info->inactivity_interval;
3190 ricIE.TSPEC.burst_size = pTspec_Info->max_burst_size;
3191 ricIE.TSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size;
3192 ricIE.TSPEC.max_service_int = pTspec_Info->max_service_interval;
3193 ricIE.TSPEC.mean_data_rate = pTspec_Info->mean_data_rate;
3194 ricIE.TSPEC.medium_time = 0;
3195 ricIE.TSPEC.min_data_rate = pTspec_Info->min_data_rate;
3196 ricIE.TSPEC.min_phy_rate = pTspec_Info->min_phy_rate;
3197 ricIE.TSPEC.min_service_int = pTspec_Info->min_service_interval;
3198 ricIE.TSPEC.size = pTspec_Info->nominal_msdu_size;
3199 ricIE.TSPEC.peak_data_rate = pTspec_Info->peak_data_rate;
3200 ricIE.TSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance;
3201 ricIE.TSPEC.suspension_int = pTspec_Info->suspension_interval;
3202 ricIE.TSPEC.service_start_time = pTspec_Info->svc_start_time;
3203 ricIE.TSPEC.direction = pTspec_Info->ts_info.direction;
3204 /* Make sure UAPSD is allowed */
3205 if (pTspec_Info->ts_info.psb) {
3206 ricIE.TSPEC.psb = pTspec_Info->ts_info.psb;
3207 } else {
3208 ricIE.TSPEC.psb = 0;
3209 }
3210 ricIE.TSPEC.tsid = pTspec_Info->ts_info.tid;
3211 ricIE.TSPEC.user_priority = pTspec_Info->ts_info.up;
3212 ricIE.TSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA;
3213
3214 *pRICIdentifier = ricIE.RICData.Identifier;
3215
3216 nStatus =
3217 dot11f_pack_ie_ric_data_desc(pMac, &ricIE, pRICBuffer, sizeof(ricIE),
3218 pRICLength);
3219 if (DOT11F_FAILED(nStatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303220 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221 FL
3222 ("Packing of RIC Data of length %d failed with status %d"),
3223 *pRICLength, nStatus);
3224 }
3225#else /* WMM TSPEC */
3226 /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
3227 Interval, Service Start Time, Suspension Interval and Delay Bound are
3228 all intended for HCCA operation and therefore must be set to zero */
3229 ricIE.WMMTSPEC.present = 1;
3230 ricIE.WMMTSPEC.version = 1;
3231 ricIE.WMMTSPEC.delay_bound = pTspec_Info->delay_bound;
3232 ricIE.WMMTSPEC.inactivity_int = pTspec_Info->inactivity_interval;
3233 ricIE.WMMTSPEC.burst_size = pTspec_Info->max_burst_size;
3234 ricIE.WMMTSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size;
3235 ricIE.WMMTSPEC.max_service_int = pTspec_Info->max_service_interval;
3236 ricIE.WMMTSPEC.mean_data_rate = pTspec_Info->mean_data_rate;
3237 ricIE.WMMTSPEC.medium_time = 0;
3238 ricIE.WMMTSPEC.min_data_rate = pTspec_Info->min_data_rate;
3239 ricIE.WMMTSPEC.min_phy_rate = pTspec_Info->min_phy_rate;
3240 ricIE.WMMTSPEC.min_service_int = pTspec_Info->min_service_interval;
3241 ricIE.WMMTSPEC.size = pTspec_Info->nominal_msdu_size;
3242 ricIE.WMMTSPEC.peak_data_rate = pTspec_Info->peak_data_rate;
3243 ricIE.WMMTSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance;
3244 ricIE.WMMTSPEC.suspension_int = pTspec_Info->suspension_interval;
3245 ricIE.WMMTSPEC.service_start_time = pTspec_Info->svc_start_time;
3246 ricIE.WMMTSPEC.direction = pTspec_Info->ts_info.direction;
3247 /* Make sure UAPSD is allowed */
3248 if (pTspec_Info->ts_info.psb) {
3249 ricIE.WMMTSPEC.psb = pTspec_Info->ts_info.psb;
3250 } else {
3251 ricIE.WMMTSPEC.psb = 0;
3252 }
3253 ricIE.WMMTSPEC.tsid = pTspec_Info->ts_info.tid;
3254 ricIE.WMMTSPEC.user_priority = pTspec_Info->ts_info.up;
3255 ricIE.WMMTSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA;
3256
3257 nStatus =
3258 dot11f_pack_ie_ric_data_desc(pMac, &ricIE, pRICBuffer, sizeof(ricIE),
3259 pRICLength);
3260 if (DOT11F_FAILED(nStatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303261 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003262 FL
3263 ("Packing of RIC Data of length %d failed with status %d"),
3264 *pRICLength, nStatus);
3265 }
3266#endif /* 80211_TSPEC */
3267 *pRICIdentifier = ricIE.RICData.Identifier;
3268 return nStatus;
3269}
3270/**
3271 * sme_qos_process_ft_reassoc_req_ev()- processes reassoc request
3272 *
3273 * @session_id: SME Session Id
3274 *
3275 * This function Process reassoc request related to QOS
3276 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303277 * Return: QDF_STATUS enumeration value.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303279static QDF_STATUS sme_qos_process_ft_reassoc_req_ev(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 uint8_t sessionId)
3281{
3282 sme_QosSessionInfo *session;
3283 sme_QosACInfo *ac_info;
3284 uint8_t ac, qos_requested = false;
3285 uint8_t tspec_index;
3286 sme_QosFlowInfoEntry *flow_info = NULL;
3287 tListElem *entry = NULL;
3288
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303289 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290 FL("Invoked on session %d"), sessionId);
3291
3292 session = &sme_qos_cb.sessionInfo[sessionId];
3293
3294 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
3295 ac_info = &session->ac_info[ac];
3296 qos_requested = false;
3297
3298 for (tspec_index = 0;
3299 tspec_index < SME_QOS_TSPEC_INDEX_MAX;
3300 tspec_index++) {
3301 /*
3302 * Only in the below case, copy the AC's curr
3303 * QoS Info to requested QoS info
3304 */
3305 if ((ac_info->ricIdentifier[tspec_index]
3306 && !ac_info->tspec_pending)
3307 || (ac_info->
3308 tspec_mask_status & (1 << tspec_index))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303309 QDF_TRACE(QDF_MODULE_ID_SME,
3310 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311 FL("Copying the currentQos to "
3312 "requestedQos for AC=%d, flow=%d"),
3313 ac, tspec_index);
3314
3315 ac_info->requested_QoSInfo[tspec_index] =
3316 ac_info->curr_QoSInfo[tspec_index];
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303317 qdf_mem_zero(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003318 &ac_info->curr_QoSInfo[tspec_index],
3319 sizeof(sme_QosWmmTspecInfo));
3320 qos_requested = true;
3321 }
3322 }
3323
3324 /*
3325 * Only if the tspec is required, transition the state to
3326 * SME_QOS_REQUESTED for this AC
3327 */
3328 if (qos_requested) {
3329 switch (ac_info->curr_state) {
3330 case SME_QOS_HANDOFF:
3331 sme_qos_state_transition(sessionId, ac,
3332 SME_QOS_REQUESTED);
3333 break;
3334 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303335 QDF_TRACE(QDF_MODULE_ID_SME,
3336 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337 FL("FT Reassoc req event in"
3338 " unexpected state %d"),
3339 ac_info->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303340 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 }
3342 }
3343 }
3344
3345 /*
3346 * At this point of time, we are
3347 * disconnected from the old AP, so it is safe
3348 * to reset all these session variables
3349 */
3350 session->apsdMask = 0;
3351 session->uapsdAlreadyRequested = 0;
3352 session->readyForPowerSave = 0;
3353
3354 /*
3355 * Now change reason and HO renewal of
3356 * all the flow in this session only
3357 */
3358 entry = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
3359 if (!entry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303360 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003361 FL("Flow List empty, nothing to update"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303362 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003363 }
3364
3365 do {
3366 flow_info = GET_BASE_ADDR(entry, sme_QosFlowInfoEntry, link);
3367 if (sessionId == flow_info->sessionId) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303368 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369 FL("Changing FlowID %d reason to SETUP"
3370 "and HO renewal to false"),
3371 flow_info->QosFlowID);
3372 flow_info->reason = SME_QOS_REASON_SETUP;
3373 flow_info->hoRenewal = true;
3374 }
3375 entry = csr_ll_next(&sme_qos_cb.flow_list, entry, false);
3376 } while (entry);
3377
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303378 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003379}
3380
3381/**
3382 * sme_qos_fill_aggr_info - fill QOS Aggregation info
3383 *
3384 * @ac_id - index to the AC
3385 * @ts_id - index to TS for a given AC
3386 * @direction - traffic direction
3387 * @msg - QOS message
3388 * @session - sme session information
3389 *
3390 * this is a helper function to populate aggregation information
3391 * for QOS message.
3392 *
3393 * Return: None
3394 */
3395static void sme_qos_fill_aggr_info(int ac_id, int ts_id,
3396 sme_QosWmmDirType direction,
3397 tSirAggrQosReq *msg,
3398 sme_QosSessionInfo *session)
3399{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303400 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003401 FL("Found tspec entry AC=%d, flow=%d, direction = %d"),
3402 ac_id, ts_id, direction);
3403
3404 msg->aggrInfo.aggrAddTsInfo[ac_id].dialogToken =
3405 sme_qos_assign_dialog_token();
3406 msg->aggrInfo.aggrAddTsInfo[ac_id].lleTspecPresent =
3407 session->ac_info[ac_id].addTsRsp[ts_id].rsp.lleTspecPresent;
3408 msg->aggrInfo.aggrAddTsInfo[ac_id].numTclas =
3409 session->ac_info[ac_id].addTsRsp[ts_id].rsp.numTclas;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303410 qdf_mem_copy(msg->aggrInfo.aggrAddTsInfo[ac_id].tclasInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003411 session->ac_info[ac_id].addTsRsp[ts_id].rsp.tclasInfo,
3412 SIR_MAC_TCLASIE_MAXNUM);
3413 msg->aggrInfo.aggrAddTsInfo[ac_id].tclasProc =
3414 session->ac_info[ac_id].addTsRsp[ts_id].rsp.tclasProc;
3415 msg->aggrInfo.aggrAddTsInfo[ac_id].tclasProcPresent =
3416 session->ac_info[ac_id].addTsRsp[ts_id].rsp.tclasProcPresent;
3417 msg->aggrInfo.aggrAddTsInfo[ac_id].tspec =
3418 session->ac_info[ac_id].addTsRsp[ts_id].rsp.tspec;
3419 msg->aggrInfo.aggrAddTsInfo[ac_id].wmeTspecPresent =
3420 session->ac_info[ac_id].addTsRsp[ts_id].rsp.wmeTspecPresent;
3421 msg->aggrInfo.aggrAddTsInfo[ac_id].wsmTspecPresent =
3422 session->ac_info[ac_id].addTsRsp[ts_id].rsp.wsmTspecPresent;
3423 msg->aggrInfo.tspecIdx |= (1 << ac_id);
3424
3425 /* Mark the index for this AC as pending for response, which would be */
3426 /* used to validate the AddTS response from HAL->PE->SME */
3427 session->ac_info[ac_id].tspec_pending = (1 << ts_id);
3428
3429 return;
3430}
3431
3432/**
3433 * sme_qos_ft_aggr_qos_req - send aggregated QOS request
3434 *
3435 * @mac_ctx - global MAC context
3436 * @session_id - sme session Id
3437 *
3438 * This function is used to send aggregated QOS request to HAL.
3439 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303440 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003441 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303442QDF_STATUS sme_qos_ft_aggr_qos_req(tpAniSirGlobal mac_ctx, uint8_t session_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003443{
3444 tSirAggrQosReq *aggr_req = NULL;
3445 sme_QosSessionInfo *session;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303446 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447 int i, j = 0;
3448 uint8_t direction;
3449
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303450 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451 FL("invoked on session %d"), session_id);
3452
3453 session = &sme_qos_cb.sessionInfo[session_id];
3454
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303455 aggr_req = (tSirAggrQosReq *) qdf_mem_malloc(sizeof(tSirAggrQosReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456
3457 if (!aggr_req) {
3458 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303459 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003460 FL("couldn't allocate memory for the msg buffer"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303461 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462 }
3463
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303464 qdf_mem_zero(aggr_req, sizeof(tSirAggrQosReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465
3466 aggr_req->messageType = eWNI_SME_FT_AGGR_QOS_REQ;
3467 aggr_req->length = sizeof(tSirAggrQosReq);
3468 aggr_req->sessionId = session_id;
3469 aggr_req->timeout = 0;
3470 aggr_req->rspReqd = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303471 qdf_mem_copy(&aggr_req->bssid.bytes[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472 &session->assocInfo.pBssDesc->bssId[0],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303473 sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474
3475 for (i = 0; i < SME_QOS_EDCA_AC_MAX; i++) {
3476 for (j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303477 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003478 FL("ac=%d, tspec_mask_staus=%x, tspec_index=%d"),
3479 i, session->ac_info[i].tspec_mask_status, j);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303480 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 FL("direction = %d"),
3482 session->ac_info[i].addTsRsp[j].rsp.tspec.
3483 tsinfo.traffic.direction);
3484 /* Check if any flow is active on this AC */
3485 if (!((session->ac_info[i].tspec_mask_status) &
3486 (1 << j)))
3487 continue;
3488
3489 direction = session->ac_info[i].addTsRsp[j].rsp.tspec.
3490 tsinfo.traffic.direction;
3491
3492 if ((direction == SME_QOS_WMM_TS_DIR_UPLINK) ||
3493 (direction == SME_QOS_WMM_TS_DIR_BOTH)) {
3494 sme_qos_fill_aggr_info(i, j, direction,
3495 aggr_req, session);
3496 }
3497 }
3498 }
3499
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303500 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003501 FL("Sending aggregated message to HAL 0x%x"),
3502 aggr_req->aggrInfo.tspecIdx);
3503
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303504 if (QDF_IS_STATUS_SUCCESS(cds_send_mb_message_to_mac(aggr_req))) {
3505 status = QDF_STATUS_SUCCESS;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303506 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 FL("sent down a AGGR QoS req to PE"));
3508 }
3509
3510 return status;
3511}
3512
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303513QDF_STATUS sme_qos_process_ftric_response(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514 tDot11fIERICDataDesc *pRicDataDesc,
3515 uint8_t ac, uint8_t tspecIndex)
3516{
3517 uint8_t i = 0;
3518 tpSirAddtsRsp pAddtsRsp
3519 =
3520 &sme_qos_cb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex];
3521
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303522 qdf_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523
3524 pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP;
3525 pAddtsRsp->length = sizeof(tSirAddtsRsp);
3526 pAddtsRsp->rc = pRicDataDesc->RICData.statusCode;
3527 pAddtsRsp->sessionId = sessionId;
3528 pAddtsRsp->rsp.dialogToken = pRicDataDesc->RICData.Identifier;
3529 pAddtsRsp->rsp.status = pRicDataDesc->RICData.statusCode;
3530 pAddtsRsp->rsp.wmeTspecPresent = pRicDataDesc->TSPEC.present;
3531 if (pAddtsRsp->rsp.wmeTspecPresent) {
3532 /* Copy TSPEC params received in RIC response to addts response */
3533 convert_tspec(pMac, &pAddtsRsp->rsp.tspec, &pRicDataDesc->TSPEC);
3534 }
3535
3536 pAddtsRsp->rsp.numTclas = pRicDataDesc->num_TCLAS;
3537 if (pAddtsRsp->rsp.numTclas) {
3538 for (i = 0; i < pAddtsRsp->rsp.numTclas; i++) {
3539 /* Copy TCLAS info per index to the addts response */
3540 convert_tclas(pMac, &pAddtsRsp->rsp.tclasInfo[i],
3541 &pRicDataDesc->TCLAS[i]);
3542 }
3543 }
3544
3545 pAddtsRsp->rsp.tclasProcPresent = pRicDataDesc->TCLASSPROC.present;
3546 if (pAddtsRsp->rsp.tclasProcPresent)
3547 pAddtsRsp->rsp.tclasProc = pRicDataDesc->TCLASSPROC.processing;
3548
3549 pAddtsRsp->rsp.schedulePresent = pRicDataDesc->Schedule.present;
3550 if (pAddtsRsp->rsp.schedulePresent) {
3551 /* Copy Schedule IE params to addts response */
3552 convert_schedule(pMac, &pAddtsRsp->rsp.schedule,
3553 &pRicDataDesc->Schedule);
3554 }
3555 /* Need to check the below portion is a part of WMM TSPEC */
3556 /* Process Delay element */
3557 if (pRicDataDesc->TSDelay.present)
3558 convert_ts_delay(pMac, &pAddtsRsp->rsp.delay,
3559 &pRicDataDesc->TSDelay);
3560
3561 /* Need to call for WMMTSPEC */
3562 if (pRicDataDesc->WMMTSPEC.present) {
3563 convert_wmmtspec(pMac, &pAddtsRsp->rsp.tspec,
3564 &pRicDataDesc->WMMTSPEC);
3565 }
3566 /* return sme_qos_process_add_ts_rsp(pMac, &addtsRsp); */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303567 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003568}
3569
3570/**
3571 * sme_qos_process_aggr_qos_rsp - process qos aggregation response
3572 *
3573 * @mac_ctx - global mac context
3574 * @msgbuf - SME message buffer
3575 *
3576 * this function process the QOS aggregation response received.
3577 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303578 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003579 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303580QDF_STATUS sme_qos_process_aggr_qos_rsp(tpAniSirGlobal mac_ctx, void *msgbuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581{
3582 tpSirAggrQosRsp rsp = (tpSirAggrQosRsp) msgbuf;
3583 tSirAddtsRsp addtsrsp;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303584 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 int i, j = 0;
3586 uint8_t sessionid = rsp->sessionId;
3587
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303588 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 FL("Received AGGR_QOS resp from LIM"));
3590
3591 /* Copy the updated response information for TSPEC of all the ACs */
3592 for (i = 0; i < SIR_QOS_NUM_AC_MAX; i++) {
3593 uint8_t tspec_mask_status =
3594 sme_qos_cb.sessionInfo[sessionid].ac_info[i].
3595 tspec_mask_status;
3596 for (j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++) {
3597 uint8_t direction =
3598 sme_qos_cb.sessionInfo[sessionid].
3599 ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic.
3600 direction;
3601
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303602 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003603 FL("Addts rsp from LIM AC=%d, flow=%d dir=%d, tspecIdx=%x"),
3604 i, j, direction, rsp->aggrInfo.tspecIdx);
3605
3606 /* Check if the direction is Uplink or bi-directional */
3607 if (!(((1 << i) & rsp->aggrInfo.tspecIdx) &&
3608 ((tspec_mask_status) & (1 << j)) &&
3609 ((direction == SME_QOS_WMM_TS_DIR_UPLINK) ||
3610 (direction == SME_QOS_WMM_TS_DIR_BOTH)))) {
3611 continue;
3612 }
3613 addtsrsp =
3614 sme_qos_cb.sessionInfo[sessionid].ac_info[i].
3615 addTsRsp[j];
3616 addtsrsp.rc = rsp->aggrInfo.aggrRsp[i].status;
3617 addtsrsp.rsp.status = rsp->aggrInfo.aggrRsp[i].status;
3618 addtsrsp.rsp.tspec = rsp->aggrInfo.aggrRsp[i].tspec;
3619
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303620 QDF_TRACE(QDF_MODULE_ID_SME,
3621 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622 FL("Processing Addts rsp from LIM AC=%d, flow=%d"),
3623 i, j);
3624 /* post ADD TS response for each */
3625 if (sme_qos_process_add_ts_rsp(mac_ctx, &addtsrsp) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303626 QDF_STATUS_SUCCESS)
3627 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003628 }
3629 }
3630 return status;
3631}
3632
3633/**
3634 * sme_qos_find_matching_tspec() - utility function to find matching tspec
3635 * @mac_ctx: global MAC context
3636 * @sessionid: session ID
3637 * @ac: AC index
3638 * @ac_info: Current AC info
3639 * @ric_data_desc: pointer to ric data
3640 * @ric_rsplen: pointer to ric response length
3641 *
3642 * This utility function is called by sme_qos_process_ft_reassoc_rsp_ev
3643 * to find the matching tspec
3644 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303645 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303647static QDF_STATUS sme_qos_find_matching_tspec(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003648 uint8_t sessionid, uint8_t ac, sme_QosACInfo *ac_info,
3649 tDot11fIERICDataDesc *ric_data_desc, uint32_t *ric_rsplen)
3650{
3651 uint8_t tspec_flow_index;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303652 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003653
3654 for (tspec_flow_index = 0;
3655 tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++) {
3656 /*
3657 * Only in the below case, copy the AC's curr QoS Info
3658 * to requested QoS info
3659 */
3660 if (!ac_info->ricIdentifier[tspec_flow_index])
3661 continue;
3662
3663 if (!*ric_rsplen) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303664 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 FL("RIC Response not received for AC %d on "
3666 "TSPEC Index %d, RIC Req Identifier = %d"),
3667 ac, tspec_flow_index,
3668 ac_info->ricIdentifier[tspec_flow_index]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303669 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670 continue;
3671 }
3672 /* Now we got response for this identifier. Process it. */
3673 if (!ric_data_desc->present)
3674 continue;
3675 if (!ric_data_desc->RICData.present)
3676 continue;
3677
3678 if (ric_data_desc->RICData.Identifier !=
3679 ac_info->ricIdentifier[tspec_flow_index]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303680 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 FL("RIC response order not same as request sent. "
3682 "Request ID = %d, Response ID = %d"),
3683 ac_info->ricIdentifier[tspec_flow_index],
3684 ric_data_desc->RICData.Identifier);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303685 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303687 QDF_TRACE(QDF_MODULE_ID_SME,
3688 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 FL("Processing RIC Response for AC %d, "
3690 "TSPEC Flow index %d with RIC ID %d "),
3691 ac, tspec_flow_index,
3692 ric_data_desc->RICData.Identifier);
3693 status = sme_qos_process_ftric_response(mac_ctx,
3694 sessionid, ric_data_desc, ac,
3695 tspec_flow_index);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303696 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303697 QDF_TRACE(QDF_MODULE_ID_SME,
3698 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003699 FL("Failed with status %d for AC %d in "
3700 "TSPEC Flow index = %d"),
3701 status, ac, tspec_flow_index);
3702 }
3703 }
3704 ric_data_desc++;
3705 *ric_rsplen -= sizeof(tDot11fIERICDataDesc);
3706 }
3707 return status;
3708}
3709
3710#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3711/**
3712 * sme_qos_find_matching_tspec_lfr3() - utility function to find matching tspec
3713 * @mac_ctx: global MAC context
3714 * @sessionid: session ID
3715 * @ac: AC index
3716 * @qos_session: QOS session
3717 * @ric_data_desc: pointer to ric data
3718 * @ric_rsplen: ric response length
3719 *
3720 * This utility function is called by sme_qos_process_ft_reassoc_rsp_ev
3721 * to find the matching tspec while LFR3 is enabled.
3722 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303723 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003724 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303725static QDF_STATUS sme_qos_find_matching_tspec_lfr3(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 uint8_t sessionid, uint8_t ac, sme_QosSessionInfo *qos_session,
3727 tDot11fIERICDataDesc *ric_data_desc, uint32_t ric_rsplen)
3728{
3729 sme_QosACInfo *ac_info;
3730 uint8_t tspec_flow_idx;
3731 bool found = false;
3732 sme_QosWmmDirType direction, qos_dir;
3733 uint8_t ac1;
3734 tDot11fIERICDataDesc *ric_data = NULL;
3735 uint32_t ric_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303736 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737
3738 ric_data = ric_data_desc;
3739 ric_len = ric_rsplen;
3740 ac_info = &qos_session->ac_info[ac];
3741 for (tspec_flow_idx = 0; tspec_flow_idx < SME_QOS_TSPEC_INDEX_MAX;
3742 tspec_flow_idx++) {
3743 if (!((qos_session->ac_info[ac].tspec_mask_status) &
3744 (1 << tspec_flow_idx)))
3745 goto sme_qos_next_ric;
3746 qos_dir =
3747 ac_info->requested_QoSInfo[tspec_flow_idx].ts_info.direction;
3748 do {
3749 ac1 = sme_qos_up_to_ac(
3750 ric_data->WMMTSPEC.user_priority);
3751 if (ac == SME_QOS_EDCA_AC_MAX) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303752 QDF_TRACE(QDF_MODULE_ID_SME,
3753 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003754 FL("Invalid AC %d UP %d"), ac,
3755 ric_data->WMMTSPEC.user_priority);
3756 break;
3757 }
3758 direction = ric_data->WMMTSPEC.direction;
3759 if (ac == ac1 && direction == qos_dir) {
3760 found = true;
3761 status = sme_qos_process_ftric_response(mac_ctx,
3762 sessionid, ric_data, ac,
3763 tspec_flow_idx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303764 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303765 QDF_TRACE(QDF_MODULE_ID_SME,
3766 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003767 FL("Failed with status %d for AC %d "
3768 "in TSPEC Flow index = %d"),
3769 status, ac, tspec_flow_idx);
3770 }
3771 break;
3772 }
3773 ric_data++;
3774 ric_len -= sizeof(tDot11fIERICDataDesc);
3775 } while (ric_len);
3776sme_qos_next_ric:
3777 ric_data = ric_data_desc;
3778 ric_len = ric_rsplen;
3779 found = false;
3780 }
3781
3782 return status;
3783}
3784#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
3785
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303786QDF_STATUS sme_qos_process_ft_reassoc_rsp_ev(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 uint8_t sessionid, void *event_info)
3788{
3789 sme_QosSessionInfo *qos_session;
3790 sme_QosACInfo *ac_info;
3791 uint8_t ac;
3792 tDot11fIERICDataDesc *ric_data_desc = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303793 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003794 tCsrRoamSession *csr_session = CSR_GET_SESSION(mac_ctx, sessionid);
3795 tCsrRoamConnectedInfo *csr_conn_info = NULL;
3796 uint32_t ric_rsplen;
3797#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3798 tDot11fIERICDataDesc *ric_data = NULL;
3799 uint32_t ric_len;
3800#endif
3801
3802 if (NULL == csr_session) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303803 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804 FL("The Session pointer is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303805 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806 }
3807 csr_conn_info = &csr_session->connectedInfo;
3808 ric_rsplen = csr_conn_info->nRICRspLength;
3809
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303810 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 FL("invoked on session %d"), sessionid);
3812
3813 qos_session = &sme_qos_cb.sessionInfo[sessionid];
3814
3815 ric_data_desc = (tDot11fIERICDataDesc *) ((csr_conn_info->pbFrames) +
3816 (csr_conn_info->nBeaconLength +
3817 csr_conn_info->nAssocReqLength +
3818 csr_conn_info->nAssocRspLength));
3819
3820#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003821 if (!csr_session->roam_synch_in_progress) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822#endif
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003823 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
3824 ac_info = &qos_session->ac_info[ac];
3825 sme_qos_find_matching_tspec(mac_ctx, sessionid, ac,
3826 ac_info, ric_data_desc, &ric_rsplen);
3827 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003829 if (ric_rsplen) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303830 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003831 FL("RIC Resp still follows . Rem len = %d"),
3832 ric_rsplen);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303833 QDF_ASSERT(0);
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08003834 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003835#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3836 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303837 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 FL("LFR3-11r Compare RIC in Reassoc Resp to find"
3839 " matching tspec in host."));
3840 ric_data = ric_data_desc;
3841 ric_len = ric_rsplen;
3842 if (ric_rsplen && ric_data_desc->present &&
3843 ric_data_desc->WMMTSPEC.present) {
3844 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX;
3845 ac++) {
3846 sme_qos_find_matching_tspec_lfr3(mac_ctx,
3847 sessionid, ac, qos_session, ric_data,
3848 ric_len);
3849 }
3850 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303851 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852 FL("LFR3-11r ric_rsplen is zero or ric_data_desc is"
3853 " not present or wmmtspec is not present"));
3854 }
3855 }
3856#endif
3857
3858 /* Send the Aggregated QoS request to HAL */
3859 status = sme_qos_ft_aggr_qos_req(mac_ctx, sessionid);
3860
3861 return status;
3862}
3863
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864/**
3865 * sme_qos_add_ts_req() - send ADDTS request.
3866 * @pMac: Pointer to the global MAC parameter structure.
3867 * @sessionId: Session upon which the TSPEC should be added
3868 * @pTspec_Info: Pointer to sme_QosWmmTspecInfo which contains the WMM
3869 * TSPEC related info as defined above
3870 * @ac: Enumeration of the various EDCA Access Categories.
3871 *
3872 * This function is used to send down the ADDTS request with TSPEC params to PE
3873 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303874 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003875 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303876QDF_STATUS sme_qos_add_ts_req(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 uint8_t sessionId,
3878 sme_QosWmmTspecInfo *pTspec_Info,
3879 sme_QosEdcaAcType ac)
3880{
3881 tSirAddtsReq *pMsg = NULL;
3882 sme_QosSessionInfo *pSession;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303883 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884#ifdef FEATURE_WLAN_ESE
3885 tCsrRoamSession *pCsrSession = CSR_GET_SESSION(pMac, sessionId);
3886#endif
3887#ifdef FEATURE_WLAN_DIAG_SUPPORT
3888 WLAN_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type);
3889#endif
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303890 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003891 "%s: %d: invoked on session %d for AC %d",
3892 __func__, __LINE__, sessionId, ac);
3893 if (sessionId >= CSR_ROAM_SESSION_MAX) {
3894 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303895 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 "%s: %d: sessionId(%d) is invalid",
3897 __func__, __LINE__, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303898 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003899 }
3900
3901 pSession = &sme_qos_cb.sessionInfo[sessionId];
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303902 pMsg = (tSirAddtsReq *) qdf_mem_malloc(sizeof(tSirAddtsReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903 if (!pMsg) {
3904 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303905 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003906 "%s: %d: couldn't allocate memory for the msg buffer",
3907 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303908 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303910 qdf_mem_zero(pMsg, sizeof(tSirAddtsReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003911 pMsg->messageType = eWNI_SME_ADDTS_REQ;
3912 pMsg->length = sizeof(tSirAddtsReq);
3913 pMsg->sessionId = sessionId;
3914 pMsg->timeout = 0;
3915 pMsg->rspReqd = true;
3916 pMsg->req.dialogToken = sme_qos_assign_dialog_token();
3917 /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service
3918 Interval, Service Start Time, Suspension Interval and Delay Bound are
3919 all intended for HCCA operation and therefore must be set to zero */
3920 pMsg->req.tspec.delayBound = 0;
3921 pMsg->req.tspec.inactInterval = pTspec_Info->inactivity_interval;
3922 pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH;
3923 pMsg->req.tspec.maxBurstSz = pTspec_Info->max_burst_size;
3924 pMsg->req.tspec.maxMsduSz = pTspec_Info->maximum_msdu_size;
3925 pMsg->req.tspec.maxSvcInterval = pTspec_Info->max_service_interval;
3926 pMsg->req.tspec.meanDataRate = pTspec_Info->mean_data_rate;
3927 pMsg->req.tspec.mediumTime = pTspec_Info->medium_time;
3928 pMsg->req.tspec.minDataRate = pTspec_Info->min_data_rate;
3929 pMsg->req.tspec.minPhyRate = pTspec_Info->min_phy_rate;
3930 pMsg->req.tspec.minSvcInterval = pTspec_Info->min_service_interval;
3931 pMsg->req.tspec.nomMsduSz = pTspec_Info->nominal_msdu_size;
3932 pMsg->req.tspec.peakDataRate = pTspec_Info->peak_data_rate;
3933 pMsg->req.tspec.surplusBw = pTspec_Info->surplus_bw_allowance;
3934 pMsg->req.tspec.suspendInterval = pTspec_Info->suspension_interval;
3935 pMsg->req.tspec.svcStartTime = 0;
3936 pMsg->req.tspec.tsinfo.traffic.direction =
3937 pTspec_Info->ts_info.direction;
3938 /* Make sure UAPSD is allowed */
3939 if (pTspec_Info->ts_info.psb) {
3940 pMsg->req.tspec.tsinfo.traffic.psb = pTspec_Info->ts_info.psb;
3941 } else {
3942 pMsg->req.tspec.tsinfo.traffic.psb = 0;
3943 pTspec_Info->ts_info.psb = 0;
3944 }
3945 pMsg->req.tspec.tsinfo.traffic.tsid = pTspec_Info->ts_info.tid;
3946 pMsg->req.tspec.tsinfo.traffic.userPrio = pTspec_Info->ts_info.up;
3947 pMsg->req.tspec.tsinfo.traffic.accessPolicy =
3948 SME_QOS_ACCESS_POLICY_EDCA;
3949 pMsg->req.tspec.tsinfo.traffic.burstSizeDefn =
3950 pTspec_Info->ts_info.burst_size_defn;
3951 pMsg->req.tspec.tsinfo.traffic.ackPolicy =
3952 pTspec_Info->ts_info.ack_policy;
3953 pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE;
3954 /*Fill the BSSID pMsg->req.bssId */
3955 if (NULL == pSession->assocInfo.pBssDesc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303956 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 "%s: %d: BSS descriptor is NULL so we don't send request to PE",
3958 __func__, __LINE__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303959 qdf_mem_free(pMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303960 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003961 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303962 qdf_mem_copy(&pMsg->bssid.bytes[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 &pSession->assocInfo.pBssDesc->bssId[0],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303964 sizeof(struct qdf_mac_addr));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303965 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966 "%s: %d: up = %d, tid = %d",
3967 __func__, __LINE__,
3968 pTspec_Info->ts_info.up, pTspec_Info->ts_info.tid);
3969#ifdef FEATURE_WLAN_ESE
3970 if (pCsrSession->connectedProfile.isESEAssoc) {
3971 pMsg->req.tsrsIE.tsid = pTspec_Info->ts_info.up;
3972 pMsg->req.tsrsPresent = 1;
3973 }
3974#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303975 if (QDF_IS_STATUS_SUCCESS(cds_send_mb_message_to_mac(pMsg))) {
3976 status = QDF_STATUS_SUCCESS;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303977 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 "%s: %d: sent down a ADDTS req to PE",
3979 __func__, __LINE__);
3980 /* event: EVENT_WLAN_QOS */
3981#ifdef FEATURE_WLAN_DIAG_SUPPORT
3982 qos.eventId = SME_QOS_DIAG_ADDTS_REQ;
3983 qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED;
3984 WLAN_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
3985#endif /* FEATURE_WLAN_DIAG_SUPPORT */
3986 }
3987 return status;
3988}
3989
3990/*--------------------------------------------------------------------------
3991 \brief sme_qos_del_ts_req() - To send down the DELTS request with TSPEC params
3992 to PE
3993
3994 \param pMac - Pointer to the global MAC parameter structure.
3995 \param sessionId - Session from which the TSPEC should be deleted
3996 \param ac - Enumeration of the various EDCA Access Categories.
3997 \param tspec_mask - on which tspec per AC, the delts is requested
3998
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303999 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000
4001 \sa
4002
4003 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304004QDF_STATUS sme_qos_del_ts_req(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005 uint8_t sessionId,
4006 sme_QosEdcaAcType ac, uint8_t tspec_mask)
4007{
4008 sme_QosSessionInfo *pSession;
4009 sme_QosACInfo *pACInfo;
4010 tSirDeltsReq *pMsg;
4011 sme_QosWmmTspecInfo *pTspecInfo;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304012 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013#ifdef FEATURE_WLAN_DIAG_SUPPORT
4014 WLAN_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type);
4015#endif
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304016 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 "%s: %d: invoked on session %d for AC %d",
4018 __func__, __LINE__, sessionId, ac);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304019 pMsg = (tSirDeltsReq *) qdf_mem_malloc(sizeof(tSirDeltsReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 if (!pMsg) {
4021 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304022 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 "%s: %d: couldn't allocate memory for the msg buffer",
4024 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304025 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304027 qdf_mem_zero(pMsg, sizeof(tSirDeltsReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028 /* get pointer to the TSPEC being deleted */
4029 pSession = &sme_qos_cb.sessionInfo[sessionId];
4030 pACInfo = &pSession->ac_info[ac];
4031 pTspecInfo = &pACInfo->curr_QoSInfo[tspec_mask - 1];
4032 pMsg->messageType = eWNI_SME_DELTS_REQ;
4033 pMsg->length = sizeof(tSirDeltsReq);
4034 pMsg->sessionId = sessionId;
4035 pMsg->rspReqd = true;
4036 pMsg->req.tspec.delayBound = pTspecInfo->delay_bound;
4037 pMsg->req.tspec.inactInterval = pTspecInfo->inactivity_interval;
4038 pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH;
4039 pMsg->req.tspec.maxBurstSz = pTspecInfo->max_burst_size;
4040 pMsg->req.tspec.maxMsduSz = pTspecInfo->maximum_msdu_size;
4041 pMsg->req.tspec.maxSvcInterval = pTspecInfo->max_service_interval;
4042 pMsg->req.tspec.meanDataRate = pTspecInfo->mean_data_rate;
4043 pMsg->req.tspec.mediumTime = pTspecInfo->medium_time;
4044 pMsg->req.tspec.minDataRate = pTspecInfo->min_data_rate;
4045 pMsg->req.tspec.minPhyRate = pTspecInfo->min_phy_rate;
4046 pMsg->req.tspec.minSvcInterval = pTspecInfo->min_service_interval;
4047 pMsg->req.tspec.nomMsduSz = pTspecInfo->nominal_msdu_size;
4048 pMsg->req.tspec.peakDataRate = pTspecInfo->peak_data_rate;
4049 pMsg->req.tspec.surplusBw = pTspecInfo->surplus_bw_allowance;
4050 pMsg->req.tspec.suspendInterval = pTspecInfo->suspension_interval;
4051 pMsg->req.tspec.svcStartTime = pTspecInfo->svc_start_time;
4052 pMsg->req.tspec.tsinfo.traffic.direction =
4053 pTspecInfo->ts_info.direction;
4054 pMsg->req.tspec.tsinfo.traffic.psb = pTspecInfo->ts_info.psb;
4055 pMsg->req.tspec.tsinfo.traffic.tsid = pTspecInfo->ts_info.tid;
4056 pMsg->req.tspec.tsinfo.traffic.userPrio = pTspecInfo->ts_info.up;
4057 pMsg->req.tspec.tsinfo.traffic.accessPolicy =
4058 SME_QOS_ACCESS_POLICY_EDCA;
4059 pMsg->req.tspec.tsinfo.traffic.burstSizeDefn =
4060 pTspecInfo->ts_info.burst_size_defn;
4061 pMsg->req.tspec.tsinfo.traffic.ackPolicy =
4062 pTspecInfo->ts_info.ack_policy;
4063 pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE;
4064 /*Fill the BSSID pMsg->req.bssId */
4065 if (NULL == pSession->assocInfo.pBssDesc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304066 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 "%s: %d: BSS descriptor is NULL so we don't send request to PE",
4068 __func__, __LINE__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304069 qdf_mem_free(pMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304070 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304072 qdf_mem_copy(&pMsg->bssid.bytes[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 &pSession->assocInfo.pBssDesc->bssId[0],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304074 sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304076 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077 "%s: %d: up = %d, tid = %d",
4078 __func__, __LINE__,
4079 pTspecInfo->ts_info.up, pTspecInfo->ts_info.tid);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304080 qdf_mem_zero(&pACInfo->curr_QoSInfo[tspec_mask - 1],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 sizeof(sme_QosWmmTspecInfo));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304082 if (QDF_IS_STATUS_SUCCESS(cds_send_mb_message_to_mac(pMsg))) {
4083 status = QDF_STATUS_SUCCESS;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304084 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004085 "%s: %d: sme_qos_del_ts_req:Test: sent down a DELTS req to PE",
4086 __func__, __LINE__);
4087 /* event: EVENT_WLAN_QOS */
4088#ifdef FEATURE_WLAN_DIAG_SUPPORT
4089 qos.eventId = SME_QOS_DIAG_DELTS;
4090 qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED;
4091 WLAN_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
4092#endif /* FEATURE_WLAN_DIAG_SUPPORT */
4093 }
4094 sme_set_tspec_uapsd_mask_per_session(pMac,
4095 &pMsg->req.tspec.tsinfo,
4096 sessionId);
4097
4098 return status;
4099}
4100
4101/*--------------------------------------------------------------------------
4102 \brief sme_qos_process_add_ts_rsp() - Function to process the
4103 eWNI_SME_ADDTS_RSP came from PE
4104
4105 \param pMac - Pointer to the global MAC parameter structure.
4106 \param pMsgBuf - Pointer to the msg buffer came from PE.
4107
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304108 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109
4110 \sa
4111
4112 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304113QDF_STATUS sme_qos_process_add_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114{
4115 tpSirAddtsRsp paddts_rsp = (tpSirAddtsRsp) pMsgBuf;
4116 sme_QosSessionInfo *pSession;
4117 uint8_t sessionId = paddts_rsp->sessionId;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304118 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119 sme_QosWmmUpType up =
4120 (sme_QosWmmUpType) paddts_rsp->rsp.tspec.tsinfo.traffic.userPrio;
4121 sme_QosACInfo *pACInfo;
4122 sme_QosEdcaAcType ac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123#ifdef FEATURE_WLAN_DIAG_SUPPORT
4124 WLAN_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type);
4125#endif
4126
4127 pSession = &sme_qos_cb.sessionInfo[sessionId];
4128
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304129 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004130 "%s: %d: invoked on session %d for UP %d",
4131 __func__, __LINE__, sessionId, up);
4132
4133 ac = sme_qos_up_to_ac(up);
4134 if (SME_QOS_EDCA_AC_MAX == ac) {
4135 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304136 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 "%s: %d: invalid AC %d from UP %d",
4138 __func__, __LINE__, ac, up);
4139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304140 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004141 }
4142 pACInfo = &pSession->ac_info[ac];
4143 if (SME_QOS_HANDOFF == pACInfo->curr_state) {
4144 sms_log(pMac, LOG1,
4145 FL
4146 ("ADDTS Response received for AC %d in HANDOFF State.. Dropping"),
4147 ac);
4148 pSession->readyForPowerSave = true;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304149 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304152 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153 "%s: %d: Invoked on session %d with return code %d",
4154 __func__, __LINE__, sessionId, paddts_rsp->rc);
4155 /* our outstanding request has been serviced */
4156 /* we can go into powersave */
4157 pSession->readyForPowerSave = true;
4158 if (paddts_rsp->rc) {
4159 /* event: EVENT_WLAN_QOS */
4160#ifdef FEATURE_WLAN_DIAG_SUPPORT
4161 qos.eventId = SME_QOS_DIAG_ADDTS_RSP;
4162 qos.reasonCode = SME_QOS_DIAG_ADDTS_REFUSED;
4163 WLAN_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
4164#endif /* FEATURE_WLAN_DIAG_SUPPORT */
4165 status =
4166 sme_qos_process_add_ts_failure_rsp(pMac, sessionId,
4167 &paddts_rsp->rsp);
4168 } else {
4169 status =
4170 sme_qos_process_add_ts_success_rsp(pMac, sessionId,
4171 &paddts_rsp->rsp);
4172 }
4173 return status;
4174}
4175
4176/*--------------------------------------------------------------------------
4177 \brief sme_qos_process_del_ts_rsp() - Function to process the
4178 eWNI_SME_DELTS_RSP came from PE
4179
4180 \param pMac - Pointer to the global MAC parameter structure.
4181 \param pMsgBuf - Pointer to the msg buffer came from PE.
4182
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304183 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184
4185 \sa
4186
4187 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304188QDF_STATUS sme_qos_process_del_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189{
4190 tpSirDeltsRsp pDeltsRsp = (tpSirDeltsRsp) pMsgBuf;
4191 sme_QosSessionInfo *pSession;
4192 uint8_t sessionId = pDeltsRsp->sessionId;
4193 /* msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304194 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195 "%s: %d: Invoked on session %d with return code %d",
4196 __func__, __LINE__, sessionId, pDeltsRsp->rc);
4197 pSession = &sme_qos_cb.sessionInfo[sessionId];
4198 /* our outstanding request has been serviced */
4199 /* we can go into powersave */
4200 pSession->readyForPowerSave = true;
4201 (void)sme_qos_process_buffered_cmd(sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304202 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203}
4204
4205/*--------------------------------------------------------------------------
4206 \brief sme_qos_process_del_ts_ind() - Function to process the
4207 eWNI_SME_DELTS_IND came from PE
4208
4209 Since it's a DELTS indication from AP, will notify all the flows running on
4210 this AC about QoS release
4211 \param pMac - Pointer to the global MAC parameter structure.
4212 \param pMsgBuf - Pointer to the msg buffer came from PE.
4213
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304214 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215
4216 \sa
4217
4218 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304219QDF_STATUS sme_qos_process_del_ts_ind(tpAniSirGlobal pMac, void *pMsgBuf)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004220{
4221 tpSirDeltsRsp pdeltsind = (tpSirDeltsRsp) pMsgBuf;
4222 sme_QosSessionInfo *pSession;
4223 sme_QosACInfo *pACInfo;
4224 uint8_t sessionId = pdeltsind->sessionId;
4225 sme_QosEdcaAcType ac;
4226 sme_QosSearchInfo search_key;
4227 sme_QosWmmUpType up =
4228 (sme_QosWmmUpType) pdeltsind->rsp.tspec.tsinfo.traffic.userPrio;
4229#ifdef FEATURE_WLAN_DIAG_SUPPORT
4230 WLAN_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type);
4231#endif
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304232 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 "%s: %d: Invoked on session %d for UP %d",
4234 __func__, __LINE__, sessionId, up);
4235 ac = sme_qos_up_to_ac(up);
4236 if (SME_QOS_EDCA_AC_MAX == ac) {
4237 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304238 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004239 "%s: %d: invalid AC %d from UP %d",
4240 __func__, __LINE__, ac, up);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304241 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004242 }
4243 pSession = &sme_qos_cb.sessionInfo[sessionId];
4244 pACInfo = &pSession->ac_info[ac];
4245
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304246 qdf_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 /* set the key type & the key to be searched in the Flow List */
4248 search_key.key.ac_type = ac;
4249 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
4250 search_key.sessionId = sessionId;
4251 /* find all Flows on the perticular AC & delete them, also send HDD indication */
4252 /* through the callback it registered per request */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304253 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 (sme_qos_find_all_in_flow_list(pMac, search_key, sme_qos_del_ts_ind_fnp))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304255 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256 "%s: %d: no match found for ac = %d", __func__,
4257 __LINE__, search_key.key.ac_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304258 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304259 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260 }
4261/* event: EVENT_WLAN_QOS */
4262#ifdef FEATURE_WLAN_DIAG_SUPPORT
4263 qos.eventId = SME_QOS_DIAG_DELTS;
4264 qos.reasonCode = SME_QOS_DIAG_DELTS_IND_FROM_AP;
4265 WLAN_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
4266#endif /* FEATURE_WLAN_DIAG_SUPPORT */
4267
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304268 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269}
4270
4271/*--------------------------------------------------------------------------
4272 \brief sme_qos_process_assoc_complete_ev() - Function to process the
4273 SME_QOS_CSR_ASSOC_COMPLETE event indication from CSR
4274 \param pEvent_info - Pointer to relevant info from CSR.
4275
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304276 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004277
4278 \sa
4279
4280 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304281QDF_STATUS sme_qos_process_assoc_complete_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004282 void *pEvent_info)
4283{
4284 sme_QosSessionInfo *pSession;
4285 sme_QosACInfo *pACInfo;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304286 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004287 sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_BE;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304288 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289 "%s: %d: invoked on session %d",
4290 __func__, __LINE__, sessionId);
4291 pSession = &sme_qos_cb.sessionInfo[sessionId];
4292 if (((SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state)
4293 && (SME_QOS_INIT ==
4294 pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state)
4295 && (SME_QOS_INIT ==
4296 pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state)
4297 && (SME_QOS_INIT ==
4298 pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state))
4299 || (pSession->handoffRequested)) {
4300 /* get the association info */
4301 if (!pEvent_info) {
4302 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304303 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 "%s: %d: pEvent_info is NULL",
4305 __func__, __LINE__);
4306 return status;
4307 }
4308 if (!((sme_QosAssocInfo *) pEvent_info)->pBssDesc) {
4309 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304310 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311 "%s: %d: pBssDesc is NULL",
4312 __func__, __LINE__);
4313 return status;
4314 }
4315 if ((pSession->assocInfo.pBssDesc) &&
4316 (csr_is_bssid_match
Anurag Chouhan6d760662016-02-20 16:05:43 +05304317 (pMac, (struct qdf_mac_addr *) &pSession->assocInfo.pBssDesc->bssId,
4318 (struct qdf_mac_addr *) &(((sme_QosAssocInfo *) pEvent_info)->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004319 pBssDesc->bssId)))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304320 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004321 "%s: %d: assoc with the same BSS, no update needed",
4322 __func__, __LINE__);
4323 } else {
4324 status = sme_qos_save_assoc_info(pSession, pEvent_info);
4325 }
4326 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304327 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004328 "%s: %d: wrong state: BE %d, BK %d, VI %d, VO %d",
4329 __func__, __LINE__,
4330 pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state,
4331 pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state,
4332 pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state,
4333 pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304334 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 return status;
4336 }
4337 /* the session is active */
4338 pSession->sessionActive = true;
4339 if (pSession->handoffRequested) {
4340 pSession->handoffRequested = false;
4341 /* renew all flows */
4342 (void)sme_qos_process_buffered_cmd(sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304343 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344 } else {
4345 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
4346 pACInfo = &pSession->ac_info[ac];
4347 switch (pACInfo->curr_state) {
4348 case SME_QOS_INIT:
4349 sme_qos_state_transition(sessionId, ac,
4350 SME_QOS_LINK_UP);
4351 break;
4352 case SME_QOS_LINK_UP:
4353 case SME_QOS_REQUESTED:
4354 case SME_QOS_QOS_ON:
4355 case SME_QOS_HANDOFF:
4356 case SME_QOS_CLOSED:
4357 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304358 QDF_TRACE(QDF_MODULE_ID_SME,
4359 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 "%s: %d: On session %d AC %d is in wrong state %d",
4361 __func__, __LINE__, sessionId, ac,
4362 pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304363 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364 break;
4365 }
4366 }
4367 }
4368 return status;
4369}
4370
4371/*--------------------------------------------------------------------------
4372 \brief sme_qos_process_reassoc_req_ev() - Function to process the
4373 SME_QOS_CSR_REASSOC_REQ event indication from CSR
4374 \param pEvent_info - Pointer to relevant info from CSR.
4375
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304376 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377
4378 \sa
4379
4380 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304381QDF_STATUS sme_qos_process_reassoc_req_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 void *pEvent_info)
4383{
4384 sme_QosSessionInfo *pSession;
4385 sme_QosACInfo *pACInfo;
4386 sme_QosEdcaAcType ac;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304387 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388 "%s: %d: invoked on session %d",
4389 __func__, __LINE__, sessionId);
4390 pSession = &sme_qos_cb.sessionInfo[sessionId];
4391
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 if (pSession->ftHandoffInProgress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304393 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 "%s: %d: no need for state transition, should "
4395 "already be in handoff state", __func__, __LINE__);
4396 if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) ||
4397 (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) ||
4398 (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) ||
4399 (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304400 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304401 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004402 }
4403 sme_qos_process_ft_reassoc_req_ev(sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304404 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406
4407 if (pSession->handoffRequested) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304408 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409 "%s: %d: no need for state transition, should "
4410 "already be in handoff state", __func__, __LINE__);
4411
4412 if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) ||
4413 (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) ||
4414 (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) ||
4415 (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304416 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304417 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004418 }
4419 /* buffer the existing flows to be renewed after handoff is done */
4420 sme_qos_buffer_existing_flows(pMac, sessionId);
4421 /* clean up the control block partially for handoff */
4422 sme_qos_cleanup_ctrl_blk_for_handoff(pMac, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304423 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004424 }
4425/* TBH: Assuming both handoff algo & 11r willn't be enabled at the same time */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 if (pSession->ftHandoffInProgress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304427 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 "%s: %d: no need for state transition, should "
4429 "already be in handoff state", __func__, __LINE__);
4430
4431 if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) ||
4432 (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) ||
4433 (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) ||
4434 (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304435 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304436 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004437 }
4438
4439 sme_qos_process_ft_reassoc_req_ev(sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304440 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004441 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004442
4443 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
4444 pACInfo = &pSession->ac_info[ac];
4445 switch (pACInfo->curr_state) {
4446 case SME_QOS_LINK_UP:
4447 case SME_QOS_REQUESTED:
4448 case SME_QOS_QOS_ON:
4449 sme_qos_state_transition(sessionId, ac, SME_QOS_HANDOFF);
4450 break;
4451 case SME_QOS_HANDOFF:
4452 /* This is normal because sme_qos_request_reassoc may already change the state */
4453 break;
4454 case SME_QOS_CLOSED:
4455 case SME_QOS_INIT:
4456 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304457 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004458 "%s: %d: On session %d AC %d is in wrong state %d",
4459 __func__, __LINE__,
4460 sessionId, ac, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304461 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 break;
4463 }
4464 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304465 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004466}
4467
4468/**
4469 * sme_qos_handle_handoff_state() - utility function called by
4470 * sme_qos_process_reassoc_success_ev
4471 * @mac_ctx: global MAC context
4472 * @qos_session: QOS session
4473 * @ac_info: AC information
4474 * @ac: current AC index
4475 * @sessionid: session id
4476 *
4477 * This function is called by sme_qos_process_reassoc_success_ev
4478 * to update the state machine on the reception of reassoc success
4479 * notificaiton
4480 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304481 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304483QDF_STATUS sme_qos_handle_handoff_state(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004484 sme_QosSessionInfo *qos_session, sme_QosACInfo *ac_info,
4485 sme_QosEdcaAcType ac, uint8_t sessionid)
4486
4487{
4488 sme_QosSearchInfo search_key;
4489 sme_QosSearchInfo search_key1;
4490 sme_QosEdcaAcType ac_index;
4491 tListElem *list_elt = NULL;
4492 sme_QosFlowInfoEntry *flow_info = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304493 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494
4495 /* return to our previous state */
4496 sme_qos_state_transition(sessionid, ac, ac_info->prev_state);
4497 /* for which ac APSD (hence the reassoc) is requested */
4498 if (!ac_info->reassoc_pending)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304499 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500
4501 /*
4502 * update the apsd mask in CB - make sure to take care of the
4503 * case where we are resetting the bit in apsd_mask
4504 */
4505 if (ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb)
4506 qos_session->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
4507 else
4508 qos_session->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac));
4509
4510 ac_info->reassoc_pending = false;
4511 /*
4512 * during setup it gets set as addts & reassoc both gets a
4513 * pending flag ac_info->tspec_pending = 0;
4514 */
4515 sme_qos_state_transition(sessionid, ac, SME_QOS_QOS_ON);
4516 /* notify HDD with new Service Interval */
4517 ac_info->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] =
4518 ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0];
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304519 qdf_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004520 /* set the key type & the key to be searched in the Flow List */
4521 search_key.key.ac_type = ac;
4522 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
4523 search_key.sessionId = sessionid;
4524 /* notify PMC that reassoc is done for APSD on certain AC?? */
4525
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304526 qdf_mem_zero(&search_key1, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 /* set the hoRenewal field in control block if needed */
4528 search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3;
4529 search_key1.key.reason = SME_QOS_REASON_SETUP;
4530 search_key1.sessionId = sessionid;
4531 for (ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX;
4532 ac_index++) {
4533 list_elt = sme_qos_find_in_flow_list(search_key1);
4534 if (list_elt) {
4535 flow_info = GET_BASE_ADDR(list_elt,
4536 sme_QosFlowInfoEntry, link);
4537 if (flow_info->ac_type == ac) {
4538 ac_info->hoRenewal = flow_info->hoRenewal;
4539 break;
4540 }
4541 }
4542 }
4543 /*
4544 * notify HDD the success for the requested flow notify all the
4545 * other flows running on the AC that QoS got modified
4546 */
4547 status = sme_qos_find_all_in_flow_list(mac_ctx, search_key,
4548 sme_qos_reassoc_success_ev_fnp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304549 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304550 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 FL("no match found for ac = %d"),
4552 search_key.key.ac_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304553 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304554 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 }
4556 ac_info->hoRenewal = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304557 qdf_mem_zero(&ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 sizeof(sme_QosWmmTspecInfo));
4559
4560 return status;
4561}
4562
4563/**
4564 * sme_qos_process_reassoc_success_ev() - process SME_QOS_CSR_REASSOC_COMPLETE
4565 *
4566 * @mac_ctx: global MAC context
4567 * @sessionid: session ID
4568 * @event_info: event buffer from CSR
4569 *
4570 * Function to process the SME_QOS_CSR_REASSOC_COMPLETE event indication
4571 * from CSR
4572 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304573 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304575QDF_STATUS sme_qos_process_reassoc_success_ev(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 uint8_t sessionid, void *event_info)
4577{
4578
4579 tCsrRoamSession *csr_roam_session = NULL;
4580 sme_QosSessionInfo *qos_session;
4581 sme_QosACInfo *ac_info;
4582 sme_QosEdcaAcType ac;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304583 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004584
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304585 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586 FL("invoked on session %d"), sessionid);
4587
4588 if (CSR_ROAM_SESSION_MAX <= sessionid) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304589 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004590 FL("invoked on session %d"), sessionid);
4591 return status;
4592 }
4593
4594 csr_roam_session = CSR_GET_SESSION(mac_ctx, sessionid);
4595
4596 qos_session = &sme_qos_cb.sessionInfo[sessionid];
4597 /*
4598 * our pending reassociation has completed
4599 * we can allow powersave
4600 */
4601 qos_session->readyForPowerSave = true;
4602
4603 /* get the association info */
4604 if (!event_info) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304605 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004606 FL("event_info is NULL"));
4607 return status;
4608 }
4609
4610 if (!((sme_QosAssocInfo *) event_info)->pBssDesc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304611 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 FL("pBssDesc is NULL"));
4613 return status;
4614 }
4615 status = sme_qos_save_assoc_info(qos_session, event_info);
4616 if (status)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304617 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004618 FL("sme_qos_save_assoc_info() failed"));
4619
4620 /*
4621 * Assuming both handoff algo & 11r willn't be enabled
4622 * at the same time
4623 */
4624 if (qos_session->handoffRequested) {
4625 qos_session->handoffRequested = false;
4626 /* renew all flows */
4627 (void)sme_qos_process_buffered_cmd(sessionid);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304628 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004629 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 if (qos_session->ftHandoffInProgress) {
4631 if (csr_roam_is11r_assoc(mac_ctx, sessionid)) {
4632 if (csr_roam_session &&
4633 csr_roam_session->connectedInfo.nRICRspLength) {
4634 status = sme_qos_process_ft_reassoc_rsp_ev(
4635 mac_ctx, sessionid, event_info);
4636 }
4637 }
4638#ifdef FEATURE_WLAN_ESE
4639 /*
4640 * If ESE association check for TSPEC IEs in the
4641 * reassoc rsp frame
4642 */
4643 if (csr_roam_is_ese_assoc(mac_ctx, sessionid)) {
4644 if (csr_roam_session &&
4645 csr_roam_session->connectedInfo.nTspecIeLength) {
4646 status = sme_qos_ese_process_reassoc_tspec_rsp(
4647 mac_ctx, sessionid, event_info);
4648 }
4649 }
4650#endif
4651 qos_session->ftHandoffInProgress = false;
4652 qos_session->handoffRequested = false;
4653 return status;
4654 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655
4656 qos_session->sessionActive = true;
4657 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
4658 ac_info = &qos_session->ac_info[ac];
4659 switch (ac_info->curr_state) {
4660 case SME_QOS_HANDOFF:
4661 status = sme_qos_handle_handoff_state(mac_ctx,
4662 qos_session, ac_info, ac, sessionid);
4663 break;
4664 case SME_QOS_INIT:
4665 case SME_QOS_CLOSED:
4666 /* NOP */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304667 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668 break;
4669 case SME_QOS_LINK_UP:
4670 case SME_QOS_REQUESTED:
4671 case SME_QOS_QOS_ON:
4672 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304673 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 FL("session %d AC %d is in wrong state %d"),
4675 sessionid, ac, ac_info->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304676 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677 break;
4678 }
4679 }
4680 (void)sme_qos_process_buffered_cmd(sessionid);
4681 return status;
4682}
4683
4684/*--------------------------------------------------------------------------
4685 \brief sme_qos_process_reassoc_failure_ev() - Function to process the
4686 SME_QOS_CSR_REASSOC_FAILURE event indication from CSR
4687 \param pEvent_info - Pointer to relevant info from CSR.
4688
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304689 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690
4691 \sa
4692
4693 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304694QDF_STATUS sme_qos_process_reassoc_failure_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004695 uint8_t sessionId, void *pEvent_info)
4696{
4697 sme_QosSessionInfo *pSession;
4698 sme_QosACInfo *pACInfo;
4699 sme_QosEdcaAcType ac;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304700 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 "%s: %d: invoked on session %d",
4702 __func__, __LINE__, sessionId);
4703 pSession = &sme_qos_cb.sessionInfo[sessionId];
4704 /* our pending reassociation has completed */
4705 /* we can allow powersave */
4706 pSession->readyForPowerSave = true;
4707 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
4708 pACInfo = &pSession->ac_info[ac];
4709 switch (pACInfo->curr_state) {
4710 case SME_QOS_HANDOFF:
4711 sme_qos_state_transition(sessionId, ac, SME_QOS_INIT);
4712 if (pACInfo->reassoc_pending) {
4713 pACInfo->reassoc_pending = false;
4714 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304715 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716 curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4717 sizeof(sme_QosWmmTspecInfo));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304718 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004719 requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4720 sizeof(sme_QosWmmTspecInfo));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304721 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722 curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4723 sizeof(sme_QosWmmTspecInfo));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304724 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725 requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4726 sizeof(sme_QosWmmTspecInfo));
4727 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
4728 pACInfo->tspec_pending = 0;
4729 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0;
4730 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0;
4731 break;
4732 case SME_QOS_INIT:
4733 case SME_QOS_CLOSED:
4734 /* NOP */
4735 break;
4736 case SME_QOS_LINK_UP:
4737 case SME_QOS_REQUESTED:
4738 case SME_QOS_QOS_ON:
4739 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304740 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741 "%s: %d: On session %d AC %d is in wrong state %d",
4742 __func__, __LINE__,
4743 sessionId, ac, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304744 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004745 break;
4746 }
4747 }
4748 /* need to clean up flows */
4749 sme_qos_delete_existing_flows(pMac, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304750 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004751}
4752
4753/*--------------------------------------------------------------------------
4754 \brief sme_qos_process_handoff_assoc_req_ev() - Function to process the
4755 SME_QOS_CSR_HANDOFF_ASSOC_REQ event indication from CSR
4756 \param pEvent_info - Pointer to relevant info from CSR.
4757
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304758 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004759
4760 \sa
4761
4762 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304763QDF_STATUS sme_qos_process_handoff_assoc_req_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 uint8_t sessionId, void *pEvent_info)
4765{
4766 sme_QosSessionInfo *pSession;
4767 sme_QosACInfo *pACInfo;
4768 uint8_t ac;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304769 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 "%s: %d: invoked on session %d",
4771 __func__, __LINE__, sessionId);
4772 pSession = &sme_qos_cb.sessionInfo[sessionId];
4773 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
4774 pACInfo = &pSession->ac_info[ac];
4775 switch (pACInfo->curr_state) {
4776 case SME_QOS_LINK_UP:
4777 case SME_QOS_REQUESTED:
4778 case SME_QOS_QOS_ON:
4779 sme_qos_state_transition(sessionId, ac, SME_QOS_HANDOFF);
4780 break;
4781 case SME_QOS_HANDOFF:
4782 /* print error msg */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004783 if (pSession->ftHandoffInProgress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304784 QDF_TRACE(QDF_MODULE_ID_SME,
4785 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 "%s: %d: SME_QOS_CSR_HANDOFF_ASSOC_REQ received in "
4787 "SME_QOS_HANDOFF state with FT in progress",
4788 __func__, __LINE__);
4789 break;
4790 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004791
4792 case SME_QOS_CLOSED:
4793 case SME_QOS_INIT:
4794 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304795 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004796 "%s: %d: On session %d AC %d is in wrong state %d",
4797 __func__, __LINE__,
4798 sessionId, ac, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304799 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004800 break;
4801 }
4802 }
4803#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4804 if (csr_roam_is11r_assoc(pMac, sessionId)) {
4805 pSession->ftHandoffInProgress = true;
4806 }
4807#endif
4808 /* If FT handoff is in progress, legacy handoff need not be enabled */
4809 if (!pSession->ftHandoffInProgress) {
4810 pSession->handoffRequested = true;
4811 }
4812 /* this session no longer needs UAPSD */
4813 pSession->apsdMask = 0;
4814 /* do any sessions still require UAPSD? */
4815 sme_ps_uapsd_disable(pMac, sessionId);
4816 pSession->uapsdAlreadyRequested = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304817 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004818}
4819
4820/*--------------------------------------------------------------------------
4821 \brief sme_qos_process_handoff_success_ev() - Function to process the
4822 SME_QOS_CSR_HANDOFF_COMPLETE event indication from CSR
4823 \param pEvent_info - Pointer to relevant info from CSR.
4824
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304825 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826
4827 \sa
4828
4829 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304830QDF_STATUS sme_qos_process_handoff_success_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 uint8_t sessionId, void *pEvent_info)
4832{
4833 sme_QosSessionInfo *pSession;
4834 sme_QosACInfo *pACInfo;
4835 uint8_t ac;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304836 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304837 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 "%s: %d: invoked on session %d",
4839 __func__, __LINE__, sessionId);
4840 pSession = &sme_qos_cb.sessionInfo[sessionId];
4841 /* go back to original state before handoff */
4842 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
4843 pACInfo = &pSession->ac_info[ac];
4844 switch (pACInfo->curr_state) {
4845 case SME_QOS_HANDOFF:
4846 sme_qos_state_transition(sessionId, ac,
4847 pACInfo->prev_state);
4848 /* we will retry for the requested flow(s) with the new AP */
4849 if (SME_QOS_REQUESTED == pACInfo->curr_state) {
4850 pACInfo->curr_state = SME_QOS_LINK_UP;
4851 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304852 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004853 break;
4854 /* FT logic, has already moved it to QOS_REQUESTED state during the */
4855 /* reassoc request event, which would include the Qos (TSPEC) params */
4856 /* in the reassoc req frame */
4857 case SME_QOS_REQUESTED:
4858 break;
4859 case SME_QOS_INIT:
4860 case SME_QOS_CLOSED:
4861 case SME_QOS_LINK_UP:
4862 case SME_QOS_QOS_ON:
4863 default:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004864/* In case of 11r - RIC, we request QoS and Hand-off at the same time hence the
4865 state may be SME_QOS_REQUESTED */
4866 if (pSession->ftHandoffInProgress)
4867 break;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304868 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004869 "%s: %d: On session %d AC %d is in wrong state %d",
4870 __func__, __LINE__,
4871 sessionId, ac, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304872 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 break;
4874 }
4875 }
4876 return status;
4877}
4878
4879/*--------------------------------------------------------------------------
4880 \brief sme_qos_process_handoff_failure_ev() - Function to process the
4881 SME_QOS_CSR_HANDOFF_FAILURE event indication from CSR
4882 \param pEvent_info - Pointer to relevant info from CSR.
4883
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304884 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004885
4886 \sa
4887
4888 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304889QDF_STATUS sme_qos_process_handoff_failure_ev(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 uint8_t sessionId, void *pEvent_info)
4891{
4892 sme_QosSessionInfo *pSession;
4893 sme_QosACInfo *pACInfo;
4894 uint8_t ac;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304895 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004896 "%s: %d: invoked on session %d",
4897 __func__, __LINE__, sessionId);
4898 pSession = &sme_qos_cb.sessionInfo[sessionId];
4899 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
4900 pACInfo = &pSession->ac_info[ac];
4901 switch (pACInfo->curr_state) {
4902 case SME_QOS_HANDOFF:
4903 sme_qos_state_transition(sessionId, ac, SME_QOS_INIT);
4904 /* need to clean up flows: TODO */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304905 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906 curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4907 sizeof(sme_QosWmmTspecInfo));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304908 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004909 requested_QoSInfo[SME_QOS_TSPEC_INDEX_0],
4910 sizeof(sme_QosWmmTspecInfo));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304911 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 curr_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4913 sizeof(sme_QosWmmTspecInfo));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304914 qdf_mem_zero(&pACInfo->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004915 requested_QoSInfo[SME_QOS_TSPEC_INDEX_1],
4916 sizeof(sme_QosWmmTspecInfo));
4917 pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR;
4918 pACInfo->tspec_pending = 0;
4919 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0;
4920 pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0;
4921 break;
4922 case SME_QOS_INIT:
4923 case SME_QOS_CLOSED:
4924 case SME_QOS_LINK_UP:
4925 case SME_QOS_REQUESTED:
4926 case SME_QOS_QOS_ON:
4927 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304928 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 "%s: %d: On session %d AC %d is in wrong state %d",
4930 __func__, __LINE__,
4931 sessionId, ac, pACInfo->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304932 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004933 break;
4934 }
4935 }
4936 /* no longer in handoff */
4937 pSession->handoffRequested = false;
4938 /* clean up the assoc info */
4939 if (pSession->assocInfo.pBssDesc) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304940 qdf_mem_free(pSession->assocInfo.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941 pSession->assocInfo.pBssDesc = NULL;
4942 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304943 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004944}
4945
4946/*--------------------------------------------------------------------------
4947 \brief sme_qos_process_disconnect_ev() - Function to process the
4948 SME_QOS_CSR_DISCONNECT_REQ or SME_QOS_CSR_DISCONNECT_IND event indication
4949 from CSR
4950 \param pEvent_info - Pointer to relevant info from CSR.
4951
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304952 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953
4954 \sa
4955
4956 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304957QDF_STATUS sme_qos_process_disconnect_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004958 void *pEvent_info)
4959{
4960 sme_QosSessionInfo *pSession;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304961 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962 "%s: %d: invoked on session %d",
4963 __func__, __LINE__, sessionId);
4964 pSession = &sme_qos_cb.sessionInfo[sessionId];
Deepak Dhamdhereadd334b2016-01-09 23:40:33 -08004965 /*
4966 * In case of 11r - RIC, we request QoS and Hand-off at the
4967 * same time hence the state may be SME_QOS_REQUESTED
4968 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004969 if ((pSession->handoffRequested)
Deepak Dhamdhereadd334b2016-01-09 23:40:33 -08004970 && !pSession->ftHandoffInProgress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304971 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004972 "%s: %d: no need for state transition, should "
4973 "already be in handoff state", __func__, __LINE__);
4974 if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) ||
4975 (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) ||
4976 (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) ||
4977 (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304978 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304979 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004980 }
4981
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304982 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983 }
4984 sme_qos_init_a_cs(pMac, sessionId);
4985 /* this session doesn't require UAPSD */
4986 pSession->apsdMask = 0;
4987
4988 sme_ps_uapsd_disable(pMac, sessionId);
4989
4990 pSession->uapsdAlreadyRequested = false;
4991 pSession->handoffRequested = false;
4992 pSession->readyForPowerSave = true;
4993 pSession->roamID = 0;
4994 /* need to clean up buffered req */
4995 sme_qos_delete_buffered_requests(pMac, sessionId);
4996 /* need to clean up flows */
4997 sme_qos_delete_existing_flows(pMac, sessionId);
4998 /* clean up the assoc info */
4999 if (pSession->assocInfo.pBssDesc) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305000 qdf_mem_free(pSession->assocInfo.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005001 pSession->assocInfo.pBssDesc = NULL;
5002 }
5003 sme_qos_cb.sessionInfo[sessionId].sessionActive = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305004 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005}
5006
5007/*--------------------------------------------------------------------------
5008 \brief sme_qos_process_join_req_ev() - Function to process the
5009 SME_QOS_CSR_JOIN_REQ event indication from CSR
5010 \param pEvent_info - Pointer to relevant info from CSR.
5011
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305012 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013
5014 \sa
5015
5016 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305017QDF_STATUS sme_qos_process_join_req_ev(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 void *pEvent_info)
5019{
5020 sme_QosSessionInfo *pSession;
5021 sme_QosEdcaAcType ac;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305022 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023 "%s: %d: invoked on session %d",
5024 __func__, __LINE__, sessionId);
5025 pSession = &sme_qos_cb.sessionInfo[sessionId];
5026 if (pSession->handoffRequested) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305027 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028 "%s: %d: no need for state transition, should "
5029 "already be in handoff state", __func__, __LINE__);
5030 if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) ||
5031 (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) ||
5032 (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) ||
5033 (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) {
5034 /* just print */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305035 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 }
5037 /* buffer the existing flows to be renewed after handoff is done */
5038 sme_qos_buffer_existing_flows(pMac, sessionId);
5039 /* clean up the control block partially for handoff */
5040 sme_qos_cleanup_ctrl_blk_for_handoff(pMac, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305041 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042 }
5043
5044 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
5045 sme_qos_state_transition(sessionId, ac, SME_QOS_INIT);
5046 }
5047 /* clean up the assoc info if already set */
5048 if (pSession->assocInfo.pBssDesc) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305049 qdf_mem_free(pSession->assocInfo.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 pSession->assocInfo.pBssDesc = NULL;
5051 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305052 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053}
5054
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005055/**
5056 * sme_qos_process_preauth_success_ind() - process preauth success indication
5057 * @mac_ctx: global MAC context
5058 * @sessionid: session ID
5059 * @event_info: event buffer
5060 *
5061 * Function to process the SME_QOS_CSR_PREAUTH_SUCCESS_IND event indication
5062 * from CSR
5063 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305064 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305066QDF_STATUS sme_qos_process_preauth_success_ind(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005067 uint8_t sessionid, void *event_info)
5068{
5069 sme_QosSessionInfo *qos_session;
5070 tCsrRoamSession *sme_session = CSR_GET_SESSION(mac_ctx, sessionid);
5071 sme_QosACInfo *ac_info;
5072 uint8_t ac;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305073 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074 uint16_t ric_offset = 0;
5075 uint32_t ric_ielen = 0;
5076 uint8_t *ric_ie;
5077 uint8_t tspec_mask_status = 0;
5078 uint8_t tspec_pending_status = 0;
5079
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305080 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 FL("invoked on SME session %d"), sessionid);
5082
5083 if (NULL == sme_session) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305084 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005085 FL("sme_session is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305086 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087 }
5088
5089 qos_session = &sme_qos_cb.sessionInfo[sessionid];
5090
5091 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
5092 ac_info = &qos_session->ac_info[ac];
5093
5094 switch (ac_info->curr_state) {
5095 case SME_QOS_LINK_UP:
5096 case SME_QOS_REQUESTED:
5097 case SME_QOS_QOS_ON:
5098 sme_qos_state_transition(sessionid, ac, SME_QOS_HANDOFF);
5099 break;
5100 case SME_QOS_HANDOFF:
5101 /* print error msg */
5102 case SME_QOS_CLOSED:
5103 case SME_QOS_INIT:
5104 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305105 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 FL("Session %d AC %d is in wrong state %d"),
5107 sessionid, ac, ac_info->curr_state);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305108 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005109 break;
5110 }
5111 }
5112
5113 qos_session->ftHandoffInProgress = true;
5114
5115 /* Check if its a 11R roaming before preparing the RIC IEs */
5116 if (!csr_roam_is11r_assoc(mac_ctx, sessionid))
5117 return status;
5118
5119 /* Data is accessed from saved PreAuth Rsp */
5120 if (NULL == sme_session->ftSmeContext.psavedFTPreAuthRsp) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305121 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122 FL("psavedFTPreAuthRsp is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305123 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124 }
5125
5126 /*
5127 * Any Block Ack info there, should have been already filled by PE and
5128 * present in this buffer and the ric_ies_length should contain the
5129 * length of the whole RIC IEs. Filling of TSPEC info should start
5130 * from this length
5131 */
5132 ric_ie = sme_session->ftSmeContext.psavedFTPreAuthRsp->ric_ies;
5133 ric_offset =
5134 sme_session->ftSmeContext.psavedFTPreAuthRsp->ric_ies_length;
5135
5136 /*
5137 * Now we have to process the currentTspeInfo inside this session and
5138 * create the RIC IEs
5139 */
5140 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
5141 volatile uint8_t tspec_idx = 0;
5142 ric_ielen = 0;
5143 ac_info = &qos_session->ac_info[ac];
5144 tspec_pending_status = ac_info->tspec_pending;
5145 tspec_mask_status = ac_info->tspec_mask_status;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305146 qdf_mem_zero(ac_info->ricIdentifier, SME_QOS_TSPEC_INDEX_MAX);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305147 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 FL("AC %d ==> TSPEC status = %d, tspec pending = %d"),
5149 ac, tspec_mask_status, tspec_pending_status);
5150
5151 do {
5152 if (!(tspec_mask_status & 0x1))
5153 goto add_next_ric;
5154
5155 /*
5156 * If a tspec status is pending, take requested_QoSInfo
5157 * for RIC request, else use curr_QoSInfo for the
5158 * RIC request
5159 */
5160 if (tspec_pending_status & 0x1) {
5161 status = sme_qos_create_tspec_ricie(mac_ctx,
5162 &ac_info->requested_QoSInfo[tspec_idx],
5163 ric_ie + ric_offset, &ric_ielen,
5164 &ac_info->ricIdentifier[tspec_idx]);
5165 } else {
5166 status = sme_qos_create_tspec_ricie(mac_ctx,
5167 &ac_info->curr_QoSInfo[tspec_idx],
5168 ric_ie + ric_offset, &ric_ielen,
5169 &ac_info->ricIdentifier[tspec_idx]);
5170 }
5171add_next_ric:
5172 ric_offset += ric_ielen;
5173 sme_session->ftSmeContext.psavedFTPreAuthRsp->
5174 ric_ies_length += ric_ielen;
5175 tspec_mask_status >>= 1;
5176 tspec_pending_status >>= 1;
5177 tspec_idx++;
5178 } while (tspec_mask_status);
5179 }
5180 return status;
5181}
5182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005183/*--------------------------------------------------------------------------
5184 \brief sme_qos_process_add_ts_failure_rsp() - Function to process the
5185 Addts request failure response came from PE
5186
5187 We will notify HDD only for the requested Flow, other Flows running on the AC
5188 stay intact
5189
5190 \param pMac - Pointer to the global MAC parameter structure.
5191 \param pRsp - Pointer to the addts response structure came from PE.
5192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305193 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194
5195 \sa
5196
5197 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305198QDF_STATUS sme_qos_process_add_ts_failure_rsp(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 uint8_t sessionId,
5200 tSirAddtsRspInfo *pRsp)
5201{
5202 sme_QosSessionInfo *pSession;
5203 sme_QosACInfo *pACInfo;
5204 sme_QosEdcaAcType ac;
5205 sme_QosSearchInfo search_key;
5206 uint8_t tspec_pending;
5207 sme_QosWmmUpType up =
5208 (sme_QosWmmUpType) pRsp->tspec.tsinfo.traffic.userPrio;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305209 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210 "%s: %d: invoked on session %d for UP %d", __func__, __LINE__,
5211 sessionId, up);
5212 ac = sme_qos_up_to_ac(up);
5213 if (SME_QOS_EDCA_AC_MAX == ac) {
5214 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305215 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 "%s: %d: invalid AC %d from UP %d",
5217 __func__, __LINE__, ac, up);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305218 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219 }
5220 pSession = &sme_qos_cb.sessionInfo[sessionId];
5221 pACInfo = &pSession->ac_info[ac];
5222 /* is there a TSPEC request pending on this AC? */
5223 tspec_pending = pACInfo->tspec_pending;
5224 if (!tspec_pending) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305225 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 "%s: %d: On session %d an AddTS is not pending on AC %d",
5227 __func__, __LINE__, sessionId, ac);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305228 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305229 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 }
5231
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305232 qdf_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 /* set the key type & the key to be searched in the Flow List */
5234 search_key.key.ac_type = ac;
5235 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
5236 search_key.sessionId = sessionId;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305237 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238 (sme_qos_find_all_in_flow_list
5239 (pMac, search_key, sme_qos_add_ts_failure_fnp))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305240 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 "%s: %d: On session %d no match found for ac = %d",
5242 __func__, __LINE__, sessionId,
5243 search_key.key.ac_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305244 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305245 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305247 qdf_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248 sizeof(sme_QosWmmTspecInfo));
5249
5250 if ((!pACInfo->num_flows[0]) && (!pACInfo->num_flows[1])) {
5251 pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET &
5252 (~pACInfo->tspec_pending);
5253 sme_qos_state_transition(sessionId, ac, SME_QOS_LINK_UP);
5254 } else {
5255 sme_qos_state_transition(sessionId, ac, SME_QOS_QOS_ON);
5256 }
5257 pACInfo->tspec_pending = 0;
5258
5259 (void)sme_qos_process_buffered_cmd(sessionId);
5260
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305261 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262}
5263
5264/**
5265 * sme_qos_update_tspec_mask() - Utiltity function to update the tspec.
5266 * @sessionid: Session upon which the TSPEC is being updated
5267 * @search_key: search key
5268 * @new_tspec_mask: tspec to be set for this AC
5269 *
5270 * Typical usage while aggregating unidirectional flows into a bi-directional
5271 * flow on AC which is running multiple flows
5272 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305273 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005274 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305275static QDF_STATUS sme_qos_update_tspec_mask(uint8_t sessionid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005276 sme_QosSearchInfo search_key,
5277 uint8_t new_tspec_mask)
5278{
5279 tListElem *list_elt = NULL, *list_next_elt = NULL;
5280 sme_QosFlowInfoEntry *flow_info = NULL;
5281 sme_QosSessionInfo *qos_session;
5282 sme_QosACInfo *ac_info;
5283
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305284 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 FL("invoked on session %d for AC %d TSPEC %d"),
5286 sessionid, search_key.key.ac_type, new_tspec_mask);
5287
5288 qos_session = &sme_qos_cb.sessionInfo[sessionid];
5289
5290 if (search_key.key.ac_type < SME_QOS_EDCA_AC_MAX) {
5291 ac_info = &qos_session->ac_info[search_key.key.ac_type];
5292 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305293 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005294 FL("Exceeded the array bounds"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305295 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305296 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 }
5298
5299 list_elt = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
5300 if (!list_elt) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305301 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005302 FL("Flow List empty, nothing to update"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305303 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 }
5305
5306 while (list_elt) {
5307 list_next_elt = csr_ll_next(&sme_qos_cb.flow_list, list_elt,
5308 false);
5309 flow_info = GET_BASE_ADDR(list_elt, sme_QosFlowInfoEntry, link);
5310
5311 if (search_key.sessionId != flow_info->sessionId) {
5312 list_elt = list_next_elt;
5313 continue;
5314 }
5315
5316 if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_4) {
5317 if ((search_key.key.ac_type == flow_info->ac_type) &&
5318 (search_key.direction ==
5319 flow_info->QoSInfo.ts_info.direction)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305320 QDF_TRACE(QDF_MODULE_ID_SME,
5321 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 FL("Flow %d matches"), flow_info->QosFlowID);
5323 ac_info->num_flows[flow_info->tspec_mask - 1]--;
5324 ac_info->num_flows[new_tspec_mask - 1]++;
5325 flow_info->tspec_mask = new_tspec_mask;
5326 }
5327 } else if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_5) {
5328 if ((search_key.key.ac_type == flow_info->ac_type) &&
5329 (search_key.tspec_mask == flow_info->tspec_mask)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305330 QDF_TRACE(QDF_MODULE_ID_SME,
5331 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 FL("Flow %d matches"), flow_info->QosFlowID);
5333 ac_info->num_flows[flow_info->tspec_mask - 1]--;
5334 ac_info->num_flows[new_tspec_mask - 1]++;
5335 flow_info->tspec_mask = new_tspec_mask;
5336 }
5337 }
5338 list_elt = list_next_elt;
5339 }
5340
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305341 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342}
5343
5344/*--------------------------------------------------------------------------
5345 \brief sme_qos_process_add_ts_success_rsp() - Function to process the
5346 Addts request success response came from PE
5347
5348 We will notify HDD with addts success for the requested Flow, & for other
5349 Flows running on the AC we will send an addts modify status
5350
5351 \param pMac - Pointer to the global MAC parameter structure.
5352 \param pRsp - Pointer to the addts response structure came from PE.
5353
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305354 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355
5356 \sa
5357
5358 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305359QDF_STATUS sme_qos_process_add_ts_success_rsp(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005360 uint8_t sessionId,
5361 tSirAddtsRspInfo *pRsp)
5362{
5363 sme_QosSessionInfo *pSession;
5364 sme_QosACInfo *pACInfo;
5365 sme_QosEdcaAcType ac, ac_index;
5366 sme_QosSearchInfo search_key;
5367 sme_QosSearchInfo search_key1;
5368 uint8_t tspec_pending;
5369 tListElem *pEntry = NULL;
5370 sme_QosFlowInfoEntry *flow_info = NULL;
5371 sme_QosWmmUpType up =
5372 (sme_QosWmmUpType) pRsp->tspec.tsinfo.traffic.userPrio;
5373#ifdef FEATURE_WLAN_DIAG_SUPPORT
5374 WLAN_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type);
5375 host_log_qos_tspec_pkt_type *log_ptr = NULL;
5376#endif /* FEATURE_WLAN_DIAG_SUPPORT */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305377 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378 "%s: %d: invoked on session %d for UP %d",
5379 __func__, __LINE__, sessionId, up);
5380 pSession = &sme_qos_cb.sessionInfo[sessionId];
5381 ac = sme_qos_up_to_ac(up);
5382 if (SME_QOS_EDCA_AC_MAX == ac) {
5383 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305384 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 "%s: %d: invalid AC %d from UP %d",
5386 __func__, __LINE__, ac, up);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305387 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005388 }
5389 pACInfo = &pSession->ac_info[ac];
5390 /* is there a TSPEC request pending on this AC? */
5391 tspec_pending = pACInfo->tspec_pending;
5392 if (!tspec_pending) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305393 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005394 "%s: %d: On session %d an AddTS is not pending on AC %d",
5395 __func__, __LINE__, sessionId, ac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305396 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397 }
5398 /* App is looking for APSD or the App which was looking for APSD has been */
5399 /* released, so STA re-negotiated with AP */
5400 if (pACInfo->requested_QoSInfo[tspec_pending - 1].ts_info.psb) {
5401 /* update the session's apsd mask */
5402 pSession->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac);
5403 } else {
5404 if (((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) > 0) &&
5405 ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) <=
5406 SME_QOS_TSPEC_INDEX_MAX)) {
5407 if (!pACInfo->requested_QoSInfo
5408 [(SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) -
5409 1].ts_info.psb) {
5410 /* update the session's apsd mask */
5411 pSession->apsdMask &=
5412 ~(1 << (SME_QOS_EDCA_AC_VO - ac));
5413 }
5414 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305415 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 "%s: %d: Exceeded the array bounds of pACInfo->requested_QosInfo",
5417 __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305418 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305419 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 }
5421 }
5422
5423 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.burst_size_defn =
5424 pRsp->tspec.tsinfo.traffic.burstSizeDefn;
5425 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.ack_policy =
5426 pRsp->tspec.tsinfo.traffic.ackPolicy;
5427 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.up =
5428 pRsp->tspec.tsinfo.traffic.userPrio;
5429 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.psb =
5430 pRsp->tspec.tsinfo.traffic.psb;
5431 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.direction =
5432 pRsp->tspec.tsinfo.traffic.direction;
5433 pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.tid =
5434 pRsp->tspec.tsinfo.traffic.tsid;
5435 pACInfo->curr_QoSInfo[tspec_pending - 1].nominal_msdu_size =
5436 pRsp->tspec.nomMsduSz;
5437 pACInfo->curr_QoSInfo[tspec_pending - 1].maximum_msdu_size =
5438 pRsp->tspec.maxMsduSz;
5439 pACInfo->curr_QoSInfo[tspec_pending - 1].min_service_interval =
5440 pRsp->tspec.minSvcInterval;
5441 pACInfo->curr_QoSInfo[tspec_pending - 1].max_service_interval =
5442 pRsp->tspec.maxSvcInterval;
5443 pACInfo->curr_QoSInfo[tspec_pending - 1].inactivity_interval =
5444 pRsp->tspec.inactInterval;
5445 pACInfo->curr_QoSInfo[tspec_pending - 1].suspension_interval =
5446 pRsp->tspec.suspendInterval;
5447 pACInfo->curr_QoSInfo[tspec_pending - 1].svc_start_time =
5448 pRsp->tspec.svcStartTime;
5449 pACInfo->curr_QoSInfo[tspec_pending - 1].min_data_rate =
5450 pRsp->tspec.minDataRate;
5451 pACInfo->curr_QoSInfo[tspec_pending - 1].mean_data_rate =
5452 pRsp->tspec.meanDataRate;
5453 pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate =
5454 pRsp->tspec.peakDataRate;
5455 pACInfo->curr_QoSInfo[tspec_pending - 1].max_burst_size =
5456 pRsp->tspec.maxBurstSz;
5457 pACInfo->curr_QoSInfo[tspec_pending - 1].delay_bound =
5458 pRsp->tspec.delayBound;
5459
5460 pACInfo->curr_QoSInfo[tspec_pending - 1].min_phy_rate =
5461 pRsp->tspec.minPhyRate;
5462 pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance =
5463 pRsp->tspec.surplusBw;
5464 pACInfo->curr_QoSInfo[tspec_pending - 1].medium_time =
5465 pRsp->tspec.mediumTime;
5466
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305467 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005468 "%s: %d: On session %d AddTspec Medium Time %d",
5469 __func__, __LINE__, sessionId, pRsp->tspec.mediumTime);
5470
5471 /* Check if the current flow is for bi-directional. If so, update the number of flows
5472 * to reflect that all flows are aggregated into tspec index 0. */
5473 if ((pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1].ts_info.
5474 direction == SME_QOS_WMM_TS_DIR_BOTH)
5475 && (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305476 qdf_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 /* update tspec_mask for all the flows having SME_QOS_TSPEC_MASK_BIT_2_SET to SME_QOS_TSPEC_MASK_BIT_1_SET */
5478 search_key.key.ac_type = ac;
5479 search_key.index = SME_QOS_SEARCH_KEY_INDEX_5;
5480 search_key.sessionId = sessionId;
5481 search_key.tspec_mask = SME_QOS_TSPEC_MASK_BIT_2_SET;
5482 sme_qos_update_tspec_mask(sessionId, search_key,
5483 SME_QOS_TSPEC_MASK_BIT_1_SET);
5484 }
5485
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305486 qdf_mem_zero(&search_key1, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 /* set the horenewal field in control block if needed */
5488 search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3;
5489 search_key1.key.reason = SME_QOS_REASON_SETUP;
5490 search_key1.sessionId = sessionId;
5491 for (ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX;
5492 ac_index++) {
5493 pEntry = sme_qos_find_in_flow_list(search_key1);
5494 if (pEntry) {
5495 flow_info =
5496 GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
5497 if (flow_info->ac_type == ac) {
5498 pACInfo->hoRenewal = flow_info->hoRenewal;
5499 break;
5500 }
5501 }
5502 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305503 qdf_mem_zero(&search_key, sizeof(sme_QosSearchInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005504 /* set the key type & the key to be searched in the Flow List */
5505 search_key.key.ac_type = ac;
5506 search_key.index = SME_QOS_SEARCH_KEY_INDEX_2;
5507 search_key.sessionId = sessionId;
5508 /* notify HDD the success for the requested flow */
5509 /* notify all the other flows running on the AC that QoS got modified */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305510 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 (sme_qos_find_all_in_flow_list
5512 (pMac, search_key, sme_qos_add_ts_success_fnp))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305513 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514 "%s: %d: On session %d no match found for ac %d",
5515 __func__, __LINE__, sessionId,
5516 search_key.key.ac_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305517 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305518 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005519 }
5520 pACInfo->hoRenewal = false;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305521 qdf_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 sizeof(sme_QosWmmTspecInfo));
5523 /* event: EVENT_WLAN_QOS */
5524#ifdef FEATURE_WLAN_DIAG_SUPPORT
5525 qos.eventId = SME_QOS_DIAG_ADDTS_RSP;
5526 qos.reasonCode = SME_QOS_DIAG_ADDTS_ADMISSION_ACCEPTED;
5527 WLAN_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS);
5528 WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_tspec_pkt_type,
5529 LOG_WLAN_QOS_TSPEC_C);
5530 if (log_ptr) {
5531 log_ptr->delay_bound =
5532 pACInfo->curr_QoSInfo[tspec_pending - 1].delay_bound;
5533 log_ptr->inactivity_interval =
5534 pACInfo->curr_QoSInfo[tspec_pending -
5535 1].inactivity_interval;
5536 log_ptr->max_burst_size =
5537 pACInfo->curr_QoSInfo[tspec_pending - 1].max_burst_size;
5538 log_ptr->max_service_interval =
5539 pACInfo->curr_QoSInfo[tspec_pending -
5540 1].max_service_interval;
5541 log_ptr->maximum_msdu_size =
5542 pACInfo->curr_QoSInfo[tspec_pending - 1].maximum_msdu_size;
5543 log_ptr->mean_data_rate =
5544 pACInfo->curr_QoSInfo[tspec_pending - 1].mean_data_rate;
5545 log_ptr->medium_time =
5546 pACInfo->curr_QoSInfo[tspec_pending - 1].medium_time;
5547 log_ptr->min_data_rate =
5548 pACInfo->curr_QoSInfo[tspec_pending - 1].min_data_rate;
5549 log_ptr->min_phy_rate =
5550 pACInfo->curr_QoSInfo[tspec_pending - 1].min_phy_rate;
5551 log_ptr->min_service_interval =
5552 pACInfo->curr_QoSInfo[tspec_pending -
5553 1].min_service_interval;
5554 log_ptr->nominal_msdu_size =
5555 pACInfo->curr_QoSInfo[tspec_pending - 1].nominal_msdu_size;
5556 log_ptr->peak_data_rate =
5557 pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate;
5558 log_ptr->surplus_bw_allowance =
5559 pACInfo->curr_QoSInfo[tspec_pending -
5560 1].surplus_bw_allowance;
5561 log_ptr->suspension_interval =
5562 pACInfo->curr_QoSInfo[tspec_pending -
5563 1].surplus_bw_allowance;
5564 log_ptr->suspension_interval =
5565 pACInfo->curr_QoSInfo[tspec_pending -
5566 1].suspension_interval;
5567 log_ptr->svc_start_time =
5568 pACInfo->curr_QoSInfo[tspec_pending - 1].svc_start_time;
5569 log_ptr->tsinfo[0] =
5570 pACInfo->curr_QoSInfo[tspec_pending -
5571 1].ts_info.direction << 5 | pACInfo->
5572 curr_QoSInfo[tspec_pending - 1].ts_info.tid << 1;
5573 log_ptr->tsinfo[1] =
5574 pACInfo->curr_QoSInfo[tspec_pending -
5575 1].ts_info.up << 11 | pACInfo->
5576 curr_QoSInfo[tspec_pending - 1].ts_info.psb << 10;
5577 log_ptr->tsinfo[2] = 0;
5578 }
5579 WLAN_HOST_DIAG_LOG_REPORT(log_ptr);
5580#endif /* FEATURE_WLAN_DIAG_SUPPORT */
5581 pACInfo->tspec_pending = 0;
5582
5583 sme_qos_state_transition(sessionId, ac, SME_QOS_QOS_ON);
5584
5585 sme_set_tspec_uapsd_mask_per_session(pMac,
5586 &pRsp->tspec.tsinfo, sessionId);
5587
5588 (void)sme_qos_process_buffered_cmd(sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305589 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590
5591}
5592
5593/*--------------------------------------------------------------------------
5594 \brief sme_qos_aggregate_params() - Utiltity function to increament the TSPEC
5595 params per AC. Typical usage while using flow aggregation or deletion of flows
5596
5597 \param pInput_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains the
5598 WMM TSPEC related info with which pCurrent_Tspec_Info will be updated
5599 \param pCurrent_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains
5600 current the WMM TSPEC related info
5601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305602 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005603
5604 \sa
5605
5606 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305607QDF_STATUS sme_qos_aggregate_params(sme_QosWmmTspecInfo *pInput_Tspec_Info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005608 sme_QosWmmTspecInfo *pCurrent_Tspec_Info,
5609 sme_QosWmmTspecInfo *pUpdated_Tspec_Info)
5610{
5611 sme_QosWmmTspecInfo TspecInfo;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305612 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613 "%s: %d: invoked", __func__, __LINE__);
5614 if (!pInput_Tspec_Info) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305615 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616 "%s: %d: input is NULL, nothing to aggregate",
5617 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305618 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619 }
5620 if (!pCurrent_Tspec_Info) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305621 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005622 "%s: %d: Current is NULL, can't aggregate",
5623 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305624 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305626 qdf_mem_copy(&TspecInfo, pCurrent_Tspec_Info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627 sizeof(sme_QosWmmTspecInfo));
5628 TspecInfo.ts_info.psb = pInput_Tspec_Info->ts_info.psb;
5629 /*-------------------------------------------------------------------------
5630 APSD preference is only meaningful if service interval was set by app
5631 -------------------------------------------------------------------------*/
5632 if (pCurrent_Tspec_Info->min_service_interval &&
5633 pInput_Tspec_Info->min_service_interval &&
5634 (pCurrent_Tspec_Info->ts_info.direction !=
5635 pInput_Tspec_Info->ts_info.direction)) {
5636 TspecInfo.min_service_interval =
Anurag Chouhan6d760662016-02-20 16:05:43 +05305637 QDF_MIN(pCurrent_Tspec_Info->min_service_interval,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638 pInput_Tspec_Info->min_service_interval);
5639 } else if (pInput_Tspec_Info->min_service_interval) {
5640 TspecInfo.min_service_interval =
5641 pInput_Tspec_Info->min_service_interval;
5642 }
5643 if (pCurrent_Tspec_Info->max_service_interval &&
5644 pInput_Tspec_Info->max_service_interval &&
5645 (pCurrent_Tspec_Info->ts_info.direction !=
5646 pInput_Tspec_Info->ts_info.direction)) {
5647 TspecInfo.max_service_interval =
Anurag Chouhan6d760662016-02-20 16:05:43 +05305648 QDF_MIN(pCurrent_Tspec_Info->max_service_interval,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005649 pInput_Tspec_Info->max_service_interval);
5650 } else {
5651 TspecInfo.max_service_interval =
5652 pInput_Tspec_Info->max_service_interval;
5653 }
5654 /*-------------------------------------------------------------------------
5655 If directions don't match, it must necessarily be both uplink and
5656 downlink
5657 -------------------------------------------------------------------------*/
5658 if (pCurrent_Tspec_Info->ts_info.direction !=
5659 pInput_Tspec_Info->ts_info.direction) {
5660 TspecInfo.ts_info.direction =
5661 pInput_Tspec_Info->ts_info.direction;
5662 }
5663 /*-------------------------------------------------------------------------
5664 Max MSDU size : these sizes are `maxed'
5665 -------------------------------------------------------------------------*/
5666 TspecInfo.maximum_msdu_size =
Anurag Chouhan6d760662016-02-20 16:05:43 +05305667 QDF_MAX(pCurrent_Tspec_Info->maximum_msdu_size,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 pInput_Tspec_Info->maximum_msdu_size);
5669
5670 /*-------------------------------------------------------------------------
5671 Inactivity interval : these sizes are `maxed'
5672 -------------------------------------------------------------------------*/
5673 TspecInfo.inactivity_interval =
Anurag Chouhan6d760662016-02-20 16:05:43 +05305674 QDF_MAX(pCurrent_Tspec_Info->inactivity_interval,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005675 pInput_Tspec_Info->inactivity_interval);
5676
5677 /*-------------------------------------------------------------------------
5678 Delay bounds: min of all values
5679 Check on 0: if 0, it means initial value since delay can never be 0!!
5680 -------------------------------------------------------------------------*/
5681 if (pCurrent_Tspec_Info->delay_bound) {
5682 TspecInfo.delay_bound =
Anurag Chouhan6d760662016-02-20 16:05:43 +05305683 QDF_MIN(pCurrent_Tspec_Info->delay_bound,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 pInput_Tspec_Info->delay_bound);
5685 } else {
5686 TspecInfo.delay_bound = pInput_Tspec_Info->delay_bound;
5687 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305688 TspecInfo.max_burst_size = QDF_MAX(pCurrent_Tspec_Info->max_burst_size,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689 pInput_Tspec_Info->max_burst_size);
5690
5691 /*-------------------------------------------------------------------------
5692 Nominal MSDU size also has a fixed bit that needs to be `handled' before
5693 aggregation
5694 This can be handled only if previous size is the same as new or both have
5695 the fixed bit set
5696 These sizes are not added: but `maxed'
5697 -------------------------------------------------------------------------*/
5698 TspecInfo.nominal_msdu_size =
Anurag Chouhan6d760662016-02-20 16:05:43 +05305699 QDF_MAX(pCurrent_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005700 pInput_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB);
5701
5702 if (((pCurrent_Tspec_Info->nominal_msdu_size == 0) ||
5703 (pCurrent_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB)) &&
5704 ((pInput_Tspec_Info->nominal_msdu_size == 0) ||
5705 (pInput_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB))) {
5706 TspecInfo.nominal_msdu_size |= SME_QOS_16BIT_MSB;
5707 }
5708
5709 /*-------------------------------------------------------------------------
5710 Data rates:
5711 Add up the rates for aggregation
5712 -------------------------------------------------------------------------*/
5713 SME_QOS_BOUNDED_U32_ADD_Y_TO_X(TspecInfo.peak_data_rate,
5714 pInput_Tspec_Info->peak_data_rate);
5715 SME_QOS_BOUNDED_U32_ADD_Y_TO_X(TspecInfo.min_data_rate,
5716 pInput_Tspec_Info->min_data_rate);
5717 /* mean data rate = peak data rate: aggregate to be flexible on apps */
5718 SME_QOS_BOUNDED_U32_ADD_Y_TO_X(TspecInfo.mean_data_rate,
5719 pInput_Tspec_Info->mean_data_rate);
5720
5721 /*-------------------------------------------------------------------------
5722 Suspension interval : this is set to the inactivity interval since per
5723 spec it is less than or equal to inactivity interval
5724 This is not provided by app since we currently don't support the HCCA
5725 mode of operation
5726 Currently set it to 0 to avoid confusion: Cisco ESE needs ~0; spec
5727 requires inactivity interval to be > suspension interval: this could
5728 be tricky!
5729 -------------------------------------------------------------------------*/
5730 TspecInfo.suspension_interval = pInput_Tspec_Info->suspension_interval;
5731 /*-------------------------------------------------------------------------
5732 Remaining parameters do not come from app as they are very WLAN
5733 air interface specific
5734 Set meaningful values here
5735 -------------------------------------------------------------------------*/
5736 TspecInfo.medium_time = 0; /* per WMM spec */
5737 TspecInfo.min_phy_rate = SME_QOS_MIN_PHY_RATE;
5738 TspecInfo.svc_start_time = 0; /* arbitrary */
5739 TspecInfo.surplus_bw_allowance +=
5740 pInput_Tspec_Info->surplus_bw_allowance;
5741 if (TspecInfo.surplus_bw_allowance > SME_QOS_SURPLUS_BW_ALLOWANCE) {
5742 TspecInfo.surplus_bw_allowance = SME_QOS_SURPLUS_BW_ALLOWANCE;
5743 }
5744 /* Set ack_policy to block ack even if one stream requests block ack policy */
5745 if ((pInput_Tspec_Info->ts_info.ack_policy ==
5746 SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)
5747 || (pCurrent_Tspec_Info->ts_info.ack_policy ==
5748 SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)) {
5749 TspecInfo.ts_info.ack_policy =
5750 SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
5751 }
5752
5753 if (pInput_Tspec_Info->ts_info.burst_size_defn
5754 || pCurrent_Tspec_Info->ts_info.burst_size_defn) {
5755 TspecInfo.ts_info.burst_size_defn = 1;
5756 }
5757 if (pUpdated_Tspec_Info) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305758 qdf_mem_copy(pUpdated_Tspec_Info, &TspecInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 sizeof(sme_QosWmmTspecInfo));
5760 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305761 qdf_mem_copy(pCurrent_Tspec_Info, &TspecInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762 sizeof(sme_QosWmmTspecInfo));
5763 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305764 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005765}
5766
5767/*--------------------------------------------------------------------------
5768 \brief sme_qos_update_params() - Utiltity function to update the TSPEC
5769 params per AC. Typical usage while deleting flows on AC which is running
5770 multiple flows
5771
5772 \param sessionId - Session upon which the TSPEC is being updated
5773 \param ac - Enumeration of the various EDCA Access Categories.
5774 \param tspec_mask - on which tspec per AC, the update is requested
5775
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305776 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005777
5778 \sa
5779
5780 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305781static QDF_STATUS sme_qos_update_params(uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005782 sme_QosEdcaAcType ac,
5783 uint8_t tspec_mask,
5784 sme_QosWmmTspecInfo *pTspec_Info)
5785{
5786 tListElem *pEntry = NULL, *pNextEntry = NULL;
5787 sme_QosSessionInfo *pSession;
5788 sme_QosACInfo *pACInfo;
5789 sme_QosFlowInfoEntry *flow_info = NULL;
5790 sme_QosWmmTspecInfo Tspec_Info;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305791 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005792 "%s: %d: invoked on session %d for AC %d TSPEC %d",
5793 __func__, __LINE__, sessionId, ac, tspec_mask);
5794 if (!pTspec_Info) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305795 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 "%s: %d: output is NULL, can't aggregate",
5797 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305798 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305800 qdf_mem_zero(&Tspec_Info, sizeof(sme_QosWmmTspecInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801 pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
5802 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305803 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005804 "%s: %d: Flow List empty, nothing to update",
5805 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305806 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005807 }
5808 pSession = &sme_qos_cb.sessionInfo[sessionId];
5809 pACInfo = &pSession->ac_info[ac];
5810 /* init the TS info field */
5811 Tspec_Info.ts_info.up =
5812 pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.up;
5813 Tspec_Info.ts_info.psb =
5814 pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.psb;
5815 Tspec_Info.ts_info.tid =
5816 pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.tid;
5817 while (pEntry) {
5818 pNextEntry = csr_ll_next(&sme_qos_cb.flow_list, pEntry, false);
5819 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
5820 if ((sessionId == flow_info->sessionId) &&
5821 (ac == flow_info->ac_type) &&
5822 (tspec_mask == flow_info->tspec_mask)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305823 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005824 "%s: %d: Flow %d matches",
5825 __func__, __LINE__, flow_info->QosFlowID);
5826
5827 if ((SME_QOS_REASON_RELEASE == flow_info->reason) ||
5828 (SME_QOS_REASON_MODIFY == flow_info->reason)) {
5829 /* msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305830 QDF_TRACE(QDF_MODULE_ID_SME,
5831 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832 "%s: %d: Skipping Flow %d as it is marked "
5833 "for release/modify", __func__,
5834 __LINE__, flow_info->QosFlowID);
5835 } else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305836 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005837 (sme_qos_aggregate_params
5838 (&flow_info->QoSInfo, &Tspec_Info, NULL))) {
5839 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305840 QDF_TRACE(QDF_MODULE_ID_SME,
5841 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842 "%s: %d: sme_qos_aggregate_params() failed",
5843 __func__, __LINE__);
5844 }
5845 }
5846 pEntry = pNextEntry;
5847 }
5848 /* return the aggregate */
5849 *pTspec_Info = Tspec_Info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305850 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005851}
5852
5853/*--------------------------------------------------------------------------
5854 \brief sme_qos_ac_to_up() - Utiltity function to map an AC to UP
5855 Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs
5856 Mapping is done for consistency
5857 \param ac - Enumeration of the various EDCA Access Categories.
5858 \return an User Priority
5859
5860 \sa
5861
5862 --------------------------------------------------------------------------*/
5863sme_QosWmmUpType sme_qos_ac_to_up(sme_QosEdcaAcType ac)
5864{
5865 sme_QosWmmUpType up = SME_QOS_WMM_UP_MAX;
5866 if (ac >= 0 && ac < SME_QOS_EDCA_AC_MAX) {
5867 up = sme_qos_a_cto_up_map[ac];
5868 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305869 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870 "%s: %d: ac = %d up = %d returned",
5871 __func__, __LINE__, ac, up);
5872 return up;
5873}
5874
5875/*--------------------------------------------------------------------------
5876 \brief sme_qos_up_to_ac() - Utiltity function to map an UP to AC
5877 \param up - Enumeration of the various User priorities (UP).
5878 \return an Access Category
5879
5880 \sa
5881
5882 --------------------------------------------------------------------------*/
5883sme_QosEdcaAcType sme_qos_up_to_ac(sme_QosWmmUpType up)
5884{
5885 sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_MAX;
5886 if (up >= 0 && up < SME_QOS_WMM_UP_MAX) {
5887 ac = sme_qos_u_pto_ac_map[up];
5888 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305889 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005890 "%s: %d: up = %d ac = %d returned",
5891 __func__, __LINE__, up, ac);
5892 return ac;
5893}
5894
5895/*--------------------------------------------------------------------------
5896 \brief sme_qos_state_transition() - The state transition function per AC. We
5897 save the previous state also.
5898 \param sessionId - Session upon which the state machine is running
5899 \param ac - Enumeration of the various EDCA Access Categories.
5900 \param new_state - The state FSM is moving to.
5901
5902 \return None
5903
5904 \sa
5905
5906 --------------------------------------------------------------------------*/
5907static void sme_qos_state_transition(uint8_t sessionId,
5908 sme_QosEdcaAcType ac,
5909 sme_QosStates new_state)
5910{
5911 sme_QosSessionInfo *pSession;
5912 sme_QosACInfo *pACInfo;
5913 pSession = &sme_qos_cb.sessionInfo[sessionId];
5914 pACInfo = &pSession->ac_info[ac];
5915 pACInfo->prev_state = pACInfo->curr_state;
5916 pACInfo->curr_state = new_state;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305917 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005918 "%s: %d: On session %d new state=%d, old state=%d, for AC=%d",
5919 __func__, __LINE__,
5920 sessionId, pACInfo->curr_state, pACInfo->prev_state, ac);
5921}
5922
5923/**
5924 * sme_qos_find_in_flow_list() - find a flow entry from the flow list
5925 * @search_key: We can either use the flowID or the ac type to find the
5926 * entry in the flow list.
5927 * A bitmap in sme_QosSearchInfo tells which key to use.
5928 * Starting from LSB,
5929 * bit 0 - Flow ID
5930 * bit 1 - AC type
5931 *
5932 * Utility function to find an flow entry from the flow_list.
5933 *
5934 * Return: pointer to the list element
5935 */
5936tListElem *sme_qos_find_in_flow_list(sme_QosSearchInfo search_key)
5937{
5938 tListElem *list_elt = NULL, *list_next_elt = NULL;
5939 sme_QosFlowInfoEntry *flow_info = NULL;
5940
5941 list_elt = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
5942 if (!list_elt) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305943 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005944 FL("Flow List empty, can't search"));
5945 return NULL;
5946 }
5947
5948 while (list_elt) {
5949 list_next_elt = csr_ll_next(&sme_qos_cb.flow_list, list_elt,
5950 false);
5951 flow_info = GET_BASE_ADDR(list_elt, sme_QosFlowInfoEntry, link);
5952
5953 if ((search_key.sessionId != flow_info->sessionId) &&
5954 (search_key.sessionId != SME_QOS_SEARCH_SESSION_ID_ANY)) {
5955 list_elt = list_next_elt;
5956 continue;
5957 }
5958
5959 if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_1) {
5960 if (search_key.key.QosFlowID == flow_info->QosFlowID) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305961 QDF_TRACE(QDF_MODULE_ID_SME,
5962 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005963 FL("match found on flowID, ending search"));
5964 break;
5965 }
5966 } else if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_2) {
5967 if (search_key.key.ac_type == flow_info->ac_type) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305968 QDF_TRACE(QDF_MODULE_ID_SME,
5969 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005970 FL("match found on ac, ending search"));
5971 break;
5972 }
5973 } else if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_3) {
5974 if (search_key.key.reason == flow_info->reason) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305975 QDF_TRACE(QDF_MODULE_ID_SME,
5976 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977 FL("match found on reason, ending search"));
5978 break;
5979 }
5980 } else if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_4) {
5981 if ((search_key.key.ac_type == flow_info->ac_type) &&
5982 (search_key.direction ==
5983 flow_info->QoSInfo.ts_info.direction)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305984 QDF_TRACE(QDF_MODULE_ID_SME,
5985 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986 FL("match found on reason, ending search"));
5987 break;
5988 }
5989 }
5990 list_elt = list_next_elt;
5991 }
5992 return list_elt;
5993}
5994
5995/**
5996 * sme_qos_find_all_in_flow_list() - find a flow entry in the flow list
5997 * @mac_ctx: global MAC context
5998 * @search_key: search key
5999 * @fnp: function pointer specifying the action type for the entry found
6000 *
6001 * Utility function to find an flow entry from the flow_list & act on it.
6002 * search_key - We can either use the flowID or the ac type to find the
6003 * entry in the flow list.
6004 * A bitmap in sme_QosSearchInfo tells which key to use. Starting from LSB,
6005 * bit 0 - Flow ID
6006 * bit 1 - AC type
6007 *
6008 * Return: None
6009 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306010QDF_STATUS sme_qos_find_all_in_flow_list(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006011 sme_QosSearchInfo search_key,
6012 sme_QosProcessSearchEntry fnp)
6013{
6014 tListElem *list_elt = NULL, *list_next_elt = NULL;
6015 sme_QosSessionInfo *qos_session;
6016 sme_QosFlowInfoEntry *flow_info = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306017 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006018 sme_QosEdcaAcType ac_type;
6019
6020 list_elt = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
6021 if (!list_elt) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306022 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023 FL("Flow List empty, can't search"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306024 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006025 }
6026
6027 while (list_elt) {
6028 list_next_elt = csr_ll_next(&sme_qos_cb.flow_list, list_elt,
6029 false);
6030 flow_info = GET_BASE_ADDR(list_elt, sme_QosFlowInfoEntry, link);
6031 qos_session = &sme_qos_cb.sessionInfo[flow_info->sessionId];
6032 if ((search_key.sessionId != flow_info->sessionId) &&
6033 (search_key.sessionId != SME_QOS_SEARCH_SESSION_ID_ANY)) {
6034 list_elt = list_next_elt;
6035 continue;
6036 }
6037
6038 if ((search_key.index & SME_QOS_SEARCH_KEY_INDEX_1) &&
6039 (search_key.key.QosFlowID == flow_info->QosFlowID)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306040 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041 FL("match found on flowID, ending search"));
6042 status = fnp(mac_ctx, list_elt);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306043 if (QDF_STATUS_E_FAILURE == status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306044 QDF_TRACE(QDF_MODULE_ID_SME,
6045 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 FL("Failed to process entry"));
6047 break;
6048 }
6049 } else if ((search_key.index & SME_QOS_SEARCH_KEY_INDEX_2) &&
6050 (search_key.key.ac_type == flow_info->ac_type)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306051 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006052 FL("match found on ac, ending search"));
6053 ac_type = flow_info->ac_type;
6054 flow_info->hoRenewal =
6055 qos_session->ac_info[ac_type].hoRenewal;
6056 status = fnp(mac_ctx, list_elt);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306057 if (QDF_STATUS_E_FAILURE == status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306058 QDF_TRACE(QDF_MODULE_ID_SME,
6059 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006060 FL("Failed to process entry"));
6061 break;
6062 }
6063 }
6064 list_elt = list_next_elt;
6065 }
6066 return status;
6067}
6068
6069/*--------------------------------------------------------------------------
6070 \brief sme_qos_is_acm() - Utility function to check if a particular AC
6071 mandates Admission Control.
6072 \param ac - Enumeration of the various EDCA Access Categories.
6073
6074 \return true if the AC mandates Admission Control
6075
6076 \sa
6077
6078 --------------------------------------------------------------------------*/
6079bool sme_qos_is_acm(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc,
6080 sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes)
6081{
6082 bool ret_val = false;
6083 tDot11fBeaconIEs *pIesLocal;
6084 if (!pSirBssDesc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306085 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006086 "%s: %d: pSirBssDesc is NULL", __func__, __LINE__);
6087 return false;
6088 }
6089
6090 if (NULL != pIes) {
6091 /* IEs were provided so use them locally */
6092 pIesLocal = pIes;
6093 } else {
6094 /* IEs were not provided so parse them ourselves */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306095 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006096 (csr_get_parsed_bss_description_ies
6097 (pMac, pSirBssDesc, &pIesLocal))) {
6098 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306099 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006100 "%s: %d: csr_get_parsed_bss_description_ies() failed",
6101 __func__, __LINE__);
6102 return false;
6103 }
6104
6105 /* if success then pIesLocal was allocated */
6106 }
6107
6108 if (CSR_IS_QOS_BSS(pIesLocal)) {
6109 switch (ac) {
6110 case SME_QOS_EDCA_AC_BE:
6111 if (pIesLocal->WMMParams.acbe_acm)
6112 ret_val = true;
6113 break;
6114 case SME_QOS_EDCA_AC_BK:
6115 if (pIesLocal->WMMParams.acbk_acm)
6116 ret_val = true;
6117 break;
6118 case SME_QOS_EDCA_AC_VI:
6119 if (pIesLocal->WMMParams.acvi_acm)
6120 ret_val = true;
6121 break;
6122 case SME_QOS_EDCA_AC_VO:
6123 if (pIesLocal->WMMParams.acvo_acm)
6124 ret_val = true;
6125 break;
6126 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306127 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006128 "%s: %d: unknown AC = %d",
6129 __func__, __LINE__, ac);
6130 /* Assert */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306131 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006132 break;
6133 }
6134 } /* IS_QOS_BSS */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306135 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006136 "%s: %d: ACM = %d for AC = %d",
6137 __func__, __LINE__, ret_val, ac);
6138 if (NULL == pIes) {
6139 /* IEs were allocated locally so free them */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306140 qdf_mem_free(pIesLocal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006141 }
6142 return ret_val;
6143}
6144
6145/**
6146 * sme_qos_buffer_existing_flows() - buffer existing flows in flow_list
6147 * @mac_ctx: global MAC context
6148 * @sessionid: session ID
6149 *
6150 * Utility function to buffer the existing flows in flow_list,
6151 * so that we can renew them after handoff is done.
6152 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306153 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006154 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306155static QDF_STATUS sme_qos_buffer_existing_flows(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006156 uint8_t sessionid)
6157{
6158 tListElem *list_entry = NULL, *list_nextentry = NULL;
6159 sme_QosSessionInfo *qos_session;
6160 sme_QosFlowInfoEntry *flow_info = NULL;
6161 sme_QosCmdInfo cmd;
6162 sme_qos_setupCmdInfo *setupinfo;
6163
6164 list_entry = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
6165 if (!list_entry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306166 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006167 FL("Flow List empty, nothing to buffer"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306168 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006169 }
6170
6171 while (list_entry) {
6172 list_nextentry = csr_ll_next(&sme_qos_cb.flow_list, list_entry,
6173 false);
6174 flow_info = GET_BASE_ADDR(list_entry, sme_QosFlowInfoEntry,
6175 link);
6176 if (flow_info->sessionId != sessionid) {
6177 list_entry = list_nextentry;
6178 continue;
6179 }
6180
6181 if ((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) ||
6182 (SME_QOS_REASON_SETUP == flow_info->reason)) {
6183 cmd.command = SME_QOS_SETUP_REQ;
6184 cmd.pMac = mac_ctx;
6185 cmd.sessionId = sessionid;
6186 setupinfo = &cmd.u.setupCmdInfo;
6187
6188 setupinfo->HDDcontext = flow_info->HDDcontext;
6189 setupinfo->QoSInfo = flow_info->QoSInfo;
6190 setupinfo->QoSCallback = flow_info->QoSCallback;
6191 /* shouldn't be needed */
6192 setupinfo->UPType = SME_QOS_WMM_UP_MAX;
6193 setupinfo->QosFlowID = flow_info->QosFlowID;
6194 if (SME_QOS_REASON_SETUP == flow_info->reason)
6195 setupinfo->hoRenewal = false;
6196 else
6197 setupinfo->hoRenewal = true;
6198
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306199 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006200 (sme_qos_buffer_cmd(&cmd, true)))
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306201 QDF_TRACE(QDF_MODULE_ID_SME,
6202 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006203 FL("couldn't buffer the setup request"
6204 " for flow %d in handoff state"),
6205 flow_info->QosFlowID);
6206 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306207 QDF_TRACE(QDF_MODULE_ID_SME,
6208 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006209 FL("buffered a setup request for "
6210 "flow %d in handoff state"),
6211 flow_info->QosFlowID);
6212 } else if (SME_QOS_REASON_RELEASE == flow_info->reason) {
6213 cmd.command = SME_QOS_RELEASE_REQ;
6214 cmd.pMac = mac_ctx;
6215 cmd.sessionId = sessionid;
6216 cmd.u.releaseCmdInfo.QosFlowID = flow_info->QosFlowID;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306217 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006218 (sme_qos_buffer_cmd(&cmd, true)))
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306219 QDF_TRACE(QDF_MODULE_ID_SME,
6220 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006221 FL("couldn't buffer the release req"
6222 " for flow %d in handoff state"),
6223 flow_info->QosFlowID);
6224 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306225 QDF_TRACE(QDF_MODULE_ID_SME,
6226 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006227 FL("buffered a release request for "
6228 "flow %d in handoff state"),
6229 flow_info->QosFlowID);
6230 } else if (SME_QOS_REASON_MODIFY_PENDING ==
6231 flow_info->reason) {
6232 cmd.command = SME_QOS_MODIFY_REQ;
6233 cmd.pMac = mac_ctx;
6234 cmd.sessionId = sessionid;
6235 cmd.u.modifyCmdInfo.QosFlowID = flow_info->QosFlowID;
6236 cmd.u.modifyCmdInfo.QoSInfo = flow_info->QoSInfo;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306237 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006238 (sme_qos_buffer_cmd(&cmd, true)))
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306239 QDF_TRACE(QDF_MODULE_ID_SME,
6240 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006241 FL("couldn't buffer the modify req"
6242 " for flow %d in handoff state"),
6243 flow_info->QosFlowID);
6244 else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306245 QDF_TRACE(QDF_MODULE_ID_SME,
6246 QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006247 FL("buffered a modify request for "
6248 "flow %d in handoff state"),
6249 flow_info->QosFlowID);
6250 }
6251 /* delete the entry from Flow List */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306252 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006253 FL("Deleting original entry at %p with flowID %d"),
6254 flow_info, flow_info->QosFlowID);
6255 csr_ll_remove_entry(&sme_qos_cb.flow_list, list_entry, true);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306256 qdf_mem_free(flow_info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006257
6258 list_entry = list_nextentry;
6259 }
6260 qos_session = &sme_qos_cb.sessionInfo[sessionid];
6261 qos_session->uapsdAlreadyRequested = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306262 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006263}
6264
6265/*--------------------------------------------------------------------------
6266 \brief sme_qos_delete_existing_flows() - Utility function to Delete the existing
6267 flows in flow_list, if we lost connectivity.
6268
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306269 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270
6271 \sa
6272
6273 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306274static QDF_STATUS sme_qos_delete_existing_flows(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006275 uint8_t sessionId)
6276{
6277 tListElem *pEntry = NULL, *pNextEntry = NULL;
6278 sme_QosFlowInfoEntry *flow_info = NULL;
6279 pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, true);
6280 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306281 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006282 "%s: %d: Flow List empty, nothing to delete",
6283 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306284 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006285 }
6286 while (pEntry) {
6287 pNextEntry = csr_ll_next(&sme_qos_cb.flow_list, pEntry, true);
6288 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
6289 if (flow_info->sessionId == sessionId) {
6290 if ((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) ||
6291 (SME_QOS_REASON_SETUP == flow_info->reason) ||
6292 (SME_QOS_REASON_RELEASE == flow_info->reason) ||
6293 (SME_QOS_REASON_MODIFY == flow_info->reason)) {
6294 flow_info->QoSCallback(pMac,
6295 flow_info->HDDcontext,
6296 NULL,
6297 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
6298 flow_info->QosFlowID);
6299 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306300 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006301 "%s: %d: Deleting entry at %p with flowID %d",
6302 __func__, __LINE__,
6303 flow_info, flow_info->QosFlowID);
6304 /* delete the entry from Flow List */
6305 csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry,
6306 true);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306307 qdf_mem_free(flow_info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006308 }
6309 pEntry = pNextEntry;
6310 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306311 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006312}
6313
6314/**
6315 * sme_qos_buffer_cmd() - buffer a request.
6316 * @pcmd: a pointer to the cmd structure to be saved inside the buffered
6317 * cmd link list
6318 * @insert_head: flag indicate if cmd should be added to the list head.
6319 *
6320 * Utility function to buffer a request (setup/modify/release) from client
6321 * while processing another one on the same AC.
6322 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306323 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006324 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306325QDF_STATUS sme_qos_buffer_cmd(sme_QosCmdInfo *pcmd, bool insert_head)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006326{
6327 sme_QosSessionInfo *pSession;
6328 sme_QosCmdInfoEntry *pentry = NULL;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306329 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006330 "%s: %d: Invoked", __func__, __LINE__);
6331 pentry =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306332 (sme_QosCmdInfoEntry *) qdf_mem_malloc(sizeof(sme_QosCmdInfoEntry));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006333 if (!pentry) {
6334 /* err msg */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306335 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006336 "%s: %d: Memory allocation failure",
6337 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306338 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339 }
6340 /* copy the entire CmdInfo */
6341 pentry->cmdInfo = *pcmd;
6342
6343 pSession = &sme_qos_cb.sessionInfo[pcmd->sessionId];
6344 if (insert_head) {
6345 csr_ll_insert_head(&pSession->bufferedCommandList, &pentry->link,
6346 true);
6347 } else {
6348 csr_ll_insert_tail(&pSession->bufferedCommandList, &pentry->link,
6349 true);
6350 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306351 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352}
6353
6354/**
6355 * sme_qos_process_buffered_cmd() - process qos buffered request
6356 * @session_id: Session ID
6357 *
6358 * Utility function to process a buffered request (setup/modify/release)
6359 * initially came from the client.
6360 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306361 * Return:QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006362 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306363static QDF_STATUS sme_qos_process_buffered_cmd(uint8_t session_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006364{
6365 sme_QosSessionInfo *qos_session;
6366 sme_QosCmdInfoEntry *pcmd = NULL;
6367 tListElem *list_elt = NULL;
6368 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306369 QDF_STATUS cdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006370 sme_QosCmdInfo *qos_cmd = NULL;
6371
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306372 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006373 FL("Invoked on session %d"), session_id);
6374 qos_session = &sme_qos_cb.sessionInfo[session_id];
6375 if (!csr_ll_is_list_empty(&qos_session->bufferedCommandList, false)) {
6376 list_elt = csr_ll_remove_head(&qos_session->bufferedCommandList,
6377 true);
6378 if (!list_elt) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306379 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006380 FL("no more buffered commands on session %d"),
6381 session_id);
6382 qos_session->readyForPowerSave = true;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306383 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006384 }
6385 pcmd = GET_BASE_ADDR(list_elt, sme_QosCmdInfoEntry, link);
6386 qos_cmd = &pcmd->cmdInfo;
6387 switch (qos_cmd->command) {
6388 case SME_QOS_SETUP_REQ:
6389 hdd_status = sme_qos_internal_setup_req(
6390 qos_cmd->pMac, qos_cmd->sessionId,
6391 &qos_cmd->u.setupCmdInfo.QoSInfo,
6392 qos_cmd->u.setupCmdInfo.QoSCallback,
6393 qos_cmd->u.setupCmdInfo.HDDcontext,
6394 qos_cmd->u.setupCmdInfo.UPType,
6395 qos_cmd->u.setupCmdInfo.QosFlowID,
6396 true, qos_cmd->u.setupCmdInfo.hoRenewal);
6397 if (SME_QOS_STATUS_SETUP_FAILURE_RSP == hdd_status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306398 QDF_TRACE(QDF_MODULE_ID_SME,
6399 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006400 FL("sme_qos_internal_setup_req failed on session %d"),
6401 session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306402 cdf_ret_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006403 }
6404 break;
6405 case SME_QOS_RELEASE_REQ:
6406 hdd_status = sme_qos_internal_release_req(qos_cmd->pMac,
6407 qos_cmd->u.releaseCmdInfo.QosFlowID,
6408 true);
6409 if (SME_QOS_STATUS_RELEASE_FAILURE_RSP == hdd_status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306410 QDF_TRACE(QDF_MODULE_ID_SME,
6411 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006412 FL("sme_qos_internal_release_req failed on session %d"),
6413 session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306414 cdf_ret_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006415 }
6416 break;
6417 case SME_QOS_MODIFY_REQ:
6418 hdd_status = sme_qos_internal_modify_req(qos_cmd->pMac,
6419 &qos_cmd->u.modifyCmdInfo.QoSInfo,
6420 qos_cmd->u.modifyCmdInfo.QosFlowID,
6421 true);
6422 if (SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP ==
6423 hdd_status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306424 QDF_TRACE(QDF_MODULE_ID_SME,
6425 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006426 FL("sme_qos_internal_modify_req failed on session %d"),
6427 session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306428 cdf_ret_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006429 }
6430 break;
6431 case SME_QOS_RESEND_REQ:
6432 hdd_status = sme_qos_re_request_add_ts(qos_cmd->pMac,
6433 qos_cmd->sessionId,
6434 &qos_cmd->u.resendCmdInfo.QoSInfo,
6435 qos_cmd->u.resendCmdInfo.ac,
6436 qos_cmd->u.resendCmdInfo.tspecMask);
6437 if (SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP ==
6438 hdd_status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306439 QDF_TRACE(QDF_MODULE_ID_SME,
6440 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006441 FL("sme_qos_re_request_add_ts failed on session %d"),
6442 session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306443 cdf_ret_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006444 }
6445 break;
6446 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306447 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006448 FL("On session %d unknown cmd = %d"),
6449 session_id, qos_cmd->command);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306450 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006451 break;
6452 }
6453 /* buffered command has been processed, reclaim the memory */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306454 qdf_mem_free(pcmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006455 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306456 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006457 FL("cmd buffer empty"));
6458 qos_session->readyForPowerSave = true;
6459 }
6460 return cdf_ret_status;
6461}
6462
6463/*--------------------------------------------------------------------------
6464 \brief sme_qos_delete_buffered_requests() - Utility function to Delete the buffered
6465 requests in the buffered_cmd_list, if we lost connectivity.
6466
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306467 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006468
6469 \sa
6470
6471 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306472static QDF_STATUS sme_qos_delete_buffered_requests(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006473 uint8_t sessionId)
6474{
6475 sme_QosSessionInfo *pSession;
6476 sme_QosCmdInfoEntry *pcmd = NULL;
6477 tListElem *pEntry = NULL, *pNextEntry = NULL;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306478 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006479 "%s: %d: Invoked on session %d",
6480 __func__, __LINE__, sessionId);
6481 pSession = &sme_qos_cb.sessionInfo[sessionId];
6482 pEntry = csr_ll_peek_head(&pSession->bufferedCommandList, true);
6483 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306484 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006485 "%s: %d: Buffered List empty, nothing to delete on session %d",
6486 __func__, __LINE__, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306487 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006488 }
6489 while (pEntry) {
6490 pNextEntry =
6491 csr_ll_next(&pSession->bufferedCommandList, pEntry, true);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306492 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006493 "%s: %d: deleting entry from buffered List", __func__,
6494 __LINE__);
6495 /* delete the entry from Flow List */
6496 csr_ll_remove_entry(&pSession->bufferedCommandList, pEntry,
6497 true);
6498 /* reclaim the memory */
6499 pcmd = GET_BASE_ADDR(pEntry, sme_QosCmdInfoEntry, link);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306500 qdf_mem_free(pcmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006501 pEntry = pNextEntry;
6502 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306503 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006504}
6505
6506/**
6507 * sme_qos_save_assoc_info() - save assoc info.
6508 * @pSession: pointer to QOS session
6509 * @pAssoc_info: pointer to the assoc structure to store the BSS descriptor
6510 * of the AP, the profile that HDD sent down with the
6511 * connect request
6512 *
6513 * Utility function to save the assoc info in the CB like BSS descriptor
6514 * of the AP, the profile that HDD sent down with the connect request,
6515 * while CSR notifies for assoc/reassoc success.
6516 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306517 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006518 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306519QDF_STATUS sme_qos_save_assoc_info(sme_QosSessionInfo *pSession,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006520 sme_QosAssocInfo *pAssoc_info)
6521{
6522 tSirBssDescription *pBssDesc = NULL;
6523 uint32_t bssLen = 0;
6524 if (NULL == pAssoc_info) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306525 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006526 "%s: %d: pAssoc_info is NULL", __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306527 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006528 }
6529 /* clean up the assoc info if already set */
6530 if (pSession->assocInfo.pBssDesc) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306531 qdf_mem_free(pSession->assocInfo.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006532 pSession->assocInfo.pBssDesc = NULL;
6533 }
6534 bssLen = pAssoc_info->pBssDesc->length +
6535 sizeof(pAssoc_info->pBssDesc->length);
6536 /* save the bss Descriptor */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306537 pBssDesc = (tSirBssDescription *) qdf_mem_malloc(bssLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006538 if (!pBssDesc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306539 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006540 "%s: %d: couldn't allocate memory for the bss Descriptor",
6541 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306542 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006543 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306544 qdf_mem_copy(pBssDesc, pAssoc_info->pBssDesc, bssLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006545 pSession->assocInfo.pBssDesc = pBssDesc;
6546 /* save the apsd info from assoc */
6547 if (pAssoc_info->pProfile) {
6548 pSession->apsdMask |= pAssoc_info->pProfile->uapsd_mask;
6549 }
6550 /* [TODO] Do we need to update the global APSD bitmap? */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306551 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006552}
6553
6554/*--------------------------------------------------------------------------
6555 \brief sme_qos_setup_fnp() - Utility function (pointer) to notify other entries
6556 in FLOW list on the same AC that qos params got modified
6557 \param pMac - Pointer to the global MAC parameter structure.
6558 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6559
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306560 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006561
6562 \sa
6563
6564 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306565QDF_STATUS sme_qos_setup_fnp(tpAniSirGlobal pMac, tListElem *pEntry)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006566{
6567 sme_QosSessionInfo *pSession;
6568 sme_QosACInfo *pACInfo;
6569 sme_QosFlowInfoEntry *flow_info = NULL;
6570 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
6571 sme_QosEdcaAcType ac;
6572 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306573 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006574 "%s: %d: Entry is NULL", __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306575 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306576 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006577 }
6578 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
6579 ac = flow_info->ac_type;
6580 pSession = &sme_qos_cb.sessionInfo[flow_info->sessionId];
6581 pACInfo = &pSession->ac_info[ac];
6582 if (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) {
6583 /* notify HDD, only the other Flows running on the AC */
6584 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6585 &pACInfo->curr_QoSInfo[flow_info->
6586 tspec_mask - 1],
6587 hdd_status, flow_info->QosFlowID);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306588 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006589 "%s: %d: Entry with flowID = %d getting notified",
6590 __func__, __LINE__, flow_info->QosFlowID);
6591 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306592 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006593}
6594
6595/*--------------------------------------------------------------------------
6596 \brief sme_qos_modification_notify_fnp() - Utility function (pointer) to notify
6597 other entries in FLOW list on the same AC that qos params got modified
6598 \param pMac - Pointer to the global MAC parameter structure.
6599 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6600
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306601 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602
6603 \sa
6604
6605 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306606QDF_STATUS sme_qos_modification_notify_fnp(tpAniSirGlobal pMac, tListElem *pEntry)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006607{
6608 sme_QosSessionInfo *pSession;
6609 sme_QosACInfo *pACInfo;
6610 sme_QosFlowInfoEntry *flow_info = NULL;
6611 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
6612 sme_QosEdcaAcType ac;
6613 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306614 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006615 "%s: %d: Entry is NULL", __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306616 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306617 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618 }
6619 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
6620 ac = flow_info->ac_type;
6621 pSession = &sme_qos_cb.sessionInfo[flow_info->sessionId];
6622 pACInfo = &pSession->ac_info[ac];
6623 if (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) {
6624 /* notify HDD, only the other Flows running on the AC */
6625 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6626 &pACInfo->curr_QoSInfo[flow_info->
6627 tspec_mask - 1],
6628 hdd_status, flow_info->QosFlowID);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306629 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006630 "%s: %d: Entry with flowID = %d getting notified",
6631 __func__, __LINE__, flow_info->QosFlowID);
6632 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306633 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006634}
6635
6636/*--------------------------------------------------------------------------
6637 \brief sme_qos_modify_fnp() - Utility function (pointer) to delete the origianl
6638 entry in FLOW list & add the modified one
6639 \param pMac - Pointer to the global MAC parameter structure.
6640 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6641
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306642 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006643
6644 \sa
6645
6646 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306647QDF_STATUS sme_qos_modify_fnp(tpAniSirGlobal pMac, tListElem *pEntry)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006648{
6649 sme_QosFlowInfoEntry *flow_info = NULL;
6650 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306651 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006652 "%s: %d: Entry is NULL", __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306653 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306654 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006655 }
6656 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
6657 switch (flow_info->reason) {
6658 case SME_QOS_REASON_MODIFY_PENDING:
6659 /* set the proper reason code for the new (with modified params) entry */
6660 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6661 break;
6662 case SME_QOS_REASON_MODIFY:
6663 /* delete the original entry from Flow List */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306664 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006665 "%s: %d: Deleting original entry at %p with flowID %d",
6666 __func__, __LINE__, flow_info, flow_info->QosFlowID);
6667 csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry, true);
6668 /* reclaim the memory */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306669 qdf_mem_free(flow_info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006670 break;
6671 default:
6672 break;
6673 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306674 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006675}
6676
6677/*--------------------------------------------------------------------------
6678 \brief sme_qos_del_ts_ind_fnp() - Utility function (pointer) to find all Flows on
6679 the perticular AC & delete them, also send HDD indication through the callback
6680 it registered per request
6681 \param pMac - Pointer to the global MAC parameter structure.
6682 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6683
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306684 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006685
6686 \sa
6687
6688 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306689QDF_STATUS sme_qos_del_ts_ind_fnp(tpAniSirGlobal pMac, tListElem *pEntry)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006690{
6691 sme_QosSessionInfo *pSession;
6692 sme_QosACInfo *pACInfo;
6693 sme_QosFlowInfoEntry *flow_info = NULL;
6694 sme_QosEdcaAcType ac;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306695 QDF_STATUS lock_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006696 sme_QosStatusType status;
6697
6698 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306699 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006700 "%s: %d: Entry is NULL", __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306701 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306702 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703 }
6704 /* delete the entry from Flow List */
6705 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
6706 ac = flow_info->ac_type;
6707 pSession = &sme_qos_cb.sessionInfo[flow_info->sessionId];
6708 pACInfo = &pSession->ac_info[ac];
6709 pACInfo->relTrig = SME_QOS_RELEASE_BY_AP;
6710
6711 lock_status = sme_acquire_global_lock(&pMac->sme);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306712 if (!QDF_IS_STATUS_SUCCESS(lock_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306713 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006714 "%s: %d: Unable to obtain lock", __func__, __LINE__);
6715 return SME_QOS_STATUS_RELEASE_FAILURE_RSP;
6716 }
6717 /* Call the internal function for QoS release, adding a layer of abstraction */
6718 status =
6719 sme_qos_internal_release_req(pMac, flow_info->QosFlowID, false);
6720 sme_release_global_lock(&pMac->sme);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306721 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006722 "%s: %d: QoS Release return status on Flow %d is %d",
6723 __func__, __LINE__, flow_info->QosFlowID, status);
6724
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306725 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006726}
6727
6728/**
6729 * sme_qos_reassoc_success_ev_fnp Notification function to HDD
6730 *
6731 * @mac_ctx: Mac context
6732 * @entry: Pointer to an entry in the flow_list
6733 *
6734 * Utility function (pointer) to notify HDD
6735 * the success for the requested flow & notify all the other flows
6736 * running on the same AC that QoS params got modified
6737 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306738 * Return: QDF_STATUS enumaration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006739 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306740QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006741sme_qos_reassoc_success_ev_fnp(tpAniSirGlobal mac_ctx,
6742 tListElem *entry)
6743{
6744 sme_QosSessionInfo *qos_session;
6745 sme_QosACInfo *ac_info;
6746 sme_QosFlowInfoEntry *flow_info = NULL;
6747 bool delete_entry = false;
6748 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6749 sme_QosEdcaAcType ac;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306750 QDF_STATUS pmc_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006751 if (!entry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306752 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006753 "%s: %d: Entry is NULL", __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306754 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306755 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006756 }
6757 flow_info = GET_BASE_ADDR(entry, sme_QosFlowInfoEntry, link);
6758 ac = flow_info->ac_type;
6759 qos_session = &sme_qos_cb.sessionInfo[flow_info->sessionId];
6760 ac_info = &qos_session->ac_info[ac];
6761 switch (flow_info->reason) {
6762 case SME_QOS_REASON_SETUP:
6763 hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND;
6764 delete_entry = false;
6765 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6766 /* -Check for the case where we had to do reassoc to
6767 * reset the apsd bit for the ac - release or modify
6768 * scenario.Notify PMC as App is looking for APSD
6769 * If we already requested then we don't need to
6770 * do anything.*/
6771 if (ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb &&
6772 !qos_session->uapsdAlreadyRequested) {
6773 /* this is the first flow to detect we need
6774 * PMC in UAPSD mode */
6775 pmc_status = sme_ps_start_uapsd(mac_ctx,
6776 flow_info->sessionId,
6777 sme_qos_pmc_offload_start_uapsd_callback,
6778 qos_session);
6779 /* if PMC doesn't return success right away means
6780 * it is yet to put the module in BMPS state & later
6781 * to UAPSD state */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306782 if (QDF_STATUS_E_FAILURE == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006783 hdd_status =
6784 SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED;
6785 /* we need to always notify this case */
6786 flow_info->hoRenewal = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306787 } else if (QDF_STATUS_PMC_PENDING == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006788 /* let other flows know PMC has been notified */
6789 qos_session->uapsdAlreadyRequested =
6790 true;
6791
6792 }
6793 }
6794 /* for any other pmc status we declare success */
6795 break;
6796 case SME_QOS_REASON_RELEASE:
6797 ac_info->num_flows[SME_QOS_TSPEC_INDEX_0]--;
6798 /* fall through */
6799 case SME_QOS_REASON_MODIFY:
6800 delete_entry = true;
6801 break;
6802 case SME_QOS_REASON_MODIFY_PENDING:
6803 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND;
6804 delete_entry = false;
6805 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6806 if (ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb &&
6807 !qos_session->uapsdAlreadyRequested) {
6808 /* this is the first flow to detect we need
6809 * PMC in UAPSD mode */
6810 pmc_status = sme_ps_start_uapsd(mac_ctx,
6811 flow_info->sessionId,
6812 sme_qos_pmc_offload_start_uapsd_callback,
6813 qos_session);
6814 /* if PMC doesn't return success right away means
6815 * it is yet to put the module in BMPS state &
6816 * later to UAPSD state */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306817 if (QDF_STATUS_E_FAILURE == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006818 hdd_status =
6819 SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED;
6820 /* we need to always notify this case */
6821 flow_info->hoRenewal = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306822 } else if (QDF_STATUS_PMC_PENDING == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006823 qos_session->uapsdAlreadyRequested =
6824 true;
6825 }
6826 }
6827 /* for any other pmc status we declare success */
6828 break;
6829 case SME_QOS_REASON_REQ_SUCCESS:
6830 hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
6831 /* fall through */
6832 default:
6833 delete_entry = false;
6834 break;
6835 }
6836 if (!delete_entry) {
6837 if (!flow_info->hoRenewal) {
6838 flow_info->QoSCallback(mac_ctx, flow_info->HDDcontext,
6839 &ac_info->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0],
6840 hdd_status, flow_info->QosFlowID);
6841 } else {
6842 flow_info->hoRenewal = false;
6843 }
6844 } else {
6845 /* delete the entry from Flow List */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306846 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006847 FL("Deleting entry at %p with flowID %d"),
6848 flow_info, flow_info->QosFlowID);
6849 csr_ll_remove_entry(&sme_qos_cb.flow_list, entry, true);
6850 /* reclaim the memory */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306851 qdf_mem_free(flow_info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006852 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306853 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006854}
6855
6856/*--------------------------------------------------------------------------
6857 \brief sme_qos_add_ts_failure_fnp() - Utility function (pointer),
6858 if the Addts request was for for an flow setup request, delete the entry from
6859 Flow list & notify HDD
6860 if the Addts request was for downgrading of QoS params because of an flow
6861 release requested on the AC, delete the entry from Flow list & notify HDD
6862 if the Addts request was for change of QoS params because of an flow
6863 modification requested on the AC, delete the new entry from Flow list & notify
6864 HDD
6865
6866 \param pMac - Pointer to the global MAC parameter structure.
6867 \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure)
6868
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306869 \return QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006870
6871 \sa
6872
6873 --------------------------------------------------------------------------*/
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306874QDF_STATUS sme_qos_add_ts_failure_fnp(tpAniSirGlobal pMac, tListElem *pEntry)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006875{
6876 sme_QosSessionInfo *pSession;
6877 sme_QosACInfo *pACInfo;
6878 sme_QosFlowInfoEntry *flow_info = NULL;
6879 bool inform_hdd = false;
6880 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6881 sme_QosEdcaAcType ac;
6882 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306883 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006884 "%s: %d: Entry is NULL", __func__, __LINE__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306885 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306886 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006887 }
6888 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
6889 ac = flow_info->ac_type;
6890 pSession = &sme_qos_cb.sessionInfo[flow_info->sessionId];
6891 pACInfo = &pSession->ac_info[ac];
6892 switch (flow_info->reason) {
6893 case SME_QOS_REASON_SETUP:
6894 hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6895 pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
6896 inform_hdd = true;
6897 break;
6898 case SME_QOS_REASON_RELEASE:
6899 hdd_status = SME_QOS_STATUS_RELEASE_FAILURE_RSP;
6900 pACInfo->num_flows[pACInfo->tspec_pending - 1]--;
6901 inform_hdd = true;
6902 break;
6903 case SME_QOS_REASON_MODIFY_PENDING:
6904 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
6905 inform_hdd = true;
6906 break;
6907 case SME_QOS_REASON_MODIFY:
6908 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
6909 case SME_QOS_REASON_REQ_SUCCESS:
6910 default:
6911 inform_hdd = false;
6912 break;
6913 }
6914 if (inform_hdd) {
6915 /* notify HDD, only the requested Flow, other Flows running on the AC stay */
6916 /* intact */
6917 if (!flow_info->hoRenewal) {
6918 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6919 &pACInfo->curr_QoSInfo[pACInfo->
6920 tspec_pending
6921 - 1],
6922 hdd_status,
6923 flow_info->QosFlowID);
6924 } else {
6925 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
6926 &pACInfo->curr_QoSInfo[pACInfo->
6927 tspec_pending
6928 - 1],
6929 SME_QOS_STATUS_RELEASE_QOS_LOST_IND,
6930 flow_info->QosFlowID);
6931 }
6932 /* delete the entry from Flow List */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306933 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006934 "%s: %d: Deleting entry at %p with flowID %d",
6935 __func__, __LINE__, flow_info, flow_info->QosFlowID);
6936 csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry, true);
6937 /* reclaim the memory */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306938 qdf_mem_free(flow_info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006939 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306940 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006941}
6942
6943/**
6944 * sme_qos_add_ts_success_fnp() - Utility function (pointer) to notify HDD
6945 *
6946 * @mac_ctx: Mac context
6947 * @entry: Pointer to an entry in the flow_list(i.e. tListElem structure).
6948 *
6949 * Description : Utility function (pointer),
6950 * If the Addts request was for for an flow setup request, notify
6951 * HDD for success for the flow & notify all the other flows running
6952 * on the same AC that QoS params got modified
6953 * if the Addts request was for downgrading of QoS params
6954 * because of an flow release requested on the AC, delete
6955 * the entry from Flow list & notify HDD if the Addts request
6956 * was for change of QoS params because of an flow modification
6957 * requested on the AC, delete the old entry from Flow list & notify
6958 * HDD for success for the flow & notify all the other flows running
6959 * on the same AC that QoS params got modified
6960 *
6961 * Return: Status
6962 */
6963
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306964QDF_STATUS sme_qos_add_ts_success_fnp(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006965 tListElem *entry)
6966{
6967 sme_QosSessionInfo *qos_session;
6968 sme_QosACInfo *ac_info;
6969 sme_QosFlowInfoEntry *flow_info = NULL;
6970 bool inform_hdd = false;
6971 bool delete_entry = false;
6972 sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP;
6973 sme_QosEdcaAcType ac;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306974 QDF_STATUS pmc_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006975 tCsrRoamModifyProfileFields profile_fields;
6976 uint8_t psb;
6977 uint8_t tspec_index;
6978
6979 if (!entry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306980 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006981 FL("Entry is NULL"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306982 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306983 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006984 }
6985 flow_info = GET_BASE_ADDR(entry, sme_QosFlowInfoEntry, link);
6986 ac = flow_info->ac_type;
6987 qos_session = &sme_qos_cb.sessionInfo[flow_info->sessionId];
6988 ac_info = &qos_session->ac_info[ac];
6989 tspec_index = ac_info->tspec_pending - 1;
6990 if (flow_info->tspec_mask != ac_info->tspec_pending) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306991 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006992 FL(" No need to notify the HDD, the ADDTS "
6993 "success is not for index = %d of the AC = %d"),
6994 flow_info->tspec_mask, ac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306995 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006996 }
6997 switch (flow_info->reason) {
6998 case SME_QOS_REASON_SETUP:
6999 hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND;
7000 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
7001 delete_entry = false;
7002 inform_hdd = true;
7003 /* check if App is looking for APSD
7004 * notify PMC as App is looking for APSD. If we already
7005 * requested then we don't need to do anything */
7006 if (ac_info->requested_QoSInfo[tspec_index].ts_info.psb &&
7007 !qos_session->uapsdAlreadyRequested) {
7008 /* this is the first flow to detect we need
7009 * PMC in UAPSD mode */
7010 pmc_status = sme_ps_start_uapsd(mac_ctx,
7011 flow_info->sessionId,
7012 sme_qos_pmc_offload_start_uapsd_callback,
7013 qos_session);
7014 /* if PMC doesn't return success right away means
7015 * it is yet to put the module in BMPS state & later
7016 * to UAPSD state */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307017 if (QDF_STATUS_E_FAILURE == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007018 hdd_status =
7019 SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED;
7020 /* we need to always notify this case */
7021 flow_info->hoRenewal = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307022 } else if (QDF_STATUS_PMC_PENDING == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007023 /* let other flows know PMC has been notified */
7024 qos_session->uapsdAlreadyRequested =
7025 true;
7026 }
7027 /* for any other pmc status we declare success */
7028 }
7029 break;
7030 case SME_QOS_REASON_RELEASE:
7031 ac_info->num_flows[tspec_index]--;
7032 hdd_status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP;
7033 inform_hdd = true;
7034 delete_entry = true;
7035 break;
7036 case SME_QOS_REASON_MODIFY:
7037 delete_entry = true;
7038 inform_hdd = false;
7039 break;
7040 case SME_QOS_REASON_MODIFY_PENDING:
7041 hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND;
7042 delete_entry = false;
7043 flow_info->reason = SME_QOS_REASON_REQ_SUCCESS;
7044 inform_hdd = true;
7045 psb = ac_info->requested_QoSInfo[tspec_index].ts_info.psb;
7046 /* notify PMC if App is looking for APSD
7047 * notify PMC as App is looking for APSD. If we already
7048 * requested then we don't need to do anything. */
7049 if (psb && !qos_session->uapsdAlreadyRequested) {
7050 /* this is the first flow to detect
7051 * we need PMC in UAPSD mode */
7052 pmc_status =
7053 sme_ps_start_uapsd(mac_ctx,
7054 flow_info->sessionId,
7055 sme_qos_pmc_offload_start_uapsd_callback,
7056 qos_session);
7057 /* if PMC doesn't return success right
7058 * away means it is yet to put
7059 * the module in BMPS state & later to UAPSD state */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307060 if (QDF_STATUS_E_FAILURE == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007061 hdd_status =
7062 SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED;
7063 /* we need to always notify this case */
7064 flow_info->hoRenewal = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307065 } else if (QDF_STATUS_PMC_PENDING == pmc_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007066 /* let other flows know PMC has been notified */
7067 qos_session->uapsdAlreadyRequested =
7068 true;
7069 }
7070 /* for any other pmc status we declare success */
7071 } else if (!psb &&
7072 ((ac_info->num_flows[flow_info->tspec_mask - 1] == 1)
7073 && (SME_QOS_TSPEC_MASK_BIT_1_2_SET !=
7074 ac_info->tspec_mask_status))) {
7075 /* this is the only TSPEC active on this AC */
7076 /* so indicate that we no longer require APSD */
7077 qos_session->apsdMask &=
7078 ~(1 << (SME_QOS_EDCA_AC_VO - ac));
7079 /* Also update modifyProfileFields.uapsd_mask
7080 * in CSR for consistency */
7081 csr_get_modify_profile_fields(mac_ctx,
7082 flow_info->sessionId,
7083 &profile_fields);
7084 profile_fields.uapsd_mask =
7085 qos_session->apsdMask;
7086 csr_set_modify_profile_fields(mac_ctx,
7087 flow_info->sessionId,
7088 &profile_fields);
7089 if (!qos_session->apsdMask) {
7090 sme_ps_uapsd_disable(mac_ctx,
7091 flow_info->sessionId);
7092 }
7093 }
7094 break;
7095 case SME_QOS_REASON_REQ_SUCCESS:
7096 hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND;
7097 inform_hdd = true;
7098 default:
7099 delete_entry = false;
7100 break;
7101 }
7102 if (inform_hdd) {
7103 if (!flow_info->hoRenewal) {
7104 flow_info->QoSCallback(mac_ctx, flow_info->HDDcontext,
7105 &ac_info->curr_QoSInfo[tspec_index],
7106 hdd_status,
7107 flow_info->QosFlowID);
7108 } else {
7109 flow_info->hoRenewal = false;
7110 }
7111 }
7112 if (delete_entry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307113 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007114 FL("Deleting entry at %p with flowID %d"),
7115 flow_info, flow_info->QosFlowID);
7116 /* delete the entry from Flow List */
7117 csr_ll_remove_entry(&sme_qos_cb.flow_list, entry, true);
7118 /* reclaim the memory */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307119 qdf_mem_free(flow_info);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007120 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307121 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007122}
7123
7124/*--------------------------------------------------------------------------
7125 \brief sme_qos_is_rsp_pending() - Utility function to check if we are waiting
7126 for an AddTS or reassoc response on some AC other than the given AC
7127
7128 \param sessionId - Session we are interted in
7129 \param ac - Enumeration of the various EDCA Access Categories.
7130
7131 \return bool
7132 true - Response is pending on an AC
7133
7134 \sa
7135
7136 --------------------------------------------------------------------------*/
7137static bool sme_qos_is_rsp_pending(uint8_t sessionId, sme_QosEdcaAcType ac)
7138{
7139 sme_QosSessionInfo *pSession;
7140 sme_QosACInfo *pACInfo;
7141 sme_QosEdcaAcType acIndex;
7142 bool status = false;
7143 pSession = &sme_qos_cb.sessionInfo[sessionId];
7144 for (acIndex = SME_QOS_EDCA_AC_BE; acIndex < SME_QOS_EDCA_AC_MAX;
7145 acIndex++) {
7146 if (acIndex == ac) {
7147 continue;
7148 }
7149 pACInfo = &pSession->ac_info[acIndex];
7150 if ((pACInfo->tspec_pending) || (pACInfo->reassoc_pending)) {
7151 status = true;
7152 break;
7153 }
7154 }
7155 return status;
7156}
7157
7158/*--------------------------------------------------------------------------
7159 \brief sme_qos_update_hand_off() - Function which can be called to update
7160 Hand-off state of SME QoS Session
7161 \param sessionId - session id
7162 \param updateHandOff - value True/False to update the handoff flag
7163
7164 \sa
7165
7166 -------------------------------------------------------------------------*/
7167void sme_qos_update_hand_off(uint8_t sessionId, bool updateHandOff)
7168{
7169 sme_QosSessionInfo *pSession;
7170 pSession = &sme_qos_cb.sessionInfo[sessionId];
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307171 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007172 "%s: %d: handoffRequested %d updateHandOff %d",
7173 __func__, __LINE__, pSession->handoffRequested,
7174 updateHandOff);
7175
7176 pSession->handoffRequested = updateHandOff;
7177
7178}
7179
7180/*--------------------------------------------------------------------------
7181 \brief sme_qos_is_uapsd_active() - Function which can be called to determine
7182 if any sessions require PMC to be in U-APSD mode.
7183 \return bool
7184
7185 Returns true if at least one session required PMC to be in U-APSD mode
7186 Returns false if no sessions require PMC to be in U-APSD mode
7187
7188 \sa
7189
7190 --------------------------------------------------------------------------*/
7191static bool sme_qos_is_uapsd_active(void)
7192{
7193 sme_QosSessionInfo *pSession;
7194 uint8_t sessionId;
7195 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) {
7196 pSession = &sme_qos_cb.sessionInfo[sessionId];
7197 if ((pSession->sessionActive) && (pSession->apsdMask)) {
7198 return true;
7199 }
7200 }
7201 /* no active sessions have U-APSD active */
7202 return false;
7203}
7204
7205/*--------------------------------------------------------------------------
7206 \brief sme_QosPmcStartUAPSDCallback() - Callback function registered with PMC
7207 to notify SME-QoS when it puts the chip into UAPSD mode
7208
7209 \param callbackContext - The context passed to PMC during pmc_start_uapsd call.
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307210 \param status - QDF_STATUS returned by PMC.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007211
7212 \return None
7213
7214 \sa
7215
7216 --------------------------------------------------------------------------*/
7217void sme_qos_pmc_offload_start_uapsd_callback(void *callbackContext,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307218 uint32_t sessionId, QDF_STATUS status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007219{
7220 sme_QosSessionInfo *pSession = callbackContext;
7221 pSession->uapsdAlreadyRequested = false;
7222}
7223
7224bool sme_qos_pmc_offload_check_routine(void *callbackContext, uint32_t sessionId)
7225{
7226 sme_QosSessionInfo *pSession = &sme_qos_cb.sessionInfo[sessionId];
7227
7228 if ((pSession->sessionActive) && (!pSession->readyForPowerSave)) {
7229 return false;
7230 }
7231 return true;
7232
7233}
7234
7235
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307236QDF_STATUS sme_offload_qos_process_out_of_uapsd_mode(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007237 uint32_t sessionId)
7238{
7239 sme_QosSessionInfo *pSession;
7240 tListElem *pEntry = NULL, *pNextEntry = NULL;
7241 sme_QosFlowInfoEntry *flow_info = NULL;
7242
7243 pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
7244 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307245 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007246 "%s: %d: Flow List empty, can't search",
7247 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307248 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007249 }
7250 while (pEntry) {
7251 pNextEntry = csr_ll_next(&sme_qos_cb.flow_list, pEntry, false);
7252 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
7253 pSession = &sme_qos_cb.sessionInfo[flow_info->sessionId];
7254 /* only notify the flows which already successfully setup UAPSD */
7255 if ((sessionId == flow_info->sessionId) &&
7256 (flow_info->QoSInfo.max_service_interval ||
7257 flow_info->QoSInfo.min_service_interval) &&
7258 (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)) {
7259 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
7260 &pSession->ac_info[flow_info->
7261 ac_type].curr_QoSInfo
7262 [flow_info->tspec_mask - 1],
7263 SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND,
7264 flow_info->QosFlowID);
7265 }
7266 pEntry = pNextEntry;
7267 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307268 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007269}
7270
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307271QDF_STATUS sme_offload_qos_process_into_uapsd_mode(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007272 uint32_t sessionId)
7273{
7274 sme_QosSessionInfo *pSession;
7275 tListElem *pEntry = NULL, *pNextEntry = NULL;
7276 sme_QosFlowInfoEntry *flow_info = NULL;
7277
7278 pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, false);
7279 if (!pEntry) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307280 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007281 "%s: %d: Flow List empty, can't search",
7282 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307283 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007284 }
7285 while (pEntry) {
7286 pNextEntry = csr_ll_next(&sme_qos_cb.flow_list, pEntry, false);
7287 flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link);
7288 pSession = &sme_qos_cb.sessionInfo[flow_info->sessionId];
7289 /* only notify the flows which already successfully setup UAPSD */
7290 if ((sessionId == flow_info->sessionId) &&
7291 (flow_info->QoSInfo.max_service_interval ||
7292 flow_info->QoSInfo.min_service_interval) &&
7293 (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)) {
7294 flow_info->QoSCallback(pMac, flow_info->HDDcontext,
7295 &pSession->ac_info[flow_info->
7296 ac_type].curr_QoSInfo
7297 [flow_info->tspec_mask - 1],
7298 SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND,
7299 flow_info->QosFlowID);
7300 }
7301 pEntry = pNextEntry;
7302 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307303 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007304}
7305
7306void sme_qos_cleanup_ctrl_blk_for_handoff(tpAniSirGlobal pMac, uint8_t sessionId)
7307{
7308 sme_QosSessionInfo *pSession;
7309 sme_QosACInfo *pACInfo;
7310 sme_QosEdcaAcType ac;
7311 pSession = &sme_qos_cb.sessionInfo[sessionId];
7312 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
7313 pACInfo = &pSession->ac_info[ac];
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307314 qdf_mem_zero(pACInfo->curr_QoSInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007315 sizeof(sme_QosWmmTspecInfo) *
7316 SME_QOS_TSPEC_INDEX_MAX);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307317 qdf_mem_zero(pACInfo->requested_QoSInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007318 sizeof(sme_QosWmmTspecInfo) *
7319 SME_QOS_TSPEC_INDEX_MAX);
7320 pACInfo->num_flows[0] = 0;
7321 pACInfo->num_flows[1] = 0;
7322 pACInfo->reassoc_pending = false;
7323 pACInfo->tspec_mask_status = 0;
7324 pACInfo->tspec_pending = false;
7325 pACInfo->hoRenewal = false;
7326 pACInfo->prev_state = SME_QOS_LINK_UP;
7327 }
7328}
7329
7330/**
7331 * sme_qos_is_ts_info_ack_policy_valid() - check if ACK policy is allowed.
7332 * @pMac: The handle returned by mac_open.
7333 * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC
7334 * @ related info, provided by HDD
7335 * @sessionId: sessionId returned by sme_open_session.
7336 *
7337 * The SME QoS API exposed to HDD to check if TS info ack policy field can be
7338 * set to "HT-immediate block acknowledgement"
7339 *
7340 * Return: true - Current Association is HT association and so TS info ack
7341 * policy can be set to "HT-immediate block acknowledgement"
7342 */
7343bool sme_qos_is_ts_info_ack_policy_valid(tpAniSirGlobal pMac,
7344 sme_QosWmmTspecInfo *pQoSInfo,
7345 uint8_t sessionId)
7346{
7347 tDot11fBeaconIEs *pIes = NULL;
7348 sme_QosSessionInfo *pSession;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307349 QDF_STATUS hstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007350 if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307351 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007352 "%s: %d: Session Id %d is invalid",
7353 __func__, __LINE__, sessionId);
7354 return false;
7355 }
7356
7357 pSession = &sme_qos_cb.sessionInfo[sessionId];
7358
7359 if (!pSession->sessionActive) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307360 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007361 "%s: %d: Session %d is inactive",
7362 __func__, __LINE__, sessionId);
7363 return false;
7364 }
7365
7366 if (!pSession->assocInfo.pBssDesc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307367 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007368 "%s: %d: Session %d has an Invalid BSS Descriptor",
7369 __func__, __LINE__, sessionId);
7370 return false;
7371 }
7372
7373 hstatus = csr_get_parsed_bss_description_ies(pMac,
7374 pSession->assocInfo.pBssDesc,
7375 &pIes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307376 if (!QDF_IS_STATUS_SUCCESS(hstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307377 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007378 "%s: %d: On session %d unable to parse BSS IEs",
7379 __func__, __LINE__, sessionId);
7380 return false;
7381 }
7382
7383 /* success means pIes was allocated */
7384
7385 if (!pIes->HTCaps.present &&
7386 pQoSInfo->ts_info.ack_policy ==
7387 SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307388 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007389 "%s: %d: On session %d HT Caps aren't present but application set ack policy to HT ",
7390 __func__, __LINE__, sessionId);
7391
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307392 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007393 return false;
7394 }
7395
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307396 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007397 return true;
7398}
7399
7400bool sme_qos_validate_requested_params(tpAniSirGlobal pMac,
7401 sme_QosWmmTspecInfo *pQoSInfo,
7402 uint8_t sessionId)
7403{
7404 bool rc = false;
7405
7406 do {
7407 if (SME_QOS_WMM_TS_DIR_RESV == pQoSInfo->ts_info.direction)
7408 break;
7409 if (!sme_qos_is_ts_info_ack_policy_valid(pMac, pQoSInfo, sessionId))
7410 break;
7411
7412 rc = true;
7413 } while (0);
7414 return rc;
7415}
7416
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307417static QDF_STATUS qos_issue_command(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007418 eSmeCommandType cmdType,
7419 sme_QosWmmTspecInfo *pQoSInfo,
7420 sme_QosEdcaAcType ac, uint8_t tspec_mask)
7421{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307422 QDF_STATUS status = QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007423 tSmeCmd *pCommand = NULL;
7424 do {
7425 pCommand = sme_get_command_buffer(pMac);
7426 if (!pCommand) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307427 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007428 "%s: %d: fail to get command buffer for command %d",
7429 __func__, __LINE__, cmdType);
7430 break;
7431 }
7432 pCommand->command = cmdType;
7433 pCommand->sessionId = sessionId;
7434 switch (cmdType) {
7435 case eSmeCommandAddTs:
7436 if (pQoSInfo) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307437 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007438 pCommand->u.qosCmd.tspecInfo = *pQoSInfo;
7439 pCommand->u.qosCmd.ac = ac;
7440 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307441 QDF_TRACE(QDF_MODULE_ID_SME,
7442 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007443 "%s: %d: NULL pointer passed",
7444 __func__, __LINE__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307445 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007446 }
7447 break;
7448 case eSmeCommandDelTs:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307449 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007450 pCommand->u.qosCmd.ac = ac;
7451 pCommand->u.qosCmd.tspec_mask = tspec_mask;
7452 break;
7453 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307454 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007455 "%s: %d: invalid command type %d",
7456 __func__, __LINE__, cmdType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307457 status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007458 break;
7459 }
7460 } while (0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307461 if (QDF_IS_STATUS_SUCCESS(status) && pCommand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007462 sme_push_command(pMac, pCommand, false);
7463 } else if (pCommand) {
7464 qos_release_command(pMac, pCommand);
7465 }
7466 return status;
7467}
7468
7469bool qos_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand)
7470{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307471 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007472 bool fRemoveCmd = true;
7473 do {
7474 switch (pCommand->command) {
7475 case eSmeCommandAddTs:
7476 status =
7477 sme_qos_add_ts_req(pMac, (uint8_t) pCommand->sessionId,
7478 &pCommand->u.qosCmd.tspecInfo,
7479 pCommand->u.qosCmd.ac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307480 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007481 fRemoveCmd = false;
7482 status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP;
7483 }
7484 break;
7485 case eSmeCommandDelTs:
7486 status =
7487 sme_qos_del_ts_req(pMac, (uint8_t) pCommand->sessionId,
7488 pCommand->u.qosCmd.ac,
7489 pCommand->u.qosCmd.tspec_mask);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307490 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007491 fRemoveCmd = false;
7492 }
7493 break;
7494 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307495 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007496 "%s: %d: invalid command type %d",
7497 __func__, __LINE__, pCommand->command);
7498 break;
7499 } /* switch */
7500 } while (0);
7501 return fRemoveCmd;
7502}
7503
7504/**
7505 * sme_qos_re_request_add_ts - Re-send AddTS for the combined QoS request
7506 *
7507 * @mac_ctx Pointer to mac context
7508 * @session_id SME session id
7509 * @qos_info - Tspec information
7510 * @ac - Access category
7511 * @tspec_mask - Tspec Mask
7512 *
7513 * This function is called to re-send AddTS for the combined QoS request
7514 *
7515 * Return: status
7516 */
7517static
7518sme_QosStatusType sme_qos_re_request_add_ts(tpAniSirGlobal mac_ctx,
7519 uint8_t session_id, sme_QosWmmTspecInfo *qos_info,
7520 sme_QosEdcaAcType ac, uint8_t tspec_mask)
7521{
7522 sme_QosSessionInfo *session;
7523 sme_QosACInfo *ac_info;
7524 sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
7525 sme_QosCmdInfo cmd;
7526
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307527 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007528 FL(" Invoked on session %d for AC %d TSPEC %d"),
7529 session_id, ac, tspec_mask);
7530 session = &sme_qos_cb.sessionInfo[session_id];
7531 ac_info = &session->ac_info[ac];
7532 /* need to vote off powersave for the duration of this request */
7533 session->readyForPowerSave = false;
7534 /*
7535 * call PMC's request for power function
7536 * AND another check is added considering the flowing scenario
7537 * Addts reqest is pending on one AC, while APSD requested on
7538 * another which needs a reassoc. Will buffer a request if Addts
7539 * is pending on any AC, which will safegaurd the above scenario,
7540 * 2& also won't confuse PE with back to back Addts or Addts
7541 * followed by Reassoc.
7542 */
7543 if (sme_qos_is_rsp_pending(session_id, ac)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307544 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007545 FL(" On session %d buffering the AddTS request "
7546 "for AC %d in state %d as Addts is pending "
7547 "on other AC or waiting for full power"),
7548 session_id, ac,
7549 ac_info->curr_state);
7550 /* buffer cmd */
7551 cmd.command = SME_QOS_RESEND_REQ;
7552 cmd.pMac = mac_ctx;
7553 cmd.sessionId = session_id;
7554 cmd.u.resendCmdInfo.ac = ac;
7555 cmd.u.resendCmdInfo.tspecMask = tspec_mask;
7556 cmd.u.resendCmdInfo.QoSInfo = *qos_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307557 if (!QDF_IS_STATUS_SUCCESS(sme_qos_buffer_cmd(&cmd, false))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307558 QDF_TRACE(QDF_MODULE_ID_SME,
7559 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007560 FL("On session %d unable to buffer the AddTS "
7561 "request for AC %d TSPEC %d in state %d"),
7562 session_id, ac, tspec_mask,
7563 ac_info->curr_state);
7564 /* unable to buffer the request
7565 * nothing is pending so vote powersave back on */
7566 session->readyForPowerSave = true;
7567 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
7568 }
7569 return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
7570 }
7571
7572 /* get into the stat m/c to see if the request can be granted */
7573 switch (ac_info->curr_state) {
7574 case SME_QOS_QOS_ON:
7575 {
7576 /* if ACM, send out a new ADDTS */
7577 ac_info->hoRenewal = true;
7578 status = sme_qos_setup(mac_ctx, session_id, qos_info, ac);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307579 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007580 FL("sme_qos_setup returned in SME_QOS_QOS_ON state"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307581 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007582 FL("sme_qos_setup AC %d with status =%d"), ac, status);
7583 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) {
7584 /* we aren't waiting for a response from the AP */
7585 /* so vote powersave back on */
7586 session->readyForPowerSave = true;
7587 }
7588 if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) {
7589 status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
7590 ac_info->tspec_pending = tspec_mask;
7591 } else if ((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP ==
7592 status) ||
7593 (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY ==
7594 status) ||
7595 (SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING ==
7596 status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307597 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007598 FL("UAPSD is setup already status = %d "),
7599 status);
7600 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307601 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007602 FL("sme_qos_setup return status = %d "),
7603 status);
7604 }
7605 }
7606 break;
7607 case SME_QOS_HANDOFF:
7608 case SME_QOS_REQUESTED:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307609 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007610 FL("Re-Add request in state = %d buffer the request"),
7611 ac_info->curr_state);
7612 cmd.command = SME_QOS_RESEND_REQ;
7613 cmd.pMac = mac_ctx;
7614 cmd.sessionId = session_id;
7615 cmd.u.resendCmdInfo.ac = ac;
7616 cmd.u.resendCmdInfo.tspecMask = tspec_mask;
7617 cmd.u.resendCmdInfo.QoSInfo = *qos_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307618 if (!QDF_IS_STATUS_SUCCESS(sme_qos_buffer_cmd(&cmd, false))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307619 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007620 FL(" couldn't buf the read request state = %d"),
7621 ac_info->curr_state);
7622 /* unable to buffer the request
7623 * nothing is pending so vote powersave back on */
7624 session->readyForPowerSave = true;
7625 return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP;
7626 }
7627 status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP;
7628 break;
7629 case SME_QOS_CLOSED:
7630 case SME_QOS_INIT:
7631 case SME_QOS_LINK_UP:
7632 default:
7633 /* print error msg, */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307634 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007635 FL("ReAdd request in unexpected state = %d"),
7636 ac_info->curr_state);
7637 /* unable to service the request
7638 * nothing is pending so vote powersave back on */
7639 session->readyForPowerSave = true;
7640 break;
7641 }
7642 if ((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP ==
7643 status) ||
7644 (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY ==
7645 status)) {
7646 (void)sme_qos_process_buffered_cmd(session_id);
7647 }
7648 return status;
7649}
7650
7651static void sme_qos_init_a_cs(tpAniSirGlobal pMac, uint8_t sessionId)
7652{
7653 sme_QosSessionInfo *pSession;
7654 sme_QosEdcaAcType ac;
7655 pSession = &sme_qos_cb.sessionInfo[sessionId];
7656 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307657 qdf_mem_zero(&pSession->ac_info[ac], sizeof(sme_QosACInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007658 sme_qos_state_transition(sessionId, ac, SME_QOS_INIT);
7659 }
7660}
7661
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307662static QDF_STATUS sme_qos_request_reassoc(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007663 tCsrRoamModifyProfileFields *
7664 pModFields, bool fForce)
7665{
7666 sme_QosSessionInfo *pSession;
7667 sme_QosACInfo *pACInfo;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307668 QDF_STATUS status;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307669 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007670 "%s: %d: Invoked on session %d with UAPSD mask 0x%X",
7671 __func__, __LINE__, sessionId, pModFields->uapsd_mask);
7672 pSession = &sme_qos_cb.sessionInfo[sessionId];
7673 status =
7674 csr_reassoc(pMac, sessionId, pModFields, &pSession->roamID, fForce);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307675 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007676 /* Update the state to Handoff so subsequent requests are queued until */
7677 /* this one is finished */
7678 sme_QosEdcaAcType ac;
7679 for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) {
7680 pACInfo = &pSession->ac_info[ac];
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307681 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007682 "%s: %d: AC[%d] is in state [%d]",
7683 __func__, __LINE__, ac, pACInfo->curr_state);
7684 /* If it is already in HANDOFF state, don't do anything since we */
7685 /* MUST preserve the previous state and sme_qos_state_transition */
7686 /* will change the previous state */
7687 if (SME_QOS_HANDOFF != pACInfo->curr_state) {
7688 sme_qos_state_transition(sessionId, ac,
7689 SME_QOS_HANDOFF);
7690 }
7691 }
7692 }
7693 return status;
7694}
7695
7696static uint32_t sme_qos_assign_flow_id(void)
7697{
7698 uint32_t flowId;
7699 flowId = sme_qos_cb.nextFlowId;
7700 if (SME_QOS_MAX_FLOW_ID == flowId) {
7701 /* The Flow ID wrapped. This is obviously not a real life scenario */
7702 /* but handle it to keep the software test folks happy */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307703 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007704 "%s: %d: Software Test made the flow counter wrap, "
7705 "QoS may no longer be functional",
7706 __func__, __LINE__);
7707 sme_qos_cb.nextFlowId = SME_QOS_MIN_FLOW_ID;
7708 } else {
7709 sme_qos_cb.nextFlowId++;
7710 }
7711 return flowId;
7712}
7713
7714static uint8_t sme_qos_assign_dialog_token(void)
7715{
7716 uint8_t token;
7717 token = sme_qos_cb.nextDialogToken;
7718 if (SME_QOS_MAX_DIALOG_TOKEN == token) {
7719 /* wrap is ok */
7720 sme_qos_cb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN;
7721 } else {
7722 sme_qos_cb.nextDialogToken++;
7723 }
7724 return token;
7725}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007726#endif /* WLAN_MDM_CODE_REDUCTION_OPT */