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