1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**=========================================================================
21 
22    \brief implementation for PE 11r VoWiFi FT Protocol
23 
24    ========================================================================*/
25 
26 /* $Header$ */
27 
28 /*--------------------------------------------------------------------------
29    Include Files
30    ------------------------------------------------------------------------*/
31 #include <lim_send_messages.h>
32 #include <lim_types.h>
33 #include <lim_ft.h>
34 #include <lim_ft_defs.h>
35 #include <lim_utils.h>
36 #include <lim_prop_exts_utils.h>
37 #include <lim_assoc_utils.h>
38 #include <lim_session.h>
39 #include <lim_admit_control.h>
40 #include <lim_security_utils.h>
41 #include "wmm_apsd.h"
42 #include "wma.h"
43 #include "wlan_cmn.h"
44 
45 /*--------------------------------------------------------------------------
46    Initialize the FT variables.
47    ------------------------------------------------------------------------*/
lim_ft_open(struct mac_context * mac,struct pe_session * pe_session)48 void lim_ft_open(struct mac_context *mac, struct pe_session *pe_session)
49 {
50 	if (pe_session)
51 		qdf_mem_zero(&pe_session->ftPEContext, sizeof(tftPEContext));
52 }
53 
lim_ft_cleanup_all_ft_sessions(struct mac_context * mac)54 void lim_ft_cleanup_all_ft_sessions(struct mac_context *mac)
55 {
56 	/* Wrapper function to cleanup all FT sessions */
57 	int i;
58 
59 	for (i = 0; i < mac->lim.maxBssId; i++) {
60 		if (true == mac->lim.gpSession[i].valid) {
61 			/* The session is valid, may have FT data */
62 			lim_ft_cleanup(mac, &mac->lim.gpSession[i]);
63 		}
64 	}
65 }
66 
lim_ft_cleanup(struct mac_context * mac,struct pe_session * pe_session)67 void lim_ft_cleanup(struct mac_context *mac, struct pe_session *pe_session)
68 {
69 	if (!pe_session) {
70 		pe_err("pe_session is NULL");
71 		return;
72 	}
73 
74 	/* Nothing to be done if the session is not in STA mode */
75 	if (!LIM_IS_STA_ROLE(pe_session)) {
76 		pe_debug("pe_session is not in STA mode");
77 		return;
78 	}
79 
80 	if (pe_session->ftPEContext.pFTPreAuthReq) {
81 		pe_debug("Freeing pFTPreAuthReq: %pK",
82 			       pe_session->ftPEContext.pFTPreAuthReq);
83 		if (NULL !=
84 		    pe_session->ftPEContext.pFTPreAuthReq->
85 		    pbssDescription) {
86 			qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq->
87 				     pbssDescription);
88 			pe_session->ftPEContext.pFTPreAuthReq->
89 			pbssDescription = NULL;
90 		}
91 		qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq);
92 		pe_session->ftPEContext.pFTPreAuthReq = NULL;
93 	}
94 
95 	if (pe_session->ftPEContext.pAddBssReq) {
96 		qdf_mem_free(pe_session->ftPEContext.pAddBssReq);
97 		pe_session->ftPEContext.pAddBssReq = NULL;
98 	}
99 
100 	if (pe_session->ftPEContext.pAddStaReq) {
101 		qdf_mem_free(pe_session->ftPEContext.pAddStaReq);
102 		pe_session->ftPEContext.pAddStaReq = NULL;
103 	}
104 
105 	/* The session is being deleted, cleanup the contents */
106 	qdf_mem_zero(&pe_session->ftPEContext, sizeof(tftPEContext));
107 }
108 
109 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
110 /*------------------------------------------------------------------
111  *
112  * Create the new Add Bss Req to the new AP.
113  * This will be used when we are ready to FT to the new AP.
114  * The newly created ft Session entry is passed to this function
115  *
116  *------------------------------------------------------------------*/
lim_ft_prepare_add_bss_req(struct mac_context * mac,struct pe_session * ft_session,struct bss_description * bssDescription)117 void lim_ft_prepare_add_bss_req(struct mac_context *mac,
118 		struct pe_session *ft_session,
119 		struct bss_description *bssDescription)
120 {
121 	struct bss_params *pAddBssParams = NULL;
122 	tAddStaParams *sta_ctx;
123 	bool chan_width_support = false;
124 	tSchBeaconStruct *pBeaconStruct;
125 	tDot11fIEVHTCaps *vht_caps = NULL;
126 
127 	/* Nothing to be done if the session is not in STA mode */
128 	if (!LIM_IS_STA_ROLE(ft_session)) {
129 		pe_err("pe_session is not in STA mode");
130 		return;
131 	}
132 
133 	pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct));
134 	if (!pBeaconStruct)
135 		return;
136 
137 	/* Package SIR_HAL_ADD_BSS_REQ message parameters */
138 	pAddBssParams = qdf_mem_malloc(sizeof(struct bss_params));
139 	if (!pAddBssParams) {
140 		qdf_mem_free(pBeaconStruct);
141 		return;
142 	}
143 
144 	lim_extract_ap_capabilities(mac, (uint8_t *) bssDescription->ieFields,
145 			lim_get_ielen_from_bss_description(bssDescription),
146 			pBeaconStruct);
147 
148 	if (mac->lim.gLimProtectionControl !=
149 	    MLME_FORCE_POLICY_PROTECTION_DISABLE)
150 		lim_decide_sta_protection_on_assoc(mac, pBeaconStruct,
151 						   ft_session);
152 
153 	qdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId,
154 		     sizeof(tSirMacAddr));
155 	pAddBssParams->beaconInterval = bssDescription->beaconInterval;
156 
157 	pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod;
158 	pAddBssParams->updateBss = false;
159 
160 	pAddBssParams->nwType = bssDescription->nwType;
161 
162 	pAddBssParams->shortSlotTimeSupported =
163 		(uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime;
164 	pAddBssParams->llbCoexist =
165 		(uint8_t) ft_session->beaconParams.llbCoexist;
166 	pAddBssParams->rmfEnabled = ft_session->limRmfEnabled;
167 
168 	/* Use the advertised capabilities from the received beacon/PR */
169 	if (IS_DOT11_MODE_HT(ft_session->dot11mode) &&
170 	    (pBeaconStruct->HTCaps.present)) {
171 		chan_width_support =
172 			lim_get_ht_capability(mac,
173 					      eHT_SUPPORTED_CHANNEL_WIDTH_SET,
174 					      ft_session);
175 		lim_sta_add_bss_update_ht_parameter(bssDescription->chan_freq,
176 						    &pBeaconStruct->HTCaps,
177 						    &pBeaconStruct->HTInfo,
178 						    chan_width_support,
179 						    pAddBssParams);
180 		qdf_mem_copy(&pAddBssParams->staContext.capab_info,
181 			     &pBeaconStruct->capabilityInfo,
182 			     sizeof(pAddBssParams->staContext.capab_info));
183 		qdf_mem_copy(&pAddBssParams->staContext.ht_caps,
184 			     (uint8_t *) &pBeaconStruct->HTCaps +
185 			     sizeof(uint8_t),
186 			     sizeof(pAddBssParams->staContext.ht_caps));
187 	}
188 
189 	ft_session->htSecondaryChannelOffset =
190 		pBeaconStruct->HTInfo.secondaryChannelOffset;
191 	sta_ctx = &pAddBssParams->staContext;
192 	/*
193 	 * in lim_extract_ap_capability function intersection of FW
194 	 * advertised channel width and AP advertised channel
195 	 * width has been taken into account for calculating
196 	 * pe_session->ch_width
197 	 */
198 	pAddBssParams->ch_width = ft_session->ch_width;
199 	sta_ctx->ch_width = ft_session->ch_width;
200 
201 	if (ft_session->vhtCapability &&
202 	    ft_session->vhtCapabilityPresentInBeacon) {
203 		pAddBssParams->vhtCapable = pBeaconStruct->VHTCaps.present;
204 		vht_caps = &pBeaconStruct->VHTCaps;
205 		lim_update_vhtcaps_assoc_resp(mac, pAddBssParams,
206 					      vht_caps, ft_session);
207 	} else if (ft_session->vhtCapability &&
208 	    pBeaconStruct->vendor_vht_ie.VHTCaps.present) {
209 		pe_debug("VHT caps are present in vendor specific IE");
210 		pAddBssParams->vhtCapable =
211 			pBeaconStruct->vendor_vht_ie.VHTCaps.present;
212 		vht_caps = &pBeaconStruct->vendor_vht_ie.VHTCaps;
213 		lim_update_vhtcaps_assoc_resp(mac, pAddBssParams,
214 					      vht_caps, ft_session);
215 	} else {
216 		pAddBssParams->vhtCapable = 0;
217 	}
218 
219 	if (lim_is_session_he_capable(ft_session) &&
220 	    pBeaconStruct->he_cap.present) {
221 		lim_update_bss_he_capable(mac, pAddBssParams);
222 		lim_add_bss_he_cfg(pAddBssParams, ft_session);
223 	}
224 
225 	if (lim_is_session_eht_capable(ft_session) &&
226 	    pBeaconStruct->eht_cap.present) {
227 		lim_update_bss_eht_capable(mac, pAddBssParams);
228 		lim_add_bss_eht_cfg(pAddBssParams, ft_session);
229 	}
230 
231 	pe_debug("SIR_HAL_ADD_BSS_REQ with frequency: %d, width: %d",
232 		 bssDescription->chan_freq, pAddBssParams->ch_width);
233 
234 	/* Populate the STA-related parameters here */
235 	/* Note that the STA here refers to the AP */
236 	{
237 		pAddBssParams->staContext.staType = STA_ENTRY_OTHER;
238 
239 		qdf_mem_copy(pAddBssParams->staContext.bssId,
240 			     bssDescription->bssId, sizeof(tSirMacAddr));
241 		pAddBssParams->staContext.listenInterval =
242 			bssDescription->beaconInterval;
243 
244 		pAddBssParams->staContext.assocId = 0;
245 		pAddBssParams->staContext.uAPSD = 0;
246 		pAddBssParams->staContext.maxSPLen = 0;
247 		pAddBssParams->staContext.updateSta = false;
248 		pAddBssParams->staContext.encryptType =
249 			ft_session->encryptType;
250 		pAddBssParams->staContext.rmfEnabled =
251 			ft_session->limRmfEnabled;
252 
253 		if (IS_DOT11_MODE_HT(ft_session->dot11mode) &&
254 		    (pBeaconStruct->HTCaps.present)) {
255 			pAddBssParams->staContext.htCapable = 1;
256 			if (ft_session->vhtCapability &&
257 			    IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) {
258 				pAddBssParams->staContext.vhtCapable = 1;
259 				if ((pBeaconStruct->VHTCaps.suBeamFormerCap ||
260 				     pBeaconStruct->VHTCaps.muBeamformerCap) &&
261 				    ft_session->vht_config.su_beam_formee)
262 					sta_ctx->vhtTxBFCapable
263 						= 1;
264 				if (pBeaconStruct->VHTCaps.suBeamformeeCap &&
265 				    ft_session->vht_config.su_beam_former)
266 					sta_ctx->enable_su_tx_bformer = 1;
267 			}
268 			if (lim_is_session_he_capable(ft_session) &&
269 				pBeaconStruct->he_cap.present)
270 				lim_intersect_ap_he_caps(ft_session,
271 							 pAddBssParams,
272 							 pBeaconStruct, NULL,
273 							 bssDescription);
274 
275 			if (lim_is_session_eht_capable(ft_session) &&
276 			    pBeaconStruct->eht_cap.present)
277 				lim_intersect_ap_eht_caps(ft_session,
278 							  pAddBssParams,
279 							  pBeaconStruct, NULL);
280 
281 			pAddBssParams->staContext.mimoPS =
282 				(tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps.
283 				mimoPowerSave;
284 			pAddBssParams->staContext.maxAmpduDensity =
285 				pBeaconStruct->HTCaps.mpduDensity;
286 			pAddBssParams->staContext.fShortGI20Mhz =
287 				(uint8_t) pBeaconStruct->HTCaps.shortGI20MHz;
288 			pAddBssParams->staContext.fShortGI40Mhz =
289 				(uint8_t) pBeaconStruct->HTCaps.shortGI40MHz;
290 			pAddBssParams->staContext.maxAmpduSize =
291 				pBeaconStruct->HTCaps.maxRxAMPDUFactor;
292 		}
293 
294 		if ((ft_session->limWmeEnabled
295 		     && pBeaconStruct->wmeEdcaPresent)
296 		    || (ft_session->limQosEnabled
297 			&& pBeaconStruct->edcaPresent))
298 			pAddBssParams->staContext.wmmEnabled = 1;
299 		else
300 			pAddBssParams->staContext.wmmEnabled = 0;
301 
302 		pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent;
303 		/* For OSEN Connection AP does not advertise RSN or WPA IE
304 		 * so from the IEs we get from supplicant we get this info
305 		 * so for FW to transmit EAPOL message 4 we shall set
306 		 * wpa_rsn
307 		 */
308 		pAddBssParams->staContext.wpa_rsn |=
309 			(pBeaconStruct->wpaPresent << 1);
310 		if ((!pAddBssParams->staContext.wpa_rsn)
311 		    && (ft_session->isOSENConnection))
312 			pAddBssParams->staContext.wpa_rsn = 1;
313 		/* Update the rates */
314 		lim_populate_peer_rate_set(mac,
315 					   &pAddBssParams->staContext.
316 					   supportedRates,
317 					   pBeaconStruct->HTCaps.supportedMCSSet,
318 					   false, ft_session,
319 					   &pBeaconStruct->VHTCaps,
320 					   &pBeaconStruct->he_cap,
321 					   &pBeaconStruct->eht_cap, NULL,
322 					   bssDescription);
323 	}
324 
325 	pAddBssParams->maxTxPower = ft_session->maxTxPower;
326 
327 	if (ft_session->limRmfEnabled) {
328 		pAddBssParams->rmfEnabled = 1;
329 		pAddBssParams->staContext.rmfEnabled = 1;
330 	}
331 	pAddBssParams->staContext.sessionId = ft_session->peSessionId;
332 	pAddBssParams->staContext.smesessionId = ft_session->smeSessionId;
333 
334 	/* Set a new state for MLME */
335 	if (!lim_is_roam_synch_in_progress(mac->psoc, ft_session)) {
336 		ft_session->limMlmState =
337 			eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE;
338 		MTRACE(mac_trace
339 			(mac, TRACE_CODE_MLM_STATE,
340 			ft_session->peSessionId,
341 			eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE));
342 	}
343 	ft_session->ftPEContext.pAddBssReq = pAddBssParams;
344 
345 	pe_debug("Saving SIR_HAL_ADD_BSS_REQ for pre-auth ap");
346 
347 	qdf_mem_free(pBeaconStruct);
348 	return;
349 }
350 #endif
351 
352 #if defined(WLAN_FEATURE_ROAM_OFFLOAD)
353 
354 /**
355  * lim_convert_phymode_to_dot11mode() - get dot11 mode from phymode
356  * @phymode: phymode
357  *
358  * The function is to convert the phymode to corresponding dot11 mode
359  *
360  * Return: dot11mode.
361  */
lim_convert_phymode_to_dot11mode(enum wlan_phymode phymode)362 static uint8_t lim_convert_phymode_to_dot11mode(enum wlan_phymode phymode)
363 {
364 
365 	if (IS_WLAN_PHYMODE_HE(phymode))
366 		return MLME_DOT11_MODE_11AX;
367 
368 	if (IS_WLAN_PHYMODE_VHT(phymode))
369 		return MLME_DOT11_MODE_11AC;
370 
371 	if (IS_WLAN_PHYMODE_HT(phymode))
372 		return MLME_DOT11_MODE_11N;
373 
374 #ifdef WLAN_FEATURE_11BE
375 	if (IS_WLAN_PHYMODE_EHT(phymode))
376 		return MLME_DOT11_MODE_11BE;
377 #endif
378 
379 	if (phymode == WLAN_PHYMODE_11G)
380 		return MLME_DOT11_MODE_11G;
381 
382 	if (phymode == WLAN_PHYMODE_11G_ONLY)
383 		return MLME_DOT11_MODE_11G_ONLY;
384 
385 	if (phymode == WLAN_PHYMODE_11A)
386 		return MLME_DOT11_MODE_11A;
387 
388 	if (phymode == WLAN_PHYMODE_11B)
389 		return MLME_DOT11_MODE_11B;
390 
391 	return MLME_DOT11_MODE_ALL;
392 }
393 
394 /**
395  * lim_calculate_dot11_mode() - calculate dot11 mode.
396  * @mac_ctx: mac context
397  * @bcn: beacon structure
398  * @band: reg_wifi_band
399  *
400  * The function is to calculate dot11 mode in case fw doesn't send phy mode.
401  *
402  * Return: dot11mode.
403  */
lim_calculate_dot11_mode(struct mac_context * mac_ctx,tSchBeaconStruct * bcn,enum reg_wifi_band band)404 static uint8_t lim_calculate_dot11_mode(struct mac_context *mac_ctx,
405 					tSchBeaconStruct *bcn,
406 					enum reg_wifi_band band)
407 {
408 	enum mlme_dot11_mode self_dot11_mode;
409 	enum mlme_dot11_mode new_dot11_mode;
410 
411 	self_dot11_mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode;
412 
413 	if (band == REG_BAND_2G)
414 		new_dot11_mode = MLME_DOT11_MODE_11G;
415 	else
416 		new_dot11_mode = MLME_DOT11_MODE_11A;
417 
418 	switch (self_dot11_mode) {
419 	case MLME_DOT11_MODE_11AX:
420 	case MLME_DOT11_MODE_11AX_ONLY:
421 	case MLME_DOT11_MODE_ALL:
422 		if (bcn->he_cap.present)
423 			return MLME_DOT11_MODE_11AX;
424 		else if ((bcn->VHTCaps.present ||
425 			  bcn->vendor_vht_ie.present) &&
426 			 (!(band == REG_BAND_2G &&
427 			  !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band)
428 			 ))
429 
430 			return MLME_DOT11_MODE_11AC;
431 		else if (bcn->HTCaps.present)
432 			return MLME_DOT11_MODE_11N;
433 		fallthrough;
434 	case MLME_DOT11_MODE_11AC:
435 	case MLME_DOT11_MODE_11AC_ONLY:
436 		if ((bcn->VHTCaps.present ||
437 		     bcn->vendor_vht_ie.present) &&
438 		   (!(band == REG_BAND_2G &&
439 		    !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band)
440 		   ))
441 			return MLME_DOT11_MODE_11AC;
442 		else if (bcn->HTCaps.present)
443 			return MLME_DOT11_MODE_11N;
444 		fallthrough;
445 	case MLME_DOT11_MODE_11N:
446 	case MLME_DOT11_MODE_11N_ONLY:
447 		if (bcn->HTCaps.present)
448 			return MLME_DOT11_MODE_11N;
449 		fallthrough;
450 	default:
451 			return new_dot11_mode;
452 	}
453 
454 }
455 
456 /**
457  * lim_fill_dot11mode() - to fill 802.11 mode in FT session
458  * @mac_ctx: pointer to mac ctx
459  * @ft_session: FT session
460  * @pe_session: PE session
461  * @bcn: AP beacon pointer
462  * @bss_phymode: bss phy mode
463  *
464  * This API fills FT session's dot11mode either from pe session or
465  * from CFG depending on the condition.
466  *
467  * Return: none
468  */
lim_fill_dot11mode(struct mac_context * mac_ctx,struct pe_session * ft_session,struct pe_session * pe_session,tSchBeaconStruct * bcn,enum wlan_phymode bss_phymode)469 static void lim_fill_dot11mode(struct mac_context *mac_ctx,
470 			       struct pe_session *ft_session,
471 			       struct pe_session *pe_session,
472 			       tSchBeaconStruct *bcn,
473 			       enum wlan_phymode bss_phymode)
474 {
475 	if (pe_session->ftPEContext.pFTPreAuthReq &&
476 	    !wlan_is_roam_offload_enabled(mac_ctx->mlme_cfg->lfr)) {
477 		ft_session->dot11mode =
478 			pe_session->ftPEContext.pFTPreAuthReq->dot11mode;
479 		return;
480 	}
481 
482 	if (bss_phymode == WLAN_PHYMODE_AUTO)
483 		ft_session->dot11mode = lim_calculate_dot11_mode(
484 							mac_ctx, bcn,
485 							ft_session->limRFBand);
486 
487 	else
488 		ft_session->dot11mode =
489 			lim_convert_phymode_to_dot11mode(bss_phymode);
490 }
491 #elif defined(WLAN_FEATURE_HOST_ROAM)
492 /**
493  * lim_fill_dot11mode() - to fill 802.11 mode in FT session
494  * @mac_ctx: pointer to mac ctx
495  * @ft_session: FT session
496  * @pe_session: PE session
497  * @bcn: AP beacon pointer
498  * @bss_phymode: bss phy mode
499  *
500  * This API fills FT session's dot11mode either from pe session.
501  *
502  * Return: none
503  */
lim_fill_dot11mode(struct mac_context * mac_ctx,struct pe_session * ft_session,struct pe_session * pe_session,tSchBeaconStruct * bcn,enum wlan_phymode bss_phymode)504 static void lim_fill_dot11mode(struct mac_context *mac_ctx,
505 			       struct pe_session *ft_session,
506 			       struct pe_session *pe_session,
507 			       tSchBeaconStruct *bcn,
508 			       enum wlan_phymode bss_phymode)
509 {
510 	ft_session->dot11mode =
511 			pe_session->ftPEContext.pFTPreAuthReq->dot11mode;
512 }
513 #endif
514 
515 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
516 /**
517  * lim_fill_session_power_info() - to fill power info in session
518  * @mac: pointer to mac ctx
519  * @pbssDescription: Pointer to pbssDescription
520  * @ft_session: Pointer to FT session
521  * @pe_session: Pointer to PE session
522  *
523  * Return: QDF_STATUS
524  */
lim_fill_session_power_info(struct mac_context * mac,struct bss_description * pbssDescription,struct pe_session * ft_session,struct pe_session * pe_session)525 static QDF_STATUS lim_fill_session_power_info(
526 				struct mac_context *mac,
527 				struct bss_description *pbssDescription,
528 				struct pe_session *ft_session,
529 				struct pe_session *pe_session)
530 {
531 	uint8_t currentBssUapsd;
532 	int8_t localPowerConstraint = 0;
533 	int8_t regMax = 0;
534 	bool is_pwr_constraint = false;
535 	struct vdev_mlme_obj *mlme_obj;
536 	enum reg_6g_ap_type power_type_6g;
537 	QDF_STATUS status;
538 
539 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
540 	if (!mlme_obj) {
541 		pe_err("vdev component object is NULL");
542 		return QDF_STATUS_E_FAILURE;
543 	}
544 
545 	lim_extract_ap_capability(mac, (uint8_t *)pbssDescription->ieFields,
546 		lim_get_ielen_from_bss_description(pbssDescription),
547 		&ft_session->limCurrentBssQosCaps,
548 		&currentBssUapsd,
549 		&localPowerConstraint, ft_session, &is_pwr_constraint);
550 
551 	mlme_obj->reg_tpc_obj.is_power_constraint_abs = !is_pwr_constraint;
552 
553 	if (wlan_reg_is_6ghz_chan_freq(pbssDescription->chan_freq)) {
554 		status = wlan_reg_get_best_6g_power_type(
555 				mac->psoc, mac->pdev,
556 				&power_type_6g,
557 				ft_session->ap_defined_power_type_6g,
558 				pbssDescription->chan_freq);
559 		if (QDF_IS_STATUS_ERROR(status))
560 			return status;
561 
562 		ft_session->best_6g_power_type = power_type_6g;
563 		mlme_set_best_6g_power_type(ft_session->vdev, power_type_6g);
564 	}
565 
566 	if (wlan_reg_is_ext_tpc_supported(mac->psoc)) {
567 		mlme_obj->reg_tpc_obj.ap_constraint_power =
568 						localPowerConstraint;
569 	} else {
570 		regMax = wlan_reg_get_channel_reg_power_for_freq(
571 				mac->pdev, ft_session->curr_op_freq);
572 		if (is_pwr_constraint)
573 			localPowerConstraint = regMax - localPowerConstraint;
574 		if (!localPowerConstraint)
575 			localPowerConstraint = regMax;
576 
577 		mlme_obj->reg_tpc_obj.reg_max[0] = regMax;
578 		mlme_obj->reg_tpc_obj.ap_constraint_power =
579 						localPowerConstraint;
580 		mlme_obj->reg_tpc_obj.frequency[0] = ft_session->curr_op_freq;
581 
582 #ifdef FEATURE_WLAN_ESE
583 		ft_session->maxTxPower = lim_get_max_tx_power(mac, mlme_obj);
584 #else
585 		ft_session->maxTxPower = QDF_MIN(regMax, localPowerConstraint);
586 #endif
587 		ft_session->def_max_tx_pwr = ft_session->maxTxPower;
588 	}
589 
590 	/*
591 	 * for mdm platform which QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
592 	 * will not call from android framework every 3 seconds, and tx
593 	 * power will never update. So we use iw dev get tx power need
594 	 * set maxTxPower non-zero value, that firmware can calc a non-zero
595 	 * tx power, and update to host driver.
596 	 */
597 	if (ft_session->maxTxPower == 0)
598 		ft_session->maxTxPower =
599 			wlan_reg_get_channel_reg_power_for_freq(mac->pdev,
600 						ft_session->curr_op_freq);
601 
602 	pe_debug("Reg max: %d local pwr: %d, max tx pwr: %d", regMax,
603 		 localPowerConstraint, ft_session->maxTxPower);
604 
605 	return QDF_STATUS_SUCCESS;
606 }
607 
608 /*------------------------------------------------------------------
609  *
610  * Setup the new session for the pre-auth AP.
611  * Return the newly created session entry.
612  *
613  *------------------------------------------------------------------*/
614 QDF_STATUS
lim_fill_ft_session(struct mac_context * mac,struct bss_description * pbssDescription,struct pe_session * ft_session,struct pe_session * pe_session,enum wlan_phymode bss_phymode)615 lim_fill_ft_session(struct mac_context *mac,
616 		    struct bss_description *pbssDescription,
617 		    struct pe_session *ft_session,
618 		    struct pe_session *pe_session,
619 		    enum wlan_phymode bss_phymode)
620 {
621 	uint8_t bss_chan_id;
622 	tSchBeaconStruct *pBeaconStruct;
623 	uint8_t cb_mode;
624 	QDF_STATUS status = QDF_STATUS_SUCCESS;
625 
626 	pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct));
627 	if (!pBeaconStruct)
628 		return QDF_STATUS_E_NOMEM;
629 
630 	/* Retrieve the session that was already created and update the entry */
631 	ft_session->limWmeEnabled = pe_session->limWmeEnabled;
632 	ft_session->limQosEnabled = pe_session->limQosEnabled;
633 	ft_session->limWsmEnabled = pe_session->limWsmEnabled;
634 	ft_session->lim11hEnable = pe_session->lim11hEnable;
635 	ft_session->isOSENConnection = pe_session->isOSENConnection;
636 	ft_session->connected_akm = pe_session->connected_akm;
637 
638 	/* Fields to be filled later */
639 	ft_session->lim_join_req = NULL;
640 	ft_session->smeSessionId = pe_session->smeSessionId;
641 
642 	lim_extract_ap_capabilities(mac, (uint8_t *) pbssDescription->ieFields,
643 			lim_get_ielen_from_bss_description(pbssDescription),
644 			pBeaconStruct);
645 
646 	qdf_mem_zero(&ft_session->wmm_params, sizeof(tDot11fIEWMMParams));
647 	if (pBeaconStruct->wmm_params.present)
648 		qdf_mem_copy(&ft_session->wmm_params,
649 			     &pBeaconStruct->wmm_params,
650 			     sizeof(tDot11fIEWMMParams));
651 
652 	ft_session->rateSet.numRates =
653 		pBeaconStruct->supportedRates.numRates;
654 	qdf_mem_copy(ft_session->rateSet.rate,
655 		     pBeaconStruct->supportedRates.rate,
656 		     pBeaconStruct->supportedRates.numRates);
657 
658 	ft_session->extRateSet.numRates =
659 		pBeaconStruct->extendedRates.numRates;
660 	qdf_mem_copy(ft_session->extRateSet.rate,
661 		     pBeaconStruct->extendedRates.rate,
662 		     ft_session->extRateSet.numRates);
663 
664 	ft_session->ssId.length = pBeaconStruct->ssId.length;
665 	qdf_mem_copy(ft_session->ssId.ssId, pBeaconStruct->ssId.ssId,
666 		     ft_session->ssId.length);
667 	/* Copy The channel Id to the session Table */
668 	bss_chan_id =
669 		wlan_reg_freq_to_chan(mac->pdev, pbssDescription->chan_freq);
670 	ft_session->lim_reassoc_chan_freq = pbssDescription->chan_freq;
671 	ft_session->curr_op_freq = pbssDescription->chan_freq;
672 	ft_session->limRFBand = lim_get_rf_band(ft_session->curr_op_freq);
673 
674 	lim_fill_dot11mode(mac, ft_session, pe_session, pBeaconStruct,
675 			   bss_phymode);
676 	pe_debug("dot11mode: %d bss_phymode %d", ft_session->dot11mode,
677 		 bss_phymode);
678 
679 	ft_session->vhtCapability =
680 		(IS_DOT11_MODE_VHT(ft_session->dot11mode) &&
681 		 (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) ||
682 		  IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor_vht_ie.VHTCaps)));
683 	ft_session->htCapability =
684 		(IS_DOT11_MODE_HT(ft_session->dot11mode)
685 		 && pBeaconStruct->HTCaps.present);
686 
687 	if (IS_DOT11_MODE_HE(ft_session->dot11mode) &&
688 	    pBeaconStruct->he_cap.present) {
689 		lim_update_session_he_capable(mac, ft_session);
690 		lim_copy_join_req_he_cap(ft_session);
691 	}
692 	if (IS_DOT11_MODE_EHT(ft_session->dot11mode) &&
693 	    pBeaconStruct->eht_cap.present) {
694 		lim_update_session_eht_capable(mac, ft_session);
695 		lim_copy_join_req_eht_cap(ft_session);
696 	}
697 	/* Assign default configured nss value in the new session */
698 	if (!wlan_reg_is_24ghz_ch_freq(ft_session->curr_op_freq))
699 		ft_session->vdev_nss = mac->vdev_type_nss_5g.sta;
700 	else
701 		ft_session->vdev_nss = mac->vdev_type_nss_2g.sta;
702 
703 	ft_session->nss = ft_session ->vdev_nss;
704 
705 	cb_mode = lim_get_cb_mode_for_freq(mac, ft_session,
706 					   ft_session->curr_op_freq);
707 
708 	ft_session->htSupportedChannelWidthSet =
709 	    (pBeaconStruct->HTInfo.present) ?
710 	    (cb_mode && pBeaconStruct->HTInfo.recommendedTxWidthSet &&
711 	     pBeaconStruct->HTCaps.supportedChannelWidthSet) : 0;
712 	ft_session->htRecommendedTxWidthSet =
713 		ft_session->htSupportedChannelWidthSet;
714 
715 	if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) &&
716 		pBeaconStruct->VHTOperation.present &&
717 		ft_session->vhtCapability) {
718 		ft_session->vhtCapabilityPresentInBeacon = 1;
719 	} else if (IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor_vht_ie.VHTCaps) &&
720 		    pBeaconStruct->vendor_vht_ie.VHTOperation.present &&
721 		    ft_session->vhtCapability){
722 		ft_session->vhtCapabilityPresentInBeacon = 1;
723 	} else {
724 		ft_session->vhtCapabilityPresentInBeacon = 0;
725 	}
726 
727 	if (ft_session->htRecommendedTxWidthSet) {
728 		ft_session->ch_width = CH_WIDTH_40MHZ;
729 		if (ft_session->vhtCapabilityPresentInBeacon &&
730 		    pBeaconStruct->VHTOperation.chanWidth) {
731 			ft_session->ch_width =
732 				pBeaconStruct->VHTOperation.chanWidth + 1;
733 			ft_session->ch_center_freq_seg0 =
734 			pBeaconStruct->VHTOperation.chan_center_freq_seg0;
735 			ft_session->ch_center_freq_seg1 =
736 			pBeaconStruct->VHTOperation.chan_center_freq_seg1;
737 		} else if (ft_session->vhtCapabilityPresentInBeacon &&
738 			   pBeaconStruct->vendor_vht_ie.VHTOperation.chanWidth) {
739 			ft_session->ch_width =
740 				pBeaconStruct->vendor_vht_ie.VHTOperation.chanWidth + 1;
741 			ft_session->ch_center_freq_seg0 =
742 				pBeaconStruct->vendor_vht_ie.VHTOperation.chan_center_freq_seg0;
743 			ft_session->ch_center_freq_seg1 =
744 				pBeaconStruct->vendor_vht_ie.VHTOperation.chan_center_freq_seg1;
745 
746 		} else {
747 			if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
748 					PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
749 				ft_session->ch_center_freq_seg0 =
750 					bss_chan_id + 2;
751 			else if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
752 					PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
753 				ft_session->ch_center_freq_seg0 =
754 					bss_chan_id - 2;
755 			else {
756 				pe_warn("Invalid sec ch offset");
757 				ft_session->ch_width = CH_WIDTH_20MHZ;
758 				ft_session->ch_center_freq_seg0 = 0;
759 				ft_session->ch_center_freq_seg1 = 0;
760 			}
761 		}
762 	} else {
763 		ft_session->ch_width = CH_WIDTH_20MHZ;
764 		ft_session->ch_center_freq_seg0 = 0;
765 		ft_session->ch_center_freq_seg1 = 0;
766 	}
767 
768 	sir_copy_mac_addr(ft_session->self_mac_addr,
769 			  wlan_vdev_mlme_get_macaddr(pe_session->vdev));
770 	sir_copy_mac_addr(ft_session->limReAssocbssId,
771 			  pbssDescription->bssId);
772 	sir_copy_mac_addr(ft_session->prev_ap_bssid, pe_session->bssId);
773 
774 	/* Store beaconInterval */
775 	ft_session->beaconParams.beaconInterval =
776 		pbssDescription->beaconInterval;
777 	ft_session->bssType = pe_session->bssType;
778 
779 	ft_session->statypeForBss = STA_ENTRY_PEER;
780 	ft_session->nwType = pbssDescription->nwType;
781 
782 
783 	if (ft_session->bssType == eSIR_INFRASTRUCTURE_MODE) {
784 		ft_session->limSystemRole = eLIM_STA_ROLE;
785 	} else {
786 		/* Throw an error & return & make sure to delete the session */
787 		pe_warn("Invalid bss type");
788 	}
789 
790 	ft_session->limCurrentBssCaps = pbssDescription->capabilityInfo;
791 	ft_session->limReassocBssCaps = pbssDescription->capabilityInfo;
792 	if (mac->mlme_cfg->ht_caps.short_slot_time_enabled &&
793 	    SIR_MAC_GET_SHORT_SLOT_TIME(ft_session->limReassocBssCaps)) {
794 		ft_session->shortSlotTimeSupported = true;
795 	}
796 
797 	status = lim_fill_session_power_info(mac, pbssDescription, ft_session,
798 					     pe_session);
799 	if (QDF_IS_STATUS_ERROR(status)) {
800 		pe_err("Failed to fill power info in ft session");
801 		goto exit;
802 	}
803 
804 	ft_session->limReassocBssQosCaps =
805 		ft_session->limCurrentBssQosCaps;
806 
807 	ft_session->is11Rconnection = pe_session->is11Rconnection;
808 
809 #ifdef FEATURE_WLAN_ESE
810 	ft_session->is_ese_version_ie_present =
811 		pBeaconStruct->is_ese_ver_ie_present;
812 #endif
813 
814 	if (!lim_is_roam_synch_in_progress(mac->psoc, pe_session)) {
815 		ft_session->limPrevSmeState = ft_session->limSmeState;
816 		ft_session->limSmeState = eLIM_SME_WT_REASSOC_STATE;
817 		MTRACE(mac_trace(mac,
818 				TRACE_CODE_SME_STATE,
819 				ft_session->peSessionId,
820 				ft_session->limSmeState));
821 	}
822 	ft_session->encryptType = pe_session->encryptType;
823 	ft_session->limRmfEnabled = pe_session->limRmfEnabled;
824 	/* Load default OBSS parameters to session entry */
825 	lim_init_obss_params(mac, ft_session);
826 
827 	/*
828 	 * By default supported NSS 1x1 is set to true
829 	 * and later on updated while determining session
830 	 * supported rates which is the intersection of
831 	 * self and peer rates
832 	 */
833 	ft_session->supported_nss_1x1 = true;
834 	pe_debug("FT enable smps: %d mode: %d supported nss 1x1: %d",
835 		mac->mlme_cfg->ht_caps.enable_smps,
836 		mac->mlme_cfg->ht_caps.smps,
837 		ft_session->supported_nss_1x1);
838 
839 exit:
840 	qdf_mem_free(pBeaconStruct);
841 	return status;
842 }
843 #endif
844 
845 static void
lim_ft_send_aggr_qos_rsp(struct mac_context * mac,uint8_t rspReqd,struct aggr_add_ts_param * aggrQosRsp,uint8_t smesessionId)846 lim_ft_send_aggr_qos_rsp(struct mac_context *mac, uint8_t rspReqd,
847 			 struct aggr_add_ts_param *aggrQosRsp,
848 			 uint8_t smesessionId)
849 {
850 	tpSirAggrQosRsp rsp;
851 	int i = 0;
852 
853 	if (!rspReqd) {
854 		return;
855 	}
856 	rsp = qdf_mem_malloc(sizeof(tSirAggrQosRsp));
857 	if (!rsp)
858 		return;
859 
860 	rsp->messageType = eWNI_SME_FT_AGGR_QOS_RSP;
861 	rsp->sessionId = smesessionId;
862 	rsp->length = sizeof(*rsp);
863 	rsp->aggrInfo.tspecIdx = aggrQosRsp->tspecIdx;
864 	for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
865 		if ((1 << i) & aggrQosRsp->tspecIdx) {
866 			if (QDF_IS_STATUS_SUCCESS(aggrQosRsp->status[i]))
867 				rsp->aggrInfo.aggrRsp[i].status =
868 					STATUS_SUCCESS;
869 			else
870 				rsp->aggrInfo.aggrRsp[i].status =
871 					STATUS_UNSPECIFIED_FAILURE;
872 			rsp->aggrInfo.aggrRsp[i].tspec = aggrQosRsp->tspec[i];
873 		}
874 	}
875 	lim_send_sme_aggr_qos_rsp(mac, rsp, smesessionId);
876 	return;
877 }
878 
lim_process_ft_aggr_qos_rsp(struct mac_context * mac,struct scheduler_msg * limMsg)879 void lim_process_ft_aggr_qos_rsp(struct mac_context *mac,
880 				 struct scheduler_msg *limMsg)
881 {
882 	struct aggr_add_ts_param *pAggrQosRspMsg;
883 	struct add_ts_param addTsParam = { 0 };
884 	tpDphHashNode pSta = NULL;
885 	uint16_t assocId = 0;
886 	tSirMacAddr peerMacAddr;
887 	uint8_t rspReqd = 1;
888 	struct pe_session *pe_session = NULL;
889 	int i = 0;
890 
891 	pe_debug(" Received AGGR_QOS_RSP from HAL");
892 	SET_LIM_PROCESS_DEFD_MESGS(mac, true);
893 	pAggrQosRspMsg = limMsg->bodyptr;
894 	if (!pAggrQosRspMsg) {
895 		pe_err("NULL pAggrQosRspMsg");
896 		return;
897 	}
898 	pe_session =
899 		pe_find_session_by_session_id(mac, pAggrQosRspMsg->sessionId);
900 	if (!pe_session) {
901 		pe_err("Cant find session entry");
902 		if (pAggrQosRspMsg) {
903 			qdf_mem_free(pAggrQosRspMsg);
904 		}
905 		return;
906 	}
907 	if (!LIM_IS_STA_ROLE(pe_session)) {
908 		pe_err("pe_session is not in STA mode");
909 		return;
910 	}
911 	for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
912 		if ((((1 << i) & pAggrQosRspMsg->tspecIdx)) &&
913 		    (pAggrQosRspMsg->status[i] != QDF_STATUS_SUCCESS)) {
914 			sir_copy_mac_addr(peerMacAddr, pe_session->bssId);
915 			addTsParam.pe_session_id = pAggrQosRspMsg->sessionId;
916 			addTsParam.tspec = pAggrQosRspMsg->tspec[i];
917 			addTsParam.tspec_idx = pAggrQosRspMsg->tspecIdx;
918 			lim_send_delts_req_action_frame(mac, peerMacAddr,
919 							rspReqd,
920 							&addTsParam.tspec.tsinfo,
921 							&addTsParam.tspec,
922 							pe_session);
923 			pSta =
924 				dph_lookup_hash_entry(mac, peerMacAddr,
925 						      &assocId,
926 						      &pe_session->
927 						      dph.dphHashTable);
928 
929 			if (pSta) {
930 				lim_admit_control_delete_ts(mac, assocId,
931 							    &addTsParam.tspec.
932 							    tsinfo, NULL,
933 							    (uint8_t *) &
934 							    addTsParam.tspec_idx);
935 			}
936 		}
937 	}
938 	lim_ft_send_aggr_qos_rsp(mac, rspReqd, pAggrQosRspMsg,
939 				 pe_session->smeSessionId);
940 	if (pAggrQosRspMsg) {
941 		qdf_mem_free(pAggrQosRspMsg);
942 	}
943 	return;
944 }
945 
lim_process_ft_aggr_qos_req(struct mac_context * mac,uint32_t * msg_buf)946 QDF_STATUS lim_process_ft_aggr_qos_req(struct mac_context *mac,
947 				       uint32_t *msg_buf)
948 {
949 	struct scheduler_msg msg = {0};
950 	tSirAggrQosReq *aggrQosReq = (tSirAggrQosReq *) msg_buf;
951 	struct aggr_add_ts_param *pAggrAddTsParam;
952 	struct pe_session *pe_session = NULL;
953 	tpLimTspecInfo tspecInfo;
954 	uint8_t ac;
955 	tpDphHashNode pSta;
956 	uint16_t aid;
957 	uint8_t sessionId;
958 	int i;
959 
960 	pAggrAddTsParam = qdf_mem_malloc(sizeof(*pAggrAddTsParam));
961 	if (!pAggrAddTsParam)
962 		return QDF_STATUS_E_NOMEM;
963 
964 	pe_session = pe_find_session_by_bssid(mac, aggrQosReq->bssid.bytes,
965 					      &sessionId);
966 
967 	if (!pe_session) {
968 		pe_err("psession Entry Null for sessionId: %d",
969 			       aggrQosReq->sessionId);
970 		qdf_mem_free(pAggrAddTsParam);
971 		return QDF_STATUS_E_FAILURE;
972 	}
973 
974 	/* Nothing to be done if the session is not in STA mode */
975 	if (!LIM_IS_STA_ROLE(pe_session)) {
976 		pe_err("pe_session is not in STA mode");
977 		qdf_mem_free(pAggrAddTsParam);
978 		return QDF_STATUS_E_FAILURE;
979 	}
980 
981 	pSta = dph_lookup_hash_entry(mac, aggrQosReq->bssid.bytes, &aid,
982 				     &pe_session->dph.dphHashTable);
983 	if (!pSta) {
984 		pe_err("Station context not found - ignoring AddTsRsp");
985 		qdf_mem_free(pAggrAddTsParam);
986 		return QDF_STATUS_E_FAILURE;
987 	}
988 
989 	/* Fill in the sessionId specific to PE */
990 	pAggrAddTsParam->sessionId = sessionId;
991 	pAggrAddTsParam->tspecIdx = aggrQosReq->aggrInfo.tspecIdx;
992 	pAggrAddTsParam->vdev_id = pe_session->smeSessionId;
993 
994 	for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
995 		if (aggrQosReq->aggrInfo.tspecIdx & (1 << i)) {
996 			struct mac_tspec_ie *pTspec =
997 				&aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec;
998 			/* Since AddTS response was successful, check for the PSB flag
999 			 * and directional flag inside the TS Info field.
1000 			 * An AC is trigger enabled AC if the PSB subfield is set to 1
1001 			 * in the uplink direction.
1002 			 * An AC is delivery enabled AC if the PSB subfield is set to 1
1003 			 * in the downlink direction.
1004 			 * An AC is trigger and delivery enabled AC if the PSB subfield
1005 			 * is set to 1 in the bi-direction field.
1006 			 */
1007 			if (pTspec->tsinfo.traffic.psb == 1) {
1008 				lim_set_tspec_uapsd_mask_per_session(mac,
1009 								     pe_session,
1010 								     &pTspec->
1011 								     tsinfo,
1012 								     SET_UAPSD_MASK);
1013 			} else {
1014 				lim_set_tspec_uapsd_mask_per_session(mac,
1015 								     pe_session,
1016 								     &pTspec->
1017 								     tsinfo,
1018 								     CLEAR_UAPSD_MASK);
1019 			}
1020 			/*
1021 			 * ADDTS success, so AC is now admitted.
1022 			 * We shall now use the default
1023 			 * EDCA parameters as advertised by AP and
1024 			 * send the updated EDCA params
1025 			 * to HAL.
1026 			 */
1027 			ac = upToAc(pTspec->tsinfo.traffic.userPrio);
1028 			if (pTspec->tsinfo.traffic.direction ==
1029 			    SIR_MAC_DIRECTION_UPLINK) {
1030 				pe_session->
1031 				gAcAdmitMask
1032 				[SIR_MAC_DIRECTION_UPLINK] |=
1033 					(1 << ac);
1034 			} else if (pTspec->tsinfo.traffic.direction ==
1035 				   SIR_MAC_DIRECTION_DNLINK) {
1036 				pe_session->
1037 				gAcAdmitMask
1038 				[SIR_MAC_DIRECTION_DNLINK] |=
1039 					(1 << ac);
1040 			} else if (pTspec->tsinfo.traffic.direction ==
1041 				   SIR_MAC_DIRECTION_BIDIR) {
1042 				pe_session->
1043 				gAcAdmitMask
1044 				[SIR_MAC_DIRECTION_UPLINK] |=
1045 					(1 << ac);
1046 				pe_session->
1047 					gAcAdmitMask
1048 					[SIR_MAC_DIRECTION_DNLINK] |=
1049 					(1 << ac);
1050 			}
1051 			lim_set_active_edca_params(mac,
1052 						   pe_session->gLimEdcaParams,
1053 						   pe_session);
1054 
1055 				lim_send_edca_params(mac,
1056 					     pe_session->gLimEdcaParamsActive,
1057 					     pe_session->vdev_id, false);
1058 
1059 			if (QDF_STATUS_SUCCESS !=
1060 			    lim_tspec_add(mac, pSta->staAddr, pSta->assocId,
1061 					  pTspec, 0, &tspecInfo)) {
1062 				pe_err("Adding entry in lim Tspec Table failed");
1063 				mac->lim.gLimAddtsSent = false;
1064 				qdf_mem_free(pAggrAddTsParam);
1065 				return QDF_STATUS_E_FAILURE;
1066 			}
1067 
1068 			pAggrAddTsParam->tspec[i] =
1069 				aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec;
1070 		}
1071 	}
1072 
1073 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1074 	if (!mac->mlme_cfg->lfr.lfr3_roaming_offload ||
1075 	    (mac->mlme_cfg->lfr.lfr3_roaming_offload &&
1076 	     !pe_session->is11Rconnection))
1077 #endif
1078 	{
1079 	msg.type = WMA_AGGR_QOS_REQ;
1080 	msg.bodyptr = pAggrAddTsParam;
1081 	msg.bodyval = 0;
1082 
1083 	/* We need to defer any incoming messages until we get a
1084 	 * WMA_AGGR_QOS_RSP from HAL.
1085 	 */
1086 	SET_LIM_PROCESS_DEFD_MESGS(mac, false);
1087 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msg.type));
1088 
1089 	if (QDF_STATUS_SUCCESS != wma_post_ctrl_msg(mac, &msg)) {
1090 			pe_warn("wma_post_ctrl_msg() failed");
1091 			SET_LIM_PROCESS_DEFD_MESGS(mac, true);
1092 			qdf_mem_free(pAggrAddTsParam);
1093 			return QDF_STATUS_E_FAILURE;
1094 		}
1095 	}
1096 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1097 	else {
1098 		/* Implies it is a LFR3.0 based 11r connection
1099 		 * so donot send add ts request to firmware since it
1100 		 * already has the RIC IEs */
1101 
1102 		/* Send the Aggr QoS response to SME */
1103 		lim_ft_send_aggr_qos_rsp(mac, true, pAggrAddTsParam,
1104 					 pe_session->smeSessionId);
1105 		if (pAggrAddTsParam) {
1106 			qdf_mem_free(pAggrAddTsParam);
1107 		}
1108 	}
1109 #endif
1110 
1111 	return QDF_STATUS_SUCCESS;
1112 }
1113