1  /*
2   * Copyright (c) 2011-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   * This file lim_process_assoc_rsp_frame.cc contains the code
23   * for processing Re/Association Response Frame.
24   * Author:        Chandra Modumudi
25   * Date:          03/18/02
26   * History:-
27   * Date           Modified by    Modification Information
28   * --------------------------------------------------------------------
29   *
30   */
31  
32  #include "wni_api.h"
33  #include "wni_cfg.h"
34  #include "ani_global.h"
35  #include "sch_api.h"
36  
37  #include "utils_api.h"
38  #include "lim_types.h"
39  #include "lim_utils.h"
40  #include "lim_assoc_utils.h"
41  #include "lim_security_utils.h"
42  #include "lim_ser_des_utils.h"
43  #include "lim_send_messages.h"
44  #include "lim_process_fils.h"
45  #include "wlan_dlm_api.h"
46  #include "wlan_mlme_twt_api.h"
47  #include "wlan_mlme_ucfg_api.h"
48  #include "wlan_connectivity_logging.h"
49  #include <lim_mlo.h>
50  #include "parser_api.h"
51  #include "wlan_twt_cfg_ext_api.h"
52  #include "wlan_mlo_mgr_roam.h"
53  
54  /**
55   * lim_update_stads_htcap() - Updates station Descriptor HT capability
56   * @mac_ctx: Pointer to Global MAC structure
57   * @sta_ds: Station Descriptor in DPH
58   * @assoc_rsp: Pointer to Association Response Structure
59   * @session_entry : PE session Entry
60   *
61   * This function is called to Update the HT capabilities in
62   * Station Descriptor (dph) Details from
63   * Association / ReAssociation Response Frame
64   *
65   * Return: None
66   */
lim_update_stads_htcap(struct mac_context * mac_ctx,tpDphHashNode sta_ds,tpSirAssocRsp assoc_rsp,struct pe_session * session_entry)67  static void lim_update_stads_htcap(struct mac_context *mac_ctx,
68  		tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
69  		struct pe_session *session_entry)
70  {
71  	uint16_t highest_rxrate = 0;
72  	tDot11fIEHTCaps *ht_caps;
73  
74  	ht_caps = &assoc_rsp->HTCaps;
75  	sta_ds->mlmStaContext.htCapability = assoc_rsp->HTCaps.present;
76  	if (assoc_rsp->HTCaps.present) {
77  		sta_ds->htGreenfield =
78  			(uint8_t) ht_caps->greenField;
79  		if (session_entry->htSupportedChannelWidthSet) {
80  			sta_ds->htSupportedChannelWidthSet =
81  				(uint8_t) (ht_caps->supportedChannelWidthSet ?
82  				assoc_rsp->HTInfo.recommendedTxWidthSet :
83  				ht_caps->supportedChannelWidthSet);
84  		} else
85  			sta_ds->htSupportedChannelWidthSet =
86  				eHT_CHANNEL_WIDTH_20MHZ;
87  		sta_ds->htLsigTXOPProtection =
88  			(uint8_t) ht_caps->lsigTXOPProtection;
89  		sta_ds->htMIMOPSState =
90  			(tSirMacHTMIMOPowerSaveState)ht_caps->mimoPowerSave;
91  		sta_ds->htMaxAmsduLength =
92  			(uint8_t) ht_caps->maximalAMSDUsize;
93  		sta_ds->htAMpduDensity = ht_caps->mpduDensity;
94  		sta_ds->htDsssCckRate40MHzSupport =
95  			(uint8_t) ht_caps->dsssCckMode40MHz;
96  		sta_ds->htMaxRxAMpduFactor =
97  			ht_caps->maxRxAMPDUFactor;
98  		lim_fill_rx_highest_supported_rate(mac_ctx, &highest_rxrate,
99  			ht_caps->supportedMCSSet);
100  		sta_ds->supportedRates.rxHighestDataRate =
101  			highest_rxrate;
102  		/*
103  		 * This is for AP as peer STA and we are INFRA STA
104  		 *.We will put APs offset in dph node which is peer STA
105  		 */
106  		sta_ds->htSecondaryChannelOffset =
107  			(uint8_t) assoc_rsp->HTInfo.secondaryChannelOffset;
108  
109  		/* Check if we have support for gShortGI20Mhz and
110  		 * gShortGI40Mhz from ini file
111  		 */
112  		if (session_entry->ht_config.short_gi_20_mhz)
113  			sta_ds->htShortGI20Mhz =
114  			      (uint8_t)assoc_rsp->HTCaps.shortGI20MHz;
115  		else
116  			sta_ds->htShortGI20Mhz = false;
117  
118  		if (session_entry->ht_config.short_gi_40_mhz)
119  			sta_ds->htShortGI40Mhz =
120  				      (uint8_t)assoc_rsp->HTCaps.shortGI40MHz;
121  		else
122  			sta_ds->htShortGI40Mhz = false;
123  	}
124  }
125  
126  /**
127   * lim_update_assoc_sta_datas() - Updates station Descriptor
128   * mac_ctx: Pointer to Global MAC structure
129   * sta_ds: Station Descriptor in DPH
130   * assoc_rsp: Pointer to Association Response Structure
131   * session_entry : PE session Entry
132   *
133   * This function is called to Update the Station Descriptor (dph) Details from
134   * Association / ReAssociation Response Frame
135   *
136   * Return: None
137   */
lim_update_assoc_sta_datas(struct mac_context * mac_ctx,tpDphHashNode sta_ds,tpSirAssocRsp assoc_rsp,struct pe_session * session_entry,tSchBeaconStruct * beacon)138  void lim_update_assoc_sta_datas(struct mac_context *mac_ctx,
139  	tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
140  	struct pe_session *session_entry, tSchBeaconStruct *beacon)
141  {
142  	uint32_t phy_mode;
143  	bool qos_mode;
144  	tDot11fIEVHTCaps *vht_caps = NULL;
145  	tDot11fIEhe_cap *he_cap = NULL;
146  	tDot11fIEeht_cap *eht_cap = NULL;
147  	struct bss_description *bss_desc = NULL;
148  	tDot11fIEVHTOperation *vht_oper = NULL;
149  	enum phy_ch_width omn_ie_ch_width;
150  
151  	lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
152  	sta_ds->staType = STA_ENTRY_SELF;
153  	limGetQosMode(session_entry, &qos_mode);
154  	sta_ds->mlmStaContext.authType = session_entry->limCurrentAuthType;
155  
156  	/* Add capabilities information, rates and AID */
157  	sta_ds->mlmStaContext.capabilityInfo = assoc_rsp->capabilityInfo;
158  	sta_ds->shortPreambleEnabled =
159  		(uint8_t) assoc_rsp->capabilityInfo.shortPreamble;
160  
161  	/* Update HT Capabilities only when the self mode supports HT */
162  	if (IS_DOT11_MODE_HT(session_entry->dot11mode))
163  		lim_update_stads_htcap(mac_ctx, sta_ds, assoc_rsp,
164  				       session_entry);
165  
166  	if (assoc_rsp->VHTCaps.present) {
167  		vht_caps = &assoc_rsp->VHTCaps;
168  		vht_oper = &assoc_rsp->VHTOperation;
169  	} else if (assoc_rsp->vendor_vht_ie.VHTCaps.present) {
170  		vht_caps = &assoc_rsp->vendor_vht_ie.VHTCaps;
171  		vht_oper = &assoc_rsp->vendor_vht_ie.VHTOperation;
172  	}
173  
174  	if (session_entry->vhtCapability && (vht_caps && vht_caps->present)) {
175  		sta_ds->mlmStaContext.vhtCapability =
176  			vht_caps->present;
177  
178  		/*
179  		 * If 11ac is supported and if the peer is
180  		 * sending VHT capabilities,
181  		 * then htMaxRxAMpduFactor should be
182  		 * overloaded with VHT maxAMPDULenExp
183  		 */
184  		sta_ds->htMaxRxAMpduFactor = vht_caps->maxAMPDULenExp;
185  		if (session_entry->htSupportedChannelWidthSet) {
186  			if (vht_oper && vht_oper->present)
187  				sta_ds->vhtSupportedChannelWidthSet =
188  				     lim_get_vht_ch_width(vht_caps,
189  							  vht_oper,
190  							  &assoc_rsp->HTInfo);
191  			else
192  				sta_ds->vhtSupportedChannelWidthSet =
193  					   WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
194  		}
195  		sta_ds->vht_mcs_10_11_supp = 0;
196  		if (mac_ctx->mlme_cfg->vht_caps.vht_cap_info.
197  		    vht_mcs_10_11_supp &&
198  		    assoc_rsp->qcn_ie.present &&
199  		    assoc_rsp->qcn_ie.vht_mcs11_attr.present)
200  			sta_ds->vht_mcs_10_11_supp =
201  				assoc_rsp->qcn_ie.vht_mcs11_attr.
202  				vht_mcs_10_11_supp;
203  	}
204  
205  	lim_update_stads_he_caps(mac_ctx, sta_ds, assoc_rsp,
206  				 session_entry, beacon);
207  
208  	lim_update_stads_eht_caps(mac_ctx, sta_ds, assoc_rsp,
209  				  session_entry, beacon);
210  
211  	if (lim_is_sta_he_capable(sta_ds))
212  		he_cap = &assoc_rsp->he_cap;
213  
214  	if (lim_is_sta_eht_capable(sta_ds))
215  		eht_cap = &assoc_rsp->eht_cap;
216  
217  	if (session_entry->lim_join_req)
218  		bss_desc = &session_entry->lim_join_req->bssDescription;
219  
220  	if (lim_populate_peer_rate_set(mac_ctx, &sta_ds->supportedRates,
221  				assoc_rsp->HTCaps.supportedMCSSet,
222  				false, session_entry,
223  				vht_caps, he_cap, eht_cap,
224  				sta_ds, bss_desc) !=
225  				QDF_STATUS_SUCCESS) {
226  		pe_err("could not get rateset and extended rate set");
227  		return;
228  	}
229  	sta_ds->vhtSupportedRxNss =
230  		((sta_ds->supportedRates.vhtTxMCSMap & MCSMAPMASK2x2)
231  		 == MCSMAPMASK2x2) ? 1 : 2;
232  
233  	/* If one of the rates is 11g rates, set the ERP mode. */
234  	if ((phy_mode == WNI_CFG_PHY_MODE_11G) &&
235  		sirIsArate(sta_ds->supportedRates.llaRates[0] & 0x7f))
236  		sta_ds->erpEnabled = eHAL_SET;
237  
238  	/* Could not get prop rateset from CFG. Log error. */
239  	sta_ds->qosMode = 0;
240  	sta_ds->lleEnabled = 0;
241  
242  	/* update TSID to UP mapping */
243  	if (qos_mode) {
244  		if (assoc_rsp->edcaPresent) {
245  			QDF_STATUS status;
246  
247  			qdf_mem_copy(&sta_ds->qos.peer_edca_params,
248  				     &assoc_rsp->edca,
249  				     sizeof(assoc_rsp->edca));
250  
251  			status =
252  				sch_beacon_edca_process(mac_ctx,
253  					&assoc_rsp->edca, session_entry);
254  			pe_debug("Edca set update based on AssocRsp: status %d",
255  				status);
256  			if (status != QDF_STATUS_SUCCESS) {
257  				pe_err("Edca error in AssocResp");
258  			} else {
259  				/* update default tidmap based on ACM */
260  				sta_ds->qosMode = 1;
261  				sta_ds->lleEnabled = 1;
262  			}
263  		}
264  	}
265  
266  	sta_ds->wmeEnabled = 0;
267  	sta_ds->wsmEnabled = 0;
268  	if (session_entry->limWmeEnabled && assoc_rsp->wmeEdcaPresent) {
269  		QDF_STATUS status;
270  
271  		qdf_mem_copy(&sta_ds->qos.peer_edca_params,
272  			     &assoc_rsp->edca,
273  			     sizeof(assoc_rsp->edca));
274  
275  		status = sch_beacon_edca_process(mac_ctx, &assoc_rsp->edca,
276  				session_entry);
277  		pe_debug("WME Edca set update based on AssocRsp: status %d",
278  			status);
279  
280  		if (status != QDF_STATUS_SUCCESS)
281  			pe_err("WME Edca error in AssocResp - ignoring");
282  
283  			else {
284  				/* update default tidmap based on HashACM */
285  				sta_ds->qosMode = 1;
286  				sta_ds->wmeEnabled = 1;
287  			}
288  	} else {
289  		/*
290  		 * We received assoc rsp from a legacy AP.
291  		 * So fill in the default  local EDCA params.
292  		 * This is needed (refer to bug #14989) as we'll
293  		 * be passing the gLimEdcaParams to HAL in
294  		 * lim_process_sta_mlm_add_bss_rsp().
295  		 */
296  		sch_set_default_edca_params(mac_ctx, session_entry);
297  	}
298  
299  	if (qos_mode && (!sta_ds->qosMode) &&
300  		 sta_ds->mlmStaContext.htCapability) {
301  		/*
302  		 * Enable QOS for all HT AP's even though WMM
303  		 * or 802.11E IE is not present
304  		 */
305  		sta_ds->qosMode = 1;
306  		sta_ds->wmeEnabled = 1;
307  	}
308  	if (session_entry->limRmfEnabled)
309  		sta_ds->rmfEnabled = 1;
310  
311  	if (session_entry->vhtCapability && assoc_rsp->oper_mode_ntf.present) {
312  		/**
313  		 * OMN IE is present in the Assoc response, but the channel
314  		 * width/Rx NSS update will happen through the peer_assoc cmd.
315  		 */
316  		omn_ie_ch_width = assoc_rsp->oper_mode_ntf.chanWidth;
317  		pe_debug("OMN IE present in re/assoc rsp, omn_ie_ch_width: %d",
318  			 omn_ie_ch_width);
319  		lim_update_omn_ie_ch_width(session_entry->vdev,
320  					   omn_ie_ch_width);
321  	}
322  
323  	if (lim_process_srp_ie(assoc_rsp, sta_ds) == QDF_STATUS_SUCCESS)
324  		lim_update_vdev_sr_elements(session_entry, sta_ds);
325  }
326  
327  /**
328   * lim_update_ric_data() - update session with ric data
329   * @mac_ctx: Pointer to Global MAC structure
330   * @session_entry: PE session handle
331   * @assoc_rsp:  pointer to assoc response
332   *
333   * This function is called by lim_process_assoc_rsp_frame() to
334   * update PE session context with RIC data.
335   *
336   * Return: None
337   */
lim_update_ric_data(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)338  static void lim_update_ric_data(struct mac_context *mac_ctx,
339  	 struct pe_session *session_entry, tpSirAssocRsp assoc_rsp)
340  {
341  	if (session_entry->ricData) {
342  		qdf_mem_free(session_entry->ricData);
343  		session_entry->ricData = NULL;
344  		session_entry->RICDataLen = 0;
345  	}
346  	if (assoc_rsp->ricPresent) {
347  		session_entry->RICDataLen =
348  			assoc_rsp->num_RICData * sizeof(tDot11fIERICDataDesc);
349  		if (session_entry->RICDataLen) {
350  			session_entry->ricData =
351  				qdf_mem_malloc(session_entry->RICDataLen);
352  			if (!session_entry->ricData)
353  				session_entry->RICDataLen = 0;
354  			else
355  				qdf_mem_copy(session_entry->ricData,
356  					&assoc_rsp->RICData[0],
357  					session_entry->RICDataLen);
358  		} else {
359  			pe_err("RIC data not present");
360  		}
361  	} else {
362  		session_entry->RICDataLen = 0;
363  		session_entry->ricData = NULL;
364  	}
365  	return;
366  }
367  
368  #ifdef FEATURE_WLAN_ESE
369  /**
370   * lim_update_ese_tspec() - update session with Tspec info.
371   * @mac_ctx: Pointer to Global MAC structure
372   * @session_entry: PE session handle
373   * @assoc_rsp:  pointer to assoc response
374   *
375   * This function is called by lim_process_assoc_rsp_frame() to
376   * update PE session context with Tspec data.
377   *
378   * Return: None
379   */
lim_update_ese_tspec(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)380  static void lim_update_ese_tspec(struct mac_context *mac_ctx,
381  	 struct pe_session *session_entry, tpSirAssocRsp assoc_rsp)
382  {
383  	if (session_entry->tspecIes) {
384  		qdf_mem_free(session_entry->tspecIes);
385  		session_entry->tspecIes = NULL;
386  		session_entry->tspecLen = 0;
387  	}
388  	if (assoc_rsp->tspecPresent) {
389  		pe_debug("Tspec EID present in assoc rsp");
390  		session_entry->tspecLen =
391  			assoc_rsp->num_tspecs * sizeof(tDot11fIEWMMTSPEC);
392  		if (session_entry->tspecLen) {
393  			session_entry->tspecIes =
394  				qdf_mem_malloc(session_entry->tspecLen);
395  			if (!session_entry->tspecIes)
396  				session_entry->tspecLen = 0;
397  			else
398  				qdf_mem_copy(session_entry->tspecIes,
399  						&assoc_rsp->TSPECInfo[0],
400  						session_entry->tspecLen);
401  		} else {
402  			pe_err("TSPEC has Zero length");
403  		}
404  	} else {
405  		session_entry->tspecLen = 0;
406  		session_entry->tspecIes = NULL;
407  	}
408  	return;
409  }
410  
411  /**
412   * lim_update_ese_tsm() - update session with TSM info.
413   * @mac_ctx: Pointer to Global MAC structure
414   * @session_entry: PE session handle
415   * @assoc_rsp:  pointer to assoc response
416   *
417   * This function is called by lim_process_assoc_rsp_frame() to
418   * update PE session context with TSM IE data and send
419   * eWNI_TSM_IE_IND to SME.
420   *
421   * Return: None
422   */
lim_update_ese_tsm(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)423  static void lim_update_ese_tsm(struct mac_context *mac_ctx,
424  	 struct pe_session *session_entry, tpSirAssocRsp assoc_rsp)
425  {
426  	uint8_t cnt = 0;
427  	tpEseTSMContext tsm_ctx;
428  
429  	pe_debug("TSM IE Present in Reassoc Rsp");
430  	/*
431  	 * Start the TSM  timer only if the TSPEC
432  	 * Ie is present in the reassoc rsp
433  	 */
434  	if (!assoc_rsp->tspecPresent) {
435  		pe_debug("TSM present but TSPEC IE not present");
436  		return;
437  	}
438  	tsm_ctx = &session_entry->eseContext.tsm;
439  	/* Find the TSPEC IE with VO user priority */
440  	for (cnt = 0; cnt < assoc_rsp->num_tspecs; cnt++) {
441  		if (upToAc(assoc_rsp->TSPECInfo[cnt].user_priority) ==
442  			QCA_WLAN_AC_VO) {
443  			tsm_ctx->tid =
444  				assoc_rsp->TSPECInfo[cnt].user_priority;
445  			qdf_mem_copy(&tsm_ctx->tsmInfo,
446  				&assoc_rsp->tsmIE, sizeof(struct ese_tsm_ie));
447  			lim_send_sme_tsm_ie_ind(mac_ctx,
448  				session_entry, assoc_rsp->tsmIE.tsid,
449  				assoc_rsp->tsmIE.state,
450  				assoc_rsp->tsmIE.msmt_interval);
451  			if (tsm_ctx->tsmInfo.state)
452  				tsm_ctx->tsmMetrics.RoamingCount++;
453  			break;
454  		}
455  	}
456  }
457  #endif
458  
459  /**
460   * lim_update_stads_ext_cap() - update sta ds with ext cap
461   * @mac_ctx: Pointer to Global MAC structure
462   * @session_entry: PE session handle
463   * @assoc_rsp:  pointer to assoc response
464   *
465   * This function is called by lim_process_assoc_rsp_frame() to
466   * update STA DS with ext capabilities.
467   *
468   * Return: None
469   */
lim_update_stads_ext_cap(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirAssocRsp assoc_rsp,tpDphHashNode sta_ds)470  static void lim_update_stads_ext_cap(struct mac_context *mac_ctx,
471  	struct pe_session *session_entry, tpSirAssocRsp assoc_rsp,
472  	tpDphHashNode sta_ds)
473  {
474  	struct s_ext_cap *ext_cap;
475  	struct wlan_objmgr_vdev *vdev;
476  	struct vdev_mlme_obj *mlme_obj;
477  
478  	if (!assoc_rsp->ExtCap.present) {
479  		sta_ds->timingMeasCap = 0;
480  #ifdef FEATURE_WLAN_TDLS
481  		mlme_set_tdls_prohibited(session_entry->vdev, false);
482  		mlme_set_tdls_chan_switch_prohibited(session_entry->vdev,
483  						     false);
484  #endif
485  		pe_debug("ExtCap not present");
486  		return;
487  	}
488  
489  	ext_cap = (struct s_ext_cap *)assoc_rsp->ExtCap.bytes;
490  	lim_set_stads_rtt_cap(sta_ds, ext_cap, mac_ctx);
491  
492  	vdev = session_entry->vdev;
493  	if (vdev) {
494  		mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
495  		if (!mlme_obj)
496  			pe_err("vdev component object is NULL");
497  		else
498  			mlme_obj->ext_vdev_ptr->connect_info.timing_meas_cap =
499  							sta_ds->timingMeasCap;
500  	}
501  
502  #ifdef FEATURE_WLAN_TDLS
503  	mlme_set_tdls_prohibited(session_entry->vdev, ext_cap->tdls_prohibited);
504  	mlme_set_tdls_chan_switch_prohibited(session_entry->vdev,
505  					    ext_cap->tdls_chan_swit_prohibited);
506  		;
507  	pe_debug("ExtCap: tdls_prohibited: %d tdls_chan_swit_prohibited: %d",
508  		ext_cap->tdls_prohibited,
509  		ext_cap->tdls_chan_swit_prohibited);
510  #endif
511  	lim_set_peer_twt_cap(session_entry, ext_cap);
512  }
513  
514  /**
515   * lim_stop_reassoc_retry_timer() - Cleanup after reassoc response is received
516   *  @mac_ctx: Global MAC context
517   *
518   *  Stop the reassoc retry timer and release the stored reassoc request.
519   *
520   *  Return: None
521   */
lim_stop_reassoc_retry_timer(struct mac_context * mac_ctx)522  static void lim_stop_reassoc_retry_timer(struct mac_context *mac_ctx)
523  {
524  	mac_ctx->lim.reAssocRetryAttempt = 0;
525  	if ((mac_ctx->lim.pe_session)
526  		&& (NULL !=
527  			mac_ctx->lim.pe_session->pLimMlmReassocRetryReq)) {
528  		qdf_mem_free(
529  			mac_ctx->lim.pe_session->pLimMlmReassocRetryReq);
530  		mac_ctx->lim.pe_session->pLimMlmReassocRetryReq = NULL;
531  	}
532  	lim_deactivate_and_change_timer(mac_ctx, eLIM_REASSOC_FAIL_TIMER);
533  }
534  
lim_get_nss_supported_by_ap(tDot11fIEVHTCaps * vht_caps,tDot11fIEHTCaps * ht_caps,tDot11fIEhe_cap * he_caps)535  uint8_t lim_get_nss_supported_by_ap(tDot11fIEVHTCaps *vht_caps,
536  				    tDot11fIEHTCaps *ht_caps,
537  				    tDot11fIEhe_cap *he_caps)
538  {
539  	if (he_caps->present) {
540  		if ((he_caps->rx_he_mcs_map_lt_80 & 0xC0) != 0xC0)
541  			return NSS_4x4_MODE;
542  
543  		if ((he_caps->rx_he_mcs_map_lt_80 & 0x30) != 0x30)
544  			return NSS_3x3_MODE;
545  
546  		if ((he_caps->rx_he_mcs_map_lt_80 & 0x0C) != 0x0C)
547  			return NSS_2x2_MODE;
548  	} else if (vht_caps->present) {
549  		if ((vht_caps->rxMCSMap & 0xC0) != 0xC0)
550  			return NSS_4x4_MODE;
551  
552  		if ((vht_caps->rxMCSMap & 0x30) != 0x30)
553  			return NSS_3x3_MODE;
554  
555  		if ((vht_caps->rxMCSMap & 0x0C) != 0x0C)
556  			return NSS_2x2_MODE;
557  	} else if (ht_caps->present) {
558  		if (ht_caps->supportedMCSSet[3])
559  			return NSS_4x4_MODE;
560  
561  		if (ht_caps->supportedMCSSet[2])
562  			return NSS_3x3_MODE;
563  
564  		if (ht_caps->supportedMCSSet[1])
565  			return NSS_2x2_MODE;
566  	}
567  
568  	return NSS_1x1_MODE;
569  }
570  
571  #ifdef WLAN_FEATURE_11AX
lim_process_he_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)572  static void lim_process_he_info(tpSirProbeRespBeacon beacon,
573  				tpDphHashNode sta_ds)
574  {
575  	if (beacon->he_op.present)
576  		sta_ds->parsed_ies.he_operation = beacon->he_op;
577  }
578  #else
lim_process_he_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)579  static inline void lim_process_he_info(tpSirProbeRespBeacon beacon,
580  				       tpDphHashNode sta_ds)
581  {
582  }
583  #endif
584  
585  #ifdef WLAN_FEATURE_SR
lim_process_srp_ie(tpSirAssocRsp ar,tpDphHashNode sta_ds)586  QDF_STATUS lim_process_srp_ie(tpSirAssocRsp ar, tpDphHashNode sta_ds)
587  {
588  	QDF_STATUS status = QDF_STATUS_E_NOSUPPORT;
589  
590  	if (ar->srp_ie.present) {
591  		sta_ds->parsed_ies.srp_ie = ar->srp_ie;
592  		status = QDF_STATUS_SUCCESS;
593  	}
594  
595  	return status;
596  }
597  #endif
598  
599  #ifdef WLAN_FEATURE_11BE
lim_process_eht_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)600  static void lim_process_eht_info(tpSirProbeRespBeacon beacon,
601  				 tpDphHashNode sta_ds)
602  {
603  	if (beacon->eht_op.present)
604  		sta_ds->parsed_ies.eht_operation = beacon->eht_op;
605  }
606  #else
lim_process_eht_info(tpSirProbeRespBeacon beacon,tpDphHashNode sta_ds)607  static inline void lim_process_eht_info(tpSirProbeRespBeacon beacon,
608  					tpDphHashNode sta_ds)
609  {
610  }
611  #endif
612  
613  #define MAX_RETRY_TIMER 1500
614  static QDF_STATUS
lim_handle_pmfcomeback_timer(struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)615  lim_handle_pmfcomeback_timer(struct pe_session *session_entry,
616  			     tpSirAssocRsp assoc_rsp)
617  {
618  	uint16_t timeout_value;
619  
620  	if (session_entry->opmode != QDF_STA_MODE)
621  		return QDF_STATUS_E_FAILURE;
622  
623  	if (session_entry->limRmfEnabled &&
624  	    session_entry->pmf_retry_timer_info.retried &&
625  	    assoc_rsp->status_code == STATUS_ASSOC_REJECTED_TEMPORARILY) {
626  		pe_debug("Already retry in progress");
627  		return QDF_STATUS_SUCCESS;
628  	}
629  
630  	/*
631  	 * Handle association Response for sta mode with RMF enabled and TRY
632  	 * again later with timeout interval and Assoc comeback type
633  	 */
634  	if (!session_entry->limRmfEnabled || assoc_rsp->status_code !=
635  	    STATUS_ASSOC_REJECTED_TEMPORARILY ||
636  	    !assoc_rsp->TimeoutInterval.present ||
637  	    assoc_rsp->TimeoutInterval.timeoutType !=
638  	    SIR_MAC_TI_TYPE_ASSOC_COMEBACK ||
639  	    session_entry->pmf_retry_timer_info.retried)
640  		return QDF_STATUS_E_FAILURE;
641  
642  	timeout_value = assoc_rsp->TimeoutInterval.timeoutValue;
643  	if (timeout_value < 10) {
644  		/*
645  		 * if this value is less than 10 then our timer
646  		 * will fail to start and due to this we will
647  		 * never re-attempt. Better modify the timer
648  		 * value here.
649  		 */
650  		timeout_value = 10;
651  	}
652  	timeout_value = QDF_MIN(MAX_RETRY_TIMER, timeout_value);
653  	pe_debug("ASSOC res with eSIR_MAC_TRY_AGAIN_LATER recvd.Starting timer to wait timeout: %d",
654  		 timeout_value);
655  	if (QDF_STATUS_SUCCESS !=
656  	    qdf_mc_timer_start(&session_entry->pmf_retry_timer,
657  			       timeout_value)) {
658  		pe_err("Failed to start comeback timer");
659  		return QDF_STATUS_E_FAILURE;
660  	}
661  	session_entry->pmf_retry_timer_info.retried = true;
662  
663  	return QDF_STATUS_SUCCESS;
664  }
665  
clean_up_ft_sha384(tpSirAssocRsp assoc_rsp,bool sha384_akm)666  static void clean_up_ft_sha384(tpSirAssocRsp assoc_rsp, bool sha384_akm)
667  {
668  	if (sha384_akm) {
669  		qdf_mem_free(assoc_rsp->sha384_ft_subelem.gtk);
670  		qdf_mem_free(assoc_rsp->sha384_ft_subelem.igtk);
671  	}
672  }
673  
674  #ifdef WLAN_FEATURE_ROAM_OFFLOAD
lim_set_r0kh(tpSirAssocRsp assoc_rsp,struct pe_session * session)675  static void lim_set_r0kh(tpSirAssocRsp assoc_rsp, struct pe_session *session)
676  {
677  	struct mlme_legacy_priv *mlme_priv;
678  
679  	mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
680  	if (!mlme_priv)
681  		return;
682  	if (assoc_rsp->sha384_ft_subelem.r0kh_id.present) {
683  		mlme_priv->connect_info.ft_info.r0kh_id_len =
684  			assoc_rsp->sha384_ft_subelem.r0kh_id.num_PMK_R0_ID;
685  		qdf_mem_copy(mlme_priv->connect_info.ft_info.r0kh_id,
686  			     assoc_rsp->sha384_ft_subelem.r0kh_id.PMK_R0_ID,
687  			     mlme_priv->connect_info.ft_info.r0kh_id_len);
688  	} else if (assoc_rsp->FTInfo.R0KH_ID.present) {
689  		mlme_priv->connect_info.ft_info.r0kh_id_len =
690  			assoc_rsp->FTInfo.R0KH_ID.num_PMK_R0_ID;
691  		qdf_mem_copy(mlme_priv->connect_info.ft_info.r0kh_id,
692  			assoc_rsp->FTInfo.R0KH_ID.PMK_R0_ID,
693  			mlme_priv->connect_info.ft_info.r0kh_id_len);
694  	} else {
695  		mlme_priv->connect_info.ft_info.r0kh_id_len = 0;
696  		qdf_mem_zero(mlme_priv->connect_info.ft_info.r0kh_id,
697  			     ROAM_R0KH_ID_MAX_LEN);
698  	}
699  }
700  #else
701  static inline
lim_set_r0kh(tpSirAssocRsp assoc_rsp,struct pe_session * session)702  void lim_set_r0kh(tpSirAssocRsp assoc_rsp, struct pe_session *session) {}
703  #endif
704  
705  /**
706   * lim_get_iot_aggr_sz() - check and get IOT aggr size for configured OUI
707   *
708   * @mac_ctx: Pointer to Global MAC structure
709   * @ie_ptr: Pointer to starting IE in Beacon/Probe Response
710   * @ie_len: Length of all IEs combined
711   * @amsdu_sz: pointer to buffer to store AMSDU size
712   * @ampdu_sz: pointer to buffer to store AMPDU size
713   *
714   * This function is called to find configured vendor specific OUIs
715   * from the IEs in Beacon/Probe Response frames, if one of the OUI is
716   * present, get the configured aggr size for the OUI.
717   *
718   * Return: true if found, false otherwise.
719   */
720  static bool
lim_get_iot_aggr_sz(struct mac_context * mac,uint8_t * ie_ptr,uint32_t ie_len,uint32_t * amsdu_sz,uint32_t * ampdu_sz)721  lim_get_iot_aggr_sz(struct mac_context *mac, uint8_t *ie_ptr, uint32_t ie_len,
722  		    uint32_t *amsdu_sz, uint32_t *ampdu_sz)
723  {
724  	const uint8_t *oui, *vendor_ie;
725  	struct wlan_mlme_iot *iot;
726  	uint32_t oui_len, aggr_num;
727  	int i;
728  
729  	iot = &mac->mlme_cfg->iot;
730  	aggr_num = iot->aggr_num;
731  	if (!aggr_num)
732  		return false;
733  
734  	for (i = 0; i < aggr_num; i++) {
735  		oui = iot->aggr[i].oui;
736  		oui_len = iot->aggr[i].oui_len;
737  		vendor_ie = wlan_get_vendor_ie_ptr_from_oui(oui, oui_len,
738  							    ie_ptr, ie_len);
739  		if (!vendor_ie)
740  			continue;
741  
742  		*amsdu_sz = iot->aggr[i].amsdu_sz;
743  		*ampdu_sz = iot->aggr[i].ampdu_sz;
744  		return true;
745  	}
746  
747  	return false;
748  }
749  
750  /**
751   * lim_update_iot_aggr_sz() - check and update IOT aggr size
752   *
753   * @mac_ctx: Pointer to Global MAC structure
754   * @ie_ptr: Pointer to starting IE in Beacon/Probe Response
755   * @ie_len: Length of all IEs combined
756   * @session_entry: A pointer to session entry
757   *
758   * This function is called to find configured vendor specific OUIs
759   * from the IEs in Beacon/Probe Response frames, and set the aggr
760   * size accordingly.
761   *
762   * Return: None
763   */
764  static void
lim_update_iot_aggr_sz(struct mac_context * mac_ctx,uint8_t * ie_ptr,uint32_t ie_len,struct pe_session * session_entry)765  lim_update_iot_aggr_sz(struct mac_context *mac_ctx, uint8_t *ie_ptr,
766  		       uint32_t ie_len, struct pe_session *session_entry)
767  {
768  	int ret;
769  	uint32_t amsdu_sz, ampdu_sz;
770  	bool iot_hit;
771  
772  	if (!ie_ptr || !ie_len)
773  		return;
774  
775  	iot_hit = lim_get_iot_aggr_sz(mac_ctx, ie_ptr, ie_len,
776  				      &amsdu_sz, &ampdu_sz);
777  	if (!iot_hit)
778  		return;
779  
780  	pe_debug("Try to set iot amsdu size: %u", amsdu_sz);
781  	ret = wma_cli_set_command(session_entry->smeSessionId,
782  				  GEN_VDEV_PARAM_AMSDU, amsdu_sz, GEN_CMD);
783  	if (ret)
784  		pe_err("Failed to set iot amsdu size: %d", ret);
785  }
786  
787  /**
788   * hdd_cm_update_mcs_rate_set() - Update MCS rate set from HT capability
789   * @vdev: Pointer to vdev object
790   * @ht_cap: pointer to parsed HT capability
791   *
792   * Return: None.
793   */
794  static inline void
lim_update_mcs_rate_set(struct wlan_objmgr_vdev * vdev,tDot11fIEHTCaps * ht_cap)795  lim_update_mcs_rate_set(struct wlan_objmgr_vdev *vdev, tDot11fIEHTCaps *ht_cap)
796  {
797  	qdf_size_t len = 0;
798  	int i;
799  	uint32_t *mcs_set;
800  	uint8_t dst_rate[VALID_MAX_MCS_INDEX] = {0};
801  
802  	mcs_set = (uint32_t *)ht_cap->supportedMCSSet;
803  	for (i = 0; i < VALID_MAX_MCS_INDEX; i++) {
804  		if (!QDF_GET_BITS(*mcs_set, i, 1))
805  			continue;
806  
807  		dst_rate[len++] = i;
808  	}
809  
810  	mlme_set_mcs_rate(vdev, dst_rate, len);
811  }
812  
813  #ifdef WLAN_FEATURE_11BE
814  /**
815   * lim_update_sta_vdev_punc() - Update puncture set according to assoc resp
816   * @psoc: Pointer to psoc object
817   * @vdev_id: vdev id
818   * @assoc_resp: pointer to parsed associate response
819   *
820   * Return: None.
821   */
822  static QDF_STATUS
lim_update_sta_vdev_punc(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,tpSirAssocRsp assoc_resp)823  lim_update_sta_vdev_punc(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
824  			 tpSirAssocRsp assoc_resp)
825  {
826  	struct wlan_objmgr_vdev *vdev;
827  	struct wlan_channel *des_chan;
828  	enum phy_ch_width ori_bw;
829  	uint16_t ori_puncture_bitmap;
830  	uint16_t primary_puncture_bitmap = 0;
831  	qdf_freq_t center_freq_320;
832  	uint8_t band_mask;
833  
834  	if (!assoc_resp->eht_op.disabled_sub_chan_bitmap_present)
835  		return QDF_STATUS_SUCCESS;
836  	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
837  						    WLAN_LEGACY_MAC_ID);
838  	if (!vdev) {
839  		pe_err("vdev not found for id: %d", vdev_id);
840  		return QDF_STATUS_E_FAILURE;
841  	}
842  
843  	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
844  	ori_puncture_bitmap =
845  		*(uint16_t *)assoc_resp->eht_op.disabled_sub_chan_bitmap;
846  
847  	ori_bw = wlan_mlme_convert_eht_op_bw_to_phy_ch_width(
848  					assoc_resp->eht_op.channel_width);
849  
850  	if (ori_bw == CH_WIDTH_320MHZ) {
851  		if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq))
852  			band_mask = BIT(REG_BAND_2G);
853  		else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq))
854  			band_mask = BIT(REG_BAND_6G);
855  		else
856  			band_mask = BIT(REG_BAND_5G);
857  		center_freq_320 = wlan_reg_chan_band_to_freq(
858  						wlan_vdev_get_pdev(vdev),
859  						assoc_resp->eht_op.ccfs1,
860  						band_mask);
861  	} else {
862  		center_freq_320 = 0;
863  	}
864  	wlan_reg_extract_puncture_by_bw(ori_bw, ori_puncture_bitmap,
865  					des_chan->ch_freq,
866  					center_freq_320,
867  					CH_WIDTH_20MHZ,
868  					&primary_puncture_bitmap);
869  	if (primary_puncture_bitmap) {
870  		pe_err("sta vdev %d freq %d assoc rsp bw %d puncture 0x%x primary chan is punctured",
871  		       vdev_id, des_chan->ch_freq, ori_bw, ori_puncture_bitmap);
872  		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
873  		return QDF_STATUS_E_FAILURE;
874  	}
875  	if (des_chan->ch_width == ori_bw)
876  		des_chan->puncture_bitmap = ori_puncture_bitmap;
877  	else
878  		wlan_reg_extract_puncture_by_bw(ori_bw, ori_puncture_bitmap,
879  						des_chan->ch_freq,
880  						center_freq_320,
881  						des_chan->ch_width,
882  						&des_chan->puncture_bitmap);
883  	pe_debug("sta vdev %d freq %d assoc rsp bw %d puncture 0x%x 320M center frequency %d intersect bw %d puncture 0x%x",
884  		 vdev_id, des_chan->ch_freq, ori_bw, ori_puncture_bitmap,
885  		 center_freq_320, des_chan->ch_width,
886  		 des_chan->puncture_bitmap);
887  	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
888  
889  	return QDF_STATUS_SUCCESS;
890  }
891  #else
892  static QDF_STATUS
lim_update_sta_vdev_punc(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,tpSirAssocRsp assoc_resp)893  lim_update_sta_vdev_punc(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
894  			 tpSirAssocRsp assoc_resp)
895  {
896  	return QDF_STATUS_SUCCESS;
897  }
898  #endif
899  
900  /**
901   * hdd_cm_update_rate_set() - Update rate set according to assoc resp
902   * @psoc: Pointer to psoc object
903   * @vdev_id: vdev id
904   * @assoc_resp: pointer to parsed associate response
905   *
906   * Return: None.
907   */
908  static void
lim_update_vdev_rate_set(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,tpSirAssocRsp assoc_resp)909  lim_update_vdev_rate_set(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
910  			 tpSirAssocRsp assoc_resp)
911  {
912  	struct wlan_objmgr_vdev *vdev;
913  
914  	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
915  						    WLAN_LEGACY_MAC_ID);
916  	if (!vdev) {
917  		pe_err("vdev not found for id: %d", vdev_id);
918  		return;
919  	}
920  
921  	if (assoc_resp->suppRatesPresent && assoc_resp->supportedRates.numRates)
922  		mlme_set_opr_rate(vdev, assoc_resp->supportedRates.rate,
923  				  assoc_resp->supportedRates.numRates);
924  
925  	if (assoc_resp->extendedRatesPresent &&
926  	    assoc_resp->extendedRates.numRates)
927  		mlme_set_ext_opr_rate(vdev,
928  				      assoc_resp->extendedRates.rate,
929  				      assoc_resp->extendedRates.numRates);
930  	else
931  		mlme_clear_ext_opr_rate(vdev);
932  
933  	if (assoc_resp->HTCaps.present)
934  		lim_update_mcs_rate_set(vdev, &assoc_resp->HTCaps);
935  	else
936  		mlme_clear_mcs_rate(vdev);
937  
938  	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
939  }
940  
941  #ifdef WLAN_FEATURE_11BE_MLO
942  static void
lim_process_assoc_rsp_t2lm(struct pe_session * session,tpSirAssocRsp assoc_rsp)943  lim_process_assoc_rsp_t2lm(struct pe_session *session,
944  			   tpSirAssocRsp assoc_rsp)
945  {
946  	struct wlan_objmgr_vdev *vdev;
947  	struct wlan_t2lm_context *t2lm_ctx;
948  	struct wlan_mlo_dev_context *mlo_dev_ctx;
949  	struct wlan_objmgr_psoc *psoc;
950  
951  	if (!session || !assoc_rsp) {
952  		pe_err("invalid input parameters");
953  		return;
954  	}
955  
956  	vdev = session->vdev;
957  	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
958  		return;
959  
960  	psoc = wlan_vdev_get_psoc(vdev);
961  	if (!psoc)
962  		return;
963  
964  	if (!wlan_mlme_get_t2lm_negotiation_supported(psoc)) {
965  		pe_err_rl("T2LM negotiation not supported");
966  		return;
967  	}
968  
969  	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
970  	if (!mlo_dev_ctx) {
971  		pe_err("ml dev ctx is null");
972  		return;
973  	}
974  
975  	if (wlan_vdev_mlme_is_mlo_link_vdev(vdev))
976  		return;
977  
978  	if (assoc_rsp->t2lm_ctx.upcoming_t2lm.t2lm.direction ==
979  	    WLAN_T2LM_INVALID_DIRECTION &&
980  	    assoc_rsp->t2lm_ctx.established_t2lm.t2lm.direction ==
981  	    WLAN_T2LM_INVALID_DIRECTION) {
982  		pe_debug("No t2lm IE");
983  		return;
984  	}
985  
986  	t2lm_ctx = &mlo_dev_ctx->sta_ctx->copied_t2lm_ie_assoc_rsp;
987  
988  	if (assoc_rsp->t2lm_ctx.established_t2lm.t2lm.expected_duration_present &&
989  	    !assoc_rsp->t2lm_ctx.established_t2lm.t2lm.mapping_switch_time_present &&
990  	    assoc_rsp->t2lm_ctx.established_t2lm.t2lm.direction !=
991  			WLAN_T2LM_INVALID_DIRECTION) {
992  		qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm,
993  			     &assoc_rsp->t2lm_ctx.established_t2lm.t2lm,
994  			     sizeof(struct wlan_t2lm_info));
995  	}
996  
997  	if (assoc_rsp->t2lm_ctx.upcoming_t2lm.t2lm.mapping_switch_time_present &&
998  	    assoc_rsp->t2lm_ctx.established_t2lm.t2lm.direction !=
999  			WLAN_T2LM_INVALID_DIRECTION) {
1000  		qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm,
1001  			     &assoc_rsp->t2lm_ctx.upcoming_t2lm.t2lm,
1002  			     sizeof(struct wlan_t2lm_info));
1003  	}
1004  }
1005  #else
1006  static inline void
lim_process_assoc_rsp_t2lm(struct pe_session * session,tpSirAssocRsp assoc_rsp)1007  lim_process_assoc_rsp_t2lm(struct pe_session *session,
1008  			   tpSirAssocRsp assoc_rsp)
1009  {
1010  }
1011  #endif
1012  
1013  #ifdef WLAN_FEATURE_11BE_MLO
1014  /**
1015   * lim_cache_emlsr_params() - cache the EMLSR parameters in ML STA context
1016   * @session_entry: session entry
1017   * @assoc_rsp: pointer to parsed associate response
1018   *
1019   * Return: None
1020   */
lim_cache_emlsr_params(struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)1021  static void lim_cache_emlsr_params(struct pe_session *session_entry,
1022  				   tpSirAssocRsp assoc_rsp)
1023  {
1024  	struct wlan_mlo_sta *sta_ctx;
1025  	struct wlan_objmgr_vdev *vdev = session_entry->vdev;
1026  	struct emlsr_capability *ml_emlcap;
1027  
1028  	wlan_objmgr_vdev_get_ref(vdev, WLAN_MLME_SB_ID);
1029  	if (!vdev) {
1030  		pe_err("vdev is null");
1031  		return;
1032  	}
1033  
1034  	if (!vdev->mlo_dev_ctx) {
1035  		pe_err("mlo dev ctx is null");
1036  		goto end;
1037  	}
1038  
1039  	sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
1040  	if (!sta_ctx) {
1041  		pe_err("sta ctx is null");
1042  		goto end;
1043  	}
1044  
1045  	ml_emlcap = &sta_ctx->emlsr_cap;
1046  
1047  	if (wlan_vdev_mlme_cap_get(vdev,
1048  				   WLAN_VDEV_C_EMLSR_CAP)) {
1049  		ml_emlcap->emlsr_supp = true;
1050  		ml_emlcap->trans_timeout =
1051  		assoc_rsp->mlo_ie.mlo_ie.eml_capabilities_info.transition_timeout;
1052  	} else {
1053  		ml_emlcap->emlsr_supp = false;
1054  		ml_emlcap->trans_timeout = 0;
1055  	}
1056  
1057  	pe_debug("EML caps support%d timeout%d", ml_emlcap->emlsr_supp,
1058  		 ml_emlcap->trans_timeout);
1059  end:
1060  	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
1061  }
1062  #else
lim_cache_emlsr_params(struct pe_session * session_entry,tpSirAssocRsp assoc_rsp)1063  static inline void lim_cache_emlsr_params(struct pe_session *session_entry,
1064  					  tpSirAssocRsp assoc_rsp)
1065  {
1066  }
1067  #endif
1068  
1069  /**
1070   * lim_send_join_fail_on_vdev() - Send join failure for link vdev
1071   * @mac_ctx: Pointer to Global MAC structure
1072   * @session_entry: Session entry
1073   * @result_code: result code to send in join result
1074   *
1075   * This function sends join failure when bssid of assoc/reassoc
1076   * resp doesn't match with current bssid
1077   */
1078  static
lim_send_join_fail_on_vdev(struct mac_context * mac_ctx,struct pe_session * session_entry,enum eSirResultCodes result_code)1079  void lim_send_join_fail_on_vdev(struct mac_context *mac_ctx,
1080  				struct pe_session *session_entry,
1081  				enum eSirResultCodes result_code)
1082  {
1083  	if (!wlan_vdev_mlme_is_mlo_link_vdev(session_entry->vdev))
1084  		return;
1085  
1086  	session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
1087  	MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
1088  			 session_entry->peSessionId,
1089  			 session_entry->limSmeState));
1090  
1091  	/* Send Join response to Host */
1092  	lim_handle_sme_join_result(
1093  			mac_ctx, result_code, STATUS_UNSPECIFIED_FAILURE,
1094  			session_entry);
1095  }
1096  
1097  /**
1098   * lim_process_assoc_rsp_frame() - Processes assoc response
1099   * @mac_ctx: Pointer to Global MAC structure
1100   * @rx_packet_info    - A pointer to Rx packet info structure
1101   * @frame_body_length - frame body length of reassoc/assoc response frame
1102   * @sub_type - Indicates whether it is Association Response (=0) or
1103   *                   Reassociation Response (=1) frame
1104   * @session_entry: Session entry
1105   *
1106   * This function is called by limProcessMessageQueue() upon
1107   * Re/Association Response frame reception.
1108   *
1109   * Return: None
1110   */
1111  void
lim_process_assoc_rsp_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,uint32_t frame_body_len,uint8_t subtype,struct pe_session * session_entry)1112  lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
1113  			    uint32_t frame_body_len,
1114  			    uint8_t subtype, struct pe_session *session_entry)
1115  {
1116  	uint8_t *body, *ie;
1117  	uint16_t caps, ie_len;
1118  	tSirMacAddr current_bssid;
1119  	tpSirMacMgmtHdr hdr = NULL;
1120  	tSirMacCapabilityInfo mac_capab;
1121  	tpDphHashNode sta_ds;
1122  	tpSirAssocRsp assoc_rsp;
1123  	tLimMlmAssocCnf assoc_cnf;
1124  	tSchBeaconStruct *beacon;
1125  	uint8_t ap_nss;
1126  	uint16_t aid;
1127  	int8_t rssi;
1128  	QDF_STATUS status;
1129  	enum ani_akm_type auth_type;
1130  	bool sha384_akm, twt_support_in_11n = false;
1131  	struct s_ext_cap *ext_cap;
1132  
1133  	assoc_cnf.resultCode = eSIR_SME_SUCCESS;
1134  	/* Update PE session Id */
1135  	assoc_cnf.sessionId = session_entry->peSessionId;
1136  
1137  	if (LIM_IS_AP_ROLE(session_entry)) {
1138  		/*
1139  		 * Should not have received Re/Association
1140  		 * Response frame on AP. Log error
1141  		 */
1142  		pe_err("Should not received Re/Assoc Response in role: %d",
1143  			GET_LIM_SYSTEM_ROLE(session_entry));
1144  		return;
1145  	}
1146  
1147  	if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry) ||
1148  	    wlan_vdev_mlme_is_mlo_link_vdev(session_entry->vdev)) {
1149  		hdr = (tpSirMacMgmtHdr)rx_pkt_info;
1150  		rssi = 0;
1151  	} else {
1152  		hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
1153  		rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
1154  	}
1155  
1156  	if (!hdr) {
1157  		pe_err("LFR3: Reassoc response packet header is NULL");
1158  		return;
1159  	}
1160  
1161  	pe_nofl_rl_info("Assoc rsp RX: subtype %d vdev %d sys role %d lim state %d rssi %d from " QDF_MAC_ADDR_FMT,
1162  			subtype, session_entry->vdev_id,
1163  			GET_LIM_SYSTEM_ROLE(session_entry),
1164  			session_entry->limMlmState, rssi,
1165  			QDF_MAC_ADDR_REF(hdr->sa));
1166  
1167  	beacon = qdf_mem_malloc(sizeof(tSchBeaconStruct));
1168  	if (!beacon)
1169  		return;
1170  
1171  	if (((subtype == LIM_ASSOC) &&
1172  		(session_entry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE)) ||
1173  		((subtype == LIM_REASSOC) &&
1174  		 !lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry) &&
1175  		 !MLME_IS_MLO_ROAM_SYNCH_IN_PROGRESS(mac_ctx->psoc,
1176  						     session_entry->vdev_id) &&
1177  		((session_entry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE)
1178  		&& (session_entry->limMlmState !=
1179  		eLIM_MLM_WT_FT_REASSOC_RSP_STATE)
1180  		))) {
1181  		/* Received unexpected Re/Association Response frame */
1182  		pe_debug("Received Re/Assoc rsp in unexpected state: %d on session: %d",
1183  			session_entry->limMlmState, session_entry->peSessionId);
1184  		if (!hdr->fc.retry) {
1185  			if (!(mac_ctx->lim.retry_packet_cnt & 0xf)) {
1186  				pe_err("recvd Re/Assoc rsp:not a retry frame");
1187  				lim_print_mlm_state(mac_ctx, LOGE,
1188  						session_entry->limMlmState);
1189  			} else {
1190  				mac_ctx->lim.retry_packet_cnt++;
1191  			}
1192  		}
1193  		qdf_mem_free(beacon);
1194  		return;
1195  	}
1196  	sir_copy_mac_addr(current_bssid, session_entry->bssId);
1197  	if (subtype == LIM_ASSOC) {
1198  		if (qdf_mem_cmp
1199  			(hdr->sa, current_bssid, sizeof(tSirMacAddr))) {
1200  			/*
1201  			 * Received Association Response frame from an entity
1202  			 * other than one to which request was initiated.
1203  			 * Ignore this and wait until Assoc Failure Timeout
1204  			 */
1205  			pe_warn("received AssocRsp from unexpected peer "QDF_MAC_ADDR_FMT,
1206  				QDF_MAC_ADDR_REF(hdr->sa));
1207  
1208  			if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry)) {
1209  				session_entry->is_unexpected_peer_error = true;
1210  				qdf_mem_free(beacon);
1211  				return;
1212  			}
1213  			/*
1214  			 * Send Assoc failure to avoid connection in
1215  			 * progress state for link vdev.
1216  			 */
1217  			lim_send_join_fail_on_vdev(mac_ctx, session_entry,
1218  						   eSIR_SME_ASSOC_REFUSED);
1219  			qdf_mem_free(beacon);
1220  			return;
1221  		}
1222  	} else {
1223  		if (qdf_mem_cmp
1224  			(hdr->sa, session_entry->limReAssocbssId,
1225  			sizeof(tSirMacAddr))) {
1226  			/*
1227  			 * Received Reassociation Response frame from an entity
1228  			 * other than one to which request was initiated.
1229  			 * Ignore this and wait until Reassoc Failure Timeout.
1230  			 */
1231  			pe_warn("received ReassocRsp from unexpected peer "QDF_MAC_ADDR_FMT,
1232  				QDF_MAC_ADDR_REF(hdr->sa));
1233  
1234  			if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry)) {
1235  				session_entry->is_unexpected_peer_error = true;
1236  				qdf_mem_free(beacon);
1237  				return;
1238  			}
1239  
1240  			/*
1241  			 * Send Reassoc failure to avoid connection in
1242  			 * progress state for link vdev.
1243  			 */
1244  			lim_send_join_fail_on_vdev(mac_ctx, session_entry,
1245  						   eSIR_SME_REASSOC_REFUSED);
1246  			qdf_mem_free(beacon);
1247  			return;
1248  		}
1249  	}
1250  
1251  	assoc_rsp = qdf_mem_malloc(sizeof(*assoc_rsp));
1252  	if (!assoc_rsp) {
1253  		qdf_mem_free(beacon);
1254  		return;
1255  	}
1256  	/* Get pointer to Re/Association Response frame body */
1257  	if (lim_is_roam_synch_in_progress(mac_ctx->psoc, session_entry) ||
1258  	    wlan_vdev_mlme_is_mlo_link_vdev(session_entry->vdev))
1259  		body =  rx_pkt_info + SIR_MAC_HDR_LEN_3A;
1260  	else
1261  		body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
1262  	/* parse Re/Association Response frame. */
1263  	if (sir_convert_assoc_resp_frame2_struct(mac_ctx, session_entry, body,
1264  		frame_body_len, assoc_rsp) == QDF_STATUS_E_FAILURE) {
1265  		qdf_mem_free(assoc_rsp);
1266  		pe_err("Parse error Assoc resp subtype: %d" "length: %d",
1267  			frame_body_len, subtype);
1268  		qdf_mem_free(beacon);
1269  		return;
1270  	}
1271  
1272  	if (subtype == LIM_REASSOC) {
1273  		lim_cp_stats_cstats_log_assoc_resp_evt
1274  			(session_entry, CSTATS_DIR_RX, assoc_rsp->status_code,
1275  			 assoc_rsp->aid, hdr->bssId, hdr->da,
1276  			 assoc_rsp->HTCaps.present,
1277  			 assoc_rsp->VHTCaps.present, assoc_rsp->he_cap.present,
1278  			 assoc_rsp->eht_op.present, true);
1279  	} else if (subtype == LIM_ASSOC) {
1280  		lim_cp_stats_cstats_log_assoc_resp_evt
1281  			(session_entry, CSTATS_DIR_RX, assoc_rsp->status_code,
1282  			 assoc_rsp->aid, hdr->bssId, hdr->da,
1283  			 assoc_rsp->HTCaps.present,
1284  			 assoc_rsp->VHTCaps.present, assoc_rsp->he_cap.present,
1285  			 assoc_rsp->eht_op.present, false);
1286  	}
1287  
1288  	if (subtype != LIM_REASSOC) {
1289  		aid = assoc_rsp->aid & 0x3FFF;
1290  		wlan_connectivity_mgmt_event(mac_ctx->psoc,
1291  					     (struct wlan_frame_hdr *)hdr,
1292  					     session_entry->vdev_id,
1293  					     assoc_rsp->status_code, 0, rssi,
1294  					     0, 0, 0, aid,
1295  					     WLAN_ASSOC_RSP);
1296  	}
1297  
1298  	if (lim_is_session_eht_capable(session_entry)) {
1299  		uint8_t ies_offset;
1300  
1301  		if (subtype == LIM_ASSOC)
1302  			ies_offset = WLAN_ASSOC_RSP_IES_OFFSET;
1303  		else
1304  			ies_offset = WLAN_REASSOC_REQ_IES_OFFSET;
1305  
1306  		if (frame_body_len < ies_offset) {
1307  			pe_err("frame body length is < ies_offset");
1308  			return;
1309  		}
1310  
1311  		status = lim_strip_and_decode_eht_op(
1312  					body + ies_offset,
1313  					frame_body_len - ies_offset,
1314  					&assoc_rsp->eht_op,
1315  					assoc_rsp->VHTOperation,
1316  					assoc_rsp->he_op,
1317  					assoc_rsp->HTInfo);
1318  
1319  		if (status != QDF_STATUS_SUCCESS) {
1320  			pe_err("Failed to extract eht op");
1321  			return;
1322  		}
1323  
1324  		status = lim_strip_and_decode_eht_cap(
1325  					body + ies_offset,
1326  					frame_body_len - ies_offset,
1327  					&assoc_rsp->eht_cap,
1328  					assoc_rsp->he_cap,
1329  					session_entry->curr_op_freq);
1330  		if (status != QDF_STATUS_SUCCESS) {
1331  			pe_err("Failed to extract eht cap");
1332  			return;
1333  		}
1334  	}
1335  
1336  	if (!assoc_rsp->suppRatesPresent) {
1337  		pe_debug("assoc response does not have supported rate set");
1338  		qdf_mem_copy(&assoc_rsp->supportedRates,
1339  			&session_entry->rateSet,
1340  			sizeof(tSirMacRateSet));
1341  	}
1342  
1343  	assoc_cnf.protStatusCode = assoc_rsp->status_code;
1344  	if (session_entry->assocRsp) {
1345  		pe_warn("session_entry->assocRsp is not NULL freeing it and setting NULL");
1346  		qdf_mem_free(session_entry->assocRsp);
1347  		session_entry->assocRsp = NULL;
1348  		session_entry->assocRspLen = 0;
1349  	}
1350  
1351  	if (frame_body_len) {
1352  		session_entry->assocRsp = qdf_mem_malloc(frame_body_len);
1353  		if (session_entry->assocRsp) {
1354  			/*
1355  			 * Store the Assoc response. This is sent
1356  			 * to csr/hdd in join cnf response.
1357  			 */
1358  			qdf_mem_copy(session_entry->assocRsp, body, frame_body_len);
1359  			session_entry->assocRspLen = frame_body_len;
1360  		}
1361  	}
1362  
1363  	lim_update_ric_data(mac_ctx, session_entry, assoc_rsp);
1364  
1365  	lim_set_r0kh(assoc_rsp, session_entry);
1366  
1367  #ifdef FEATURE_WLAN_ESE
1368  	lim_update_ese_tspec(mac_ctx, session_entry, assoc_rsp);
1369  #endif
1370  
1371  	auth_type = session_entry->connected_akm;
1372  	sha384_akm = lim_is_sha384_akm(auth_type);
1373  
1374  	if (lim_get_capability_info(mac_ctx, &caps, session_entry)
1375  		!= QDF_STATUS_SUCCESS) {
1376  		clean_up_ft_sha384(assoc_rsp, sha384_akm);
1377  		qdf_mem_free(assoc_rsp);
1378  		qdf_mem_free(beacon);
1379  		pe_err("could not retrieve Capabilities");
1380  		return;
1381  	}
1382  	lim_copy_u16((uint8_t *) &mac_capab, caps);
1383  
1384  	if (assoc_rsp->status_code == STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
1385  	    assoc_rsp->rssi_assoc_rej.present) {
1386  		struct sir_rssi_disallow_lst ap_info = {{0}};
1387  
1388  		if (!assoc_rsp->rssi_assoc_rej.retry_delay)
1389  			ap_info.expected_rssi = assoc_rsp->rssi_assoc_rej.delta_rssi +
1390  				WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info) +
1391  				wlan_dlm_get_rssi_denylist_threshold(mac_ctx->pdev);
1392  		else
1393  			ap_info.expected_rssi = assoc_rsp->rssi_assoc_rej.delta_rssi +
1394  				WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
1395  
1396  		ap_info.retry_delay = assoc_rsp->rssi_assoc_rej.retry_delay *
1397  							QDF_MC_TIMER_TO_MS_UNIT;
1398  		qdf_mem_copy(ap_info.bssid.bytes, hdr->sa, QDF_MAC_ADDR_SIZE);
1399  		ap_info.reject_reason = REASON_ASSOC_REJECT_OCE;
1400  		ap_info.source = ADDED_BY_DRIVER;
1401  		ap_info.original_timeout = ap_info.retry_delay;
1402  		ap_info.received_time = qdf_mc_timer_get_system_time();
1403  		lim_add_bssid_to_reject_list(mac_ctx->pdev, &ap_info);
1404  	}
1405  
1406  	status = lim_handle_pmfcomeback_timer(session_entry, assoc_rsp);
1407  	/* return if retry again timer is started and ignore this assoc resp */
1408  	if (QDF_IS_STATUS_SUCCESS(status)) {
1409  		qdf_mem_free(beacon);
1410  		clean_up_ft_sha384(assoc_rsp, sha384_akm);
1411  		qdf_mem_free(assoc_rsp);
1412  		return;
1413  	}
1414  
1415  	/* Stop Association failure timer */
1416  	if (subtype == LIM_ASSOC)
1417  		lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER);
1418  	else
1419  		lim_stop_reassoc_retry_timer(mac_ctx);
1420  
1421  	if (assoc_rsp->status_code != STATUS_SUCCESS) {
1422  		/*
1423  		 *Re/Association response was received
1424  		 * either with failure code.
1425  		*/
1426  		pe_err("received Re/AssocRsp frame failure code: %d",
1427  			 assoc_rsp->status_code);
1428  		/*
1429  		 * Need to update 'association failure' error counter
1430  		 * along with STATUS CODE
1431  		 * Return Assoc confirm to SME with received failure code
1432  		*/
1433  		assoc_cnf.resultCode = eSIR_SME_ASSOC_REFUSED;
1434  		/* Delete Pre-auth context for the associated BSS */
1435  		if (lim_search_pre_auth_list(mac_ctx, hdr->sa))
1436  			lim_delete_pre_auth_node(mac_ctx, hdr->sa);
1437  		goto assocReject;
1438  	} else if ((assoc_rsp->aid & 0x3FFF) > 2007) {
1439  		/*
1440  		 * Re/Association response was received
1441  		 * with invalid AID value
1442  		*/
1443  		pe_err("received Re/AssocRsp frame with invalid aid: %X",
1444  			assoc_rsp->aid);
1445  		assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
1446  		assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1447  		/* Send advisory Disassociation frame to AP */
1448  		lim_send_disassoc_mgmt_frame(mac_ctx,
1449  			REASON_UNSPEC_FAILURE,
1450  			hdr->sa, session_entry, false);
1451  		goto assocReject;
1452  	}
1453  
1454  	/*
1455  	 * If it is FILS connection, check is FILS params are matching
1456  	 * with Authentication stage.
1457  	 */
1458  	if (!lim_verify_fils_params_assoc_rsp(mac_ctx, session_entry,
1459  						assoc_rsp, &assoc_cnf)) {
1460  		pe_err("FILS params does not match");
1461  		assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
1462  		assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1463  		/* Send advisory Disassociation frame to AP */
1464  		lim_send_disassoc_mgmt_frame(mac_ctx,
1465  			REASON_UNSPEC_FAILURE,
1466  			hdr->sa, session_entry, false);
1467  		goto assocReject;
1468  	}
1469  
1470  	if (assoc_rsp->QosMapSet.present)
1471  		qdf_mem_copy(&session_entry->QosMapSet,
1472  			     &assoc_rsp->QosMapSet,
1473  			     sizeof(struct qos_map_set));
1474  	else
1475  		qdf_mem_zero(&session_entry->QosMapSet,
1476  			     sizeof(struct qos_map_set));
1477  
1478  	if (assoc_rsp->obss_scanparams.present)
1479  		lim_update_obss_scanparams(session_entry,
1480  				&assoc_rsp->obss_scanparams);
1481  
1482  	if (lim_is_session_he_capable(session_entry)) {
1483  		if (!wlan_cm_is_vdev_roaming(session_entry->vdev))
1484  			lim_set_twt_peer_capabilities(
1485  				mac_ctx,
1486  				(struct qdf_mac_addr *)current_bssid,
1487  				&assoc_rsp->he_cap,
1488  				&assoc_rsp->he_op);
1489  
1490  	} else {
1491  		wlan_twt_cfg_get_support_in_11n(mac_ctx->psoc,
1492  						&twt_support_in_11n);
1493  		if (twt_support_in_11n && session_entry->htCapability &&
1494  		    assoc_rsp->HTCaps.present && assoc_rsp->ExtCap.present) {
1495  			ext_cap = (struct s_ext_cap *)assoc_rsp->ExtCap.bytes;
1496  			lim_set_twt_ext_capabilities(
1497  				mac_ctx,
1498  				(struct qdf_mac_addr *)current_bssid,
1499  				ext_cap);
1500  		}
1501  	}
1502  
1503  	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT,
1504  			      session_entry,
1505  			      (assoc_rsp->status_code ? QDF_STATUS_E_FAILURE :
1506  			       QDF_STATUS_SUCCESS), assoc_rsp->status_code);
1507  
1508  	ap_nss = lim_get_nss_supported_by_ap(&assoc_rsp->VHTCaps,
1509  					     &assoc_rsp->HTCaps,
1510  					     &assoc_rsp->he_cap);
1511  
1512  	if (subtype == LIM_REASSOC) {
1513  		pe_debug("Successfully Reassociated with BSS");
1514  #ifdef FEATURE_WLAN_ESE
1515  	if (assoc_rsp->tsmPresent)
1516  		lim_update_ese_tsm(mac_ctx, session_entry, assoc_rsp);
1517  #endif
1518  		if (session_entry->pLimMlmJoinReq) {
1519  			qdf_mem_free(session_entry->pLimMlmJoinReq);
1520  			session_entry->pLimMlmJoinReq = NULL;
1521  		}
1522  
1523  		if (session_entry->limAssocResponseData) {
1524  			tpSirAssocRsp pre_assoc_rsp;
1525  
1526  			pre_assoc_rsp = (tpSirAssocRsp)
1527  					session_entry->limAssocResponseData;
1528  			qdf_mem_free(pre_assoc_rsp->sha384_ft_subelem.gtk);
1529  			qdf_mem_free(pre_assoc_rsp->sha384_ft_subelem.igtk);
1530  			qdf_mem_free(session_entry->limAssocResponseData);
1531  		}
1532  		session_entry->limAssocResponseData = (void *)assoc_rsp;
1533  		/*
1534  		 * Store the ReAssocRsp Frame in DphTable
1535  		 * to be used during processing DelSta and
1536  		 * DelBss to send AddBss again
1537  		 */
1538  		sta_ds =
1539  			dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
1540  				&session_entry->dph.dphHashTable);
1541  
1542  		if (!sta_ds) {
1543  			pe_err("could not get hash entry at DPH for SA: "QDF_MAC_ADDR_FMT,
1544  			       QDF_MAC_ADDR_REF(hdr->sa));
1545  			assoc_cnf.resultCode =
1546  				eSIR_SME_INVALID_ASSOC_RSP_RXED;
1547  			assoc_cnf.protStatusCode =
1548  				STATUS_UNSPECIFIED_FAILURE;
1549  
1550  			/* Send advisory Disassociation frame to AP */
1551  			lim_send_disassoc_mgmt_frame(mac_ctx,
1552  				REASON_UNSPEC_FAILURE, hdr->sa,
1553  				session_entry, false);
1554  			goto assocReject;
1555  		}
1556  
1557  		if (ap_nss < session_entry->nss)
1558  			session_entry->nss = ap_nss;
1559  
1560  		lim_objmgr_update_vdev_nss(mac_ctx->psoc,
1561  					   session_entry->smeSessionId,
1562  					   session_entry->nss);
1563  		lim_update_vdev_rate_set(mac_ctx->psoc,
1564  					 session_entry->smeSessionId,
1565  					 assoc_rsp);
1566  
1567  		if ((session_entry->limMlmState ==
1568  		     eLIM_MLM_WT_FT_REASSOC_RSP_STATE) ||
1569  		    lim_is_roam_synch_in_progress(mac_ctx->psoc,
1570  						  session_entry)) {
1571  			pe_debug("Sending self sta");
1572  			lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp,
1573  				session_entry, NULL);
1574  			lim_update_stads_ext_cap(mac_ctx, session_entry,
1575  						 assoc_rsp, sta_ds);
1576  			/* Store assigned AID for TIM processing */
1577  			session_entry->limAID = assoc_rsp->aid & 0x3FFF;
1578  			/* Downgrade the EDCA parameters if needed */
1579  			lim_set_active_edca_params(mac_ctx,
1580  				session_entry->gLimEdcaParams,
1581  				session_entry);
1582  			/* Send the active EDCA parameters to HAL */
1583  			if (!lim_is_roam_synch_in_progress(mac_ctx->psoc,
1584  							   session_entry)) {
1585  				lim_send_edca_params(mac_ctx,
1586  					session_entry->gLimEdcaParamsActive,
1587  					session_entry->vdev_id, false);
1588  				lim_add_ft_sta_self(mac_ctx,
1589  					(assoc_rsp->aid & 0x3FFF),
1590  					session_entry);
1591  			} else {
1592  				lim_set_emlsr_caps(mac_ctx, session_entry);
1593  				lim_objmgr_update_emlsr_caps(mac_ctx->psoc,
1594  							session_entry->vdev_id,
1595  							assoc_rsp);
1596  				lim_cache_emlsr_params(session_entry,
1597  						       assoc_rsp);
1598  			}
1599  			qdf_mem_free(beacon);
1600  			return;
1601  		}
1602  
1603  		/*
1604  		 * If we're re-associating to the same BSS,
1605  		 * we don't want to invoke delete STA, delete
1606  		 * BSS, as that would remove the already
1607  		 * established TSPEC. Just go ahead and re-add
1608  		 * the BSS, STA with new capability information.
1609  		 * However, if we're re-associating to a different
1610  		 * BSS, then follow thru with del STA, del BSS,
1611  		 * add BSS, add STA.
1612  		 */
1613  		if (sir_compare_mac_addr(session_entry->bssId,
1614  			session_entry->limReAssocbssId))
1615  			lim_handle_add_bss_in_re_assoc_context(mac_ctx, sta_ds,
1616  				 session_entry);
1617  		else {
1618  			/*
1619  			 * reset the uapsd mask settings since
1620  			 * we're re-associating to new AP
1621  			 */
1622  			session_entry->gUapsdPerAcDeliveryEnableMask = 0;
1623  			session_entry->gUapsdPerAcTriggerEnableMask = 0;
1624  
1625  			lim_mlo_notify_peer_disconn(session_entry, sta_ds);
1626  			if (lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry,
1627  						true) != QDF_STATUS_SUCCESS) {
1628  				pe_err("Could not cleanup the rx path");
1629  				goto assocReject;
1630  			}
1631  		}
1632  		if (!mlo_roam_is_auth_status_connected(mac_ctx->psoc,
1633  						       wlan_vdev_get_id(session_entry->vdev))) {
1634  			qdf_mem_free(beacon);
1635  			return;
1636  		}
1637  	}
1638  	pe_debug("Successfully Associated with BSS " QDF_MAC_ADDR_FMT,
1639  		 QDF_MAC_ADDR_REF(hdr->sa));
1640  
1641  #ifdef FEATURE_WLAN_ESE
1642  	if (session_entry->eseContext.tsm.tsmInfo.state)
1643  		session_entry->eseContext.tsm.tsmMetrics.RoamingCount = 0;
1644  #endif
1645  	/* Store assigned AID for TIM processing */
1646  	session_entry->limAID = assoc_rsp->aid & 0x3FFF;
1647  
1648  	/* STA entry was created during pre-assoc state. */
1649  	sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
1650  			&session_entry->dph.dphHashTable);
1651  	if (!sta_ds) {
1652  		/* Could not add hash table entry */
1653  		pe_err("could not get hash entry at DPH SA: "QDF_MAC_ADDR_FMT,
1654  		       QDF_MAC_ADDR_REF(hdr->sa));
1655  		assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
1656  		assoc_cnf.protStatusCode = eSIR_SME_SUCCESS;
1657  		lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
1658  			(uint32_t *) &assoc_cnf);
1659  		clean_up_ft_sha384(assoc_rsp, sha384_akm);
1660  		/*
1661  		 * Don't free the assoc rsp if it's cached in pe_session.
1662  		 * It would be reused in link connect in cases like OWE
1663  		 * roaming
1664  		 */
1665  		if (session_entry->limAssocResponseData != assoc_rsp)
1666  			qdf_mem_free(assoc_rsp);
1667  		qdf_mem_free(beacon);
1668  		return;
1669  	}
1670  	/* Delete Pre-auth context for the associated BSS */
1671  	if (lim_search_pre_auth_list(mac_ctx, hdr->sa))
1672  		lim_delete_pre_auth_node(mac_ctx, hdr->sa);
1673  
1674  	if (ap_nss < session_entry->nss)
1675  		session_entry->nss = ap_nss;
1676  
1677  	lim_objmgr_update_vdev_nss(mac_ctx->psoc,
1678  				   session_entry->smeSessionId,
1679  				   session_entry->nss);
1680  	lim_update_vdev_rate_set(mac_ctx->psoc, session_entry->smeSessionId,
1681  				 assoc_rsp);
1682  	if (QDF_IS_STATUS_ERROR(lim_update_sta_vdev_punc(
1683  					mac_ctx->psoc,
1684  					session_entry->smeSessionId,
1685  					assoc_rsp))) {
1686  		assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
1687  		assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1688  		/* Send advisory Disassociation frame to AP */
1689  		lim_send_disassoc_mgmt_frame(mac_ctx,
1690  					     REASON_UNSPEC_FAILURE,
1691  					     hdr->sa, session_entry, false);
1692  		goto assocReject;
1693  	}
1694  
1695  	lim_objmgr_update_emlsr_caps(mac_ctx->psoc, session_entry->smeSessionId,
1696  				     assoc_rsp);
1697  
1698  	lim_process_assoc_rsp_t2lm(session_entry, assoc_rsp);
1699  	/*
1700  	 * Extract the AP capabilities from the beacon that
1701  	 * was received earlier
1702  	 */
1703  	ie_len = lim_get_ielen_from_bss_description(
1704  		&session_entry->lim_join_req->bssDescription);
1705  	ie = (uint8_t *)session_entry->lim_join_req->bssDescription.ieFields;
1706  	lim_update_iot_aggr_sz(mac_ctx, ie, ie_len, session_entry);
1707  
1708  	lim_extract_ap_capabilities(mac_ctx, ie, ie_len, beacon);
1709  
1710  	if (session_entry->opmode == QDF_STA_MODE) {
1711  		lim_enable_cts_to_self_for_exempted_iot_ap(
1712  			mac_ctx, session_entry,
1713  			ie, ie_len);
1714  	}
1715  
1716  	lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp,
1717  				   session_entry, beacon);
1718  
1719  	if (lim_is_session_he_capable(session_entry)) {
1720  		session_entry->mu_edca_present = assoc_rsp->mu_edca_present;
1721  		if (session_entry->mu_edca_present) {
1722  			pe_debug("Save MU EDCA params to session");
1723  			session_entry->ap_mu_edca_params[QCA_WLAN_AC_BE] =
1724  				assoc_rsp->mu_edca.acbe;
1725  			session_entry->ap_mu_edca_params[QCA_WLAN_AC_BK] =
1726  				assoc_rsp->mu_edca.acbk;
1727  			session_entry->ap_mu_edca_params[QCA_WLAN_AC_VI] =
1728  				assoc_rsp->mu_edca.acvi;
1729  			session_entry->ap_mu_edca_params[QCA_WLAN_AC_VO] =
1730  				assoc_rsp->mu_edca.acvo;
1731  		}
1732  	}
1733  
1734  	if (beacon->VHTCaps.present)
1735  		sta_ds->parsed_ies.vht_caps = beacon->VHTCaps;
1736  	if (beacon->HTCaps.present)
1737  		sta_ds->parsed_ies.ht_caps = beacon->HTCaps;
1738  	if (beacon->hs20vendor_ie.present)
1739  		sta_ds->parsed_ies.hs20vendor_ie = beacon->hs20vendor_ie;
1740  	if (beacon->HTInfo.present)
1741  		sta_ds->parsed_ies.ht_operation = beacon->HTInfo;
1742  	if (beacon->VHTOperation.present)
1743  		sta_ds->parsed_ies.vht_operation = beacon->VHTOperation;
1744  
1745  	lim_process_he_info(beacon, sta_ds);
1746  	if (lim_process_srp_ie(assoc_rsp, sta_ds) == QDF_STATUS_SUCCESS)
1747  		lim_update_vdev_sr_elements(session_entry, sta_ds);
1748  
1749  	if (lim_is_session_eht_capable(session_entry))
1750  		lim_process_eht_info(beacon, sta_ds);
1751  
1752  	if (mac_ctx->lim.gLimProtectionControl !=
1753  	    MLME_FORCE_POLICY_PROTECTION_DISABLE)
1754  		lim_decide_sta_protection_on_assoc(mac_ctx, beacon,
1755  						   session_entry);
1756  
1757  	if (beacon->erpPresent) {
1758  		if (beacon->erpIEInfo.barkerPreambleMode)
1759  			session_entry->beaconParams.fShortPreamble = false;
1760  		else
1761  			session_entry->beaconParams.fShortPreamble = true;
1762  	}
1763  
1764  #ifdef FEATURE_WLAN_DIAG_SUPPORT
1765  	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_CONNECTED, session_entry,
1766  			      QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
1767  #endif
1768  	lim_update_stads_ext_cap(mac_ctx, session_entry, assoc_rsp, sta_ds);
1769  
1770  	/* Update the BSS Entry, this entry was added during preassoc. */
1771  	if (QDF_STATUS_SUCCESS ==
1772  	    lim_sta_send_add_bss(mac_ctx, assoc_rsp, beacon,
1773  				 &session_entry->lim_join_req->bssDescription,
1774  				 true, session_entry)) {
1775  		clean_up_ft_sha384(assoc_rsp, sha384_akm);
1776  		if (session_entry->limAssocResponseData != assoc_rsp)
1777  			qdf_mem_free(assoc_rsp);
1778  
1779  		qdf_mem_free(beacon);
1780  
1781  		return;
1782  	}
1783  
1784  	pe_err("vdev:%d could not update the bss entry",
1785  	       session_entry->vdev_id);
1786  	assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
1787  	assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
1788  
1789  assocReject:
1790  	if (subtype == LIM_ASSOC ||
1791  	    (subtype == LIM_REASSOC &&
1792  	     session_entry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE)) {
1793  		pe_err("Assoc Rejected by the peer mlmestate: %d sessionid: %d Reason: %d MACADDR:"
1794  			QDF_MAC_ADDR_FMT, session_entry->limMlmState,
1795  			session_entry->peSessionId, assoc_cnf.resultCode,
1796  			QDF_MAC_ADDR_REF(hdr->sa));
1797  
1798  		session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
1799  		MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
1800  			session_entry->peSessionId,
1801  			session_entry->limMlmState));
1802  		if (session_entry->pLimMlmJoinReq) {
1803  			qdf_mem_free(session_entry->pLimMlmJoinReq);
1804  			session_entry->pLimMlmJoinReq = NULL;
1805  		}
1806  
1807  		if (subtype == LIM_ASSOC) {
1808  			lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
1809  				(uint32_t *) &assoc_cnf);
1810  		} else {
1811  			assoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
1812  			lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
1813  					(uint32_t *)&assoc_cnf);
1814  		}
1815  	} else {
1816  		lim_restore_pre_reassoc_state(mac_ctx,
1817  			eSIR_SME_REASSOC_REFUSED,
1818  			assoc_cnf.protStatusCode,
1819  			session_entry);
1820  	}
1821  
1822  	qdf_mem_free(beacon);
1823  	qdf_mem_free(assoc_rsp->sha384_ft_subelem.gtk);
1824  	qdf_mem_free(assoc_rsp->sha384_ft_subelem.igtk);
1825  	qdf_mem_free(assoc_rsp);
1826  
1827  	return;
1828  }
1829