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