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