xref: /wlan-dirver/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c (revision a4715adff446403c8635800dda08025c59945475)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 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  * This file lim_process_sme_req_messages.cc contains the code
22  * for processing SME request messages.
23  * Author:        Chandra Modumudi
24  * Date:          02/11/02
25  * History:-
26  * Date           Modified by    Modification Information
27  * --------------------------------------------------------------------
28  *
29  */
30 
31 #include "cds_api.h"
32 #include "wni_api.h"
33 #include "wni_cfg.h"
34 #include "sir_api.h"
35 #include "sch_api.h"
36 #include "utils_api.h"
37 #include "lim_types.h"
38 #include "lim_utils.h"
39 #include "lim_assoc_utils.h"
40 #include "lim_security_utils.h"
41 #include "lim_ser_des_utils.h"
42 #include "lim_sme_req_utils.h"
43 #include "lim_admit_control.h"
44 #include "dph_hash_table.h"
45 #include "lim_send_messages.h"
46 #include "lim_api.h"
47 #include "wmm_apsd.h"
48 #include "sir_mac_prot_def.h"
49 #include "rrm_api.h"
50 #include "nan_datapath.h"
51 #include "sap_api.h"
52 #include <lim_ft.h>
53 #include "cds_regdomain.h"
54 #include <wlan_reg_services_api.h>
55 #include "lim_process_fils.h"
56 #include "wlan_utility.h"
57 #include <wlan_crypto_global_api.h>
58 #include "../../core/src/vdev_mgr_ops.h"
59 #include "wma.h"
60 #include <../../core/src/wlan_cm_vdev_api.h>
61 #include "wlan_action_oui_main.h"
62 #include <wlan_cm_api.h>
63 #include <wlan_mlme_api.h>
64 #include <wlan_mlme_ucfg_api.h>
65 #include <wlan_reg_ucfg_api.h>
66 #include "wlan_lmac_if_def.h"
67 #include "wlan_reg_services_api.h"
68 #include <lim_mlo.h>
69 #include <wlan_vdev_mgr_utils_api.h>
70 #include "cfg_ucfg_api.h"
71 #include "wlan_twt_cfg_ext_api.h"
72 #include <spatial_reuse_api.h>
73 #include "wlan_psoc_mlme_api.h"
74 #include "wma_he.h"
75 #include "wlan_mlo_mgr_sta.h"
76 #include "wlan_mlme_main.h"
77 #ifdef WLAN_FEATURE_11BE_MLO
78 #include <wlan_mlo_mgr_peer.h>
79 #endif
80 
81 /* SME REQ processing function templates */
82 static bool __lim_process_sme_sys_ready_ind(struct mac_context *, uint32_t *);
83 static bool __lim_process_sme_start_bss_req(struct mac_context *,
84 					    struct scheduler_msg *pMsg);
85 static void __lim_process_sme_disassoc_req(struct mac_context *, uint32_t *);
86 static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx,
87 					 struct scheduler_msg *msg);
88 static void lim_process_sme_deauth_req(struct mac_context *mac_ctx,
89 				       struct scheduler_msg *msg);
90 static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx,
91 					 struct scheduler_msg *msg);
92 static void __lim_process_sme_disassoc_cnf(struct mac_context *, uint32_t *);
93 static void __lim_process_sme_deauth_req(struct mac_context *, uint32_t *);
94 static bool __lim_process_sme_stop_bss_req(struct mac_context *,
95 					   struct scheduler_msg *pMsg);
96 static void lim_process_sme_channel_change_request(struct mac_context *mac,
97 						   uint32_t *pMsg);
98 static void lim_process_sme_start_beacon_req(struct mac_context *mac, uint32_t *pMsg);
99 static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac, uint32_t *pMsg);
100 static void lim_process_nss_update_request(struct mac_context *mac, uint32_t *pMsg);
101 static void lim_process_set_ie_req(struct mac_context *mac, uint32_t *pMsg);
102 
103 static void lim_start_bss_update_add_ie_buffer(struct mac_context *mac,
104 					       uint8_t **pDstData_buff,
105 					       uint16_t *pDstDataLen,
106 					       uint8_t *pSrcData_buff,
107 					       uint16_t srcDataLen);
108 
109 static void lim_update_add_ie_buffer(struct mac_context *mac,
110 				     uint8_t **pDstData_buff,
111 				     uint16_t *pDstDataLen,
112 				     uint8_t *pSrcData_buff, uint16_t srcDataLen);
113 static void lim_process_modify_add_ies(struct mac_context *mac, uint32_t *pMsg);
114 
115 static void lim_process_update_add_ies(struct mac_context *mac, uint32_t *pMsg);
116 
117 static void lim_process_ext_change_channel(struct mac_context *mac_ctx,
118 						uint32_t *msg);
119 
120 static void lim_mlo_sap_validate_and_update_ra(struct pe_session *session,
121 					       struct qdf_mac_addr *peer_addr);
122 /**
123  * enum get_next_lower_bw - Get next higher bandwidth for a given BW.
124  * This enum is used in conjunction with
125  * wlan_reg_set_channel_params_for_pwrmode API to fetch center frequencies
126  * for each BW starting from 20MHz upto Max BSS BW in case of non-PSD power.
127  *
128  */
129 static const enum phy_ch_width get_next_higher_bw[] = {
130 	[CH_WIDTH_20MHZ] = CH_WIDTH_40MHZ,
131 	[CH_WIDTH_40MHZ] = CH_WIDTH_80MHZ,
132 	[CH_WIDTH_80MHZ] = CH_WIDTH_160MHZ,
133 #if !defined(WLAN_FEATURE_11BE)
134 	[CH_WIDTH_160MHZ] = CH_WIDTH_INVALID
135 #else
136 	[CH_WIDTH_160MHZ] = CH_WIDTH_320MHZ,
137 	[CH_WIDTH_320MHZ] = CH_WIDTH_INVALID
138 #endif
139 };
140 
141 /**
142  * lim_process_set_hw_mode() - Send set HW mode command to WMA
143  * @mac: Globacl MAC pointer
144  * @msg: Message containing the hw mode index
145  *
146  * Send the set HW mode command to WMA
147  *
148  * Return: QDF_STATUS_SUCCESS if message posting is successful
149  */
150 static QDF_STATUS lim_process_set_hw_mode(struct mac_context *mac, uint32_t *msg)
151 {
152 	QDF_STATUS status = QDF_STATUS_SUCCESS;
153 	struct scheduler_msg message = {0};
154 	struct policy_mgr_hw_mode *req_msg;
155 	uint32_t len;
156 	struct s_sir_set_hw_mode *buf;
157 	struct scheduler_msg resp_msg = {0};
158 	struct sir_set_hw_mode_resp *param;
159 
160 	buf = (struct s_sir_set_hw_mode *) msg;
161 	if (!buf) {
162 		pe_err("Set HW mode param is NULL");
163 		status = QDF_STATUS_E_INVAL;
164 		/* To free the active command list */
165 		goto fail;
166 	}
167 
168 	len = sizeof(*req_msg);
169 
170 	req_msg = qdf_mem_malloc(len);
171 	if (!req_msg) {
172 		status = QDF_STATUS_E_NOMEM;
173 		goto fail;
174 	}
175 
176 	req_msg->hw_mode_index = buf->set_hw.hw_mode_index;
177 	req_msg->reason = buf->set_hw.reason;
178 	/* Other parameters are not needed for WMA */
179 
180 	message.bodyptr = req_msg;
181 	message.type    = SIR_HAL_PDEV_SET_HW_MODE;
182 
183 	pe_debug("Posting SIR_HAL_SOC_SET_HW_MOD to WMA");
184 	status = scheduler_post_message(QDF_MODULE_ID_PE,
185 					QDF_MODULE_ID_WMA,
186 					QDF_MODULE_ID_WMA, &message);
187 	if (!QDF_IS_STATUS_SUCCESS(status)) {
188 		pe_err("scheduler_post_msg failed!(err=%d)",
189 			status);
190 		qdf_mem_free(req_msg);
191 		goto fail;
192 	}
193 	return status;
194 fail:
195 	param = qdf_mem_malloc(sizeof(*param));
196 	if (!param)
197 		return QDF_STATUS_E_FAILURE;
198 	param->status = SET_HW_MODE_STATUS_ECANCELED;
199 	param->cfgd_hw_mode_index = 0;
200 	param->num_vdev_mac_entries = 0;
201 	resp_msg.type = eWNI_SME_SET_HW_MODE_RESP;
202 	resp_msg.bodyptr = param;
203 	resp_msg.bodyval = 0;
204 	lim_sys_process_mmh_msg_api(mac, &resp_msg);
205 	return status;
206 }
207 
208 /**
209  * lim_process_set_dual_mac_cfg_req() - Set dual mac config command to WMA
210  * @mac: Global MAC pointer
211  * @msg: Message containing the dual mac config parameter
212  *
213  * Send the set dual mac config command to WMA
214  *
215  * Return: QDF_STATUS_SUCCESS if message posting is successful
216  */
217 static QDF_STATUS lim_process_set_dual_mac_cfg_req(struct mac_context *mac,
218 		uint32_t *msg)
219 {
220 	QDF_STATUS status = QDF_STATUS_SUCCESS;
221 	struct scheduler_msg message = {0};
222 	struct policy_mgr_dual_mac_config *req_msg;
223 	uint32_t len;
224 	struct sir_set_dual_mac_cfg *buf;
225 	struct scheduler_msg resp_msg = {0};
226 	struct sir_dual_mac_config_resp *param;
227 
228 	buf = (struct sir_set_dual_mac_cfg *) msg;
229 	if (!buf) {
230 		pe_err("Set Dual mac config is NULL");
231 		status = QDF_STATUS_E_INVAL;
232 		/* To free the active command list */
233 		goto fail;
234 	}
235 
236 	len = sizeof(*req_msg);
237 
238 	req_msg = qdf_mem_malloc(len);
239 	if (!req_msg) {
240 		status = QDF_STATUS_E_NOMEM;
241 		goto fail;
242 	}
243 
244 	req_msg->scan_config = buf->set_dual_mac.scan_config;
245 	req_msg->fw_mode_config = buf->set_dual_mac.fw_mode_config;
246 	/* Other parameters are not needed for WMA */
247 
248 	message.bodyptr = req_msg;
249 	message.type    = SIR_HAL_PDEV_DUAL_MAC_CFG_REQ;
250 
251 	pe_debug("Post SIR_HAL_PDEV_DUAL_MAC_CFG_REQ to WMA: %x %x",
252 		req_msg->scan_config, req_msg->fw_mode_config);
253 	status = scheduler_post_message(QDF_MODULE_ID_PE,
254 					QDF_MODULE_ID_WMA,
255 					QDF_MODULE_ID_WMA, &message);
256 	if (!QDF_IS_STATUS_SUCCESS(status)) {
257 		pe_err("scheduler_post_msg failed!(err=%d)",
258 				status);
259 		qdf_mem_free(req_msg);
260 		goto fail;
261 	}
262 	return status;
263 fail:
264 	param = qdf_mem_malloc(sizeof(*param));
265 	if (!param)
266 		return QDF_STATUS_E_FAILURE;
267 	param->status = SET_HW_MODE_STATUS_ECANCELED;
268 	resp_msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP;
269 	resp_msg.bodyptr = param;
270 	resp_msg.bodyval = 0;
271 	lim_sys_process_mmh_msg_api(mac, &resp_msg);
272 	return status;
273 }
274 
275 #ifdef FEATURE_WLAN_ESE
276 static inline bool
277 lim_is_ese_enabled(struct mac_context *mac_ctx)
278 {
279 	return mac_ctx->mlme_cfg->lfr.ese_enabled;
280 }
281 #else
282 static inline bool
283 lim_is_ese_enabled(struct mac_context *mac_ctx)
284 {
285 	return false;
286 }
287 #endif
288 
289 /**
290  * lim_process_set_antenna_mode_req() - Set antenna mode command
291  * to WMA
292  * @mac: Global MAC pointer
293  * @msg: Message containing the antenna mode parameter
294  *
295  * Send the set antenna mode command to WMA
296  *
297  * Return: QDF_STATUS_SUCCESS if message posting is successful
298  */
299 static QDF_STATUS lim_process_set_antenna_mode_req(struct mac_context *mac,
300 		uint32_t *msg)
301 {
302 	QDF_STATUS status = QDF_STATUS_SUCCESS;
303 	struct scheduler_msg message = {0};
304 	struct sir_antenna_mode_param *req_msg;
305 	struct sir_set_antenna_mode *buf;
306 	struct scheduler_msg resp_msg = {0};
307 	struct sir_antenna_mode_resp *param;
308 
309 	buf = (struct sir_set_antenna_mode *) msg;
310 	if (!buf) {
311 		pe_err("Set antenna mode is NULL");
312 		status = QDF_STATUS_E_INVAL;
313 		/* To free the active command list */
314 		goto fail;
315 	}
316 
317 	req_msg = qdf_mem_malloc(sizeof(*req_msg));
318 	if (!req_msg) {
319 		status = QDF_STATUS_E_NOMEM;
320 		goto fail;
321 	}
322 
323 	req_msg->num_rx_chains = buf->set_antenna_mode.num_rx_chains;
324 	req_msg->num_tx_chains = buf->set_antenna_mode.num_tx_chains;
325 
326 	message.bodyptr = req_msg;
327 	message.type    = SIR_HAL_SOC_ANTENNA_MODE_REQ;
328 
329 	pe_debug("Post SIR_HAL_SOC_ANTENNA_MODE_REQ to WMA: %d %d",
330 		req_msg->num_rx_chains,
331 		req_msg->num_tx_chains);
332 	status = scheduler_post_message(QDF_MODULE_ID_PE,
333 					QDF_MODULE_ID_WMA,
334 					QDF_MODULE_ID_WMA, &message);
335 	if (!QDF_IS_STATUS_SUCCESS(status)) {
336 		pe_err("scheduler_post_msg failed!(err=%d)",
337 				status);
338 		qdf_mem_free(req_msg);
339 		goto fail;
340 	}
341 	return status;
342 fail:
343 	param = qdf_mem_malloc(sizeof(*param));
344 	if (!param)
345 		return QDF_STATUS_E_NOMEM;
346 	param->status = SET_ANTENNA_MODE_STATUS_ECANCELED;
347 	resp_msg.type = eWNI_SME_SET_ANTENNA_MODE_RESP;
348 	resp_msg.bodyptr = param;
349 	resp_msg.bodyval = 0;
350 	lim_sys_process_mmh_msg_api(mac, &resp_msg);
351 	return status;
352 }
353 
354 /**
355  * __lim_is_sme_assoc_cnf_valid() -- Validate ASSOC_CNF message
356  * @assoc_cnf: Pointer to Received ASSOC_CNF message
357  *
358  * This function is called by __lim_process_sme_assoc_cnf_new() upon
359  * receiving SME_ASSOC_CNF.
360  *
361  * Return: true when received SME_ASSOC_CNF is formatted correctly
362  *         false otherwise
363  */
364 static bool __lim_is_sme_assoc_cnf_valid(struct assoc_cnf *assoc_cnf)
365 {
366 	if (qdf_is_macaddr_group(&assoc_cnf->peer_macaddr))
367 		return false;
368 
369 	return true;
370 }
371 
372 /**
373  * __lim_is_deferred_msg_for_radar() - Defers the message if radar is detected
374  * @mac_ctx: Pointer to Global MAC structure
375  * @message: Pointer to message posted from SME to LIM.
376  *
377  * Has role only if 11h is enabled. Not used on STA side.
378  * Defers the message if radar is detected.
379  *
380  * Return: true, if deferred otherwise return false.
381  */
382 static bool
383 __lim_is_deferred_msg_for_radar(struct mac_context *mac_ctx,
384 				struct scheduler_msg *message)
385 {
386 	/*
387 	 * fRadarDetCurOperChan will be set only if we
388 	 * detect radar in current operating channel and
389 	 * System Role == AP ROLE
390 	 *
391 	 * TODO: Need to take care radar detection.
392 	 *
393 	 * if (LIM_IS_RADAR_DETECTED(mac_ctx))
394 	 */
395 	if (0) {
396 		if (lim_defer_msg(mac_ctx, message) != TX_SUCCESS) {
397 			pe_err("Could not defer Msg: %d", message->type);
398 			return false;
399 		}
400 		pe_debug("Defer the message, in learn mode type: %d",
401 			message->type);
402 		return true;
403 	}
404 	return false;
405 }
406 
407 /**
408  * __lim_process_sme_sys_ready_ind () - Process ready indication from WMA
409  * @mac: Global MAC context
410  * @msg_buf: Message from WMA
411  *
412  * handles the notification from HDD. PE just forwards this message to HAL.
413  *
414  * Return: true-Posting to HAL failed, so PE will consume the buffer.
415  *         false-Posting to HAL successful, so HAL will consume the buffer.
416  */
417 
418 static bool __lim_process_sme_sys_ready_ind(struct mac_context *mac,
419 					    uint32_t *msg_buf)
420 {
421 	struct scheduler_msg msg = {0};
422 	struct sme_ready_req *ready_req = (struct sme_ready_req *)msg_buf;
423 
424 	msg.type = WMA_SYS_READY_IND;
425 	msg.reserved = 0;
426 	msg.bodyptr = msg_buf;
427 	msg.bodyval = 0;
428 
429 	if (ANI_DRIVER_TYPE(mac) != QDF_DRIVER_TYPE_MFG) {
430 		ready_req->pe_roam_synch_cb = pe_roam_synch_callback;
431 		ready_req->pe_disconnect_cb = pe_disconnect_callback;
432 		ready_req->pe_roam_set_ie_cb = pe_set_ie_for_roam_invoke;
433 		pe_register_mgmt_rx_frm_callback(mac);
434 		pe_register_callbacks_with_wma(mac, ready_req);
435 		mac->lim.sme_msg_callback = ready_req->sme_msg_cb;
436 		mac->lim.stop_roaming_callback = ready_req->stop_roaming_cb;
437 	}
438 
439 	pe_debug("sending WMA_SYS_READY_IND msg to HAL");
440 	MTRACE(mac_trace_msg_tx(mac, NO_SESSION, msg.type));
441 
442 	if (QDF_STATUS_SUCCESS != wma_post_ctrl_msg(mac, &msg)) {
443 		pe_err("wma_post_ctrl_msg failed");
444 		return true;
445 	}
446 	return false;
447 }
448 
449 /**
450  *lim_configure_ap_start_bss_session() - Configure the AP Start BSS in session.
451  *@mac_ctx: Pointer to Global MAC structure
452  *@session: A pointer to session entry
453  *@sme_start_bss_req: Start BSS Request from upper layers.
454  *
455  * This function is used to configure the start bss parameters
456  * in to the session.
457  *
458  * Return: None.
459  */
460 static void
461 lim_configure_ap_start_bss_session(struct mac_context *mac_ctx,
462 				   struct pe_session *session,
463 				   struct start_bss_config *sme_start_bss_req)
464 {
465 	bool sap_uapsd;
466 	uint16_t ht_cap = cfg_default(CFG_AP_PROTECTION_MODE);
467 
468 	session->limSystemRole = eLIM_AP_ROLE;
469 	session->privacy = sme_start_bss_req->privacy;
470 	session->fwdWPSPBCProbeReq = 1;
471 	session->authType = sme_start_bss_req->authType;
472 	/* Store the DTIM period */
473 	session->dtimPeriod = (uint8_t) sme_start_bss_req->dtimPeriod;
474 
475 	/* Enable/disable UAPSD */
476 	wlan_mlme_is_sap_uapsd_enabled(mac_ctx->psoc, &sap_uapsd);
477 	session->apUapsdEnable = sap_uapsd;
478 
479 	session->gLimProtectionControl =
480 				wlan_mlme_is_ap_prot_enabled(mac_ctx->psoc);
481 
482 	wlan_mlme_get_ap_protection_mode(mac_ctx->psoc, &ht_cap);
483 	qdf_mem_copy((void *)&session->cfgProtection,
484 		     (void *)&ht_cap,
485 		     sizeof(uint16_t));
486 
487 	wlan_mlme_get_vendor_vht_for_24ghz(mac_ctx->psoc,
488 					   &session->vendor_vht_sap);
489 	if (session->opmode == QDF_P2P_GO_MODE) {
490 		session->sap_dot11mc = 1;
491 		session->proxyProbeRspEn = 0;
492 	} else {
493 		session->sap_dot11mc = mac_ctx->mlme_cfg->gen.sap_dot11mc;
494 		/*
495 		 * To detect PBC overlap in SAP WPS mode,
496 		 * Host handles Probe Requests.
497 		 */
498 		if (SAP_WPS_DISABLED == sme_start_bss_req->wps_state)
499 			session->proxyProbeRspEn = 1;
500 		else
501 			session->proxyProbeRspEn = 0;
502 	}
503 	session->ssidHidden = sme_start_bss_req->ssidHidden;
504 	session->wps_state = sme_start_bss_req->wps_state;
505 
506 	lim_get_short_slot_from_phy_mode(mac_ctx, session, session->gLimPhyMode,
507 		&session->shortSlotTimeSupported);
508 
509 	session->beacon_tx_rate = sme_start_bss_req->beacon_tx_rate;
510 
511 }
512 
513 static void lim_set_privacy(struct mac_context *mac_ctx,
514 			    int32_t ucast_cipher,
515 			    int32_t auth_mode, int32_t akm, bool ap_privacy)
516 {
517 	bool rsn_enabled, privacy;
518 
519 	/* set default to open */
520 	mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_OPEN_SYSTEM;
521 	if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_AUTO) &&
522 	    (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP) ||
523 	     QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_40) ||
524 	     QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_104)))
525 		mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_AUTO_SWITCH;
526 	else if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_SHARED))
527 		mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_SHARED_KEY;
528 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) ||
529 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) ||
530 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY) ||
531 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY))
532 		mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_AUTH_TYPE_SAE;
533 
534 	if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP) ||
535 	     QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_40) ||
536 	     QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_104)) {
537 		privacy = true;
538 		rsn_enabled = false;
539 	} else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_TKIP) ||
540 		   QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM) ||
541 		   QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_OCB) ||
542 		   QDF_HAS_PARAM(ucast_cipher,
543 				 WLAN_CRYPTO_CIPHER_AES_CCM_256) ||
544 		   QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM) ||
545 		   QDF_HAS_PARAM(ucast_cipher,
546 				 WLAN_CRYPTO_CIPHER_AES_GCM_256) ||
547 		   QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_GCM4) ||
548 		   QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_SMS4)) {
549 		privacy = ap_privacy;
550 		rsn_enabled = true;
551 	} else {
552 		rsn_enabled = false;
553 		privacy = false;
554 	}
555 
556 	mac_ctx->mlme_cfg->feature_flags.enable_rsn = rsn_enabled;
557 	mac_ctx->mlme_cfg->wep_params.is_privacy_enabled = privacy;
558 	mac_ctx->mlme_cfg->wep_params.wep_default_key_id = 0;
559 }
560 
561 /**
562  * lim_send_start_vdev_req() - send vdev start request
563  *@session: pe session
564  *@mlm_start_req: vdev start req
565  *
566  * Return: QDF_STATUS
567  */
568 static QDF_STATUS
569 lim_send_start_vdev_req(struct pe_session *session, tLimMlmStartReq *mlm_start_req)
570 {
571 	return wlan_vdev_mlme_sm_deliver_evt(session->vdev,
572 					     WLAN_VDEV_SM_EV_START,
573 					     sizeof(*mlm_start_req),
574 					     mlm_start_req);
575 }
576 
577 #ifdef WLAN_FEATURE_11BE
578 void lim_strip_eht_ies_from_add_ies(struct mac_context *mac_ctx,
579 				    struct pe_session *session)
580 {
581 	struct add_ie_params *add_ie = &session->add_ie_params;
582 	QDF_STATUS status;
583 	uint8_t eht_cap_buff[DOT11F_IE_EHT_CAP_MAX_LEN + 2];
584 	uint8_t eht_op_buff[DOT11F_IE_EHT_OP_MAX_LEN + 2];
585 
586 	qdf_mem_zero(eht_cap_buff, sizeof(eht_cap_buff));
587 	qdf_mem_zero(eht_op_buff, sizeof(eht_op_buff));
588 
589 	status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
590 			      &add_ie->probeRespBCNDataLen,
591 			      DOT11F_EID_EHT_CAP, ONE_BYTE,
592 			      EHT_CAP_OUI_TYPE, (uint8_t)EHT_CAP_OUI_SIZE,
593 			      eht_cap_buff, DOT11F_IE_EHT_CAP_MAX_LEN);
594 	if (status != QDF_STATUS_SUCCESS)
595 		pe_debug("Failed to strip EHT cap IE status: %d", status);
596 
597 	status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
598 			      &add_ie->probeRespBCNDataLen,
599 			      DOT11F_EID_EHT_OP, ONE_BYTE,
600 			      EHT_OP_OUI_TYPE, (uint8_t)EHT_OP_OUI_SIZE,
601 			      eht_op_buff, DOT11F_IE_EHT_OP_MAX_LEN);
602 	if (status != QDF_STATUS_SUCCESS)
603 		pe_debug("Failed to strip EHT op IE status: %d", status);
604 }
605 #else
606 void lim_strip_eht_ies_from_add_ies(struct mac_context *mac_ctx,
607 				    struct pe_session *session)
608 {
609 }
610 #endif
611 
612 #ifdef WLAN_FEATURE_11AX
613 void lim_strip_he_ies_from_add_ies(struct mac_context *mac_ctx,
614 				   struct pe_session *session)
615 {
616 	struct add_ie_params *add_ie = &session->add_ie_params;
617 	QDF_STATUS status;
618 	uint8_t he_cap_buff[DOT11F_IE_HE_CAP_MAX_LEN + 2];
619 	uint8_t he_op_buff[DOT11F_IE_HE_OP_MAX_LEN + 2];
620 
621 	qdf_mem_zero(he_cap_buff, sizeof(he_cap_buff));
622 	qdf_mem_zero(he_op_buff, sizeof(he_op_buff));
623 
624 	status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
625 			      &add_ie->probeRespBCNDataLen,
626 			      DOT11F_EID_HE_CAP, ONE_BYTE,
627 			      HE_CAP_OUI_TYPE, (uint8_t)HE_CAP_OUI_SIZE,
628 			      he_cap_buff, DOT11F_IE_HE_CAP_MAX_LEN);
629 	if (status != QDF_STATUS_SUCCESS)
630 		pe_debug("Failed to strip HE cap IE status: %d", status);
631 
632 
633 	status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
634 			      &add_ie->probeRespBCNDataLen,
635 			      DOT11F_EID_HE_OP, ONE_BYTE,
636 			      HE_OP_OUI_TYPE, (uint8_t)HE_OP_OUI_SIZE,
637 			      he_op_buff, DOT11F_IE_HE_OP_MAX_LEN);
638 	if (status != QDF_STATUS_SUCCESS)
639 		pe_debug("Failed to strip HE op IE status: %d", status);
640 }
641 #else
642 void lim_strip_he_ies_from_add_ies(struct mac_context *mac_ctx,
643 				   struct pe_session *session)
644 {
645 }
646 #endif
647 
648 #ifdef FEATURE_WLAN_WAPI
649 
650 void lim_strip_wapi_ies_from_add_ies(struct mac_context *mac_ctx,
651 				     struct pe_session *session)
652 {
653 	struct add_ie_params *add_ie = &session->add_ie_params;
654 	uint8_t wapiie_buff[DOT11F_IE_WAPIOPAQUE_MAX_LEN + 2];
655 	QDF_STATUS status;
656 
657 	qdf_mem_zero(wapiie_buff, sizeof(wapiie_buff));
658 
659 	status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
660 			      &add_ie->probeRespBCNDataLen,
661 			      DOT11F_EID_WAPIOPAQUE, ONE_BYTE,
662 			      NULL, 0,
663 			      wapiie_buff, DOT11F_IE_WAPIOPAQUE_MAX_LEN);
664 	if (status != QDF_STATUS_SUCCESS)
665 		pe_debug("Failed to strip WAPI IE status: %d", status);
666 }
667 #else
668 void lim_strip_wapi_ies_from_add_ies(struct mac_context *mac_ctx,
669 				     struct pe_session *session)
670 {
671 }
672 #endif
673 /**
674  * lim_set_ldpc_exception() - to set allow any LDPC exception permitted
675  * @mac_ctx: Pointer to mac context
676  * @vdev_mlme: vdev mlme
677  * @ch_freq: Given channel frequency where connection will go
678  *
679  * This API will check if hardware allows LDPC to be enabled for provided
680  * channel and user has enabled the RX LDPC selection
681  *
682  * Return: QDF_STATUS
683  */
684 static QDF_STATUS lim_set_ldpc_exception(struct mac_context *mac_ctx,
685 					 struct vdev_mlme_obj *vdev_mlme,
686 					 uint32_t ch_freq)
687 {
688 	struct wlan_vht_config vht_config;
689 	struct wlan_ht_config ht_caps;
690 
691 	vht_config.caps = vdev_mlme->proto.vht_info.caps;
692 	ht_caps.caps = vdev_mlme->proto.ht_info.ht_caps;
693 
694 	if (mac_ctx->mlme_cfg->ht_caps.ht_cap_info.adv_coding_cap &&
695 	    wma_is_rx_ldpc_supported_for_channel(ch_freq)) {
696 		ht_caps.ht_caps.adv_coding_cap = 1;
697 		vht_config.ldpc_coding = 1;
698 		sme_debug("LDPC enable for ch freq[%d]", ch_freq);
699 	} else {
700 		ht_caps.ht_caps.adv_coding_cap = 0;
701 		vht_config.ldpc_coding = 0;
702 		sme_debug("LDPC disable for ch freq[%d]", ch_freq);
703 	}
704 	vdev_mlme->proto.vht_info.caps = vht_config.caps;
705 	vdev_mlme->proto.ht_info.ht_caps = ht_caps.caps;
706 
707 	return QDF_STATUS_SUCCESS;
708 }
709 
710 /**
711  * lim_revise_req_vht_cap_per_band: Update vht cap based on band
712  * @session: Session pointer
713  *
714  * Return: None
715  *
716  */
717 static void lim_revise_req_vht_cap_per_band(struct pe_session *session)
718 {
719 	struct wlan_vht_config *vht_config;
720 
721 	vht_config = &session->vht_config;
722 	/* Disable shortgi160 and 80 for 2.4Ghz BSS*/
723 	if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) {
724 		vht_config->shortgi80 = 0;
725 		vht_config->shortgi160and80plus80 = 0;
726 	}
727 }
728 
729 static void lim_start_bss_update_ht_vht_caps(struct mac_context *mac_ctx,
730 					     struct pe_session *session)
731 {
732 	struct vdev_mlme_obj *vdev_mlme;
733 	struct wlan_vht_config vht_config;
734 	uint8_t value = 0;
735 	struct wlan_ht_config ht_caps;
736 
737 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
738 	if (!vdev_mlme)
739 		return;
740 	if (!policy_mgr_is_dbs_enable(mac_ctx->psoc))
741 		lim_set_ldpc_exception(mac_ctx, vdev_mlme,
742 				       session->curr_op_freq);
743 	vht_config.caps = vdev_mlme->proto.vht_info.caps;
744 	value = mac_ctx->mlme_cfg->vht_caps.vht_cap_info.su_bformee;
745 	vht_config.su_beam_formee =
746 		value && mac_ctx->mlme_cfg->vht_caps.vht_cap_info.tx_bfee_sap;
747 	value = MLME_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF;
748 	vht_config.csnof_beamformer_antSup = value;
749 	vht_config.mu_beam_formee = 0;
750 	if (session->pLimStartBssReq->vht_channel_width <= CH_WIDTH_80MHZ) {
751 		vht_config.shortgi160and80plus80 = 0;
752 		vht_config.supported_channel_widthset = 0;
753 	}
754 
755 	session->vht_config = vht_config;
756 
757 	ht_caps.caps = vdev_mlme->proto.ht_info.ht_caps;
758 	session->ht_config = ht_caps.ht_caps;
759 
760 	lim_revise_req_vht_cap_per_band(session);
761 	pe_debug("cur_op_freq %d HT capability 0x%x VHT capability 0x%x bw %d",
762 		 session->curr_op_freq, ht_caps.caps, vht_config.caps,
763 		 session->pLimStartBssReq->vht_channel_width);
764 }
765 
766 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
767 static inline void lim_fill_cc_mode(struct mac_context *mac_ctx,
768 				    struct pe_session *session)
769 {
770 	session->cc_switch_mode = mac_ctx->roam.configParam.cc_switch_mode;
771 }
772 #else
773 static inline void lim_fill_cc_mode(struct mac_context *mac_ctx,
774 				    struct pe_session *session)
775 {
776 }
777 #endif
778 
779 #ifdef WLAN_FEATURE_SON
780 /**
781  * lim_save_max_mcs_idx() - save max mcs index to mlme component
782  * @mac_ctx: Pointer to Global MAC structure
783  * @session: pointer to pe session
784  *
785  * Return: void
786  */
787 static void
788 lim_save_max_mcs_idx(struct mac_context *mac_ctx, struct pe_session *session)
789 {
790 	tDot11fIEVHTCaps vht_cap;
791 	tDot11fIEhe_cap he_cap;
792 	tDot11fIEHTCaps ht_cap;
793 	u_int8_t session_max_mcs_idx = INVALID_MCS_NSS_INDEX;
794 
795 	if (IS_DOT11_MODE_HE(session->dot11mode)) {
796 		qdf_mem_zero(&he_cap, sizeof(tDot11fIEhe_cap));
797 		populate_dot11f_he_caps(mac_ctx, session, &he_cap);
798 		session_max_mcs_idx = lim_get_he_max_mcs_idx(session->ch_width,
799 							     &he_cap);
800 	}
801 	if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX &&
802 	    IS_DOT11_MODE_VHT(session->dot11mode)) {
803 		qdf_mem_zero(&vht_cap, sizeof(tDot11fIEVHTCaps));
804 		populate_dot11f_vht_caps(mac_ctx, session, &vht_cap);
805 		session_max_mcs_idx = lim_get_vht_max_mcs_idx(&vht_cap);
806 	}
807 	if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX &&
808 	    IS_DOT11_MODE_HT(session->dot11mode)) {
809 		qdf_mem_zero(&ht_cap, sizeof(tDot11fIEHTCaps));
810 		populate_dot11f_ht_caps(mac_ctx, session, &ht_cap);
811 		session_max_mcs_idx = lim_get_ht_max_mcs_idx(&ht_cap);
812 	}
813 	if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX &&
814 	    session->extRateSet.numRates)
815 		session_max_mcs_idx =
816 				lim_get_max_rate_idx(&session->extRateSet);
817 
818 	if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX &&
819 	    session->rateSet.numRates)
820 		session_max_mcs_idx =
821 				lim_get_max_rate_idx(&session->rateSet);
822 
823 	mlme_save_vdev_max_mcs_idx(session->vdev, session_max_mcs_idx);
824 }
825 #else
826 static void
827 lim_save_max_mcs_idx(struct mac_context *mac_ctx, struct pe_session *session)
828 {
829 }
830 #endif
831 
832 /**
833  * __lim_handle_sme_start_bss_request() - process SME_START_BSS_REQ message
834  *@mac_ctx: Pointer to Global MAC structure
835  *@msg_buf: A pointer to the SME message buffer
836  *
837  * This function is called to process SME_START_BSS_REQ message
838  * from HDD or upper layer application.
839  *
840  * Return: None
841  */
842 static void
843 __lim_handle_sme_start_bss_request(struct mac_context *mac_ctx, uint32_t *msg_buf)
844 {
845 	uint16_t size;
846 	uint32_t val = 0;
847 	tSirMacChanNum channel_number;
848 	tLimMlmStartReq *mlm_start_req = NULL;
849 	struct start_bss_config *sme_start_bss_req = NULL;
850 	tSirResultCodes ret_code = eSIR_SME_SUCCESS;
851 	uint8_t session_id;
852 	struct pe_session *session = NULL;
853 	uint8_t vdev_id = 0xFF;
854 	uint32_t chanwidth;
855 	struct vdev_type_nss *vdev_type_nss;
856 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
857 	int32_t ucast_cipher;
858 	int32_t auth_mode;
859 	int32_t akm;
860 	int32_t rsn_caps;
861 	bool cfg_value = false;
862 	enum QDF_OPMODE opmode;
863 	ePhyChanBondState cb_mode;
864 	enum bss_type bss_type;
865 	struct qdf_mac_addr bssid;
866 
867 /* FEATURE_WLAN_DIAG_SUPPORT */
868 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
869 	/*
870 	 * Since the session is not created yet, sending NULL.
871 	 * The response should have the correct state.
872 	 */
873 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_START_BSS_REQ_EVENT,
874 			      NULL, 0, 0);
875 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
876 
877 	size = sizeof(*sme_start_bss_req);
878 	sme_start_bss_req = qdf_mem_malloc(size);
879 	if (!sme_start_bss_req) {
880 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
881 		goto free;
882 	}
883 	qdf_mem_copy(sme_start_bss_req, msg_buf, size);
884 	vdev_id = sme_start_bss_req->vdev_id;
885 
886 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
887 	if (opmode == QDF_NDI_MODE)
888 		bss_type = eSIR_NDI_MODE;
889 	else
890 		bss_type = eSIR_INFRA_AP_MODE;
891 
892 	wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, vdev_id, &bssid);
893 
894 	if ((mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) ||
895 	    (mac_ctx->lim.gLimSmeState == eLIM_SME_IDLE_STATE)) {
896 		if (!lim_is_sme_start_bss_req_valid(mac_ctx,
897 					sme_start_bss_req, bss_type)) {
898 			pe_warn("Received invalid eWNI_SME_START_BSS_REQ");
899 			ret_code = eSIR_SME_INVALID_PARAMETERS;
900 			goto free;
901 		}
902 		channel_number = wlan_reg_freq_to_chan(mac_ctx->pdev,
903 					sme_start_bss_req->oper_ch_freq);
904 		/*
905 		 * This is the place where PE is going to create a session.
906 		 * If session is not existed, then create a new session
907 		 */
908 		session = pe_find_session_by_bssid(mac_ctx, bssid.bytes,
909 						   &session_id);
910 		if (session) {
911 			pe_warn("Session Already exists for given BSSID");
912 			ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
913 			session = NULL;
914 			goto free;
915 		} else {
916 			session = pe_create_session(mac_ctx, bssid.bytes,
917 					&session_id,
918 					mac_ctx->lim.max_sta_of_pe_session,
919 					bss_type,
920 					sme_start_bss_req->vdev_id);
921 			if (!session) {
922 				pe_warn("Session Can not be created");
923 				ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
924 				goto free;
925 			}
926 
927 			/* Update the beacon/probe filter in mac_ctx */
928 			lim_set_bcn_probe_filter(mac_ctx, session,
929 						 channel_number);
930 		}
931 
932 		if (QDF_NDI_MODE != opmode) {
933 			/* Probe resp add ie */
934 			lim_start_bss_update_add_ie_buffer(mac_ctx,
935 				&session->add_ie_params.probeRespData_buff,
936 				&session->add_ie_params.probeRespDataLen,
937 				sme_start_bss_req->add_ie_params.
938 					probeRespData_buff,
939 				sme_start_bss_req->add_ie_params.
940 					probeRespDataLen);
941 
942 			/* Probe Beacon add ie */
943 			lim_start_bss_update_add_ie_buffer(mac_ctx,
944 				&session->add_ie_params.probeRespBCNData_buff,
945 				&session->add_ie_params.probeRespBCNDataLen,
946 				sme_start_bss_req->add_ie_params.
947 					probeRespBCNData_buff,
948 				sme_start_bss_req->add_ie_params.
949 					probeRespBCNDataLen);
950 
951 			/* Assoc resp IE */
952 			lim_start_bss_update_add_ie_buffer(mac_ctx,
953 				&session->add_ie_params.assocRespData_buff,
954 				&session->add_ie_params.assocRespDataLen,
955 				sme_start_bss_req->add_ie_params.
956 					assocRespData_buff,
957 				sme_start_bss_req->add_ie_params.
958 					assocRespDataLen);
959 		}
960 		/* Store the session related params in newly created session */
961 		session->curr_op_freq = sme_start_bss_req->oper_ch_freq;
962 		session->pLimStartBssReq = sme_start_bss_req;
963 		lim_start_bss_update_ht_vht_caps(mac_ctx, session);
964 
965 		sir_copy_mac_addr(session->self_mac_addr, bssid.bytes);
966 		/* Copy SSID to session table */
967 		qdf_mem_copy((uint8_t *) &session->ssId,
968 			     (uint8_t *) &sme_start_bss_req->ssId,
969 			     (sme_start_bss_req->ssId.length + 1));
970 
971 		session->nwType = sme_start_bss_req->nwType;
972 
973 		session->beaconParams.beaconInterval =
974 			sme_start_bss_req->beaconInterval;
975 
976 		/* Update the phymode */
977 		session->gLimPhyMode = sme_start_bss_req->nwType;
978 
979 		session->maxTxPower = wlan_reg_get_channel_reg_power_for_freq(
980 			mac_ctx->pdev, session->curr_op_freq);
981 		/* Store the dot 11 mode in to the session Table */
982 		session->dot11mode = sme_start_bss_req->dot11mode;
983 
984 		if (session->dot11mode == MLME_DOT11_MODE_11B)
985 			mac_ctx->mlme_cfg->
986 				feature_flags.enable_short_slot_time_11g = 0;
987 		else
988 			mac_ctx->mlme_cfg->feature_flags.
989 				enable_short_slot_time_11g =
990 						mac_ctx->mlme_cfg->ht_caps.
991 							short_slot_time_enabled;
992 		ucast_cipher = wlan_crypto_get_param(session->vdev,
993 					WLAN_CRYPTO_PARAM_UCAST_CIPHER);
994 		auth_mode = wlan_crypto_get_param(session->vdev,
995 					WLAN_CRYPTO_PARAM_AUTH_MODE);
996 		akm = wlan_crypto_get_param(session->vdev,
997 					    WLAN_CRYPTO_PARAM_KEY_MGMT);
998 
999 		lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm,
1000 				sme_start_bss_req->privacy);
1001 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
1002 		lim_fill_cc_mode(mac_ctx, session);
1003 #endif
1004 
1005 		if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) {
1006 			vdev_type_nss = &mac_ctx->vdev_type_nss_5g;
1007 			cb_mode = mac_ctx->roam.configParam.
1008 						channelBondingMode5GHz;
1009 		} else {
1010 			vdev_type_nss = &mac_ctx->vdev_type_nss_2g;
1011 			cb_mode = mac_ctx->roam.configParam.
1012 						channelBondingMode24GHz;
1013 		}
1014 
1015 		switch (bss_type) {
1016 		case eSIR_INFRA_AP_MODE:
1017 			lim_configure_ap_start_bss_session(mac_ctx, session,
1018 				sme_start_bss_req);
1019 			if (session->opmode == QDF_SAP_MODE)
1020 				session->vdev_nss = vdev_type_nss->sap;
1021 			else
1022 				session->vdev_nss = vdev_type_nss->p2p_go;
1023 			break;
1024 		case eSIR_NDI_MODE:
1025 			session->vdev_nss = vdev_type_nss->ndi;
1026 			session->limSystemRole = eLIM_NDI_ROLE;
1027 			break;
1028 
1029 
1030 		/*
1031 		 * There is one more mode called auto mode.
1032 		 * which is used no where
1033 		 */
1034 
1035 		/* FORBUILD -TEMPFIX.. HOW TO use AUTO MODE????? */
1036 
1037 		default:
1038 			/* not used anywhere...used in scan function */
1039 			break;
1040 		}
1041 
1042 		session->nss = session->vdev_nss;
1043 		if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2)
1044 			session->nss = 1;
1045 
1046 		session->htCapability =
1047 			IS_DOT11_MODE_HT(session->dot11mode);
1048 		session->vhtCapability =
1049 			IS_DOT11_MODE_VHT(session->dot11mode);
1050 
1051 		if (IS_DOT11_MODE_HE(session->dot11mode)) {
1052 			lim_update_session_he_capable(mac_ctx, session);
1053 			lim_copy_bss_he_cap(session);
1054 		} else if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
1055 			pe_err("Invalid oper_ch_freq %d for dot11mode %d",
1056 			       session->curr_op_freq, session->dot11mode);
1057 			ret_code = eSIR_SME_INVALID_PARAMETERS;
1058 			goto free;
1059 		} else {
1060 			lim_strip_he_ies_from_add_ies(mac_ctx, session);
1061 		}
1062 
1063 		if (IS_DOT11_MODE_EHT(session->dot11mode)) {
1064 			lim_update_session_eht_capable(mac_ctx, session);
1065 			lim_copy_bss_eht_cap(session);
1066 		} else {
1067 			lim_strip_eht_ies_from_add_ies(mac_ctx, session);
1068 		}
1069 
1070 		session->txLdpcIniFeatureEnabled =
1071 				mac_ctx->mlme_cfg->ht_caps.tx_ldpc_enable;
1072 		rsn_caps = wlan_crypto_get_param(session->vdev,
1073 						 WLAN_CRYPTO_PARAM_RSN_CAP);
1074 		session->limRmfEnabled =
1075 			rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED ? 1 : 0;
1076 
1077 		qdf_mem_copy((void *)&session->rateSet,
1078 			     (void *)&sme_start_bss_req->operationalRateSet,
1079 			     sizeof(tSirMacRateSet));
1080 		qdf_mem_copy((void *)&session->extRateSet,
1081 			     (void *)&sme_start_bss_req->extendedRateSet,
1082 			     sizeof(tSirMacRateSet));
1083 		/*
1084 		 * Allocate memory for the array of
1085 		 * parsed (Re)Assoc request structure
1086 		 */
1087 		if (bss_type == eSIR_INFRA_AP_MODE) {
1088 			session->parsedAssocReq =
1089 				qdf_mem_malloc(session->dph.dphHashTable.
1090 						size * sizeof(tpSirAssocReq));
1091 			if (!session->parsedAssocReq) {
1092 				ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
1093 				goto free;
1094 			}
1095 		}
1096 
1097 		if (!sme_start_bss_req->oper_ch_freq &&
1098 		    bss_type != eSIR_NDI_MODE) {
1099 			pe_err("Received invalid eWNI_SME_START_BSS_REQ");
1100 			ret_code = eSIR_SME_INVALID_PARAMETERS;
1101 			goto free;
1102 		}
1103 #ifdef QCA_HT_2040_COEX
1104 		if (mac_ctx->roam.configParam.obssEnabled &&
1105 		    !policy_mgr_is_vdev_ll_lt_sap(mac_ctx->psoc, vdev_id))
1106 			session->htSupportedChannelWidthSet =
1107 				session->htCapability;
1108 		else
1109 #endif
1110 		session->htSupportedChannelWidthSet =
1111 			(sme_start_bss_req->sec_ch_offset) ? 1 : 0;
1112 		session->htSecondaryChannelOffset =
1113 			sme_start_bss_req->sec_ch_offset;
1114 		session->htRecommendedTxWidthSet =
1115 			(session->htSecondaryChannelOffset) ? 1 : 0;
1116 		if (lim_is_session_he_capable(session) ||
1117 		    lim_is_session_eht_capable(session) ||
1118 		    session->vhtCapability || session->htCapability) {
1119 			chanwidth = sme_start_bss_req->vht_channel_width;
1120 			session->ch_width = chanwidth;
1121 			session->ch_center_freq_seg0 =
1122 				sme_start_bss_req->center_freq_seg0;
1123 			session->ch_center_freq_seg1 =
1124 				sme_start_bss_req->center_freq_seg1;
1125 			lim_update_he_bw_cap_mcs(session, NULL);
1126 			lim_update_eht_bw_cap_mcs(session, NULL);
1127 		}
1128 
1129 		/* Delete pre-auth list if any */
1130 		lim_delete_pre_auth_list(mac_ctx);
1131 
1132 		/*
1133 		 * keep the RSN/WPA IE information in PE Session Entry
1134 		 * later will be using this to check when received (Re)Assoc req
1135 		 */
1136 		lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(mac_ctx,
1137 				&sme_start_bss_req->rsnIE, session);
1138 
1139 		if (LIM_IS_AP_ROLE(session) || LIM_IS_NDI_ROLE(session)) {
1140 			/* Initialize WPS PBC session link list */
1141 			session->pAPWPSPBCSession = NULL;
1142 		}
1143 		/* Prepare and Issue LIM_MLM_START_REQ to MLM */
1144 		mlm_start_req = qdf_mem_malloc(sizeof(tLimMlmStartReq));
1145 		if (!mlm_start_req) {
1146 			ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
1147 			goto free;
1148 		}
1149 
1150 		/* Copy SSID to the MLM start structure */
1151 		qdf_mem_copy((uint8_t *) &mlm_start_req->ssId,
1152 			     (uint8_t *) &sme_start_bss_req->ssId,
1153 			     sme_start_bss_req->ssId.length + 1);
1154 		mlm_start_req->ssidHidden = sme_start_bss_req->ssidHidden;
1155 
1156 		mlm_start_req->bssType = session->bssType;
1157 
1158 		/* Fill PE session Id from the session Table */
1159 		mlm_start_req->sessionId = session->peSessionId;
1160 
1161 		sir_copy_mac_addr(mlm_start_req->bssId, session->bssId);
1162 		/* store the channel num in mlmstart req structure */
1163 		mlm_start_req->oper_ch_freq = session->curr_op_freq;
1164 		mlm_start_req->beaconPeriod =
1165 			session->beaconParams.beaconInterval;
1166 		mlm_start_req->cac_duration_ms =
1167 			sme_start_bss_req->cac_duration_ms;
1168 		mlm_start_req->dfs_regdomain =
1169 			sme_start_bss_req->dfs_regdomain;
1170 		if (LIM_IS_AP_ROLE(session)) {
1171 			mlm_start_req->dtimPeriod = session->dtimPeriod;
1172 			mlm_start_req->wps_state = session->wps_state;
1173 			session->cac_duration_ms =
1174 				mlm_start_req->cac_duration_ms;
1175 			session->dfs_regdomain = mlm_start_req->dfs_regdomain;
1176 			mlm_start_req->cbMode = cb_mode;
1177 			qdf_status =
1178 				wlan_mlme_is_ap_obss_prot_enabled(mac_ctx->psoc,
1179 								  &cfg_value);
1180 			if (QDF_IS_STATUS_ERROR(qdf_status))
1181 				pe_err("Unable to get obssProtEnabled");
1182 			mlm_start_req->obssProtEnabled = cfg_value;
1183 		} else {
1184 			val = mac_ctx->mlme_cfg->sap_cfg.dtim_interval;
1185 			mlm_start_req->dtimPeriod = (uint8_t) val;
1186 		}
1187 
1188 		mlm_start_req->cfParamSet.cfpPeriod =
1189 			mac_ctx->mlme_cfg->rates.cfp_period;
1190 		mlm_start_req->cfParamSet.cfpMaxDuration =
1191 			mac_ctx->mlme_cfg->rates.cfp_max_duration;
1192 
1193 		/*
1194 		 * this may not be needed anymore now,
1195 		 * as rateSet is now included in the
1196 		 * session entry and MLM has session context.
1197 		 */
1198 		qdf_mem_copy((void *)&mlm_start_req->rateSet,
1199 			     (void *)&session->rateSet,
1200 			     sizeof(tSirMacRateSet));
1201 
1202 		/* Now populate the 11n related parameters */
1203 		mlm_start_req->nwType = session->nwType;
1204 		mlm_start_req->htCapable = session->htCapability;
1205 
1206 		mlm_start_req->htOperMode = mac_ctx->lim.gHTOperMode;
1207 		/* Unused */
1208 		mlm_start_req->dualCTSProtection =
1209 			mac_ctx->lim.gHTDualCTSProtection;
1210 		mlm_start_req->txChannelWidthSet =
1211 			session->htRecommendedTxWidthSet;
1212 
1213 		session->limRFBand = lim_get_rf_band(
1214 			sme_start_bss_req->oper_ch_freq);
1215 
1216 		/* Initialize 11h Enable Flag */
1217 		session->lim11hEnable = 0;
1218 		if (CHAN_HOP_ALL_BANDS_ENABLE ||
1219 		    (session->limRFBand != REG_BAND_2G)) {
1220 			session->lim11hEnable =
1221 				mac_ctx->mlme_cfg->gen.enabled_11h;
1222 
1223 			if (session->lim11hEnable &&
1224 				(eSIR_INFRA_AP_MODE ==
1225 					mlm_start_req->bssType)) {
1226 				session->lim11hEnable =
1227 					mac_ctx->mlme_cfg->
1228 					dfs_cfg.dfs_master_capable;
1229 			}
1230 		}
1231 
1232 		if (!session->lim11hEnable)
1233 			mac_ctx->mlme_cfg->power.local_power_constraint = 0;
1234 
1235 		mlm_start_req->beacon_tx_rate = session->beacon_tx_rate;
1236 		lim_save_max_mcs_idx(mac_ctx, session);
1237 		session->limPrevSmeState = session->limSmeState;
1238 		session->limSmeState = eLIM_SME_WT_START_BSS_STATE;
1239 
1240 		lim_dump_session_info(mac_ctx, session);
1241 		lim_dump_he_info(mac_ctx, session);
1242 		lim_dump_eht_info(session);
1243 
1244 		MTRACE(mac_trace
1245 			(mac_ctx, TRACE_CODE_SME_STATE,
1246 			session->peSessionId,
1247 			session->limSmeState));
1248 
1249 		qdf_status = lim_send_start_vdev_req(session, mlm_start_req);
1250 		if (QDF_IS_STATUS_ERROR(qdf_status))
1251 			goto free;
1252 		qdf_mem_free(mlm_start_req);
1253 		lim_update_rrm_capability(mac_ctx);
1254 
1255 		return;
1256 	} else {
1257 
1258 		pe_err("Received unexpected START_BSS_REQ, in state %X",
1259 			mac_ctx->lim.gLimSmeState);
1260 		ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
1261 		goto free;
1262 	} /* if (mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) */
1263 
1264 free:
1265 	if ((session) &&
1266 	    (session->pLimStartBssReq == sme_start_bss_req)) {
1267 		session->pLimStartBssReq = NULL;
1268 	}
1269 	if (sme_start_bss_req)
1270 		qdf_mem_free(sme_start_bss_req);
1271 	if (mlm_start_req)
1272 		qdf_mem_free(mlm_start_req);
1273 	if (session) {
1274 		pe_delete_session(mac_ctx, session);
1275 		session = NULL;
1276 	}
1277 	 lim_send_sme_start_bss_rsp(mac_ctx, ret_code, session, vdev_id);
1278 }
1279 
1280 /**
1281  * __lim_process_sme_start_bss_req() - Call handler to start BSS
1282  *
1283  * @mac: Global MAC context
1284  * @pMsg: Message pointer
1285  *
1286  * Wrapper for the function __lim_handle_sme_start_bss_request
1287  * This message will be deferred until softmac come out of
1288  * scan mode or if we have detected radar on the current
1289  * operating channel.
1290  *
1291  * return true - If we consumed the buffer
1292  *        false - If have deferred the message.
1293  */
1294 static bool __lim_process_sme_start_bss_req(struct mac_context *mac,
1295 					    struct scheduler_msg *pMsg)
1296 {
1297 	if (__lim_is_deferred_msg_for_radar(mac, pMsg)) {
1298 		/**
1299 		 * If message deferred, buffer is not consumed yet.
1300 		 * So return false
1301 		 */
1302 		return false;
1303 	}
1304 
1305 	__lim_handle_sme_start_bss_request(mac, (uint32_t *) pMsg->bodyptr);
1306 	return true;
1307 }
1308 
1309 /**
1310  *  lim_get_random_bssid()
1311  *
1312  *  FUNCTION:This function is called to process generate the random number for bssid
1313  *  This function is called to process SME_SCAN_REQ message
1314  *  from HDD or upper layer application.
1315  *
1316  * LOGIC:
1317  *
1318  * ASSUMPTIONS:
1319  *
1320  * NOTE:
1321  * 1. geneartes the unique random number for bssid in ibss
1322  *
1323  *  @param  mac      Pointer to Global MAC structure
1324  *  @param  *data      Pointer to  bssid  buffer
1325  *  @return None
1326  */
1327 void lim_get_random_bssid(struct mac_context *mac, uint8_t *data)
1328 {
1329 	uint32_t random[2];
1330 
1331 	random[0] = qdf_mc_timer_get_system_ticks();
1332 	random[0] |= (random[0] << 15);
1333 	random[1] = random[0] >> 1;
1334 	qdf_mem_copy(data, random, sizeof(tSirMacAddr));
1335 }
1336 
1337 /**
1338  * lim_send_join_req() - send vdev start request for assoc
1339  *@session: pe session
1340  *@mlm_join_req: join req
1341  *
1342  * Return: QDF_STATUS
1343  */
1344 static QDF_STATUS lim_send_join_req(struct pe_session *session,
1345 				    tLimMlmJoinReq *mlm_join_req)
1346 {
1347 	QDF_STATUS status;
1348 
1349 	/* Continue connect only if Vdev is in INIT state */
1350 	status = wlan_vdev_mlme_is_init_state(session->vdev);
1351 	if (QDF_IS_STATUS_ERROR(status)) {
1352 		pe_err("Vdev %d not in int state cur state %d substate %d",
1353 			session->vdev_id,
1354 			wlan_vdev_mlme_get_state(session->vdev),
1355 			wlan_vdev_mlme_get_substate(session->vdev));
1356 		qdf_trigger_self_recovery(session->mac_ctx->psoc,
1357 					  QDF_VDEV_SM_OUT_OF_SYNC);
1358 		return status;
1359 	}
1360 	status = mlme_set_assoc_type(session->vdev, VDEV_ASSOC);
1361 	if (QDF_IS_STATUS_ERROR(status))
1362 		return status;
1363 
1364 	return wlan_vdev_mlme_sm_deliver_evt(session->vdev,
1365 					     WLAN_VDEV_SM_EV_START,
1366 					     sizeof(*mlm_join_req),
1367 					     mlm_join_req);
1368 }
1369 
1370 #ifdef WLAN_FEATURE_HOST_ROAM
1371 /**
1372  * lim_send_reassoc_req() - send vdev start request for reassoc
1373  *@session: pe session
1374  *@mlm_join_req: join req
1375  *
1376  * Return: QDF_STATUS
1377  */
1378 static QDF_STATUS lim_send_reassoc_req(struct pe_session *session,
1379 				       tLimMlmReassocReq *reassoc_req)
1380 {
1381 	QDF_STATUS status;
1382 
1383 	status = mlme_set_assoc_type(session->vdev, VDEV_REASSOC);
1384 	if (QDF_IS_STATUS_ERROR(status))
1385 		return status;
1386 
1387 	if (wlan_vdev_mlme_get_state(session->vdev) != WLAN_VDEV_S_UP) {
1388 		pe_err("Reassoc req in unexpected vdev SM state:%d",
1389 		       wlan_vdev_mlme_get_state(session->vdev));
1390 		return QDF_STATUS_E_FAILURE;
1391 	}
1392 
1393 	lim_process_mlm_reassoc_req(session->mac_ctx, reassoc_req);
1394 	return QDF_STATUS_SUCCESS;
1395 }
1396 
1397 /**
1398  * lim_send_ft_reassoc_req() - send vdev start request for ft_reassoc
1399  *@session: pe session
1400  *@mlm_join_req: join req
1401  *
1402  * Return: QDF_STATUS
1403  */
1404 static QDF_STATUS lim_send_ft_reassoc_req(struct pe_session *session,
1405 					  tLimMlmReassocReq *reassoc_req)
1406 {
1407 	QDF_STATUS status;
1408 
1409 	status = mlme_set_assoc_type(session->vdev, VDEV_FT_REASSOC);
1410 	if (QDF_IS_STATUS_ERROR(status))
1411 		return status;
1412 
1413 	if (wlan_vdev_mlme_get_state(session->vdev) == WLAN_VDEV_S_UP) {
1414 		pe_err("ft_reassoc req in unexpected vdev SM state:%d",
1415 		       wlan_vdev_mlme_get_state(session->vdev));
1416 		return QDF_STATUS_E_FAILURE;
1417 	}
1418 
1419 	return wlan_vdev_mlme_sm_deliver_evt(session->vdev,
1420 					     WLAN_VDEV_SM_EV_START,
1421 					     sizeof(*reassoc_req),
1422 					     reassoc_req);
1423 }
1424 #endif
1425 
1426 static void lim_join_req_update_ht_vht_caps(struct mac_context *mac,
1427 					    struct pe_session *session,
1428 					    struct bss_description *bss_desc,
1429 					    tDot11fBeaconIEs *bcn_ie)
1430 {
1431 	struct vdev_mlme_obj *vdev_mlme;
1432 	struct wlan_vht_config vht_config;
1433 	uint8_t value, value1;
1434 	tDot11fIEVHTCaps *vht_caps = NULL;
1435 	uint8_t tx_bf_csn = 0;
1436 	struct wlan_ht_config ht_caps;
1437 
1438 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
1439 	if (!vdev_mlme)
1440 		return;
1441 
1442 	lim_set_ldpc_exception(mac, vdev_mlme, session->curr_op_freq);
1443 	vht_config.caps = vdev_mlme->proto.vht_info.caps;
1444 
1445 	value = mac->mlme_cfg->vht_caps.vht_cap_info.su_bformee;
1446 	value1 = mac->mlme_cfg->vht_caps.vht_cap_info.tx_bfee_ant_supp;
1447 
1448 	vht_config.su_beam_formee = value;
1449 
1450 	if (bcn_ie->VHTCaps.present)
1451 		vht_caps = &bcn_ie->VHTCaps;
1452 	else if (bcn_ie->vendor_vht_ie.VHTCaps.present)
1453 		vht_caps = &bcn_ie->vendor_vht_ie.VHTCaps;
1454 	/* Set BF CSN value only if SU Bformee is enabled */
1455 	if (vht_caps && vht_config.su_beam_formee) {
1456 		tx_bf_csn = value1;
1457 		/*
1458 		 * Certain commercial AP display a bad behavior when
1459 		 * CSN value in  assoc request is more than AP's CSN.
1460 		 * Sending absolute self CSN value with such AP leads to
1461 		 * IOT issues. However this issue is observed only with
1462 		 * CSN cap of less than 4. To avoid such issues, take a
1463 		 * min of self and peer CSN while sending ASSOC request.
1464 		 */
1465 		if (bcn_ie->Vendor1IE.present &&
1466 		    vht_caps->csnofBeamformerAntSup < 4) {
1467 			if (vht_caps->csnofBeamformerAntSup)
1468 				tx_bf_csn = QDF_MIN(tx_bf_csn,
1469 					vht_caps->csnofBeamformerAntSup);
1470 		}
1471 	}
1472 	vht_config.csnof_beamformer_antSup = tx_bf_csn;
1473 
1474 	value = mac->mlme_cfg->vht_caps.vht_cap_info.su_bformer;
1475 	/*
1476 	 * Set SU Bformer only if SU Bformer is enabled in INI
1477 	 * and AP is SU Bformee capable
1478 	 */
1479 	if (value && !((IS_BSS_VHT_CAPABLE(bcn_ie->VHTCaps) &&
1480 	    bcn_ie->VHTCaps.suBeamformeeCap) ||
1481 	    (IS_BSS_VHT_CAPABLE(bcn_ie->vendor_vht_ie.VHTCaps) &&
1482 	    bcn_ie->vendor_vht_ie.VHTCaps.suBeamformeeCap)))
1483 		value = 0;
1484 
1485 	vht_config.su_beam_former = value;
1486 
1487 	/* Set num soundingdim value to 0 if SU Bformer is disabled */
1488 	if (!vht_config.su_beam_former)
1489 		vht_config.num_soundingdim = 0;
1490 
1491 	value = mac->mlme_cfg->vht_caps.vht_cap_info.enable_mu_bformee;
1492 	/*
1493 	 * Set MU Bformee only if SU Bformee is enabled and
1494 	 * MU Bformee is enabled in INI
1495 	 */
1496 	if (value && vht_config.su_beam_formee &&
1497 	    bcn_ie->VHTCaps.muBeamformerCap)
1498 		vht_config.mu_beam_formee = 1;
1499 	else
1500 		vht_config.mu_beam_formee = 0;
1501 
1502 	if (IS_DOT11_MODE_VHT(session->dot11mode) &&
1503 	    session->opmode != QDF_STA_MODE)
1504 		vht_config.su_beam_formee = 0;
1505 
1506 	session->vht_config = vht_config;
1507 	ht_caps.caps = vdev_mlme->proto.ht_info.ht_caps;
1508 	session->ht_config = ht_caps.ht_caps;
1509 
1510 	if (session->opmode == QDF_STA_MODE) {
1511 		if (session->ht_config.short_gi_20_mhz)
1512 			session->ht_config.short_gi_20_mhz =
1513 						bcn_ie->HTCaps.shortGI20MHz;
1514 
1515 		if (session->ht_config.short_gi_40_mhz)
1516 			session->ht_config.short_gi_40_mhz =
1517 						bcn_ie->HTCaps.shortGI40MHz;
1518 	}
1519 
1520 	lim_revise_req_vht_cap_per_band(session);
1521 	pe_debug("HT cap 0x%x VHT cap 0x%x, AP cap sgi_20 %d sgi_40 %d",
1522 		 ht_caps.caps, vht_config.caps,
1523 		 bcn_ie->HTCaps.shortGI20MHz, bcn_ie->HTCaps.shortGI40MHz);
1524 }
1525 
1526 bool
1527 lim_get_vdev_rmf_capable(struct mac_context *mac, struct pe_session *session)
1528 {
1529 	struct wlan_objmgr_vdev *vdev;
1530 	int32_t rsn_caps;
1531 	bool peer_rmf_capable = false;
1532 
1533 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc,
1534 						    session->vdev_id,
1535 						    WLAN_LEGACY_SME_ID);
1536 	if (!vdev) {
1537 		pe_err("Invalid vdev");
1538 		return false;
1539 	}
1540 	rsn_caps = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP);
1541 	if (rsn_caps < 0) {
1542 		pe_err("Invalid mgmt cipher");
1543 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1544 		return false;
1545 	}
1546 	if (wlan_crypto_vdev_has_mgmtcipher(
1547 				vdev,
1548 				(1 << WLAN_CRYPTO_CIPHER_AES_GMAC) |
1549 				(1 << WLAN_CRYPTO_CIPHER_AES_GMAC_256) |
1550 				(1 << WLAN_CRYPTO_CIPHER_AES_CMAC)) &&
1551 	    (rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED))
1552 		peer_rmf_capable = true;
1553 
1554 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1555 
1556 	return peer_rmf_capable;
1557 }
1558 
1559 /**
1560  * lim_get_nss_supported_by_sta_and_ap() - finds out nss from session
1561  * and beacon from AP
1562  * @vht_caps: VHT capabilities
1563  * @ht_caps: HT capabilities
1564  * @dot11_mode: dot11 mode
1565  *
1566  * Return: number of nss advertised by beacon
1567  */
1568 static uint8_t
1569 lim_get_nss_supported_by_sta_and_ap(tDot11fIEVHTCaps *vht_caps,
1570 				    tDot11fIEHTCaps *ht_caps,
1571 				    tDot11fIEhe_cap *he_cap,
1572 				    enum mlme_dot11_mode dot11_mode)
1573 {
1574 	bool vht_capability, ht_capability, he_capability;
1575 
1576 	vht_capability = IS_DOT11_MODE_VHT(dot11_mode);
1577 	ht_capability = IS_DOT11_MODE_HT(dot11_mode);
1578 	he_capability = IS_DOT11_MODE_HE(dot11_mode);
1579 
1580 	if (he_capability && he_cap->present) {
1581 		if ((he_cap->rx_he_mcs_map_lt_80 & 0xC0) != 0xC0)
1582 			return NSS_4x4_MODE;
1583 
1584 		if ((he_cap->rx_he_mcs_map_lt_80 & 0x30) != 0x30)
1585 			return NSS_3x3_MODE;
1586 
1587 		if ((he_cap->rx_he_mcs_map_lt_80 & 0x0C) != 0x0C)
1588 			return NSS_2x2_MODE;
1589 	} else if (vht_capability && vht_caps->present) {
1590 		if ((vht_caps->rxMCSMap & 0xC0) != 0xC0)
1591 			return NSS_4x4_MODE;
1592 
1593 		if ((vht_caps->rxMCSMap & 0x30) != 0x30)
1594 			return NSS_3x3_MODE;
1595 
1596 		if ((vht_caps->rxMCSMap & 0x0C) != 0x0C)
1597 			return NSS_2x2_MODE;
1598 	} else if (ht_capability && ht_caps->present) {
1599 		if (ht_caps->supportedMCSSet[3])
1600 			return NSS_4x4_MODE;
1601 
1602 		if (ht_caps->supportedMCSSet[2])
1603 			return NSS_3x3_MODE;
1604 
1605 		if (ht_caps->supportedMCSSet[1])
1606 			return NSS_2x2_MODE;
1607 	}
1608 
1609 	return NSS_1x1_MODE;
1610 }
1611 
1612 /**
1613  * lim_check_vendor_ap_3_present() - Check if Vendor AP 3 is present
1614  * @mac_ctx: Pointer to Global MAC structure
1615  * @ie: Pointer to starting IE in Beacon/Probe Response
1616  * @ie_len: Length of all IEs combined
1617  *
1618  * For Vendor AP 3, the condition is that Vendor AP 3 IE should be present
1619  * and Vendor AP 4 IE should not be present.
1620  * If Vendor AP 3 IE is present and Vendor AP 4 IE is also present,
1621  * return false, else return true.
1622  *
1623  * Return: true or false
1624  */
1625 static bool
1626 lim_check_vendor_ap_3_present(struct mac_context *mac_ctx, uint8_t *ie,
1627 			      uint16_t ie_len)
1628 {
1629 	bool ret = true;
1630 
1631 	if ((wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_VENDOR_AP_3_OUI,
1632 	    SIR_MAC_VENDOR_AP_3_OUI_LEN, ie, ie_len)) &&
1633 	    (wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_VENDOR_AP_4_OUI,
1634 	    SIR_MAC_VENDOR_AP_4_OUI_LEN, ie, ie_len))) {
1635 		pe_debug("Vendor OUI 3 and Vendor OUI 4 found");
1636 		ret = false;
1637 	}
1638 
1639 	return ret;
1640 }
1641 
1642 #ifdef WLAN_FEATURE_11AX
1643 static void
1644 lim_handle_iot_ap_no_common_he_rates(struct mac_context *mac,
1645 				     struct pe_session *session,
1646 				     tDot11fBeaconIEs *ies)
1647 {
1648 	uint16_t int_mcs;
1649 	struct wlan_objmgr_vdev *vdev = session->vdev;
1650 	struct mlme_legacy_priv *mlme_priv;
1651 
1652 	/* if the connection is not 11AX mode then return */
1653 	if (session->dot11mode != MLME_DOT11_MODE_11AX)
1654 		return;
1655 
1656 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
1657 	if (!mlme_priv)
1658 		return;
1659 
1660 	int_mcs = HE_INTERSECT_MCS(mlme_priv->he_config.tx_he_mcs_map_lt_80,
1661 				   ies->he_cap.rx_he_mcs_map_lt_80);
1662 	pe_debug("HE self rates %x AP rates %x int_mcs %x vendorIE %d",
1663 		 mlme_priv->he_config.rx_he_mcs_map_lt_80,
1664 		 ies->he_cap.rx_he_mcs_map_lt_80, int_mcs,
1665 		 ies->vendor_vht_ie.present);
1666 	if (ies->he_cap.present)
1667 		if ((int_mcs == 0xFFFF) &&
1668 		    (ies->vendor_vht_ie.present ||
1669 		     ies->VHTCaps.present)) {
1670 			session->dot11mode = MLME_DOT11_MODE_11AC;
1671 			sme_debug("No common 11AX rate. Force 11AC connection");
1672 	}
1673 }
1674 #else
1675 static void lim_handle_iot_ap_no_common_he_rates(struct mac_context *mac,
1676 					struct pe_session *session,
1677 					tDot11fBeaconIEs *ies)
1678 {
1679 }
1680 #endif
1681 
1682 #ifdef WLAN_FEATURE_11AX
1683 
1684 /**
1685  * lim_update_he_caps_htc() - Update htc in he caps
1686  * @session: Pointer to PE session
1687  * @val: htc he enabled status
1688  *
1689  * Return: void
1690  */
1691 static void
1692 lim_update_he_caps_htc(struct pe_session *session, bool val)
1693 {
1694 	struct wlan_objmgr_vdev *vdev = session->vdev;
1695 	struct mlme_legacy_priv *mlme_priv;
1696 
1697 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
1698 	if (!mlme_priv)
1699 		return;
1700 
1701 	pe_debug("new htc he: %d", val);
1702 	mlme_priv->he_config.htc_he = val;
1703 }
1704 #else
1705 
1706 static void
1707 lim_update_he_caps_htc(struct pe_session *session,  bool val)
1708 {
1709 }
1710 #endif
1711 
1712 #ifdef WLAN_FEATURE_11BE
1713 void
1714 lim_update_eht_caps_mcs(struct mac_context *mac, struct pe_session *session)
1715 {
1716 	uint8_t tx_nss = 0;
1717 	uint8_t rx_nss = 0;
1718 	struct wlan_objmgr_vdev *vdev = session->vdev;
1719 	struct mlme_legacy_priv *mlme_priv;
1720 	struct wlan_mlme_cfg *mlme_cfg = mac->mlme_cfg;
1721 	tDot11fIEeht_cap *dot11_eht_cap;
1722 	tDot11fIEeht_cap *eht_config;
1723 
1724 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
1725 	if (!mlme_priv)
1726 		return;
1727 
1728 	eht_config = &mlme_priv->eht_config;
1729 	dot11_eht_cap = &mlme_cfg->eht_caps.dot11_eht_cap;
1730 
1731 	if (session->nss == 1) {
1732 		tx_nss = 1;
1733 		rx_nss = 1;
1734 	} else {
1735 		tx_nss = dot11_eht_cap->bw_20_tx_max_nss_for_mcs_0_to_7;
1736 		rx_nss = dot11_eht_cap->bw_20_rx_max_nss_for_mcs_0_to_7;
1737 	}
1738 
1739 	if (!tx_nss || tx_nss > 2 || !rx_nss || rx_nss > 2) {
1740 		pe_err("invalid Nss values tx_nss: %u rx_nss: %u",
1741 		       tx_nss, rx_nss);
1742 		return;
1743 	}
1744 
1745 	eht_config->bw_20_rx_max_nss_for_mcs_0_to_7 = rx_nss;
1746 	eht_config->bw_20_tx_max_nss_for_mcs_0_to_7 = tx_nss;
1747 	eht_config->bw_20_rx_max_nss_for_mcs_8_and_9 = rx_nss;
1748 	eht_config->bw_20_tx_max_nss_for_mcs_8_and_9 = tx_nss;
1749 	if (dot11_eht_cap->bw_20_rx_max_nss_for_mcs_10_and_11) {
1750 		eht_config->bw_20_rx_max_nss_for_mcs_10_and_11 = rx_nss;
1751 		eht_config->bw_20_tx_max_nss_for_mcs_10_and_11 = tx_nss;
1752 	}
1753 	if (dot11_eht_cap->bw_20_rx_max_nss_for_mcs_12_and_13) {
1754 		eht_config->bw_20_rx_max_nss_for_mcs_12_and_13 = rx_nss;
1755 		eht_config->bw_20_tx_max_nss_for_mcs_12_and_13 = tx_nss;
1756 	}
1757 	eht_config->bw_le_80_rx_max_nss_for_mcs_0_to_9 = rx_nss;
1758 	eht_config->bw_le_80_tx_max_nss_for_mcs_0_to_9 = tx_nss;
1759 	if (dot11_eht_cap->bw_le_80_rx_max_nss_for_mcs_10_and_11) {
1760 		eht_config->bw_le_80_rx_max_nss_for_mcs_10_and_11 = rx_nss;
1761 		eht_config->bw_le_80_tx_max_nss_for_mcs_10_and_11 = tx_nss;
1762 	}
1763 	if (dot11_eht_cap->bw_le_80_rx_max_nss_for_mcs_12_and_13) {
1764 		eht_config->bw_le_80_rx_max_nss_for_mcs_12_and_13 = rx_nss;
1765 		eht_config->bw_le_80_tx_max_nss_for_mcs_12_and_13 = tx_nss;
1766 	}
1767 	eht_config->bw_160_rx_max_nss_for_mcs_0_to_9 = rx_nss;
1768 	eht_config->bw_160_tx_max_nss_for_mcs_0_to_9 = tx_nss;
1769 	if (dot11_eht_cap->bw_160_rx_max_nss_for_mcs_10_and_11) {
1770 		eht_config->bw_160_rx_max_nss_for_mcs_10_and_11 = rx_nss;
1771 		eht_config->bw_160_tx_max_nss_for_mcs_10_and_11 = tx_nss;
1772 	}
1773 	if (dot11_eht_cap->bw_160_rx_max_nss_for_mcs_12_and_13) {
1774 		eht_config->bw_160_rx_max_nss_for_mcs_12_and_13 = rx_nss;
1775 		eht_config->bw_160_tx_max_nss_for_mcs_12_and_13 = tx_nss;
1776 	}
1777 	eht_config->bw_320_rx_max_nss_for_mcs_0_to_9 = rx_nss;
1778 	eht_config->bw_320_tx_max_nss_for_mcs_0_to_9 = tx_nss;
1779 
1780 	if (dot11_eht_cap->bw_320_rx_max_nss_for_mcs_10_and_11) {
1781 		eht_config->bw_320_rx_max_nss_for_mcs_10_and_11 = rx_nss;
1782 		eht_config->bw_320_tx_max_nss_for_mcs_10_and_11 = tx_nss;
1783 	}
1784 	if (dot11_eht_cap->bw_320_rx_max_nss_for_mcs_12_and_13) {
1785 		eht_config->bw_320_rx_max_nss_for_mcs_12_and_13 = rx_nss;
1786 		eht_config->bw_320_tx_max_nss_for_mcs_12_and_13 = tx_nss;
1787 	}
1788 }
1789 #endif
1790 
1791 static void lim_check_oui_and_update_session(struct mac_context *mac_ctx,
1792 					     struct pe_session *session,
1793 					     tDot11fBeaconIEs *ie_struct)
1794 {
1795 	struct action_oui_search_attr vendor_ap_search_attr;
1796 	uint16_t ie_len;
1797 	bool follow_ap_edca;
1798 	struct bss_description *bss_desc =
1799 					&session->lim_join_req->bssDescription;
1800 	bool is_vendor_ap_present;
1801 	uint8_t ap_nss;
1802 	struct vdev_type_nss *vdev_type_nss;
1803 
1804 	if (wlan_reg_is_5ghz_ch_freq(bss_desc->chan_freq))
1805 		vdev_type_nss = &mac_ctx->vdev_type_nss_5g;
1806 	else
1807 		vdev_type_nss = &mac_ctx->vdev_type_nss_2g;
1808 
1809 	if (wlan_vdev_mlme_get_opmode(session->vdev) == QDF_P2P_CLIENT_MODE)
1810 		session->vdev_nss = vdev_type_nss->p2p_cli;
1811 	else
1812 		session->vdev_nss = vdev_type_nss->sta;
1813 	session->nss = session->vdev_nss;
1814 
1815 	ie_len = wlan_get_ielen_from_bss_description(bss_desc);
1816 
1817 	/* Fill the Vendor AP search params */
1818 	vendor_ap_search_attr.ie_data =
1819 			(uint8_t *)&bss_desc->ieFields[0];
1820 	vendor_ap_search_attr.ie_length = ie_len;
1821 	vendor_ap_search_attr.mac_addr = &bss_desc->bssId[0];
1822 	ap_nss = lim_get_nss_supported_by_sta_and_ap(
1823 					&ie_struct->VHTCaps, &ie_struct->HTCaps,
1824 					&ie_struct->he_cap, session->dot11mode);
1825 	vendor_ap_search_attr.nss = ap_nss;
1826 	vendor_ap_search_attr.ht_cap = ie_struct->HTCaps.present;
1827 	vendor_ap_search_attr.vht_cap = ie_struct->VHTCaps.present;
1828 	vendor_ap_search_attr.enable_2g =
1829 				wlan_reg_is_24ghz_ch_freq(bss_desc->chan_freq);
1830 	vendor_ap_search_attr.enable_5g =
1831 				wlan_reg_is_5ghz_ch_freq(bss_desc->chan_freq);
1832 
1833 	if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2) {
1834 		session->nss = 1;
1835 		session->vdev_nss = 1;
1836 	}
1837 
1838 	/*
1839 	 * If CCK WAR is set for current AP, update to firmware via
1840 	 * wmi_vdev_param_abg_mode_tx_chain_num
1841 	 */
1842 	is_vendor_ap_present =
1843 			wlan_action_oui_search(mac_ctx->psoc,
1844 					       &vendor_ap_search_attr,
1845 					       ACTION_OUI_CCKM_1X1);
1846 	if (is_vendor_ap_present) {
1847 		pe_debug("vdev: %d wmi_vdev_param_abg_mode_tx_chain_num 1",
1848 			 session->vdev_id);
1849 		wma_cli_set_command(session->vdev_id,
1850 			(int)wmi_vdev_param_abg_mode_tx_chain_num, 1,
1851 			VDEV_CMD);
1852 	}
1853 
1854 	/*
1855 	 * If Switch to 11N WAR is set for current AP, change dot11
1856 	 * mode to 11N.
1857 	 */
1858 	is_vendor_ap_present =
1859 		wlan_action_oui_search(mac_ctx->psoc,
1860 				       &vendor_ap_search_attr,
1861 				       ACTION_OUI_SWITCH_TO_11N_MODE);
1862 	if (mac_ctx->roam.configParam.is_force_1x1 &&
1863 	    mac_ctx->mlme_cfg->gen.as_enabled &&
1864 	    is_vendor_ap_present &&
1865 	    (session->dot11mode == MLME_DOT11_MODE_ALL ||
1866 	     session->dot11mode == MLME_DOT11_MODE_11AC ||
1867 	     session->dot11mode == MLME_DOT11_MODE_11AC_ONLY))
1868 		session->dot11mode = MLME_DOT11_MODE_11N;
1869 
1870 	follow_ap_edca = wlan_action_oui_search(mac_ctx->psoc,
1871 						&vendor_ap_search_attr,
1872 						ACTION_OUI_DISABLE_AGGRESSIVE_EDCA);
1873 	mlme_set_follow_ap_edca_flag(session->vdev, follow_ap_edca);
1874 
1875 	if (wlan_action_oui_search(mac_ctx->psoc, &vendor_ap_search_attr,
1876 				   ACTION_OUI_HOST_RECONN)) {
1877 		mlme_set_reconn_after_assoc_timeout_flag(
1878 			mac_ctx->psoc, session->vdev_id,
1879 			true);
1880 	}
1881 	is_vendor_ap_present =
1882 			wlan_action_oui_search(mac_ctx->psoc,
1883 					       &vendor_ap_search_attr,
1884 					       ACTION_OUI_CONNECT_1X1);
1885 
1886 	if (is_vendor_ap_present) {
1887 		is_vendor_ap_present = lim_check_vendor_ap_3_present(
1888 					mac_ctx,
1889 					vendor_ap_search_attr.ie_data,
1890 					ie_len);
1891 	}
1892 
1893 	/*
1894 	 * For WMI_ACTION_OUI_CONNECT_1x1_WITH_1_CHAIN, the host
1895 	 * sends the NSS as 1 to the FW and the FW then decides
1896 	 * after receiving the first beacon after connection to
1897 	 * switch to 1 Tx/Rx Chain.
1898 	 */
1899 
1900 	if (!is_vendor_ap_present) {
1901 		is_vendor_ap_present =
1902 			wlan_action_oui_search(mac_ctx->psoc,
1903 					       &vendor_ap_search_attr,
1904 					       ACTION_OUI_CONNECT_1X1_WITH_1_CHAIN);
1905 		if (is_vendor_ap_present)
1906 			pe_debug("1x1 with 1 Chain AP");
1907 	}
1908 
1909 	if (is_vendor_ap_present &&
1910 	    !policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc) &&
1911 	    ((mac_ctx->roam.configParam.is_force_1x1 ==
1912 	    FORCE_1X1_ENABLED_FOR_AS &&
1913 	    mac_ctx->mlme_cfg->gen.as_enabled) ||
1914 	    mac_ctx->roam.configParam.is_force_1x1 ==
1915 	    FORCE_1X1_ENABLED_FORCED)) {
1916 		session->vdev_nss = 1;
1917 		session->nss = 1;
1918 		session->nss_forced_1x1 = true;
1919 		pe_debug("For special ap, NSS: %d force 1x1 %d",
1920 			  session->nss,
1921 			  mac_ctx->roam.configParam.is_force_1x1);
1922 	}
1923 
1924 	if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
1925 		wlan_action_oui_search(mac_ctx->psoc,
1926 				       &vendor_ap_search_attr,
1927 				       ACTION_OUI_AUTH_ASSOC_6MBPS_2GHZ)) {
1928 		session->is_oui_auth_assoc_6mbps_2ghz_enable = true;
1929 	}
1930 
1931 	if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
1932 	    !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band &&
1933 	    session->dot11mode == MLME_DOT11_MODE_11AC) {
1934 		/* Need to disable VHT operation in 2.4 GHz band */
1935 		session->dot11mode = MLME_DOT11_MODE_11N;
1936 	}
1937 
1938 	lim_handle_iot_ap_no_common_he_rates(mac_ctx, session, ie_struct);
1939 	lim_update_he_caps_mcs(mac_ctx, session);
1940 	lim_update_eht_caps_mcs(mac_ctx, session);
1941 
1942 	is_vendor_ap_present = wlan_get_vendor_ie_ptr_from_oui(
1943 				SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI,
1944 				SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI_LEN,
1945 				vendor_ap_search_attr.ie_data, ie_len);
1946 	wlan_mlme_set_ba_2k_jump_iot_ap(session->vdev, is_vendor_ap_present);
1947 
1948 	is_vendor_ap_present = wlan_get_vendor_ie_ptr_from_oui
1949 				(SIR_MAC_BAD_HTC_HE_VENDOR_OUI1,
1950 				 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN,
1951 				 vendor_ap_search_attr.ie_data, ie_len) &&
1952 			       wlan_get_vendor_ie_ptr_from_oui
1953 				(SIR_MAC_BAD_HTC_HE_VENDOR_OUI2,
1954 				 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN,
1955 				 vendor_ap_search_attr.ie_data, ie_len);
1956 
1957 	/*
1958 	 * For SAP with special OUI, if DUT STA connect with 11ax mode with ht
1959 	 * control enabled, SAP can't decode unicast pkt from DUT.
1960 	 * Fix it by clearing ht control bit in he cap when send peer assoc cmd
1961 	 * to firmware when connect such IOT AP with 11ax mode.
1962 	 * New requirement is to change default setting for HT control to false.
1963 	 */
1964 	if (is_vendor_ap_present)
1965 		lim_update_he_caps_htc(session, !is_vendor_ap_present);
1966 }
1967 
1968 static enum mlme_dot11_mode
1969 lim_get_user_dot11_mode(struct wlan_objmgr_vdev *vdev)
1970 {
1971 	WMI_HOST_WIFI_STANDARD wifi_std;
1972 
1973 	wifi_std = mlme_get_vdev_wifi_std(vdev);
1974 
1975 	switch (wifi_std) {
1976 	case WMI_HOST_WIFI_STANDARD_4:
1977 		return MLME_DOT11_MODE_11N;
1978 	case WMI_HOST_WIFI_STANDARD_5:
1979 		return MLME_DOT11_MODE_11AC;
1980 	case WMI_HOST_WIFI_STANDARD_6:
1981 	case WMI_HOST_WIFI_STANDARD_6E:
1982 		return MLME_DOT11_MODE_11AX;
1983 	case WMI_HOST_WIFI_STANDARD_7:
1984 	default:
1985 		return MLME_DOT11_MODE_11BE;
1986 	}
1987 }
1988 
1989 static enum mlme_dot11_mode
1990 lim_intersect_user_dot11_mode(struct mac_context *mac_ctx,
1991 			      enum QDF_OPMODE opmode, uint8_t vdev_id,
1992 			      enum mlme_dot11_mode self_mode)
1993 {
1994 	struct wlan_objmgr_vdev *vdev;
1995 	enum mlme_dot11_mode user_mode;
1996 
1997 	switch (opmode) {
1998 	case QDF_STA_MODE:
1999 	case QDF_P2P_CLIENT_MODE:
2000 		break;
2001 	default:
2002 		return self_mode;
2003 	}
2004 
2005 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id,
2006 						    WLAN_MLME_OBJMGR_ID);
2007 	if (!vdev)
2008 		return self_mode;
2009 
2010 	user_mode = lim_get_user_dot11_mode(vdev);
2011 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
2012 
2013 	return user_mode > self_mode ? self_mode : user_mode;
2014 }
2015 
2016 static enum mlme_dot11_mode
2017 lim_get_self_dot11_mode(struct mac_context *mac_ctx, enum QDF_OPMODE opmode,
2018 			uint8_t vdev_id)
2019 {
2020 	struct wlan_objmgr_vdev *vdev;
2021 	struct vdev_mlme_obj *vdev_mlme;
2022 	enum mlme_vdev_dot11_mode vdev_dot11_mode;
2023 	enum mlme_dot11_mode self_dot11_mode =
2024 				mac_ctx->mlme_cfg->dot11_mode.dot11_mode;
2025 
2026 	switch (opmode) {
2027 	case QDF_STA_MODE:
2028 	case QDF_P2P_CLIENT_MODE:
2029 		break;
2030 	default:
2031 		return self_dot11_mode;
2032 	}
2033 
2034 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id,
2035 						    WLAN_MLME_OBJMGR_ID);
2036 	if (!vdev)
2037 		return self_dot11_mode;
2038 
2039 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
2040 	if (!vdev_mlme) {
2041 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
2042 		return self_dot11_mode;
2043 	}
2044 
2045 	vdev_dot11_mode = vdev_mlme->proto.vdev_dot11_mode;
2046 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
2047 
2048 	if (vdev_dot11_mode == MLME_VDEV_DOT11_MODE_AUTO)
2049 		return self_dot11_mode;
2050 
2051 	if (IS_DOT11_MODE_HT(self_dot11_mode) &&
2052 	    vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11N)
2053 		return MLME_DOT11_MODE_11N;
2054 
2055 	if (IS_DOT11_MODE_VHT(self_dot11_mode) &&
2056 	    vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11AC)
2057 		return MLME_DOT11_MODE_11AC;
2058 
2059 	if (IS_DOT11_MODE_HE(self_dot11_mode) &&
2060 	    vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11AX)
2061 		return MLME_DOT11_MODE_11AX;
2062 
2063 	if (IS_DOT11_MODE_EHT(self_dot11_mode) &&
2064 	    vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11BE)
2065 		return MLME_DOT11_MODE_11BE;
2066 
2067 	return self_dot11_mode;
2068 }
2069 
2070 static bool
2071 lim_get_bss_11be_mode_allowed(struct mac_context *mac_ctx,
2072 			      struct bss_description *bss_desc,
2073 			      tDot11fBeaconIEs *ie_struct)
2074 {
2075 	struct scan_cache_entry *scan_entry;
2076 	bool is_eht_allowed;
2077 
2078 	if (!ie_struct->eht_cap.present)
2079 		return false;
2080 
2081 	scan_entry = wlan_scan_get_entry_by_bssid(mac_ctx->pdev,
2082 						  (struct qdf_mac_addr *)
2083 						  bss_desc->bssId);
2084 
2085 	/*
2086 	 * If AP advertises multiple AKMs(WPA2 PSK + WPA3), allow connection
2087 	 * in 11BE mode as our connection is going to be WPA3
2088 	 */
2089 	if (scan_entry) {
2090 		is_eht_allowed =
2091 			wlan_cm_is_eht_allowed_for_current_security(
2092 					wlan_pdev_get_psoc(mac_ctx->pdev),
2093 					scan_entry);
2094 		util_scan_free_cache_entry(scan_entry);
2095 		if (!is_eht_allowed) {
2096 			pe_debug("Downgrade to 11ax mode due to AP security validation failure");
2097 			return false;
2098 		}
2099 	}
2100 	return mlme_get_bss_11be_allowed(
2101 			mac_ctx->psoc,
2102 			(struct qdf_mac_addr *)&bss_desc->bssId,
2103 			(uint8_t *)&bss_desc->ieFields[0],
2104 			wlan_get_ielen_from_bss_description(bss_desc));
2105 }
2106 
2107 static enum mlme_dot11_mode
2108 lim_get_bss_dot11_mode(struct mac_context *mac_ctx,
2109 		       struct bss_description *bss_desc,
2110 		       tDot11fBeaconIEs *ie_struct)
2111 {
2112 	enum mlme_dot11_mode bss_dot11_mode;
2113 
2114 	switch (bss_desc->nwType) {
2115 	case eSIR_11B_NW_TYPE:
2116 		return MLME_DOT11_MODE_11B;
2117 	case eSIR_11A_NW_TYPE:
2118 		bss_dot11_mode = MLME_DOT11_MODE_11A;
2119 		break;
2120 	case eSIR_11G_NW_TYPE:
2121 		bss_dot11_mode = MLME_DOT11_MODE_11G;
2122 		break;
2123 	default:
2124 		if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq))
2125 			bss_dot11_mode = MLME_DOT11_MODE_11G;
2126 		else
2127 			bss_dot11_mode = MLME_DOT11_MODE_11A;
2128 	}
2129 
2130 	if (ie_struct->HTCaps.present)
2131 		bss_dot11_mode = MLME_DOT11_MODE_11N;
2132 
2133 	if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) ||
2134 	    IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps))
2135 		bss_dot11_mode = MLME_DOT11_MODE_11AC;
2136 
2137 	if (ie_struct->he_cap.present)
2138 		bss_dot11_mode = MLME_DOT11_MODE_11AX;
2139 
2140 	if (ie_struct->eht_cap.present &&
2141 	    lim_get_bss_11be_mode_allowed(mac_ctx, bss_desc, ie_struct))
2142 		bss_dot11_mode = MLME_DOT11_MODE_11BE;
2143 
2144 	return bss_dot11_mode;
2145 }
2146 
2147 static QDF_STATUS
2148 lim_handle_11abg_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2149 			    enum mlme_dot11_mode *intersected_mode,
2150 			    struct bss_description *bss_desc)
2151 {
2152 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
2153 	    !WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) {
2154 		pe_err("self Dot11mode is 11ABG, BSS freq %d not 2.4 or 5 GHz",
2155 		       bss_desc->chan_freq);
2156 		return QDF_STATUS_E_INVAL;
2157 	}
2158 
2159 	switch (bss_dot11_mode) {
2160 	case MLME_DOT11_MODE_11B:
2161 		*intersected_mode = MLME_DOT11_MODE_11B;
2162 		break;
2163 	case MLME_DOT11_MODE_11A:
2164 		*intersected_mode = MLME_DOT11_MODE_11A;
2165 		break;
2166 	case MLME_DOT11_MODE_11G:
2167 		*intersected_mode = MLME_DOT11_MODE_11G;
2168 		break;
2169 	case MLME_DOT11_MODE_11N:
2170 		fallthrough;
2171 	case MLME_DOT11_MODE_11AC:
2172 		fallthrough;
2173 	case MLME_DOT11_MODE_11AX:
2174 		fallthrough;
2175 	case MLME_DOT11_MODE_11BE:
2176 		if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq))
2177 			*intersected_mode = MLME_DOT11_MODE_11G;
2178 		else
2179 			*intersected_mode = MLME_DOT11_MODE_11A;
2180 		break;
2181 	default:
2182 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2183 		return QDF_STATUS_E_FAILURE;
2184 	}
2185 
2186 	return QDF_STATUS_SUCCESS;
2187 }
2188 
2189 static QDF_STATUS
2190 lim_handle_11a_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2191 			  enum mlme_dot11_mode *intersected_mode,
2192 			  struct bss_description *bss_desc)
2193 {
2194 	if (!WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) {
2195 		pe_err("self Dot11mode is 11A and bss freq %d not 5ghz",
2196 		       bss_desc->chan_freq);
2197 		return QDF_STATUS_E_INVAL;
2198 	}
2199 
2200 	switch (bss_dot11_mode) {
2201 	case MLME_DOT11_MODE_11B:
2202 	case MLME_DOT11_MODE_11G:
2203 		/* Self 11A and BSS 11B/G cannot connect */
2204 		pe_err("Self dot11mode 11A, bss dot11mode %d not compatible",
2205 		       bss_dot11_mode);
2206 		return QDF_STATUS_E_INVAL;
2207 	case MLME_DOT11_MODE_11A:
2208 	case MLME_DOT11_MODE_11N:
2209 	case MLME_DOT11_MODE_11AC:
2210 	case MLME_DOT11_MODE_11AX:
2211 	case MLME_DOT11_MODE_11BE:
2212 		*intersected_mode = MLME_DOT11_MODE_11A;
2213 		break;
2214 	default:
2215 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2216 		return QDF_STATUS_E_FAILURE;
2217 	}
2218 
2219 	return QDF_STATUS_SUCCESS;
2220 }
2221 
2222 static QDF_STATUS
2223 lim_handle_11b_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2224 			  enum mlme_dot11_mode *intersected_mode,
2225 			  struct bss_description *bss_desc)
2226 {
2227 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) {
2228 		pe_err("self Dot11mode is 11B and bss freq %d not 2.4ghz",
2229 		       bss_desc->chan_freq);
2230 		return QDF_STATUS_E_INVAL;
2231 	}
2232 
2233 	switch (bss_dot11_mode) {
2234 	case MLME_DOT11_MODE_11N:
2235 	case MLME_DOT11_MODE_11AC:
2236 	case MLME_DOT11_MODE_11AX:
2237 	case MLME_DOT11_MODE_11B:
2238 	case MLME_DOT11_MODE_11G:
2239 	case MLME_DOT11_MODE_11BE:
2240 		/* Self 11B and BSS 11A cannot connect */
2241 		*intersected_mode = MLME_DOT11_MODE_11B;
2242 		break;
2243 	case MLME_DOT11_MODE_11A:
2244 		pe_err("Self dot11mode 11B, bss dot11mode %d not compatible",
2245 		       bss_dot11_mode);
2246 		return QDF_STATUS_E_INVAL;
2247 	default:
2248 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2249 		return QDF_STATUS_E_FAILURE;
2250 	}
2251 
2252 	return QDF_STATUS_SUCCESS;
2253 }
2254 
2255 static QDF_STATUS
2256 lim_handle_11g_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2257 			  enum mlme_dot11_mode *intersected_mode,
2258 			  struct bss_description *bss_desc)
2259 {
2260 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) {
2261 		pe_err("self Dot11mode is 11G and bss freq %d not 2.4ghz",
2262 		       bss_desc->chan_freq);
2263 		return QDF_STATUS_E_INVAL;
2264 	}
2265 
2266 	switch (bss_dot11_mode) {
2267 	case MLME_DOT11_MODE_11N:
2268 	case MLME_DOT11_MODE_11AC:
2269 	case MLME_DOT11_MODE_11AX:
2270 	case MLME_DOT11_MODE_11G:
2271 	case MLME_DOT11_MODE_11BE:
2272 		/* Self 11B and BSS 11A cannot connect */
2273 		*intersected_mode = MLME_DOT11_MODE_11G;
2274 		break;
2275 	case MLME_DOT11_MODE_11B:
2276 		*intersected_mode = MLME_DOT11_MODE_11B;
2277 		break;
2278 	case MLME_DOT11_MODE_11A:
2279 		pe_err("Self dot11mode 11G, bss dot11mode %d not compatible",
2280 		       bss_dot11_mode);
2281 		return QDF_STATUS_E_INVAL;
2282 	default:
2283 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2284 		return QDF_STATUS_E_FAILURE;
2285 	}
2286 
2287 	return QDF_STATUS_SUCCESS;
2288 }
2289 
2290 static QDF_STATUS
2291 lim_handle_11n_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2292 			  enum mlme_dot11_mode *intersected_mode,
2293 			  tDot11fBeaconIEs *ie_struct,
2294 			  struct bss_description *bss_desc)
2295 {
2296 	if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) {
2297 		pe_err("self Dot11mode is 11N and bss freq %d is 6ghz",
2298 		       bss_desc->chan_freq);
2299 		return QDF_STATUS_E_INVAL;
2300 	}
2301 
2302 	switch (bss_dot11_mode) {
2303 	case MLME_DOT11_MODE_11N:
2304 		*intersected_mode = MLME_DOT11_MODE_11N;
2305 		break;
2306 	case MLME_DOT11_MODE_11AC:
2307 	case MLME_DOT11_MODE_11BE:
2308 	case MLME_DOT11_MODE_11AX:
2309 		if (ie_struct->HTCaps.present) {
2310 			*intersected_mode = MLME_DOT11_MODE_11N;
2311 			break;
2312 		}
2313 		if (WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq))
2314 			*intersected_mode = MLME_DOT11_MODE_11A;
2315 		else
2316 			*intersected_mode = MLME_DOT11_MODE_11G;
2317 		break;
2318 	case MLME_DOT11_MODE_11G:
2319 		*intersected_mode = MLME_DOT11_MODE_11G;
2320 		break;
2321 	case MLME_DOT11_MODE_11B:
2322 		*intersected_mode = MLME_DOT11_MODE_11B;
2323 		break;
2324 	case MLME_DOT11_MODE_11A:
2325 		*intersected_mode = MLME_DOT11_MODE_11A;
2326 		break;
2327 	default:
2328 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2329 		return QDF_STATUS_E_FAILURE;
2330 	}
2331 
2332 	return QDF_STATUS_SUCCESS;
2333 }
2334 
2335 static QDF_STATUS
2336 lim_handle_11ac_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2337 			   enum mlme_dot11_mode *intersected_mode,
2338 			   tDot11fBeaconIEs *ie_struct,
2339 			   struct bss_description *bss_desc)
2340 {
2341 	bool vht_capable = false;
2342 
2343 	if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) {
2344 		pe_err("self Dot11mode is 11AC and bss freq %d is 6ghz",
2345 		       bss_desc->chan_freq);
2346 		return QDF_STATUS_E_INVAL;
2347 	}
2348 
2349 	if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) ||
2350 	    IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps))
2351 		vht_capable = true;
2352 
2353 	switch (bss_dot11_mode) {
2354 	case MLME_DOT11_MODE_11N:
2355 		*intersected_mode = MLME_DOT11_MODE_11N;
2356 		break;
2357 	case MLME_DOT11_MODE_11AC:
2358 		*intersected_mode = MLME_DOT11_MODE_11AC;
2359 		break;
2360 	case MLME_DOT11_MODE_11AX:
2361 	case MLME_DOT11_MODE_11BE:
2362 		if (vht_capable) {
2363 			*intersected_mode = MLME_DOT11_MODE_11AC;
2364 			break;
2365 		}
2366 		if (ie_struct->HTCaps.present) {
2367 			*intersected_mode = MLME_DOT11_MODE_11N;
2368 			break;
2369 		}
2370 		if (WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq))
2371 			*intersected_mode = MLME_DOT11_MODE_11A;
2372 		else
2373 			*intersected_mode = MLME_DOT11_MODE_11G;
2374 		break;
2375 	case MLME_DOT11_MODE_11G:
2376 		*intersected_mode = MLME_DOT11_MODE_11G;
2377 		break;
2378 	case MLME_DOT11_MODE_11B:
2379 		*intersected_mode = MLME_DOT11_MODE_11B;
2380 		break;
2381 	case MLME_DOT11_MODE_11A:
2382 		*intersected_mode = MLME_DOT11_MODE_11A;
2383 		break;
2384 	default:
2385 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2386 		return QDF_STATUS_E_FAILURE;
2387 	}
2388 
2389 	return QDF_STATUS_SUCCESS;
2390 }
2391 
2392 static QDF_STATUS
2393 lim_handle_11ax_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2394 			   enum mlme_dot11_mode *intersected_mode,
2395 			   tDot11fBeaconIEs *ie_struct,
2396 			   struct bss_description *bss_desc)
2397 {
2398 	bool vht_capable = false;
2399 
2400 	if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) ||
2401 	    IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps))
2402 		vht_capable = true;
2403 
2404 	switch (bss_dot11_mode) {
2405 	case MLME_DOT11_MODE_11N:
2406 		*intersected_mode = MLME_DOT11_MODE_11N;
2407 		break;
2408 	case MLME_DOT11_MODE_11AC:
2409 		*intersected_mode = MLME_DOT11_MODE_11AC;
2410 		break;
2411 	case MLME_DOT11_MODE_11AX:
2412 		*intersected_mode = MLME_DOT11_MODE_11AX;
2413 		break;
2414 	case MLME_DOT11_MODE_11BE:
2415 		if (ie_struct->he_cap.present) {
2416 			*intersected_mode = MLME_DOT11_MODE_11AX;
2417 			break;
2418 		}
2419 		if (vht_capable) {
2420 			*intersected_mode = MLME_DOT11_MODE_11AC;
2421 			break;
2422 		}
2423 		if (ie_struct->HTCaps.present) {
2424 			*intersected_mode = MLME_DOT11_MODE_11N;
2425 			break;
2426 		}
2427 		if (WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) {
2428 			*intersected_mode = MLME_DOT11_MODE_11A;
2429 		} else if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) {
2430 			*intersected_mode = MLME_DOT11_MODE_11G;
2431 		} else {
2432 			pe_err("Invalid bss dot11mode %d freq %d",
2433 			       bss_dot11_mode, bss_desc->chan_freq);
2434 			return QDF_STATUS_E_FAILURE;
2435 		}
2436 		break;
2437 	case MLME_DOT11_MODE_11G:
2438 		*intersected_mode = MLME_DOT11_MODE_11G;
2439 		break;
2440 	case MLME_DOT11_MODE_11B:
2441 		*intersected_mode = MLME_DOT11_MODE_11B;
2442 		break;
2443 	case MLME_DOT11_MODE_11A:
2444 		*intersected_mode = MLME_DOT11_MODE_11A;
2445 		break;
2446 	default:
2447 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2448 		return QDF_STATUS_E_FAILURE;
2449 	}
2450 
2451 	return QDF_STATUS_SUCCESS;
2452 }
2453 
2454 static QDF_STATUS
2455 lim_handle_11be_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2456 			   enum mlme_dot11_mode *intersected_mode)
2457 {
2458 	switch (bss_dot11_mode) {
2459 	case MLME_DOT11_MODE_11N:
2460 		*intersected_mode = MLME_DOT11_MODE_11N;
2461 		break;
2462 	case MLME_DOT11_MODE_11AC:
2463 		*intersected_mode = MLME_DOT11_MODE_11AC;
2464 		break;
2465 	case MLME_DOT11_MODE_11AX:
2466 		*intersected_mode = MLME_DOT11_MODE_11AX;
2467 		break;
2468 	case MLME_DOT11_MODE_11BE:
2469 		*intersected_mode = MLME_DOT11_MODE_11BE;
2470 		break;
2471 	case MLME_DOT11_MODE_11G:
2472 		*intersected_mode = MLME_DOT11_MODE_11G;
2473 		break;
2474 	case MLME_DOT11_MODE_11B:
2475 		*intersected_mode = MLME_DOT11_MODE_11B;
2476 		break;
2477 	case MLME_DOT11_MODE_11A:
2478 		*intersected_mode = MLME_DOT11_MODE_11A;
2479 		break;
2480 	default:
2481 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2482 		return QDF_STATUS_E_FAILURE;
2483 	}
2484 
2485 	return QDF_STATUS_SUCCESS;
2486 }
2487 
2488 static QDF_STATUS
2489 lim_handle_11g_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2490 			       enum mlme_dot11_mode *intersected_mode,
2491 			       struct bss_description *bss_desc)
2492 {
2493 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) {
2494 		pe_err("self Dot11mode is 11G ONLY and bss freq %d not 2.4ghz",
2495 		       bss_desc->chan_freq);
2496 		return QDF_STATUS_E_INVAL;
2497 	}
2498 
2499 	switch (bss_dot11_mode) {
2500 	case MLME_DOT11_MODE_11N:
2501 	case MLME_DOT11_MODE_11AC:
2502 	case MLME_DOT11_MODE_11AX:
2503 	case MLME_DOT11_MODE_11G:
2504 	case MLME_DOT11_MODE_11BE:
2505 		/* Self 11B and BSS 11A cannot connect */
2506 		*intersected_mode = MLME_DOT11_MODE_11G;
2507 		break;
2508 	case MLME_DOT11_MODE_11B:
2509 	case MLME_DOT11_MODE_11A:
2510 		pe_err("Self dot11mode 11G only, bss dot11mode %d not compatible",
2511 		       bss_dot11_mode);
2512 		return QDF_STATUS_E_INVAL;
2513 	default:
2514 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2515 		return QDF_STATUS_E_FAILURE;
2516 	}
2517 
2518 	return QDF_STATUS_SUCCESS;
2519 }
2520 
2521 static QDF_STATUS
2522 lim_handle_11n_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2523 			       enum mlme_dot11_mode *intersected_mode,
2524 			       tDot11fBeaconIEs *ie_struct,
2525 			       struct bss_description *bss_desc)
2526 {
2527 	if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) {
2528 		pe_err("self Dot11mode is 11N ONLY and bss freq %d is 6ghz",
2529 		       bss_desc->chan_freq);
2530 		return QDF_STATUS_E_INVAL;
2531 	}
2532 
2533 	switch (bss_dot11_mode) {
2534 	case MLME_DOT11_MODE_11N:
2535 		*intersected_mode = MLME_DOT11_MODE_11N;
2536 		break;
2537 	case MLME_DOT11_MODE_11AC:
2538 	case MLME_DOT11_MODE_11AX:
2539 	case MLME_DOT11_MODE_11BE:
2540 		if (ie_struct->HTCaps.present) {
2541 			*intersected_mode = MLME_DOT11_MODE_11N;
2542 			break;
2543 		}
2544 		pe_err("Self dot11mode is 11N ONLY peer is not HT capable");
2545 		return QDF_STATUS_E_INVAL;
2546 	case MLME_DOT11_MODE_11G:
2547 	case MLME_DOT11_MODE_11B:
2548 	case MLME_DOT11_MODE_11A:
2549 		pe_err("Self dot11mode 11N only, bss dot11mode %d not compatible",
2550 		       bss_dot11_mode);
2551 		return QDF_STATUS_E_INVAL;
2552 	default:
2553 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2554 		return QDF_STATUS_E_FAILURE;
2555 	}
2556 
2557 	return QDF_STATUS_SUCCESS;
2558 }
2559 
2560 static QDF_STATUS
2561 lim_handle_11ac_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2562 				enum mlme_dot11_mode *intersected_mode,
2563 				tDot11fBeaconIEs *ie_struct,
2564 				struct bss_description *bss_desc)
2565 {
2566 	bool vht_capable = false;
2567 
2568 	if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) {
2569 		pe_err("self Dot11mode is 11AC and bss freq %d is 6ghz",
2570 		       bss_desc->chan_freq);
2571 		return QDF_STATUS_E_INVAL;
2572 	}
2573 
2574 	if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) ||
2575 	    IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps))
2576 		vht_capable = true;
2577 
2578 	switch (bss_dot11_mode) {
2579 	case MLME_DOT11_MODE_11AC:
2580 		*intersected_mode = MLME_DOT11_MODE_11AC;
2581 		break;
2582 	case MLME_DOT11_MODE_11AX:
2583 	case MLME_DOT11_MODE_11BE:
2584 		if (vht_capable) {
2585 			*intersected_mode = MLME_DOT11_MODE_11AC;
2586 			break;
2587 		}
2588 		pe_err("Self dot11mode is 11AC ONLY peer is not VHT capable");
2589 		return QDF_STATUS_E_INVAL;
2590 	case MLME_DOT11_MODE_11N:
2591 	case MLME_DOT11_MODE_11G:
2592 	case MLME_DOT11_MODE_11B:
2593 	case MLME_DOT11_MODE_11A:
2594 		pe_err("Self dot11mode 11AC only, bss dot11mode %d not compatible",
2595 		       bss_dot11_mode);
2596 		return QDF_STATUS_E_INVAL;
2597 	default:
2598 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2599 		return QDF_STATUS_E_FAILURE;
2600 	}
2601 
2602 	return QDF_STATUS_SUCCESS;
2603 }
2604 
2605 static QDF_STATUS
2606 lim_handle_11ax_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2607 				enum mlme_dot11_mode *intersected_mode,
2608 				tDot11fBeaconIEs *ie_struct)
2609 {
2610 	switch (bss_dot11_mode) {
2611 	case MLME_DOT11_MODE_11AX:
2612 		*intersected_mode = MLME_DOT11_MODE_11AX;
2613 		break;
2614 	case MLME_DOT11_MODE_11BE:
2615 		if (ie_struct->he_cap.present) {
2616 			*intersected_mode = MLME_DOT11_MODE_11AX;
2617 			break;
2618 		}
2619 		fallthrough;
2620 	case MLME_DOT11_MODE_11N:
2621 	case MLME_DOT11_MODE_11AC:
2622 	case MLME_DOT11_MODE_11G:
2623 	case MLME_DOT11_MODE_11B:
2624 	case MLME_DOT11_MODE_11A:
2625 		pe_err("Self dot11mode 11AX only, bss dot11mode %d not compatible",
2626 		       bss_dot11_mode);
2627 		return QDF_STATUS_E_INVAL;
2628 	default:
2629 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2630 		return QDF_STATUS_E_FAILURE;
2631 	}
2632 
2633 	return QDF_STATUS_SUCCESS;
2634 }
2635 
2636 static QDF_STATUS
2637 lim_handle_11be_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,
2638 				enum mlme_dot11_mode *intersected_mode)
2639 {
2640 	switch (bss_dot11_mode) {
2641 	case MLME_DOT11_MODE_11BE:
2642 		*intersected_mode = MLME_DOT11_MODE_11BE;
2643 		break;
2644 	case MLME_DOT11_MODE_11N:
2645 	case MLME_DOT11_MODE_11AC:
2646 	case MLME_DOT11_MODE_11AX:
2647 	case MLME_DOT11_MODE_11G:
2648 	case MLME_DOT11_MODE_11B:
2649 	case MLME_DOT11_MODE_11A:
2650 		pe_err("Self dot11mode 11BE only, bss dot11mode %d not compatible",
2651 		       bss_dot11_mode);
2652 		return QDF_STATUS_E_INVAL;
2653 	default:
2654 		pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode);
2655 		return QDF_STATUS_E_FAILURE;
2656 	}
2657 
2658 	return QDF_STATUS_SUCCESS;
2659 }
2660 
2661 static QDF_STATUS
2662 lim_get_intersected_dot11_mode_sta_ap(struct mac_context *mac_ctx,
2663 				      enum mlme_dot11_mode self_dot11_mode,
2664 				      enum mlme_dot11_mode bss_dot11_mode,
2665 				      enum mlme_dot11_mode *intersected_mode,
2666 				      tDot11fBeaconIEs *ie_struct,
2667 				      struct bss_description *bss_desc)
2668 {
2669 	switch (self_dot11_mode) {
2670 	case MLME_DOT11_MODE_ALL:
2671 		*intersected_mode = bss_dot11_mode;
2672 		return QDF_STATUS_SUCCESS;
2673 	case MLME_DOT11_MODE_11A:
2674 		return lim_handle_11a_dot11_mode(bss_dot11_mode,
2675 						 intersected_mode, bss_desc);
2676 	case MLME_DOT11_MODE_11B:
2677 		return lim_handle_11b_dot11_mode(bss_dot11_mode,
2678 						 intersected_mode, bss_desc);
2679 	case MLME_DOT11_MODE_11G:
2680 		return lim_handle_11g_dot11_mode(bss_dot11_mode,
2681 						 intersected_mode, bss_desc);
2682 	case MLME_DOT11_MODE_11N:
2683 		return lim_handle_11n_dot11_mode(bss_dot11_mode,
2684 						 intersected_mode, ie_struct,
2685 						 bss_desc);
2686 	case MLME_DOT11_MODE_11G_ONLY:
2687 		return lim_handle_11g_only_dot11_mode(bss_dot11_mode,
2688 						      intersected_mode,
2689 						      bss_desc);
2690 	case MLME_DOT11_MODE_11N_ONLY:
2691 		return lim_handle_11n_only_dot11_mode(bss_dot11_mode,
2692 						       intersected_mode,
2693 						       ie_struct,
2694 						       bss_desc);
2695 	case MLME_DOT11_MODE_11AC:
2696 		return lim_handle_11ac_dot11_mode(bss_dot11_mode,
2697 						  intersected_mode, ie_struct,
2698 						  bss_desc);
2699 	case MLME_DOT11_MODE_11AC_ONLY:
2700 		return lim_handle_11ac_only_dot11_mode(bss_dot11_mode,
2701 						       intersected_mode,
2702 						       ie_struct,
2703 						       bss_desc);
2704 	case MLME_DOT11_MODE_11AX:
2705 		return lim_handle_11ax_dot11_mode(bss_dot11_mode,
2706 						  intersected_mode,
2707 						  ie_struct,
2708 						  bss_desc);
2709 	case MLME_DOT11_MODE_11AX_ONLY:
2710 		return lim_handle_11ax_only_dot11_mode(bss_dot11_mode,
2711 						       intersected_mode,
2712 						       ie_struct);
2713 	case MLME_DOT11_MODE_11BE:
2714 		return lim_handle_11be_dot11_mode(bss_dot11_mode,
2715 						  intersected_mode);
2716 	case MLME_DOT11_MODE_11BE_ONLY:
2717 		return lim_handle_11be_only_dot11_mode(bss_dot11_mode,
2718 						       intersected_mode);
2719 	case MLME_DOT11_MODE_ABG:
2720 		return lim_handle_11abg_dot11_mode(bss_dot11_mode,
2721 						   intersected_mode, bss_desc);
2722 	default:
2723 		pe_err("Invalid self dot11mode %d not supported",
2724 		       self_dot11_mode);
2725 		return QDF_STATUS_E_FAILURE;
2726 	}
2727 }
2728 
2729 static void
2730 lim_verify_dot11_mode_with_crypto(struct pe_session *session)
2731 {
2732 	struct bss_description *bss_desc =
2733 					&session->lim_join_req->bssDescription;
2734 	int32_t ucast_cipher;
2735 
2736 	if (!(session->dot11mode == MLME_DOT11_MODE_11N ||
2737 	    session->dot11mode == MLME_DOT11_MODE_11AC ||
2738 	    session->dot11mode == MLME_DOT11_MODE_11AX ||
2739 	    session->dot11mode == MLME_DOT11_MODE_11BE))
2740 		return;
2741 
2742 	ucast_cipher = wlan_crypto_get_param(session->vdev,
2743 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
2744 
2745 	if (ucast_cipher == -1)
2746 		return;
2747 
2748 	if (!((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) ||
2749 	      (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) ||
2750 	      (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) ||
2751 	      (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104))))
2752 		return;
2753 
2754 	if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq))
2755 		session->dot11mode = MLME_DOT11_MODE_11G;
2756 	else
2757 		session->dot11mode = MLME_DOT11_MODE_11A;
2758 
2759 	pe_info("HT not supported with TKIP/WEP overriding dot11mode to %d",
2760 		session->dot11mode);
2761 
2762 	session->he_with_wep_tkip =
2763 		session->mac_ctx->roam.configParam.wep_tkip_in_he;
2764 }
2765 
2766 static QDF_STATUS
2767 lim_fill_dot11_mode(struct mac_context *mac_ctx, struct pe_session *session,
2768 		    tDot11fBeaconIEs *ie_struct)
2769 {
2770 	struct bss_description *bss_desc =
2771 					&session->lim_join_req->bssDescription;
2772 	QDF_STATUS status;
2773 	enum mlme_dot11_mode self_dot11_mode;
2774 	enum mlme_dot11_mode bss_dot11_mode;
2775 	enum mlme_dot11_mode intersected_mode;
2776 
2777 	self_dot11_mode = lim_get_self_dot11_mode(mac_ctx, session->opmode,
2778 						  session->vdev_id);
2779 
2780 	/* if user set dot11 mode by cmd, need to do intersect first */
2781 	self_dot11_mode =
2782 		   lim_intersect_user_dot11_mode(mac_ctx, session->opmode,
2783 						 session->vdev_id,
2784 						 self_dot11_mode);
2785 
2786 	bss_dot11_mode = lim_get_bss_dot11_mode(mac_ctx, bss_desc, ie_struct);
2787 
2788 	status = lim_get_intersected_dot11_mode_sta_ap(mac_ctx, self_dot11_mode,
2789 						       bss_dot11_mode,
2790 						       &intersected_mode,
2791 						       ie_struct, bss_desc);
2792 	if (QDF_IS_STATUS_ERROR(status))
2793 		return status;
2794 
2795 	pe_debug("vdev id %d opmode %d self dot11mode %d bss_dot11 mode %d intersected %d",
2796 		 session->vdev_id, session->opmode, self_dot11_mode,
2797 		 bss_dot11_mode, intersected_mode);
2798 
2799 	if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev) &&
2800 	    !IS_DOT11_MODE_EHT(intersected_mode))
2801 		return QDF_STATUS_E_INVAL;
2802 
2803 	session->dot11mode = intersected_mode;
2804 	lim_verify_dot11_mode_with_crypto(session);
2805 
2806 	return status;
2807 }
2808 
2809 #ifdef WLAN_FEATURE_11AX
2810 static bool lim_enable_twt(struct mac_context *mac_ctx, tDot11fBeaconIEs *ie)
2811 {
2812 	struct s_ext_cap *ext_cap;
2813 	bool twt_support_in_11n = false;
2814 	bool twt_request = false;
2815 
2816 	if (!ie) {
2817 		pe_debug("ie is null");
2818 		return false;
2819 	}
2820 
2821 	wlan_twt_cfg_get_support_requestor(mac_ctx->psoc, &twt_request);
2822 	if (twt_request && (ie->qcn_ie.present || ie->he_cap.twt_responder)) {
2823 		pe_debug("TWT is supported, hence disable UAPSD; twt req supp: %d,twt respon supp: %d, QCN_IE: %d",
2824 			  mac_ctx->mlme_cfg->he_caps.dot11_he_cap.twt_request,
2825 			  ie->he_cap.twt_responder,
2826 			  ie->qcn_ie.present);
2827 		return true;
2828 	}
2829 
2830 	wlan_twt_cfg_get_support_in_11n(mac_ctx->psoc,
2831 					&twt_support_in_11n);
2832 	ext_cap = (struct s_ext_cap *)ie->ExtCap.bytes;
2833 	if (twt_support_in_11n && ie->ExtCap.present &&
2834 	    ext_cap->twt_responder_support) {
2835 		pe_debug("TWT is supported for 11n, twt_support_in_11n %d, ext_cap %d, twt_responder support %d",
2836 			 twt_support_in_11n, ie->ExtCap.present,
2837 			 ext_cap->twt_responder_support);
2838 		return true;
2839 	}
2840 
2841 	return false;
2842 }
2843 #else
2844 static inline bool
2845 lim_enable_twt(struct mac_context *mac_ctx, tDot11fBeaconIEs *ie)
2846 {
2847 	return false;
2848 }
2849 #endif
2850 
2851 static int8_t lim_get_cfg_max_tx_power(struct mac_context *mac,
2852 				       uint32_t ch_freq)
2853 {
2854 	return wlan_get_cfg_max_tx_power(mac->psoc, mac->pdev, ch_freq);
2855 }
2856 
2857 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
2858 static inline void lim_fill_rssi(struct pe_session *session,
2859 				 struct bss_description *bss_desc)
2860 {
2861 	session->rssi = bss_desc->rssi;
2862 }
2863 #else
2864 static inline void lim_fill_rssi(struct pe_session *session,
2865 				 struct bss_description *bss_desc)
2866 {
2867 }
2868 #endif
2869 
2870 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
2871 /**
2872  * lim_update_sae_single_pmk_ap_cap() - Function to update sae single pmk ap ie
2873  * @mac: pointer to mac context
2874  * @session: pe session
2875  *
2876  * Return: set sae single pmk feature
2877  */
2878 static void
2879 lim_update_sae_single_pmk_ap_cap(struct mac_context *mac,
2880 				 struct pe_session *session)
2881 {
2882 	int32_t akm;
2883 
2884 	akm = wlan_crypto_get_param(session->vdev,
2885 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
2886 
2887 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) &&
2888 	    mac->mlme_cfg->lfr.sae_single_pmk_feature_enabled)
2889 		wlan_mlme_set_sae_single_pmk_bss_cap(mac->psoc,
2890 			session->vdev_id,
2891 			session->lim_join_req->bssDescription.is_single_pmk);
2892 
2893 }
2894 #else
2895 static inline void
2896 lim_update_sae_single_pmk_ap_cap(struct mac_context *mac,
2897 				  struct pe_session *session)
2898 {
2899 }
2900 #endif
2901 
2902 #ifdef WLAN_FEATURE_11BE_MLO
2903 static void lim_get_mld_peer(struct wlan_objmgr_vdev *vdev,
2904 			     struct qdf_mac_addr *bssid)
2905 {
2906 	struct wlan_objmgr_peer *peer;
2907 
2908 	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
2909 		return;
2910 
2911 	peer = wlan_vdev_get_bsspeer(vdev);
2912 	if (!peer)
2913 		return;
2914 
2915 	qdf_mem_copy(bssid->bytes, peer->mldaddr, QDF_MAC_ADDR_SIZE);
2916 }
2917 #else
2918 static void lim_get_mld_peer(struct wlan_objmgr_vdev *vdev,
2919 			     struct qdf_mac_addr *bssid)
2920 {
2921 }
2922 #endif
2923 
2924 #ifdef WLAN_FEATURE_SAE
2925 static void lim_update_sae_config(struct mac_context *mac,
2926 				  struct pe_session *session)
2927 {
2928 	struct wlan_crypto_pmksa *pmksa;
2929 	struct qdf_mac_addr bssid;
2930 
2931 	qdf_mem_copy(bssid.bytes, session->bssId,
2932 		     QDF_MAC_ADDR_SIZE);
2933 
2934 	/* For MLO connection, override BSSID with peer mldaddr */
2935 	lim_get_mld_peer(session->vdev, &bssid);
2936 
2937 	pmksa = wlan_crypto_get_pmksa(session->vdev, &bssid);
2938 	if (!pmksa)
2939 		return;
2940 
2941 	session->sae_pmk_cached = true;
2942 	pe_debug("PMKSA Found for BSSID=" QDF_MAC_ADDR_FMT,
2943 		 QDF_MAC_ADDR_REF(bssid.bytes));
2944 }
2945 #else
2946 static inline void lim_update_sae_config(struct mac_context *mac,
2947 					 struct pe_session *session)
2948 { }
2949 #endif
2950 
2951 static void
2952 lim_fill_11r_params(struct mac_context *mac_ctx, struct pe_session *session,
2953 		    bool ese_version_present)
2954 {
2955 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2956 
2957 	mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc);
2958 	if (!mlme_obj)
2959 		return;
2960 	if (wlan_cm_is_auth_type_11r(mlme_obj, session->vdev,
2961 	    session->lim_join_req->bssDescription.mdiePresent) &&
2962 	    !cm_ese_open_present(session->vdev, mlme_obj, ese_version_present))
2963 		session->is11Rconnection = true;
2964 }
2965 
2966 #ifdef FEATURE_WLAN_ESE
2967 static void
2968 lim_fill_ese_params(struct mac_context *mac_ctx, struct pe_session *session,
2969 		    bool ese_version_present)
2970 {
2971 	wlan_cm_set_ese_assoc(mac_ctx->pdev, session->vdev_id,
2972 			      cm_is_ese_connection(session->vdev,
2973 			      ese_version_present));
2974 }
2975 #else
2976 static inline void
2977 lim_fill_ese_params(struct mac_context *mac_ctx, struct pe_session *session,
2978 		    bool ese_version_present)
2979 {
2980 }
2981 #endif
2982 
2983 void lim_get_basic_rates(tSirMacRateSet *b_rates, uint32_t chan_freq)
2984 {
2985 	/*
2986 	 * Some IOT APs don't send supported rates in
2987 	 * probe resp, hence add BSS basic rates in
2988 	 * supported rates IE of assoc request.
2989 	 */
2990 	if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq))
2991 		wlan_populate_basic_rates(b_rates, false, true);
2992 	else if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq))
2993 		wlan_populate_basic_rates(b_rates, true, true);
2994 }
2995 
2996 /*
2997  * lim_iterate_triplets() - Iterate the country IE to validate it
2998  * @country_ie: country IE to iterate through
2999  *
3000  * This function always returns success because connection should not be failed
3001  * in the case of missing elements in the country IE
3002  *
3003  * Return: QDF_STATUS
3004  */
3005 static QDF_STATUS lim_iterate_triplets(tDot11fIECountry country_ie)
3006 {
3007 	u_int8_t i;
3008 
3009 	if (country_ie.first_triplet[0] > OP_CLASS_ID_200) {
3010 		if (country_ie.more_triplets[0][0] <= OP_CLASS_ID_200)
3011 			return QDF_STATUS_SUCCESS;
3012 	}
3013 
3014 	for (i = 0; i < country_ie.num_more_triplets; i++) {
3015 		if ((country_ie.more_triplets[i][0] > OP_CLASS_ID_200) &&
3016 		    (i < country_ie.num_more_triplets - 1)) {
3017 			if (country_ie.more_triplets[i + 1][0] <=
3018 			    OP_CLASS_ID_200)
3019 				return QDF_STATUS_SUCCESS;
3020 		}
3021 	}
3022 	pe_debug("No operating class triplet followed by sub-band triplet");
3023 
3024 	return QDF_STATUS_SUCCESS;
3025 }
3026 
3027 static bool lim_is_bss_description_wme(struct mac_context *mac,
3028 				       tDot11fBeaconIEs *ie_struct)
3029 {
3030 
3031 	if (!(ie_struct->WMMParams.present || ie_struct->WMMInfoAp.present))
3032 		return false;
3033 	if (mac->roam.configParam.WMMSupportMode == WMM_USER_MODE_NO_QOS &&
3034 	    !ie_struct->HTCaps.present)
3035 		return false;
3036 
3037 	return true;
3038 }
3039 
3040 static enum medium_access_type
3041 lim_get_qos_from_bss_desc(struct mac_context *mac_ctx,
3042 			  struct bss_description *bss_desc,
3043 			  tDot11fBeaconIEs *ie_struct)
3044 {
3045 	enum medium_access_type qos_type = MEDIUM_ACCESS_DCF;
3046 	tSirMacCapabilityInfo *ap_cap_info;
3047 
3048 	/*
3049 	 * If we find WMM in the Bss Description, then we let this
3050 	 * override and use WMM.
3051 	 */
3052 	if (lim_is_bss_description_wme(mac_ctx, ie_struct))
3053 		return MEDIUM_ACCESS_WMM_EDCF_DSCP;
3054 
3055 	ap_cap_info = (tSirMacCapabilityInfo *)&bss_desc->capabilityInfo;
3056 	/* If the QoS bit is on, then the AP is advertising 11E QoS. */
3057 	if (ap_cap_info->qos)
3058 		qos_type = MEDIUM_ACCESS_11E_EDCF;
3059 
3060 	if (qos_type == MEDIUM_ACCESS_11E_EDCF &&
3061 	    !mac_ctx->roam.configParam.Is11eSupportEnabled)
3062 		qos_type = MEDIUM_ACCESS_DCF;
3063 
3064 	return qos_type;
3065 }
3066 
3067 static void lim_set_qos_to_cfg(struct pe_session *session,
3068 			       enum medium_access_type qos_type)
3069 {
3070 	bool qos_enabled;
3071 	bool wme_enabled;
3072 
3073 	switch (qos_type) {
3074 	case MEDIUM_ACCESS_WMM_EDCF_DSCP:
3075 		qos_enabled = false;
3076 		wme_enabled = true;
3077 		break;
3078 	case MEDIUM_ACCESS_11E_EDCF:
3079 		qos_enabled = true;
3080 		wme_enabled = false;
3081 		break;
3082 	default:
3083 	case MEDIUM_ACCESS_DCF:
3084 		qos_enabled = false;
3085 		wme_enabled = false;
3086 		break;
3087 	}
3088 
3089 	session->limWmeEnabled = wme_enabled;
3090 	session->limQosEnabled = qos_enabled;
3091 }
3092 
3093 static void lim_update_qos(struct mac_context *mac_ctx,
3094 			   struct pe_session *session,
3095 			   struct bss_description *bss_desc,
3096 			   tDot11fBeaconIEs *ie_struct)
3097 {
3098 	struct mlme_legacy_priv *mlme_priv;
3099 	enum medium_access_type qos_type;
3100 
3101 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
3102 	if (!mlme_priv)
3103 		return;
3104 
3105 	qos_type = lim_get_qos_from_bss_desc(mac_ctx, bss_desc, ie_struct);
3106 
3107 	if ((session->dot11mode != MLME_DOT11_MODE_11N) &&
3108 	    (mac_ctx->roam.configParam.WMMSupportMode ==
3109 	     WMM_USER_MODE_NO_QOS)) {
3110 		/*
3111 		 * Joining BSS is not 11n capable and WMM is disabled on client.
3112 		 * Disable QoS and WMM
3113 		 */
3114 		qos_type = MEDIUM_ACCESS_DCF;
3115 	}
3116 
3117 	if ((session->dot11mode == MLME_DOT11_MODE_11N ||
3118 	     session->dot11mode == MLME_DOT11_MODE_11AC) &&
3119 	     (qos_type != MEDIUM_ACCESS_WMM_EDCF_DSCP &&
3120 	      qos_type != MEDIUM_ACCESS_11E_EDCF)) {
3121 		/*
3122 		 * Joining BSS is 11n capable and WMM is disabled on AP.
3123 		 * Assume all HT AP's are QOS AP's and enable WMM
3124 		 */
3125 		qos_type = MEDIUM_ACCESS_WMM_EDCF_DSCP;
3126 	}
3127 
3128 	lim_set_qos_to_cfg(session, qos_type);
3129 	mlme_priv->connect_info.qos_enabled = session->limWmeEnabled;
3130 	pe_debug("qos_type %d QOS %d WMM %d", qos_type,
3131 		 session->limQosEnabled,
3132 		 session->limWmeEnabled);
3133 }
3134 
3135 static void lim_reset_self_ocv_caps(struct pe_session *session)
3136 {
3137 	uint16_t self_rsn_cap;
3138 
3139 	self_rsn_cap = wlan_crypto_get_param(session->vdev,
3140 					     WLAN_CRYPTO_PARAM_RSN_CAP);
3141 	if (self_rsn_cap == -1)
3142 		return;
3143 
3144 	self_rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED;
3145 
3146 	/* Update the new rsn caps */
3147 	wlan_crypto_set_vdev_param(session->vdev, WLAN_CRYPTO_PARAM_RSN_CAP,
3148 				   self_rsn_cap);
3149 
3150 }
3151 
3152 bool lim_enable_cts_to_self_for_exempted_iot_ap(
3153 				       struct mac_context *mac_ctx,
3154 				       struct pe_session *session,
3155 				       uint8_t *ie_ptr,
3156 				       uint16_t ie_len)
3157 {
3158 	struct action_oui_search_attr vendor_ap_search_attr;
3159 
3160 	vendor_ap_search_attr.ie_data = ie_ptr;
3161 	vendor_ap_search_attr.ie_length = ie_len;
3162 
3163 	if (wlan_action_oui_search(mac_ctx->psoc, &vendor_ap_search_attr,
3164 				   ACTION_OUI_ENABLE_CTS2SELF)) {
3165 		pe_debug("vdev %d: enable cts to self", session->vdev_id);
3166 		wma_cli_set_command(session->vdev_id,
3167 				    wmi_vdev_param_enable_rtscts,
3168 				    FW_CTS2SELF_PROFILE, VDEV_CMD);
3169 		return true;
3170 	}
3171 	return false;
3172 }
3173 
3174 /**
3175  * lim_disable_bformee_for_iot_ap() - disable bformee for iot ap
3176  *@mac_ctx: mac context
3177  *@session: pe session
3178  *@bss_desc: bss descriptor
3179  *
3180  * When connect IoT AP with BW 160MHz and NSS 2, disable Beamformee
3181  *
3182  * Return: None
3183  */
3184 static void
3185 lim_disable_bformee_for_iot_ap(struct mac_context *mac_ctx,
3186 			       struct pe_session *session,
3187 			       struct bss_description *bss_desc)
3188 {
3189 	struct action_oui_search_attr vendor_ap_search_attr;
3190 	uint16_t ie_len;
3191 
3192 	ie_len = wlan_get_ielen_from_bss_description(bss_desc);
3193 
3194 	vendor_ap_search_attr.ie_data = (uint8_t *)&bss_desc->ieFields[0];
3195 	vendor_ap_search_attr.ie_length = ie_len;
3196 
3197 	if (wlan_action_oui_search(mac_ctx->psoc,
3198 				   &vendor_ap_search_attr,
3199 				   ACTION_OUI_DISABLE_BFORMEE) &&
3200 	    session->nss == 2 && CH_WIDTH_160MHZ == session->ch_width) {
3201 		session->vht_config.su_beam_formee = 0;
3202 		session->vht_config.mu_beam_formee = 0;
3203 		pe_debug("IoT ap with BW 160 MHz NSS 2, disable Beamformee");
3204 	}
3205 }
3206 
3207 QDF_STATUS
3208 lim_fill_pe_session(struct mac_context *mac_ctx, struct pe_session *session,
3209 		    struct bss_description *bss_desc)
3210 {
3211 	uint8_t bss_chan_id;
3212 	tDot11fBeaconIEs *ie_struct;
3213 	QDF_STATUS status;
3214 	ePhyChanBondState cb_mode;
3215 	const uint8_t *vendor_ie;
3216 	uint16_t ie_len;
3217 	int8_t local_power_constraint;
3218 	struct vdev_mlme_obj *mlme_obj;
3219 	bool is_pwr_constraint = false;
3220 	tSirMacCapabilityInfo *ap_cap_info;
3221 	uint8_t wmm_mode, value;
3222 	struct wlan_mlme_lfr_cfg *lfr = &mac_ctx->mlme_cfg->lfr;
3223 	struct cm_roam_values_copy config = {};
3224 	bool ese_ver_present;
3225 	int8_t reg_max;
3226 	struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info;
3227 	struct ps_params *ps_param =
3228 				&ps_global_info->ps_params[session->vdev_id];
3229 	uint32_t timeout;
3230 	enum reg_6g_ap_type power_type_6g;
3231 	struct cm_roam_values_copy temp;
3232 	uint32_t neighbor_lookup_threshold;
3233 	uint32_t hi_rssi_scan_rssi_delta;
3234 
3235 	/*
3236 	 * Update the capability here itself as this is used in
3237 	 * lim_extract_ap_capability() below. If not updated issues
3238 	 * like not honoring power constraint on 1st association after
3239 	 * driver loading might occur.
3240 	 */
3241 	lim_update_rrm_capability(mac_ctx);
3242 	bss_chan_id = wlan_reg_freq_to_chan(mac_ctx->pdev,
3243 					    bss_desc->chan_freq);
3244 
3245 	lim_update_sae_config(mac_ctx, session);
3246 	lim_update_sae_single_pmk_ap_cap(mac_ctx, session);
3247 
3248 	/* Update the beacon/probe filter in mac_ctx */
3249 	lim_set_bcn_probe_filter(mac_ctx, session,
3250 				 bss_chan_id);
3251 	session->max_amsdu_num =
3252 			mac_ctx->mlme_cfg->ht_caps.max_num_amsdu;
3253 	/* Store beaconInterval */
3254 	session->beaconParams.beaconInterval =
3255 		bss_desc->beaconInterval;
3256 	/* Copy oper freq to the session Table */
3257 	session->curr_op_freq = bss_desc->chan_freq;
3258 
3259 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
3260 						     &ie_struct);
3261 	if (QDF_IS_STATUS_ERROR(status)) {
3262 		pe_err("IE parsing failed vdev id %d",
3263 		       session->vdev_id);
3264 		return QDF_STATUS_E_FAILURE;
3265 	}
3266 
3267 	qdf_mem_zero(&session->wmm_params, sizeof(tDot11fIEWMMParams));
3268 	if (ie_struct->WMMParams.present)
3269 		qdf_mem_copy(&session->wmm_params, &ie_struct->WMMParams,
3270 			     sizeof(tDot11fIEWMMParams));
3271 
3272 	mac_ctx->mlme_cfg->power.local_power_constraint =
3273 		wlan_get_11h_power_constraint(mac_ctx,
3274 					      &ie_struct->PowerConstraints);
3275 
3276 	session->enable_session_twt_support =
3277 					lim_enable_twt(mac_ctx, ie_struct);
3278 	status = lim_fill_dot11_mode(mac_ctx, session, ie_struct);
3279 	if (QDF_IS_STATUS_ERROR(status)) {
3280 		status = QDF_STATUS_E_FAILURE;
3281 		goto send;
3282 	}
3283 	cb_mode = wlan_get_cb_mode(mac_ctx, session->curr_op_freq, ie_struct,
3284 				   session);
3285 
3286 	if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
3287 	    wlan_cm_get_force_20mhz_in_24ghz(session->vdev))
3288 		cb_mode = PHY_SINGLE_CHANNEL_CENTERED;
3289 
3290 	status = wlan_get_rate_set(mac_ctx, ie_struct, session);
3291 	if (QDF_IS_STATUS_ERROR(status)) {
3292 		pe_err("Get rate failed vdev id %d", session->vdev_id);
3293 		lim_get_basic_rates(&session->rateSet, bss_desc->chan_freq);
3294 	}
3295 
3296 	if (session->dot11mode == MLME_DOT11_MODE_11B)
3297 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 0;
3298 	else
3299 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g =
3300 			mac_ctx->mlme_cfg->ht_caps.short_slot_time_enabled;
3301 
3302 	/*
3303 	 * Join timeout: if we find a BeaconInterval in the BssDescription,
3304 	 * then set the Join Timeout to be 10 x the BeaconInterval.
3305 	 *
3306 	 * 10 * BeaconInterval should be greater than the minimum join
3307 	 * timeout and lesser than the configured timeout.
3308 	 */
3309 	timeout = mac_ctx->mlme_cfg->timeouts.join_failure_timeout_ori;
3310 	if (bss_desc->beaconInterval)
3311 		timeout = QDF_MAX(10 * bss_desc->beaconInterval,
3312 				  cfg_min(CFG_JOIN_FAILURE_TIMEOUT));
3313 
3314 	mac_ctx->mlme_cfg->timeouts.join_failure_timeout =
3315 		QDF_MIN(timeout,
3316 			mac_ctx->mlme_cfg->timeouts.join_failure_timeout_ori);
3317 	/*
3318 	 * Calculate probe request retry timeout,
3319 	 * Change probe req retry to MAX_JOIN_PROBE_REQ if sta freq
3320 	 * can cause MCC
3321 	 */
3322 	timeout = JOIN_PROBE_REQ_TIMER_MS;
3323 	if (policy_mgr_will_freq_lead_to_mcc(mac_ctx->psoc,
3324 					     bss_desc->chan_freq)) {
3325 		 /* Send MAX_JOIN_PROBE_REQ probe req during join timeout */
3326 		timeout = mac_ctx->mlme_cfg->timeouts.join_failure_timeout/
3327 							MAX_JOIN_PROBE_REQ;
3328 		timeout = QDF_MAX(JOIN_PROBE_REQ_TIMER_MS, timeout);
3329 	}
3330 	mac_ctx->mlme_cfg->timeouts.probe_req_retry_timeout = timeout;
3331 
3332 	lim_join_req_update_ht_vht_caps(mac_ctx, session, bss_desc,
3333 					ie_struct);
3334 
3335 	lim_check_oui_and_update_session(mac_ctx, session, ie_struct);
3336 	ese_ver_present = ie_struct->ESEVersion.present;
3337 
3338 	/* Copying of bssId is already done, while creating session */
3339 	sir_copy_mac_addr(session->self_mac_addr,
3340 			  wlan_vdev_mlme_get_macaddr(session->vdev));
3341 
3342 	session->statypeForBss = STA_ENTRY_PEER;
3343 
3344 	lim_update_qos(mac_ctx, session, bss_desc, ie_struct);
3345 
3346 	if (session->lim_join_req->bssDescription.adaptive_11r_ap)
3347 		session->is_adaptive_11r_connection =
3348 				wlan_get_adaptive_11r_enabled(lfr);
3349 	config.bool_value = session->is_adaptive_11r_connection;
3350 	wlan_cm_roam_cfg_set_value(mac_ctx->psoc, session->vdev_id,
3351 				   ADAPTIVE_11R_CONNECTION,
3352 				   &config);
3353 	lim_fill_11r_params(mac_ctx, session , ese_ver_present);
3354 	lim_fill_ese_params(mac_ctx, session, ese_ver_present);
3355 
3356 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session->vdev_id,
3357 				   NEIGHBOUR_LOOKUP_THRESHOLD, &temp);
3358 	neighbor_lookup_threshold = temp.uint_value;
3359 
3360 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session->vdev_id,
3361 				   HI_RSSI_SCAN_RSSI_DELTA, &temp);
3362 	hi_rssi_scan_rssi_delta = temp.uint_value;
3363 
3364 	/*
3365 	 * Firmware will take care of checking hi_scan rssi delta, take care of
3366 	 * legacy -> legacy hi-rssi roam also if this feature flag is
3367 	 * advertised.
3368 	 */
3369 	if (wlan_cm_is_self_mld_roam_supported(mac_ctx->psoc)) {
3370 		wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id,
3371 					    false);
3372 	} else if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
3373 	    (abs(bss_desc->rssi) >
3374 	     (neighbor_lookup_threshold - hi_rssi_scan_rssi_delta))) {
3375 		pe_debug("Enabling HI_RSSI, rssi: %d lookup_th: %d, delta:%d",
3376 			 bss_desc->rssi, neighbor_lookup_threshold,
3377 			 hi_rssi_scan_rssi_delta);
3378 		wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id,
3379 					    false);
3380 	} else {
3381 		wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id,
3382 					    true);
3383 		pe_debug("Disabling HI_RSSI, AP freq=%d, rssi=%d",
3384 			  bss_desc->chan_freq, bss_desc->rssi);
3385 	}
3386 
3387 	if (session->opmode == QDF_STA_MODE)
3388 		session->enable_bcast_probe_rsp =
3389 			mac_ctx->mlme_cfg->oce.enable_bcast_probe_rsp;
3390 
3391 	/* Store vendor specific IE for CISCO AP */
3392 	ie_len = (bss_desc->length + sizeof(bss_desc->length) -
3393 		 GET_FIELD_OFFSET(struct bss_description, ieFields));
3394 
3395 	vendor_ie = wlan_get_vendor_ie_ptr_from_oui(
3396 			SIR_MAC_CISCO_OUI, SIR_MAC_CISCO_OUI_SIZE,
3397 			((uint8_t *)&bss_desc->ieFields), ie_len);
3398 
3399 	if (vendor_ie)
3400 		session->isCiscoVendorAP = true;
3401 	else
3402 		session->isCiscoVendorAP = false;
3403 
3404 	session->nwType = bss_desc->nwType;
3405 	session->enableAmpduPs =
3406 		mac_ctx->mlme_cfg->ht_caps.enable_ampdu_ps;
3407 	session->send_smps_action =
3408 		mac_ctx->roam.configParam.send_smps_action;
3409 	session->vhtCapability =
3410 		IS_DOT11_MODE_VHT(session->dot11mode);
3411 	if (session->vhtCapability) {
3412 		session->enableVhtpAid =
3413 		   mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_paid;
3414 		session->enableVhtGid =
3415 		   mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_gid;
3416 	}
3417 	/*Phy mode */
3418 	session->gLimPhyMode = bss_desc->nwType;
3419 	handle_ht_capabilityand_ht_info(mac_ctx, session);
3420 
3421 	session->htSupportedChannelWidthSet = cb_mode ? 1 : 0;
3422 	session->htRecommendedTxWidthSet =
3423 		session->htSupportedChannelWidthSet;
3424 	session->htSecondaryChannelOffset = cb_mode;
3425 
3426 	if (cb_mode == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) {
3427 		session->ch_center_freq_seg0 =
3428 			wlan_reg_freq_to_chan(
3429 			mac_ctx->pdev, session->curr_op_freq) - 2;
3430 		session->ch_width = CH_WIDTH_40MHZ;
3431 	} else if (cb_mode == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) {
3432 		session->ch_center_freq_seg0 =
3433 			wlan_reg_freq_to_chan(
3434 			mac_ctx->pdev, session->curr_op_freq) + 2;
3435 		session->ch_width = CH_WIDTH_40MHZ;
3436 	} else {
3437 		session->ch_center_freq_seg0 = 0;
3438 		session->ch_width = CH_WIDTH_20MHZ;
3439 	}
3440 	session->ap_ch_width = session->ch_width;
3441 
3442 	if (IS_DOT11_MODE_HE(session->dot11mode)) {
3443 		lim_update_session_he_capable(mac_ctx, session);
3444 		lim_copy_join_req_he_cap(session);
3445 	}
3446 
3447 	if (IS_DOT11_MODE_EHT(session->dot11mode)) {
3448 		lim_update_session_eht_capable(mac_ctx, session);
3449 		lim_reset_self_ocv_caps(session);
3450 		lim_copy_join_req_eht_cap(session);
3451 	}
3452 
3453 	/* Record if management frames need to be protected */
3454 	session->limRmfEnabled =
3455 		lim_get_vdev_rmf_capable(mac_ctx, session);
3456 
3457 	session->txLdpcIniFeatureEnabled =
3458 		mac_ctx->mlme_cfg->ht_caps.tx_ldpc_enable;
3459 
3460 	session->limSystemRole = eLIM_STA_ROLE;
3461 	if (session->nss == 1)
3462 		session->supported_nss_1x1 = true;
3463 
3464 	session->limCurrentBssCaps = bss_desc->capabilityInfo;
3465 
3466 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
3467 	if (!mlme_obj) {
3468 		status =  QDF_STATUS_E_FAILURE;
3469 		goto send;
3470 	}
3471 
3472 	lim_extract_ap_capability(mac_ctx,
3473 		(uint8_t *)bss_desc->ieFields,
3474 		lim_get_ielen_from_bss_description(bss_desc),
3475 		&session->limCurrentBssQosCaps,
3476 		&session->gLimCurrentBssUapsd,
3477 		&local_power_constraint, session, &is_pwr_constraint);
3478 
3479 	lim_disable_bformee_for_iot_ap(mac_ctx, session, bss_desc);
3480 
3481 	mlme_obj->reg_tpc_obj.is_power_constraint_abs =
3482 						!is_pwr_constraint;
3483 
3484 	if (wlan_reg_is_6ghz_chan_freq(bss_desc->chan_freq)) {
3485 		if (!ie_struct->Country.present)
3486 			pe_debug("Channel is 6G but country IE not present");
3487 		status = wlan_reg_get_best_6g_power_type(
3488 				mac_ctx->psoc, mac_ctx->pdev,
3489 				&power_type_6g,
3490 				session->ap_defined_power_type_6g,
3491 				bss_desc->chan_freq);
3492 		if (QDF_IS_STATUS_ERROR(status)) {
3493 			status = QDF_STATUS_E_NOSUPPORT;
3494 			goto send;
3495 		}
3496 		session->best_6g_power_type = power_type_6g;
3497 		mlme_set_best_6g_power_type(session->vdev, power_type_6g);
3498 
3499 		lim_iterate_triplets(ie_struct->Country);
3500 
3501 		if (!ie_struct->num_transmit_power_env ||
3502 		    !ie_struct->transmit_power_env[0].present)
3503 			pe_debug("TPE not present for 6G channel");
3504 	}
3505 
3506 	if (wlan_reg_is_ext_tpc_supported(mac_ctx->psoc)) {
3507 		mlme_obj->reg_tpc_obj.ap_constraint_power =
3508 						local_power_constraint;
3509 	} else {
3510 		reg_max = wlan_reg_get_channel_reg_power_for_freq(
3511 				mac_ctx->pdev, session->curr_op_freq);
3512 		if (is_pwr_constraint)
3513 			local_power_constraint = reg_max -
3514 						local_power_constraint;
3515 		if (!local_power_constraint)
3516 			local_power_constraint = reg_max;
3517 
3518 		mlme_obj->reg_tpc_obj.reg_max[0] = reg_max;
3519 		mlme_obj->reg_tpc_obj.ap_constraint_power =
3520 						local_power_constraint;
3521 		mlme_obj->reg_tpc_obj.frequency[0] = session->curr_op_freq;
3522 
3523 		session->maxTxPower = lim_get_max_tx_power(mac_ctx, mlme_obj);
3524 		session->def_max_tx_pwr = session->maxTxPower;
3525 	}
3526 
3527 	/*
3528 	 * for mdm platform which QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
3529 	 * will not call from android framework every 3 seconds, and tx
3530 	 * power will never update. So we use iw dev get tx power need
3531 	 * set maxTxPower non-zero value, that firmware can calc a non-zero
3532 	 * tx power, and update to host driver.
3533 	 */
3534 	if (LIM_IS_STA_ROLE(session) && session->maxTxPower == 0)
3535 		session->maxTxPower =
3536 			wlan_reg_get_channel_reg_power_for_freq(mac_ctx->pdev,
3537 							session->curr_op_freq);
3538 
3539 	session->limRFBand = lim_get_rf_band(session->curr_op_freq);
3540 
3541 	/* Initialize 11h Enable Flag */
3542 	if (session->limRFBand != REG_BAND_2G)
3543 		session->lim11hEnable =
3544 			mac_ctx->mlme_cfg->gen.enabled_11h;
3545 	else
3546 		session->lim11hEnable = 0;
3547 
3548 	session->limPrevSmeState = session->limSmeState;
3549 	session->limSmeState = eLIM_SME_WT_JOIN_STATE;
3550 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
3551 			session->peSessionId,
3552 			session->limSmeState));
3553 
3554 	/* Enable MBSSID only for station */
3555 	session->is_mbssid_enabled = wma_is_mbssid_enabled();
3556 
3557 	/* Enable the spectrum management if this is a DFS channel */
3558 	if (session->country_info_present &&
3559 	    lim_isconnected_on_dfs_freq(
3560 			mac_ctx,
3561 			session->curr_op_freq))
3562 		session->spectrumMgtEnabled = true;
3563 
3564 	ap_cap_info = (tSirMacCapabilityInfo *)&bss_desc->capabilityInfo;
3565 
3566 	/*
3567 	 * tell the target AP my 11H capability only if both AP and STA
3568 	 * support
3569 	 * 11H and the channel being used is 11a
3570 	 */
3571 	if (mac_ctx->mlme_cfg->gen.enabled_11h &&
3572 	    ap_cap_info->spectrumMgt && bss_desc->nwType == eSIR_11A_NW_TYPE)
3573 		session->spectrumMgtEnabled = true;
3574 
3575 	/*
3576 	 * This is required for 11k test VoWiFi Ent: Test 2.
3577 	 * We need the power capabilities for Assoc Req.
3578 	 * This macro is provided by the halPhyCfg.h. We pick our
3579 	 * max and min capability by the halPhy provided macros
3580 	 * Any change in this power cap IE should also be done
3581 	 * in csr_update_driver_assoc_ies() which would send
3582 	 * assoc IE's to FW which is used for LFR3 roaming
3583 	 * ie. used in reassociation requests from FW.
3584 	 */
3585 	session->max_11h_pwr =
3586 		QDF_MIN(lim_get_cfg_max_tx_power(mac_ctx,
3587 						 bss_desc->chan_freq),
3588 			MAX_TX_PWR_CAP);
3589 
3590 	if (!session->max_11h_pwr)
3591 		session->max_11h_pwr = MAX_TX_PWR_CAP;
3592 
3593 	if (session->max_11h_pwr > session->maxTxPower)
3594 		session->max_11h_pwr = session->maxTxPower;
3595 
3596 	session->min_11h_pwr = MIN_TX_PWR_CAP;
3597 
3598 	if (!session->enable_session_twt_support) {
3599 		status = wlan_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode);
3600 		if (!QDF_IS_STATUS_SUCCESS(status)) {
3601 			pe_err("Get wmm_mode failed");
3602 			status = QDF_STATUS_E_INVAL;
3603 			goto send;
3604 		}
3605 		if (wmm_mode == 2 || !(LIM_IS_QOS_BSS(ie_struct)) ||
3606 		    !(LIM_IS_UAPSD_BSS(ie_struct))) {
3607 			/*QoS not enabled in cfg file or in BSS*/
3608 			session->gUapsdPerAcBitmask = 0;
3609 		} else {
3610 			/*QoS enabled, update uapsd mask from cfg file */
3611 			status = wlan_mlme_get_wmm_uapsd_mask(mac_ctx->psoc,
3612 							      &value);
3613 			if (QDF_IS_STATUS_ERROR(status)) {
3614 				pe_err("Get uapsd_mask failed");
3615 				status = QDF_STATUS_E_INVAL;
3616 				goto send;
3617 			}
3618 			session->gUapsdPerAcBitmask = value;
3619 		}
3620 		ps_param->uapsd_per_ac_bit_mask = session->gUapsdPerAcBitmask;
3621 	}
3622 
3623 	if (session->gLimCurrentBssUapsd) {
3624 		/* resetting the dynamic uapsd mask  */
3625 		session->gUapsdPerAcDeliveryEnableMask = 0;
3626 		session->gUapsdPerAcTriggerEnableMask = 0;
3627 	}
3628 
3629 	lim_fill_cc_mode(mac_ctx, session);
3630 	lim_fill_rssi(session, bss_desc);
3631 
3632 	status = QDF_STATUS_SUCCESS;
3633 
3634 send:
3635 	qdf_mem_free(ie_struct);
3636 	return status;
3637 
3638 }
3639 
3640 static QDF_STATUS
3641 lim_send_connect_req_to_mlm(struct pe_session *session)
3642 {
3643 	tLimMlmJoinReq *mlm_join_req;
3644 	uint32_t len;
3645 	QDF_STATUS status;
3646 
3647 	len = sizeof(tLimMlmJoinReq) +
3648 			session->lim_join_req->bssDescription.length + 2;
3649 	mlm_join_req = qdf_mem_malloc(len);
3650 	if (!mlm_join_req)
3651 		return QDF_STATUS_E_FAILURE;
3652 
3653 	/* PE SessionId is stored as a part of JoinReq */
3654 	mlm_join_req->sessionId = session->peSessionId;
3655 
3656 	mlm_join_req->bssDescription.length =
3657 		session->lim_join_req->bssDescription.length;
3658 
3659 	qdf_mem_copy((uint8_t *) &mlm_join_req->bssDescription.bssId,
3660 		(uint8_t *)
3661 		&session->lim_join_req->bssDescription.bssId,
3662 		session->lim_join_req->bssDescription.length + 2);
3663 
3664 	/* Issue LIM_MLM_JOIN_REQ to MLM */
3665 	status = lim_send_join_req(session, mlm_join_req);
3666 	if (QDF_IS_STATUS_ERROR(status)) {
3667 		qdf_mem_free(mlm_join_req);
3668 		return QDF_STATUS_E_FAILURE;
3669 	}
3670 
3671 	return QDF_STATUS_SUCCESS;
3672 }
3673 
3674 static struct pe_session *
3675 lim_cm_create_session(struct mac_context *mac_ctx, struct cm_vdev_join_req *req)
3676 {
3677 	struct pe_session *pe_session;
3678 	uint8_t session_id;
3679 
3680 	pe_session = pe_find_session_by_bssid(mac_ctx, req->entry->bssid.bytes,
3681 					      &session_id);
3682 
3683 	if (pe_session) {
3684 		pe_err("vdev_id: %d cm_id 0x%x :pe-session(%d (vdev %d)) already exists for BSSID: "
3685 		       QDF_MAC_ADDR_FMT " in lim_sme_state = %X",
3686 		       req->vdev_id, req->cm_id, session_id,
3687 		       pe_session->vdev_id,
3688 		       QDF_MAC_ADDR_REF(req->entry->bssid.bytes),
3689 		       pe_session->limSmeState);
3690 
3691 		qdf_trigger_self_recovery(mac_ctx->psoc,
3692 					  QDF_VDEV_SM_OUT_OF_SYNC);
3693 		return NULL;
3694 	}
3695 
3696 	pe_session = pe_create_session(mac_ctx, req->entry->bssid.bytes,
3697 			&session_id,
3698 			mac_ctx->lim.max_sta_of_pe_session,
3699 			eSIR_INFRASTRUCTURE_MODE,
3700 			req->vdev_id);
3701 	if (!pe_session)
3702 		pe_err("vdev_id: %d cm_id 0x%x : pe_session create failed BSSID"
3703 		       QDF_MAC_ADDR_FMT, req->vdev_id, req->cm_id,
3704 		       QDF_MAC_ADDR_REF(req->entry->bssid.bytes));
3705 
3706 	return pe_session;
3707 }
3708 
3709 static bool
3710 lim_is_wpa_profile(struct pe_session *session)
3711 {
3712 	int32_t ucast_cipher;
3713 	int32_t auth_mode;
3714 
3715 	ucast_cipher = wlan_crypto_get_param(session->vdev,
3716 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
3717 
3718 	auth_mode = wlan_crypto_get_param(session->vdev,
3719 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
3720 
3721 	if (auth_mode == -1 || ucast_cipher == -1)
3722 		return false;
3723 
3724 	if (!QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_WPA))
3725 		return false;
3726 
3727 	if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) ||
3728 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) ||
3729 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104)) ||
3730 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) ||
3731 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) ||
3732 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_OCB)) ||
3733 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256))))
3734 		return true;
3735 
3736 	return false;
3737 }
3738 
3739 static bool
3740 lim_is_wapi_profile(struct pe_session *session)
3741 {
3742 	int32_t ucast_cipher;
3743 	int32_t auth_mode;
3744 
3745 	ucast_cipher = wlan_crypto_get_param(session->vdev,
3746 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
3747 
3748 	auth_mode = wlan_crypto_get_param(session->vdev,
3749 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
3750 
3751 	if (auth_mode == -1 || ucast_cipher == -1)
3752 		return false;
3753 
3754 	if (!QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_WAPI))
3755 		return false;
3756 
3757 	if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WAPI_GCM4)) ||
3758 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WAPI_SMS4))))
3759 		return true;
3760 
3761 	return false;
3762 }
3763 
3764 static bool
3765 lim_is_rsn_profile(struct pe_session *session)
3766 {
3767 	int32_t ucast_cipher;
3768 	int32_t auth_mode;
3769 	bool is_rsn = false;
3770 
3771 	ucast_cipher = wlan_crypto_get_param(session->vdev,
3772 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
3773 
3774 	auth_mode = wlan_crypto_get_param(session->vdev,
3775 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
3776 
3777 	if (auth_mode == -1 || ucast_cipher == -1)
3778 		return false;
3779 
3780 	if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_8021X) ||
3781 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_RSNA) ||
3782 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_CCKM) ||
3783 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_SAE) ||
3784 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_FILS_SK))
3785 		is_rsn = true;
3786 
3787 	if (!is_rsn)
3788 		return false;
3789 
3790 	if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) ||
3791 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) ||
3792 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104)) ||
3793 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) ||
3794 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) ||
3795 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_OCB)) ||
3796 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256)) ||
3797 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM_256)) ||
3798 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM))))
3799 		return true;
3800 
3801 	return false;
3802 }
3803 
3804 tAniEdType lim_get_encrypt_ed_type(int32_t ucast_cipher)
3805 {
3806 	if (ucast_cipher == -1)
3807 		return eSIR_ED_NONE;
3808 
3809 	if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM_256))
3810 		return eSIR_ED_GCMP_256;
3811 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM))
3812 		return eSIR_ED_GCMP;
3813 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM) ||
3814 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_OCB) ||
3815 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM_256))
3816 		return eSIR_ED_CCMP;
3817 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_TKIP))
3818 		return eSIR_ED_TKIP;
3819 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CMAC) ||
3820 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CMAC_256))
3821 		return eSIR_ED_AES_128_CMAC;
3822 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_GCM4) ||
3823 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_SMS4))
3824 		return eSIR_ED_WPI;
3825 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GMAC))
3826 		return eSIR_ED_AES_GMAC_128;
3827 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GMAC_256))
3828 		return eSIR_ED_AES_GMAC_256;
3829 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP))
3830 		return eSIR_ED_WEP40;
3831 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_40))
3832 		return eSIR_ED_WEP40;
3833 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_104))
3834 		return eSIR_ED_WEP104;
3835 
3836 	return eSIR_ED_NONE;
3837 }
3838 
3839 static enum ani_akm_type
3840 lim_get_wpa_akm(uint32_t akm)
3841 {
3842 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X))
3843 		return ANI_AKM_TYPE_WPA;
3844 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK))
3845 		return ANI_AKM_TYPE_WPA_PSK;
3846 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM))
3847 		return ANI_AKM_TYPE_CCKM;
3848 	else
3849 		return ANI_AKM_TYPE_UNKNOWN;
3850 }
3851 
3852 static enum ani_akm_type
3853 lim_get_rsn_akm(uint32_t akm)
3854 {
3855 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384))
3856 		return ANI_AKM_TYPE_FT_FILS_SHA384;
3857 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256))
3858 		return ANI_AKM_TYPE_FT_FILS_SHA256;
3859 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384))
3860 		return ANI_AKM_TYPE_FILS_SHA384;
3861 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256))
3862 		return ANI_AKM_TYPE_FILS_SHA256;
3863 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY))
3864 		return ANI_AKM_TYPE_FT_SAE_EXT_KEY;
3865 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE))
3866 		return ANI_AKM_TYPE_FT_SAE;
3867 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE))
3868 		return ANI_AKM_TYPE_SAE;
3869 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_DPP))
3870 		return ANI_AKM_TYPE_DPP_RSN;
3871 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OSEN))
3872 		return ANI_AKM_TYPE_OSEN;
3873 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE))
3874 		return ANI_AKM_TYPE_OWE;
3875 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X))
3876 		return ANI_AKM_TYPE_FT_RSN;
3877 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK))
3878 		return ANI_AKM_TYPE_FT_RSN_PSK;
3879 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X))
3880 		return ANI_AKM_TYPE_RSN;
3881 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK))
3882 		return ANI_AKM_TYPE_RSN_PSK;
3883 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM))
3884 		return ANI_AKM_TYPE_CCKM;
3885 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256))
3886 		return ANI_AKM_TYPE_RSN_PSK_SHA256;
3887 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256))
3888 		return ANI_AKM_TYPE_RSN_8021X_SHA256;
3889 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B))
3890 		return ANI_AKM_TYPE_SUITEB_EAP_SHA256;
3891 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192))
3892 		return ANI_AKM_TYPE_SUITEB_EAP_SHA384;
3893 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384))
3894 		return ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384;
3895 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))
3896 		return ANI_AKM_TYPE_SAE_EXT_KEY;
3897 	else
3898 		return ANI_AKM_TYPE_NONE;
3899 }
3900 
3901 enum ani_akm_type
3902 lim_get_connected_akm(struct pe_session *session, int32_t ucast_cipher,
3903 		      int32_t auth_mode, int32_t akm)
3904 {
3905 	if (auth_mode == -1 || ucast_cipher == -1 || akm == -1)
3906 		return ANI_AKM_TYPE_NONE;
3907 
3908 	if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_NONE) ||
3909 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_OPEN))
3910 		return ANI_AKM_TYPE_NONE;
3911 
3912 	if (lim_is_rsn_profile(session))
3913 		return lim_get_rsn_akm(akm);
3914 
3915 	if (lim_is_wpa_profile(session))
3916 		return lim_get_wpa_akm(akm);
3917 
3918 	if (lim_is_wapi_profile(session))
3919 		return ANI_AKM_TYPE_UNKNOWN;
3920 
3921 	return ANI_AKM_TYPE_NONE;
3922 }
3923 
3924 #ifdef WLAN_FEATURE_FILS_SK
3925 /**
3926  * lim_update_pmksa_to_profile() - update pmk and pmkid to profile which will be
3927  * used in case of fils session
3928  * @vdev: vdev
3929  * @pmkid_cache: pmksa cache
3930  *
3931  * Return: None
3932  */
3933 static inline void lim_update_pmksa_to_profile(struct wlan_objmgr_vdev *vdev,
3934 					       struct wlan_crypto_pmksa *pmksa)
3935 {
3936 	struct mlme_legacy_priv *mlme_priv;
3937 
3938 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
3939 	if (!mlme_priv) {
3940 		pe_err("vdev legacy private object is NULL");
3941 		return;
3942 	}
3943 	if (!mlme_priv->connect_info.fils_con_info)
3944 		return;
3945 	mlme_priv->connect_info.fils_con_info->pmk_len = pmksa->pmk_len;
3946 	qdf_mem_copy(mlme_priv->connect_info.fils_con_info->pmk,
3947 		     pmksa->pmk, pmksa->pmk_len);
3948 	qdf_mem_copy(mlme_priv->connect_info.fils_con_info->pmkid,
3949 		     pmksa->pmkid, PMKID_LEN);
3950 }
3951 #else
3952 static inline void lim_update_pmksa_to_profile(struct wlan_objmgr_vdev *vdev,
3953 					       struct wlan_crypto_pmksa *pmksa)
3954 {
3955 }
3956 #endif
3957 
3958 /*
3959  * lim_is_non_default_rsnxe_cap_set() - Check if non-default userspace RSNXE
3960  * CAP is set
3961  *
3962  * @mac_ctx: pointer to mac contetx
3963  * @req: join request
3964  *
3965  * Return: Non default cap set
3966  */
3967 static inline bool
3968 lim_is_non_default_rsnxe_cap_set(struct mac_context *mac_ctx,
3969 				 struct cm_vdev_join_req *req)
3970 {
3971 	const uint8_t *rsnxe, *rsnxe_cap;
3972 	uint8_t cap_len = 0, cap_index;
3973 	uint32_t cap_mask;
3974 
3975 	rsnxe = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE,
3976 					 req->assoc_ie.ptr,
3977 					 req->assoc_ie.len);
3978 	if (!rsnxe)
3979 		return false;
3980 
3981 	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe, &cap_len);
3982 	if (!rsnxe_cap || (rsnxe[SIR_MAC_IE_LEN_OFFSET] > (cap_len + 1))) {
3983 		mlme_err("RSNXE caps not present/unknown caps present. Cap len %d",
3984 			 cap_len);
3985 		return true;
3986 	}
3987 
3988 	/*
3989 	 * Below is the definition of RSNXE capabilities defined
3990 	 * in (IEEE Std 802.11-2020, 9.4.2.241, Table 9-780).
3991 	 * The Extended RSN Capabilities field, except its first 4 bits, is a
3992 	 * bit field indicating the extended RSN capabilities being advertised
3993 	 * by the STA transmitting the element. The length of the Extended
3994 	 * RSN Capabilities field is a variable n, in octets, as indicated by
3995 	 * the first 4 bits in the field.
3996 	 * Let's consider a uint32_t cap_mask which can accommodate 28(32-4)
3997 	 * bits to check if those bits are set or not. This is to keep it
3998 	 * simple as current supported bits are only 11.
3999 	 * TODO: If spec supports more than this range in future, this needs to
4000 	 * be an array to hold the complete bitmap/bitmask.
4001 	 */
4002 	cap_mask = ~(0xF | WLAN_CRYPTO_RSNX_CAP_SAE_H2E |
4003 		     WLAN_CRYPTO_RSNX_CAP_SAE_PK |
4004 		     WLAN_CRYPTO_RSNX_CAP_SECURE_LTF |
4005 		     WLAN_CRYPTO_RSNX_CAP_SECURE_RTT |
4006 		     WLAN_CRYPTO_RSNX_CAP_URNM_MFPR);
4007 
4008 	/* Check if any other bits are set than cap_mask */
4009 	for (cap_index = 0; cap_index <= cap_len; cap_index++) {
4010 		if (rsnxe_cap[cap_index] & (cap_mask & 0xFF))
4011 			return true;
4012 		cap_mask >>= 8;
4013 	}
4014 
4015 	return false;
4016 }
4017 
4018 /*
4019  * lim_rebuild_rsnxe_cap() - Rebuild the RSNXE CAP for STA
4020  *
4021  * @rsnx_ie: RSNX IE
4022  * @length: length of extended RSN cap field
4023  *
4024  * This API is used to truncate/rebuild the RSNXE based on the length
4025  * provided. This length marks the length of the extended RSN cap field.
4026  *
4027  * Return: Newly constructed RSNX IE
4028  */
4029 static inline uint8_t *lim_rebuild_rsnxe_cap(uint8_t *rsnx_ie, uint8_t length)
4030 {
4031 	const uint8_t *rsnxe_cap;
4032 	uint8_t cap_len;
4033 	uint8_t *new_rsnxe = NULL;
4034 
4035 	if (length < SIR_MAC_RSNX_CAP_MIN_LEN ||
4036 	    length > SIR_MAC_RSNX_CAP_MAX_LEN) {
4037 		pe_err("Invalid length %d", length);
4038 		return NULL;
4039 	}
4040 
4041 	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnx_ie, &cap_len);
4042 	if (!rsnxe_cap)
4043 		return NULL;
4044 
4045 	new_rsnxe = qdf_mem_malloc(length + SIR_MAC_IE_TYPE_LEN_SIZE);
4046 	if (!new_rsnxe)
4047 		return NULL;
4048 
4049 	new_rsnxe[SIR_MAC_IE_TYPE_OFFSET] = WLAN_ELEMID_RSNXE;
4050 	new_rsnxe[SIR_MAC_IE_LEN_OFFSET] = length;
4051 	qdf_mem_copy(&new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE], rsnxe_cap, length);
4052 
4053 	/* Now update the new field length in octet 0 for the new length*/
4054 	new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE] =
4055 		(new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE] & 0xF0) | (length - 1);
4056 
4057 	pe_debug("New RSNXE length %d", length);
4058 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
4059 			   new_rsnxe, length + SIR_MAC_IE_TYPE_LEN_SIZE);
4060 	return new_rsnxe;
4061 }
4062 
4063 /*
4064  * lim_append_rsnxe_to_assoc_ie() - Append the new RSNXE to the
4065  * assoc ie buffer
4066  *
4067  * @req: join request
4068  * @new_rsnxe: new rsnxe to be appended
4069  *
4070  * Return: QDF_STATUS
4071  */
4072 static inline QDF_STATUS
4073 lim_append_rsnxe_to_assoc_ie(struct cm_vdev_join_req *req,
4074 			     uint8_t *new_rsnxe)
4075 {
4076 	uint8_t *assoc_ie = NULL;
4077 	uint8_t assoc_ie_len;
4078 
4079 	assoc_ie = qdf_mem_malloc(req->assoc_ie.len +
4080 				  new_rsnxe[SIR_MAC_IE_LEN_OFFSET] +
4081 				  SIR_MAC_IE_TYPE_LEN_SIZE);
4082 	if (!assoc_ie)
4083 		return QDF_STATUS_E_FAILURE;
4084 
4085 	qdf_mem_copy(assoc_ie, req->assoc_ie.ptr, req->assoc_ie.len);
4086 	assoc_ie_len = req->assoc_ie.len;
4087 	qdf_mem_copy(&assoc_ie[assoc_ie_len], new_rsnxe,
4088 		     new_rsnxe[SIR_MAC_IE_LEN_OFFSET] +
4089 		     SIR_MAC_IE_TYPE_LEN_SIZE);
4090 	assoc_ie_len += new_rsnxe[SIR_MAC_IE_LEN_OFFSET] +
4091 			SIR_MAC_IE_TYPE_LEN_SIZE;
4092 
4093 	/* Replace the assoc ie with new assoc_ie */
4094 	qdf_mem_free(req->assoc_ie.ptr);
4095 	req->assoc_ie.ptr = &assoc_ie[0];
4096 	req->assoc_ie.len = assoc_ie_len;
4097 	return QDF_STATUS_SUCCESS;
4098 }
4099 
4100 static inline QDF_STATUS
4101 lim_strip_rsnx_ie(struct mac_context *mac_ctx,
4102 		  struct pe_session *session,
4103 		  struct cm_vdev_join_req *req)
4104 {
4105 	int32_t akm;
4106 	uint8_t ap_rsnxe_len = 0, len = 0;
4107 	uint8_t *rsnxe = NULL, *new_rsnxe = NULL;
4108 	uint8_t *ap_rsnxe = NULL;
4109 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4110 
4111 	akm = wlan_crypto_get_param(session->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
4112 	if (akm == -1 ||
4113 	    !(WLAN_CRYPTO_IS_WPA_WPA2(akm) || WLAN_CRYPTO_IS_WPA3(akm)))
4114 		return status;
4115 
4116 	if (!wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, req->assoc_ie.ptr,
4117 				      req->assoc_ie.len))
4118 		return status;
4119 
4120 	/*
4121 	 * Userspace may send RSNXE also in connect request irrespective
4122 	 * of the connecting AP capabilities. This allows the driver to chose
4123 	 * best candidate based on score. But the chosen candidate may
4124 	 * not support the RSNXE feature and may not advertise RSNXE
4125 	 * in beacon/probe response. Station is not supposed to include
4126 	 * the RSNX IE in assoc request in such cases as legacy APs
4127 	 * may misbahave due to the new IE. It's observed that few
4128 	 * legacy APs which don't support the RSNXE reject the
4129 	 * connection at EAPOL stage.
4130 	 *
4131 	 * Modify the RSNXE only when known capability bits are set.
4132 	 * i.e., don't strip when bits other than SAE_H2E, SAE_PK, SECURE_LTF,
4133 	 * SECURE_RTT, PROT_RANGE_NEGOTIOATION are set by userspace.
4134 	 *
4135 	 */
4136 	if (lim_is_non_default_rsnxe_cap_set(mac_ctx, req)) {
4137 		pe_debug("Do not strip RSNXE, unknown caps are set");
4138 		return status;
4139 	}
4140 
4141 	ap_rsnxe = util_scan_entry_rsnxe(req->entry);
4142 	if (!ap_rsnxe)
4143 		ap_rsnxe_len = 0;
4144 	else
4145 		ap_rsnxe_len = ap_rsnxe[SIR_MAC_IE_LEN_OFFSET];
4146 
4147 	/*
4148 	 * Do not modify userspace RSNXE if either:
4149 	 * a) AP supports RSNXE cap with more than 1 bytes
4150 	 * b) AP has zero length RSNXE.
4151 	 */
4152 
4153 	if (ap_rsnxe_len > 1 || (ap_rsnxe && ap_rsnxe_len == 0))
4154 		return QDF_STATUS_SUCCESS;
4155 
4156 	rsnxe = qdf_mem_malloc(WLAN_MAX_IE_LEN + SIR_MAC_IE_TYPE_LEN_SIZE);
4157 	if (!rsnxe)
4158 		return QDF_STATUS_E_FAILURE;
4159 
4160 	lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4161 		     (uint16_t *)&req->assoc_ie.len, WLAN_ELEMID_RSNXE,
4162 		     ONE_BYTE, NULL, 0, rsnxe, WLAN_MAX_IE_LEN);
4163 
4164 	if (!rsnxe[0])
4165 		goto end;
4166 
4167 	switch (ap_rsnxe_len) {
4168 	case 0:
4169 		/*
4170 		 * AP doesn't broadcast RSNXE/invalid RSNXE:
4171 		 * For WPA2 - Strip the RSNXE
4172 		 * For WPA3 - Retain only SAE caps: H2E and PK in the 1st octet
4173 		 */
4174 		if (WLAN_CRYPTO_IS_WPA_WPA2(akm)) {
4175 			mlme_debug("Strip RSNXE as it is not supported by AP");
4176 			goto end;
4177 		}
4178 		if (WLAN_CRYPTO_IS_WPA3(akm)) {
4179 			len = 1;
4180 			goto rebuild_rsnxe;
4181 		}
4182 		break;
4183 	case 1:
4184 		/*
4185 		 * In some IOT cases, APs do not recognize more than 1 octet of
4186 		 * RSNXE. This leads to connectivity failures.
4187 		 * Therefore, restrict the self RSNXE to 1 octet if AP supports
4188 		 * only 1 octet
4189 		 */
4190 		len = 1;
4191 		goto rebuild_rsnxe;
4192 	default:
4193 		break;
4194 	}
4195 
4196 	pe_err("Error in handling RSNXE. Length AP: %d SELF: %d",
4197 	       ap_rsnxe_len, rsnxe[SIR_MAC_IE_LEN_OFFSET]);
4198 	status = QDF_STATUS_E_FAILURE;
4199 	goto end;
4200 
4201 rebuild_rsnxe:
4202 	/* Build the new RSNXE */
4203 	new_rsnxe = lim_rebuild_rsnxe_cap(rsnxe, len);
4204 	if (!new_rsnxe) {
4205 		status = QDF_STATUS_E_FAILURE;
4206 		goto end;
4207 	} else if (!new_rsnxe[1]) {
4208 		qdf_mem_free(new_rsnxe);
4209 		status = QDF_STATUS_E_FAILURE;
4210 		goto end;
4211 	}
4212 
4213 	/* Append the new RSNXE to the assoc ie */
4214 	status = lim_append_rsnxe_to_assoc_ie(req, new_rsnxe);
4215 	qdf_mem_free(new_rsnxe);
4216 
4217 end:
4218 	qdf_mem_free(rsnxe);
4219 	return status;
4220 }
4221 
4222 void
4223 lim_update_connect_rsn_ie(struct pe_session *session,
4224 			  uint8_t *rsn_ie_buf, struct wlan_crypto_pmksa *pmksa)
4225 {
4226 	uint8_t *rsn_ie_end;
4227 	uint16_t rsn_ie_len = 0;
4228 
4229 	rsn_ie_end = wlan_crypto_build_rsnie_with_pmksa(session->vdev,
4230 							rsn_ie_buf, pmksa);
4231 	if (!rsn_ie_end) {
4232 		pe_debug("Build RSN IE failed");
4233 		return;
4234 	}
4235 
4236 	rsn_ie_len = rsn_ie_end - rsn_ie_buf;
4237 	session->lim_join_req->rsnIE.length = rsn_ie_len;
4238 	qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4239 		     rsn_ie_buf, rsn_ie_len);
4240 }
4241 
4242 static QDF_STATUS
4243 lim_fill_rsn_ie(struct mac_context *mac_ctx, struct pe_session *session,
4244 		struct cm_vdev_join_req *req)
4245 {
4246 	QDF_STATUS status;
4247 	uint8_t *rsn_ie;
4248 	uint8_t rsn_ie_len = 0;
4249 	struct wlan_crypto_pmksa pmksa, *pmksa_peer;
4250 	struct bss_description *bss_desc;
4251 
4252 	rsn_ie = qdf_mem_malloc(DOT11F_IE_RSN_MAX_LEN + 2);
4253 	if (!rsn_ie)
4254 		return QDF_STATUS_E_NOMEM;
4255 
4256 	status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4257 			      (uint16_t *)&req->assoc_ie.len,
4258 			      WLAN_ELEMID_RSN, ONE_BYTE,
4259 			      NULL, 0, rsn_ie, DOT11F_IE_RSN_MAX_LEN);
4260 
4261 	if (req->force_rsne_override && QDF_IS_STATUS_SUCCESS(status)) {
4262 		rsn_ie_len = rsn_ie[1] + 2;
4263 		if (rsn_ie_len < DOT11F_IE_RSN_MIN_LEN ||
4264 		    rsn_ie_len > DOT11F_IE_RSN_MAX_LEN) {
4265 			pe_err("RSN length %d not within limits", rsn_ie_len);
4266 			qdf_mem_free(rsn_ie);
4267 			return QDF_STATUS_E_FAILURE;
4268 		}
4269 
4270 		session->lim_join_req->rsnIE.length = rsn_ie_len;
4271 		qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4272 			     rsn_ie, rsn_ie_len);
4273 
4274 		qdf_mem_free(rsn_ie);
4275 		return QDF_STATUS_SUCCESS;
4276 	}
4277 
4278 	bss_desc = &session->lim_join_req->bssDescription;
4279 
4280 	qdf_mem_zero(&pmksa, sizeof(pmksa));
4281 	if (bss_desc->fils_info_element.is_cache_id_present) {
4282 		pmksa.ssid_len = session->ssId.length;
4283 		qdf_mem_copy(pmksa.ssid, session->ssId.ssId,
4284 			     session->ssId.length);
4285 		qdf_mem_copy(pmksa.cache_id,
4286 			     bss_desc->fils_info_element.cache_id,
4287 			     CACHE_ID_LEN);
4288 		pe_debug("FILS: vdev %d Cache id =0x%x 0x%x ssid: " QDF_SSID_FMT,
4289 			 session->vdev_id, pmksa.cache_id[0], pmksa.cache_id[1],
4290 			 QDF_SSID_REF(pmksa.ssid_len, pmksa.ssid));
4291 	} else {
4292 		qdf_mem_copy(&pmksa.bssid, session->bssId, QDF_MAC_ADDR_SIZE);
4293 		/* For MLO connection, override BSSID with peer mldaddr */
4294 		lim_get_mld_peer(session->vdev, &pmksa.bssid);
4295 	}
4296 
4297 	pmksa_peer = wlan_crypto_get_peer_pmksa(session->vdev, &pmksa);
4298 	if (pmksa_peer)
4299 		pe_debug("PMKSA found");
4300 
4301 	lim_update_connect_rsn_ie(session, rsn_ie, pmksa_peer);
4302 	qdf_mem_free(rsn_ie);
4303 
4304 	/*
4305 	 * If a PMK cache is found for the BSSID, then
4306 	 * update the PMK in CSR session also as this
4307 	 * will be sent to the FW during RSO.
4308 	 */
4309 	if (pmksa_peer) {
4310 		wlan_cm_set_psk_pmk(mac_ctx->pdev, session->vdev_id,
4311 				    pmksa_peer->pmk, pmksa_peer->pmk_len);
4312 		lim_update_pmksa_to_profile(session->vdev, pmksa_peer);
4313 	}
4314 
4315 	return QDF_STATUS_SUCCESS;
4316 }
4317 
4318 static QDF_STATUS
4319 lim_fill_wpa_ie(struct mac_context *mac_ctx, struct pe_session *session,
4320 		struct cm_vdev_join_req *req)
4321 {
4322 	QDF_STATUS status;
4323 	uint8_t *wpa_ie;
4324 	uint8_t ie_len = 0;
4325 	uint8_t *wpa_ie_end = NULL;
4326 
4327 	wpa_ie = qdf_mem_malloc(DOT11F_IE_WPA_MAX_LEN + 2);
4328 	if (!wpa_ie)
4329 		return QDF_STATUS_E_NOMEM;
4330 
4331 	status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4332 			      (uint16_t *)&req->assoc_ie.len,
4333 			      DOT11F_EID_WPA, ONE_BYTE,
4334 			      "\x00\x50\xf2", 3, NULL, 0);
4335 
4336 	wpa_ie_end = wlan_crypto_build_wpaie(session->vdev, wpa_ie);
4337 	if (wpa_ie_end)
4338 		ie_len = wpa_ie_end - wpa_ie;
4339 
4340 	session->lim_join_req->rsnIE.length = ie_len;
4341 	qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4342 		     wpa_ie, ie_len);
4343 
4344 	qdf_mem_free(wpa_ie);
4345 
4346 	return QDF_STATUS_SUCCESS;
4347 }
4348 
4349 #ifdef FEATURE_WLAN_WAPI
4350 static QDF_STATUS
4351 lim_fill_wapi_ie(struct mac_context *mac_ctx, struct pe_session *session,
4352 		 struct cm_vdev_join_req *req)
4353 {
4354 	QDF_STATUS status;
4355 	uint8_t *wapi_ie;
4356 	uint8_t ie_len = 0;
4357 	uint8_t *wapi_ie_end = NULL;
4358 
4359 	wapi_ie = qdf_mem_malloc(DOT11F_IE_WAPI_MAX_LEN + 2);
4360 	if (!wapi_ie)
4361 		return QDF_STATUS_E_NOMEM;
4362 
4363 	status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4364 			      (uint16_t *)&req->assoc_ie.len,
4365 			      WLAN_ELEMID_WAPI, ONE_BYTE,
4366 			      NULL, 0, NULL, 0);
4367 
4368 	wapi_ie_end = wlan_crypto_build_wapiie(session->vdev, wapi_ie);
4369 	if (wapi_ie_end)
4370 		ie_len = wapi_ie_end - wapi_ie;
4371 
4372 	session->lim_join_req->rsnIE.length = ie_len;
4373 	qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4374 		     wapi_ie, ie_len);
4375 
4376 	qdf_mem_free(wapi_ie);
4377 
4378 	return QDF_STATUS_SUCCESS;
4379 }
4380 #else
4381 static inline QDF_STATUS
4382 lim_fill_wapi_ie(struct mac_context *mac_ctx, struct pe_session *session,
4383 		 struct cm_vdev_join_req *req)
4384 {
4385 	return QDF_STATUS_SUCCESS;
4386 }
4387 #endif
4388 
4389 static QDF_STATUS lim_fill_crypto_params(struct mac_context *mac_ctx,
4390 					 struct pe_session *session,
4391 					 struct cm_vdev_join_req *req)
4392 {
4393 	int32_t ucast_cipher;
4394 	int32_t auth_mode;
4395 	int32_t akm;
4396 	tSirMacCapabilityInfo *ap_cap_info;
4397 	QDF_STATUS status;
4398 
4399 	ucast_cipher = wlan_crypto_get_param(session->vdev,
4400 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
4401 	auth_mode = wlan_crypto_get_param(session->vdev,
4402 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
4403 	akm = wlan_crypto_get_param(session->vdev,
4404 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
4405 	ap_cap_info = (tSirMacCapabilityInfo *)
4406 			&session->lim_join_req->bssDescription.capabilityInfo;
4407 
4408 	lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm,
4409 			ap_cap_info->privacy);
4410 	session->encryptType = lim_get_encrypt_ed_type(ucast_cipher);
4411 	session->connected_akm = lim_get_connected_akm(session, ucast_cipher,
4412 						       auth_mode, akm);
4413 
4414 	session->wps_registration = req->is_wps_connection;
4415 	session->isOSENConnection = req->is_osen_connection;
4416 
4417 	if (lim_is_rsn_profile(session))
4418 		lim_fill_rsn_ie(mac_ctx, session, req);
4419 	else if (lim_is_wpa_profile(session))
4420 		lim_fill_wpa_ie(mac_ctx, session, req);
4421 	else if (lim_is_wapi_profile(session))
4422 		lim_fill_wapi_ie(mac_ctx, session, req);
4423 
4424 	status = lim_strip_rsnx_ie(mac_ctx, session, req);
4425 	if (QDF_IS_STATUS_ERROR(status))
4426 		return status;
4427 
4428 	lim_update_fils_config(mac_ctx, session, req);
4429 	return QDF_STATUS_SUCCESS;
4430 }
4431 
4432 #ifdef WLAN_FEATURE_11BE_MLO
4433 static void lim_fill_ml_info(struct cm_vdev_join_req *req,
4434 			     struct join_req *pe_join_req)
4435 {
4436 	uint8_t idx, num_links = 0;
4437 	struct mlo_partner_info *partner_info = NULL;
4438 
4439 	partner_info = &pe_join_req->partner_info;
4440 	if (!partner_info)
4441 		return;
4442 
4443 	num_links = req->partner_info.num_partner_links;
4444 	if (num_links > WLAN_UMAC_MLO_MAX_VDEVS)
4445 		num_links = WLAN_UMAC_MLO_MAX_VDEVS;
4446 
4447 	partner_info->num_partner_links = num_links;
4448 
4449 	for (idx = 0; idx < num_links; idx++) {
4450 		partner_info->partner_link_info[idx].link_id =
4451 			req->partner_info.partner_link_info[idx].link_id;
4452 		qdf_copy_macaddr(
4453 			&partner_info->partner_link_info[idx].link_addr,
4454 			&req->partner_info.partner_link_info[idx].link_addr);
4455 		partner_info->partner_link_info[idx].chan_freq =
4456 			req->partner_info.partner_link_info[idx].chan_freq;
4457 	}
4458 	pe_join_req->assoc_link_id = req->assoc_link_id;
4459 }
4460 
4461 static void lim_copy_ml_partner_info_to_session(struct pe_session *session,
4462 						struct cm_vdev_join_req *req)
4463 {
4464 	session->ml_partner_info = req->partner_info;
4465 }
4466 
4467 void lim_set_emlsr_caps(struct mac_context *mac_ctx, struct pe_session *session)
4468 {
4469 	bool emlsr_cap, emlsr_allowed, emlsr_band_check, emlsr_enabled = false;
4470 
4471 	/* Check if HW supports eMLSR mode */
4472 	emlsr_cap = policy_mgr_is_hw_emlsr_capable(mac_ctx->psoc);
4473 	if (!emlsr_cap)
4474 		return;
4475 
4476 	/* Check if vendor command chooses eMLSR mode */
4477 	wlan_mlme_get_emlsr_mode_enabled(mac_ctx->psoc, &emlsr_enabled);
4478 
4479 	/* Check if ML links are in 5 GHz + 6 GHz combination */
4480 	emlsr_band_check = lim_is_emlsr_band_supported(session);
4481 
4482 	emlsr_allowed = emlsr_cap && emlsr_enabled && emlsr_band_check;
4483 
4484 	if (emlsr_allowed) {
4485 		wlan_vdev_obj_lock(session->vdev);
4486 		wlan_vdev_mlme_cap_set(session->vdev, WLAN_VDEV_C_EMLSR_CAP);
4487 		wlan_vdev_obj_unlock(session->vdev);
4488 	} else {
4489 		wlan_vdev_obj_lock(session->vdev);
4490 		wlan_vdev_mlme_cap_clear(session->vdev, WLAN_VDEV_C_EMLSR_CAP);
4491 		wlan_vdev_obj_unlock(session->vdev);
4492 	}
4493 }
4494 #else
4495 static void lim_fill_ml_info(struct cm_vdev_join_req *req,
4496 			     struct join_req *pe_join_req)
4497 {
4498 }
4499 
4500 static void
4501 lim_copy_ml_partner_info_to_session(struct pe_session *session,
4502 				    struct cm_vdev_join_req *req)
4503 {}
4504 #endif
4505 
4506 static QDF_STATUS
4507 lim_fill_session_params(struct mac_context *mac_ctx,
4508 			struct pe_session *session,
4509 			struct cm_vdev_join_req *req)
4510 {
4511 	QDF_STATUS status;
4512 	struct bss_description *bss_desc;
4513 	uint32_t ie_len;
4514 	uint32_t bss_len;
4515 	struct join_req *pe_join_req;
4516 	int32_t akm;
4517 	struct mlme_legacy_priv *mlme_priv;
4518 	uint32_t assoc_ie_len;
4519 	bool eht_capab;
4520 
4521 	ie_len = util_scan_entry_ie_len(req->entry);
4522 	bss_len = (uint16_t)(offsetof(struct bss_description,
4523 			   ieFields[0]) + ie_len);
4524 
4525 	session->lim_join_req = qdf_mem_malloc(sizeof(*session->lim_join_req) +
4526 					       bss_len);
4527 	if (!session->lim_join_req)
4528 		return QDF_STATUS_E_NOMEM;
4529 
4530 	pe_join_req = session->lim_join_req;
4531 	bss_desc = &session->lim_join_req->bssDescription;
4532 	pe_debug("Beacon/probe frame received:");
4533 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
4534 			   util_scan_entry_frame_ptr(req->entry),
4535 			   util_scan_entry_frame_len(req->entry));
4536 
4537 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
4538 						    req->entry);
4539 	if (QDF_IS_STATUS_ERROR(status)) {
4540 		qdf_mem_free(session->lim_join_req);
4541 		session->lim_join_req = NULL;
4542 		return QDF_STATUS_E_FAILURE;
4543 	}
4544 
4545 	akm = wlan_crypto_get_param(session->vdev,
4546 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
4547 	if (!req->entry->ssid.length &&
4548 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE) &&
4549 	    req->owe_trans_ssid.length) {
4550 		req->entry->ssid = req->owe_trans_ssid;
4551 		pe_debug("OWE transition ssid is " QDF_SSID_FMT,
4552 			 QDF_SSID_REF(req->entry->ssid.length,
4553 				      req->entry->ssid.ssid));
4554 	}
4555 
4556 	/* Copy the SSID from req to session entry  */
4557 	session->ssId.length = req->entry->ssid.length;
4558 	qdf_mem_copy(session->ssId.ssId, req->entry->ssid.ssid,
4559 		     session->ssId.length);
4560 	session->ssidHidden = req->is_ssid_hidden;
4561 
4562 	status = lim_fill_pe_session(mac_ctx, session, bss_desc);
4563 	if (QDF_IS_STATUS_ERROR(status)) {
4564 		pe_err("Failed to fill pe session vdev id %d",
4565 		       session->vdev_id);
4566 		qdf_mem_free(session->lim_join_req);
4567 		session->lim_join_req = NULL;
4568 		return QDF_STATUS_E_FAILURE;
4569 	}
4570 
4571 	lim_copy_ml_partner_info_to_session(session, req);
4572 
4573 	pe_debug("Assoc IE len: %d", req->assoc_ie.len);
4574 	if (req->assoc_ie.len)
4575 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
4576 				   req->assoc_ie.ptr, req->assoc_ie.len);
4577 
4578 	assoc_ie_len = req->assoc_ie.len;
4579 	status = lim_fill_crypto_params(mac_ctx, session, req);
4580 	if (QDF_IS_STATUS_ERROR(status)) {
4581 		pe_err("Error in handling RSNXE");
4582 		qdf_mem_free(session->lim_join_req);
4583 		session->lim_join_req = NULL;
4584 		return QDF_STATUS_E_FAILURE;
4585 	}
4586 
4587 	/* Reset the SPMK global cache for non-SAE connection */
4588 	if (session->connected_akm != ANI_AKM_TYPE_SAE) {
4589 		wlan_mlme_set_sae_single_pmk_bss_cap(mac_ctx->psoc,
4590 						     session->vdev_id,
4591 						     false);
4592 		wlan_mlme_clear_sae_single_pmk_info(session->vdev,
4593 						    NULL);
4594 	}
4595 
4596 	if (assoc_ie_len != req->assoc_ie.len) {
4597 		pe_debug("After stripping Assoc IE len: %d", req->assoc_ie.len);
4598 		if (req->assoc_ie.len)
4599 			QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
4600 					   QDF_TRACE_LEVEL_DEBUG,
4601 					   req->assoc_ie.ptr,
4602 					   req->assoc_ie.len);
4603 	}
4604 
4605 	qdf_mem_copy(pe_join_req->addIEAssoc.addIEdata,
4606 		     req->assoc_ie.ptr, req->assoc_ie.len);
4607 	/* update assoc ie to cm */
4608 	cm_update_session_assoc_ie(mac_ctx->psoc, session->vdev_id,
4609 				   &req->assoc_ie);
4610 	pe_join_req->addIEAssoc.length = req->assoc_ie.len;
4611 	qdf_mem_copy(pe_join_req->addIEScan.addIEdata,
4612 		     req->scan_ie.ptr, req->scan_ie.len);
4613 	pe_join_req->addIEScan.length = req->scan_ie.len;
4614 
4615 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
4616 	if (!mlme_priv) {
4617 		pe_err("Invalid mlme priv object");
4618 		qdf_mem_free(session->lim_join_req);
4619 		session->lim_join_req = NULL;
4620 		return QDF_STATUS_E_FAILURE;
4621 	}
4622 	qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie,
4623 		     DOT11F_IE_EXTCAP_MAX_LEN + 2);
4624 
4625 	if (session->lim_join_req->addIEAssoc.length) {
4626 		uint8_t *add_ie = NULL;
4627 		uint16_t add_ie_len;
4628 
4629 		add_ie_len = session->lim_join_req->addIEAssoc.length;
4630 		add_ie = qdf_mem_malloc(add_ie_len);
4631 		if (!add_ie) {
4632 			qdf_mem_free(session->lim_join_req);
4633 			session->lim_join_req = NULL;
4634 			return QDF_STATUS_E_FAILURE;
4635 		}
4636 		qdf_mem_copy(add_ie,
4637 			     session->lim_join_req->addIEAssoc.addIEdata,
4638 			     add_ie_len);
4639 
4640 		status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
4641 				      DOT11F_EID_EXTCAP, ONE_BYTE,
4642 				      NULL, 0,
4643 				      mlme_priv->connect_info.ext_cap_ie,
4644 				      DOT11F_IE_EXTCAP_MAX_LEN);
4645 		qdf_mem_free(add_ie);
4646 
4647 		if (QDF_IS_STATUS_ERROR(status)) {
4648 			pe_err("Parsing of ext cap failed with status : %d",
4649 			       status);
4650 			qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie,
4651 				     DOT11F_IE_EXTCAP_MAX_LEN + 2);
4652 			qdf_mem_free(session->lim_join_req);
4653 			session->lim_join_req = NULL;
4654 			return QDF_STATUS_E_FAILURE;
4655 		}
4656 	}
4657 
4658 	if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
4659 		if (!lim_is_session_he_capable(session)) {
4660 			pe_err("JOIN_REQ with invalid 6G security");
4661 			qdf_mem_free(session->lim_join_req);
4662 			session->lim_join_req = NULL;
4663 			return QDF_STATUS_E_FAILURE;
4664 		}
4665 	}
4666 
4667 	wlan_psoc_mlme_get_11be_capab(mac_ctx->psoc, &eht_capab);
4668 	if (eht_capab && wlan_vdev_mlme_is_mlo_vdev(session->vdev))
4669 		lim_fill_ml_info(req, pe_join_req);
4670 
4671 	lim_set_emlsr_caps(mac_ctx, session);
4672 
4673 	return QDF_STATUS_SUCCESS;
4674 }
4675 
4676 static QDF_STATUS
4677 lim_cm_handle_join_req(struct cm_vdev_join_req *req)
4678 {
4679 	struct mac_context *mac_ctx;
4680 	struct pe_session *pe_session;
4681 	QDF_STATUS status;
4682 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4683 
4684 	if (!wma)
4685 		return QDF_STATUS_E_INVAL;
4686 
4687 	if (!req)
4688 		return QDF_STATUS_E_INVAL;
4689 
4690 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
4691 
4692 	if (!mac_ctx)
4693 		return QDF_STATUS_E_INVAL;
4694 
4695 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0);
4696 
4697 	pe_session = lim_cm_create_session(mac_ctx, req);
4698 	if (!pe_session)
4699 		goto fail;
4700 
4701 	pe_session->cm_id = req->cm_id;
4702 	status = lim_fill_session_params(mac_ctx, pe_session, req);
4703 
4704 	if (QDF_IS_STATUS_ERROR(status))
4705 		goto fail;
4706 
4707 	lim_dump_session_info(mac_ctx, pe_session);
4708 	lim_dump_he_info(mac_ctx, pe_session);
4709 	lim_dump_eht_info(pe_session);
4710 
4711 	if (lim_connect_skip_join_for_gc(pe_session)) {
4712 		pe_session->beacon =
4713 			qdf_mem_malloc(util_scan_entry_frame_len(req->entry));
4714 		if (!pe_session->beacon)
4715 			goto fail;
4716 		pe_session->bcnLen = util_scan_entry_frame_len(req->entry);
4717 		qdf_mem_copy(pe_session->beacon,
4718 			     util_scan_entry_frame_ptr(req->entry),
4719 			     pe_session->bcnLen);
4720 	}
4721 
4722 	status = lim_send_connect_req_to_mlm(pe_session);
4723 	if (QDF_IS_STATUS_ERROR(status)) {
4724 		pe_err("Failed to send mlm req vdev id %d",
4725 		       pe_session->vdev_id);
4726 		goto fail;
4727 	}
4728 
4729 	if (!wlan_vdev_mlme_is_mlo_link_vdev(pe_session->vdev))
4730 		lim_send_mlo_caps_ie(mac_ctx, pe_session->vdev,
4731 				     QDF_STA_MODE,
4732 				     pe_session->vdev_id);
4733 
4734 	return QDF_STATUS_SUCCESS;
4735 
4736 fail:
4737 	if (pe_session)
4738 		pe_delete_session(mac_ctx, pe_session);
4739 	status = wma_remove_bss_peer_before_join(wma, req->vdev_id, req);
4740 	if (status == QDF_STATUS_E_PENDING)
4741 		return status;
4742 	lim_cm_send_connect_rsp(mac_ctx, NULL, req, CM_GENERIC_FAILURE,
4743 					QDF_STATUS_E_FAILURE, 0, false);
4744 
4745 	return status;
4746 }
4747 
4748 QDF_STATUS cm_process_join_req(struct scheduler_msg *msg)
4749 {
4750 	struct cm_vdev_join_req *req;
4751 	QDF_STATUS status;
4752 
4753 	if (!msg || !msg->bodyptr) {
4754 		pe_err("msg or msg->bodyptr is NULL");
4755 		return QDF_STATUS_E_INVAL;
4756 	}
4757 
4758 	req = msg->bodyptr;
4759 
4760 	status = lim_cm_handle_join_req(req);
4761 	if (status != QDF_STATUS_E_PENDING)
4762 		cm_free_join_req(req);
4763 
4764 	return status;
4765 }
4766 
4767 static void lim_process_disconnect_sta(struct pe_session *session,
4768 				       struct scheduler_msg *msg)
4769 {
4770 	if (QDF_IS_STATUS_SUCCESS(
4771 	    wlan_vdev_is_restart_progress(session->vdev)))
4772 		wlan_vdev_mlme_sm_deliver_evt(session->vdev,
4773 					      WLAN_VDEV_SM_EV_RESTART_REQ_FAIL,
4774 					      sizeof(*msg), msg);
4775 	else
4776 		wlan_vdev_mlme_sm_deliver_evt(session->vdev,
4777 					      WLAN_VDEV_SM_EV_DOWN,
4778 					      sizeof(*msg), msg);
4779 }
4780 
4781 static void lim_prepare_and_send_deauth(struct mac_context *mac_ctx,
4782 					struct pe_session *pe_session,
4783 					struct wlan_cm_vdev_discon_req *req)
4784 {
4785 	struct scheduler_msg msg = {0};
4786 	struct deauth_req deauth_req = {0};
4787 
4788 	deauth_req.messageType = eWNI_SME_DEAUTH_REQ;
4789 	deauth_req.length = sizeof(deauth_req);
4790 	deauth_req.vdev_id = req->req.vdev_id;
4791 	qdf_mem_copy(deauth_req.bssid.bytes, pe_session->bssId,
4792 		     QDF_MAC_ADDR_SIZE);
4793 	deauth_req.bssid = deauth_req.bssid;
4794 	deauth_req.peer_macaddr = req->req.bssid;
4795 	deauth_req.reasonCode = req->req.reason_code;
4796 
4797 	msg.bodyptr = &deauth_req;
4798 	msg.type = eWNI_SME_DEAUTH_REQ;
4799 	lim_process_disconnect_sta(pe_session, &msg);
4800 }
4801 
4802 static void lim_prepare_and_send_disassoc(struct mac_context *mac_ctx,
4803 					  struct pe_session *pe_session,
4804 					  struct wlan_cm_vdev_discon_req *req)
4805 {
4806 	struct scheduler_msg msg = {0};
4807 	struct disassoc_req disassoc_req = {0};
4808 
4809 	disassoc_req.messageType = eWNI_SME_DISASSOC_REQ;
4810 	disassoc_req.length = sizeof(disassoc_req);
4811 	disassoc_req.sessionId = req->req.vdev_id;
4812 	qdf_mem_copy(disassoc_req.bssid.bytes, pe_session->bssId,
4813 		     QDF_MAC_ADDR_SIZE);
4814 	disassoc_req.peer_macaddr = disassoc_req.bssid;
4815 	disassoc_req.reasonCode = req->req.reason_code;
4816 	if (req->req.reason_code == REASON_FW_TRIGGERED_ROAM_FAILURE) {
4817 		disassoc_req.process_ho_fail = true;
4818 		disassoc_req.doNotSendOverTheAir = 1;
4819 	} else if (wlan_cm_is_vdev_roam_reassoc_state(pe_session->vdev)) {
4820 		disassoc_req.doNotSendOverTheAir = 1;
4821 		disassoc_req.reasonCode =
4822 					REASON_AUTHORIZED_ACCESS_LIMIT_REACHED;
4823 	} else if (req->req.reason_code == CM_MLO_LINK_SWITCH_DISCONNECT) {
4824 		disassoc_req.doNotSendOverTheAir = 1;
4825 	}
4826 
4827 	msg.bodyptr = &disassoc_req;
4828 	msg.type = eWNI_SME_DISASSOC_REQ;
4829 	lim_process_disconnect_sta(pe_session, &msg);
4830 }
4831 
4832 static void lim_process_nb_disconnect_req(struct mac_context *mac_ctx,
4833 					  struct pe_session *pe_session,
4834 					  struct wlan_cm_vdev_discon_req *req)
4835 {
4836 	enum wlan_reason_code reason_code;
4837 	bool enable_deauth_to_disassoc_map = false;
4838 
4839 	reason_code = req->req.reason_code;
4840 
4841 	switch (reason_code) {
4842 	case REASON_IFACE_DOWN:
4843 	case REASON_DEVICE_RECOVERY:
4844 	case REASON_OPER_CHANNEL_BAND_CHANGE:
4845 	case REASON_USER_TRIGGERED_ROAM_FAILURE:
4846 	case REASON_CHANNEL_SWITCH_FAILED:
4847 	case REASON_GATEWAY_REACHABILITY_FAILURE:
4848 	case REASON_OPER_CHANNEL_DISABLED_INDOOR:
4849 		/* Set reason REASON_DEAUTH_NETWORK_LEAVING for prop deauth */
4850 		req->req.reason_code = REASON_DEAUTH_NETWORK_LEAVING;
4851 		fallthrough;
4852 	case REASON_PREV_AUTH_NOT_VALID:
4853 	case REASON_CLASS2_FRAME_FROM_NON_AUTH_STA:
4854 		lim_prepare_and_send_deauth(mac_ctx, pe_session, req);
4855 		break;
4856 	case REASON_DEAUTH_NETWORK_LEAVING:
4857 		wlan_mlme_get_enable_deauth_to_disassoc_map(
4858 					mac_ctx->psoc,
4859 					&enable_deauth_to_disassoc_map);
4860 		if (enable_deauth_to_disassoc_map) {
4861 			req->req.reason_code = REASON_DISASSOC_NETWORK_LEAVING;
4862 			return lim_prepare_and_send_disassoc(mac_ctx,
4863 							     pe_session, req);
4864 		}
4865 		lim_prepare_and_send_deauth(mac_ctx, pe_session, req);
4866 		break;
4867 	default:
4868 		/* Set reason REASON_UNSPEC_FAILURE for prop disassoc */
4869 		if (reason_code >= REASON_PROP_START &&
4870 		    reason_code != REASON_FW_TRIGGERED_ROAM_FAILURE)
4871 			req->req.reason_code = REASON_UNSPEC_FAILURE;
4872 		lim_prepare_and_send_disassoc(mac_ctx, pe_session, req);
4873 	}
4874 }
4875 
4876 static void lim_process_sb_disconnect_req(struct mac_context *mac_ctx,
4877 					  struct pe_session *pe_session,
4878 					  struct wlan_cm_vdev_discon_req *req)
4879 {
4880 	struct scheduler_msg msg = {0};
4881 	struct disassoc_cnf disassoc_cnf = {0};
4882 
4883 	/* For SB disconnect smeState should be in Deauth state
4884 	 * One scenario where the smeState is not updated is when
4885 	 * AP sends deauth on link vdev and disconnect req is triggered
4886 	 */
4887 	if (pe_session->limSmeState == eLIM_SME_LINK_EST_STATE)
4888 		pe_session->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
4889 
4890 	if (pe_session->limSmeState == eLIM_SME_WT_DEAUTH_STATE)
4891 		disassoc_cnf.messageType = eWNI_SME_DEAUTH_CNF;
4892 	else
4893 		disassoc_cnf.messageType = eWNI_SME_DISASSOC_CNF;
4894 	disassoc_cnf.vdev_id = req->req.vdev_id;
4895 	qdf_mem_copy(disassoc_cnf.bssid.bytes, pe_session->bssId,
4896 		     QDF_MAC_ADDR_SIZE);
4897 	disassoc_cnf.length = sizeof(disassoc_cnf);
4898 	disassoc_cnf.peer_macaddr = disassoc_cnf.bssid;
4899 
4900 	msg.bodyptr = &disassoc_cnf;
4901 	msg.type = disassoc_cnf.messageType;
4902 	lim_process_disconnect_sta(pe_session, &msg);
4903 }
4904 
4905 static
4906 struct pe_session *lim_get_disconnect_session(struct mac_context *mac_ctx,
4907 					struct wlan_cm_vdev_discon_req *req)
4908 {
4909 	struct pe_session *session;
4910 	uint8_t pe_session_id;
4911 
4912 	/* Try to find pe session with bssid */
4913 	session = pe_find_session_by_bssid_and_vdev_id(mac_ctx,
4914 						       req->req.bssid.bytes,
4915 						       req->req.vdev_id,
4916 						       &pe_session_id);
4917 	/*
4918 	 * If bssid search fail try to find by vdev id, this can happen if
4919 	 * Roaming change the BSSID during disconnect was getting processed.
4920 	 */
4921 	if (!session) {
4922 		session = pe_find_session_by_vdev_id(mac_ctx, req->req.vdev_id);
4923 		if (session)
4924 			pe_info("vdev_id %d cm_id 0x%x: using vdev id, session (%d) found for bssid " QDF_MAC_ADDR_FMT " [bssid in req " QDF_MAC_ADDR_FMT "] sme state %d mlm state %d",
4925 				req->req.vdev_id, req->cm_id, session->peSessionId,
4926 				QDF_MAC_ADDR_REF(session->bssId),
4927 				QDF_MAC_ADDR_REF(req->req.bssid.bytes),
4928 				session->limSmeState, session->limMlmState);
4929 	}
4930 
4931 	/*
4932 	 * In LFR2.0 roaming scenario, if HO disconnect is completed but
4933 	 * NB disconnect is received before reassoc can start OR reassoc failure
4934 	 * lead to disconnect, new AP's session will be idle in wait reassoc
4935 	 * state and vdev in INIT state, so cleanup the session and send
4936 	 * response of disconnect complete.
4937 	 */
4938 	if (session &&
4939 	    QDF_IS_STATUS_SUCCESS(wlan_vdev_mlme_is_init_state(session->vdev))) {
4940 		pe_err("vdev_id %d cm_id 0x%x: sme state %d mlm state %d: vdev is in INIT state. Delete session",
4941 		       req->req.vdev_id, req->cm_id, session->limSmeState,
4942 		       session->limMlmState);
4943 		pe_delete_session(mac_ctx, session);
4944 		session = NULL;
4945 	}
4946 
4947 	return session;
4948 }
4949 static QDF_STATUS
4950 lim_cm_handle_disconnect_req(struct wlan_cm_vdev_discon_req *req)
4951 {
4952 	struct mac_context *mac_ctx;
4953 	struct pe_session *pe_session;
4954 
4955 	if (!req)
4956 		return QDF_STATUS_E_INVAL;
4957 
4958 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
4959 	if (!mac_ctx)
4960 		return QDF_STATUS_E_INVAL;
4961 
4962 	pe_session = lim_get_disconnect_session(mac_ctx, req);
4963 	if (!pe_session) {
4964 		pe_err("vdev_id %d cm_id 0x%x: bssid " QDF_MAC_ADDR_FMT " : no session found",
4965 		       req->req.vdev_id, req->cm_id,
4966 		       QDF_MAC_ADDR_REF(req->req.bssid.bytes));
4967 		lim_cm_send_disconnect_rsp(mac_ctx, req->req.vdev_id);
4968 		return QDF_STATUS_E_INVAL;
4969 	}
4970 
4971 	if (req->req.source == CM_PEER_DISCONNECT ||
4972 	    req->req.source == CM_SB_DISCONNECT ||
4973 	    req->req.source == CM_MLO_LINK_SWITCH_DISCONNECT)
4974 		lim_process_sb_disconnect_req(mac_ctx, pe_session, req);
4975 	else
4976 		lim_process_nb_disconnect_req(mac_ctx, pe_session, req);
4977 
4978 	return QDF_STATUS_SUCCESS;
4979 }
4980 
4981 QDF_STATUS cm_process_disconnect_req(struct scheduler_msg *msg)
4982 {
4983 	struct wlan_cm_vdev_discon_req *req;
4984 	QDF_STATUS status;
4985 
4986 	if (!msg || !msg->bodyptr) {
4987 		mlme_err("msg or msg->bodyptr is NULL");
4988 		return QDF_STATUS_E_INVAL;
4989 	}
4990 
4991 	req = msg->bodyptr;
4992 
4993 	status = lim_cm_handle_disconnect_req(req);
4994 
4995 	qdf_mem_free(req);
4996 	return status;
4997 }
4998 
4999 #ifdef WLAN_FEATURE_11BE_MLO
5000 /**
5001  * wma_get_mld_info_sta() - get peer_mld_addr and assoc peer flag for sta
5002  * @req: cm_peer_create_req
5003  * @peer_mld_addr: peer mld mac addr
5004  * @is_assoc_peer: is assoc peer
5005  *
5006  * Return: void
5007  */
5008 static void wma_get_mld_info_sta(struct cm_peer_create_req *req,
5009 				 uint8_t **peer_mld_addr,
5010 				 bool *is_assoc_peer)
5011 {
5012 	if (!qdf_is_macaddr_zero(&req->mld_mac)) {
5013 		*peer_mld_addr = req->mld_mac.bytes;
5014 		*is_assoc_peer = req->is_assoc_peer;
5015 	} else {
5016 		*peer_mld_addr = NULL;
5017 		*is_assoc_peer = false;
5018 	}
5019 }
5020 #else
5021 static void wma_get_mld_info_sta(struct cm_peer_create_req *req,
5022 				 uint8_t **peer_mld_addr,
5023 				 bool *is_assoc_peer)
5024 {
5025 	*peer_mld_addr = NULL;
5026 	*is_assoc_peer = false;
5027 }
5028 #endif
5029 
5030 QDF_STATUS cm_process_peer_create(struct scheduler_msg *msg)
5031 {
5032 	struct cm_peer_create_req *req;
5033 	QDF_STATUS status;
5034 	uint8_t *peer_mld_addr = NULL;
5035 	bool is_assoc_peer = false;
5036 
5037 	if (!msg || !msg->bodyptr) {
5038 		mlme_err("msg or msg->bodyptr is NULL");
5039 		return QDF_STATUS_E_INVAL;
5040 	}
5041 
5042 	req = msg->bodyptr;
5043 
5044 	wma_get_mld_info_sta(req, &peer_mld_addr, &is_assoc_peer);
5045 	status = wma_add_bss_peer_sta(req->vdev_id, req->peer_mac.bytes, true,
5046 				      peer_mld_addr, is_assoc_peer);
5047 
5048 	qdf_mem_free(req);
5049 
5050 	return status;
5051 }
5052 
5053 #ifdef WLAN_FEATURE_HOST_ROAM
5054 static void lim_handle_reassoc_req(struct cm_vdev_join_req *req)
5055 {
5056 	struct mac_context *mac_ctx;
5057 	struct pe_session *session_entry;
5058 	uint8_t session_id;
5059 	uint8_t vdev_id;
5060 	uint32_t ie_len;
5061 	uint32_t bss_len;
5062 	struct join_req *reassoc_req = NULL;
5063 	uint16_t caps;
5064 	uint32_t val;
5065 	tLimMlmReassocReq *mlm_reassoc_req;
5066 	tSirResultCodes ret_code = eSIR_SME_SUCCESS;
5067 	int8_t local_pwr_constraint = 0, reg_max = 0;
5068 	uint32_t tele_bcn_en = 0;
5069 	QDF_STATUS status;
5070 	tDot11fBeaconIEs *ie_struct;
5071 	ePhyChanBondState cb_mode;
5072 	tSirMacCapabilityInfo *ap_cap_info;
5073 	struct bss_description *bss_desc;
5074 	uint8_t wmm_mode, value;
5075 	bool is_pwr_constraint;
5076 	int32_t ucast_cipher;
5077 	int32_t auth_mode;
5078 	int32_t akm;
5079 
5080 	if (!req)
5081 		return;
5082 
5083 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
5084 	if (!mac_ctx)
5085 		return;
5086 
5087 	vdev_id = req->vdev_id;
5088 	session_entry = pe_find_session_by_bssid(mac_ctx,
5089 						 req->entry->bssid.bytes,
5090 						 &session_id);
5091 	if (!session_entry) {
5092 		pe_err("Session does not exist for: "QDF_MAC_ADDR_FMT,
5093 			QDF_MAC_ADDR_REF(req->entry->bssid.bytes));
5094 		ret_code = eSIR_SME_INVALID_PARAMETERS;
5095 		session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
5096 		if (session_entry)
5097 			lim_handle_sme_join_result(mac_ctx,
5098 					eSIR_SME_INVALID_PARAMETERS,
5099 					STATUS_UNSPECIFIED_FAILURE,
5100 					session_entry);
5101 		goto end;
5102 	}
5103 
5104 	if  (session_entry->lim_join_req) {
5105 		qdf_mem_free(session_entry->lim_join_req);
5106 		session_entry->lim_join_req = NULL;
5107 	}
5108 
5109 	session_entry->cm_id = req->cm_id;
5110 	ie_len = util_scan_entry_ie_len(req->entry);
5111 	bss_len = (uint16_t)(offsetof(struct bss_description,
5112 			     ieFields[0]) + ie_len);
5113 
5114 	reassoc_req = qdf_mem_malloc(sizeof(*session_entry->lim_join_req) +
5115 				     bss_len);
5116 	if (!reassoc_req) {
5117 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5118 		goto end;
5119 	}
5120 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_REQ_EVENT,
5121 			      session_entry, QDF_STATUS_SUCCESS,
5122 			      QDF_STATUS_SUCCESS);
5123 
5124 	pe_debug("Beacon/probe frame received:");
5125 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
5126 			   util_scan_entry_frame_ptr(req->entry),
5127 			   util_scan_entry_frame_len(req->entry));
5128 
5129 	bss_desc = &reassoc_req->bssDescription;
5130 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
5131 						    req->entry);
5132 	if (QDF_IS_STATUS_ERROR(status)) {
5133 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5134 		goto end;
5135 	}
5136 	/* Store the reassoc handle in the session Table */
5137 	session_entry->lim_join_req = reassoc_req;
5138 	session_entry->pLimReAssocReq = reassoc_req;
5139 
5140 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5141 						     &ie_struct);
5142 	if (QDF_IS_STATUS_ERROR(status)) {
5143 		pe_err("IE parsing failed vdev id %d",
5144 		       session_entry->vdev_id);
5145 		session_entry->lim_join_req = NULL;
5146 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5147 		goto end;
5148 	}
5149 	pe_debug("Assoc IE len: %d", req->assoc_ie.len);
5150 	if (req->assoc_ie.len)
5151 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
5152 				   req->assoc_ie.ptr, req->assoc_ie.len);
5153 	if (lim_is_rsn_profile(session_entry))
5154 		lim_fill_rsn_ie(mac_ctx, session_entry, req);
5155 	else if (lim_is_wpa_profile(session_entry))
5156 		lim_fill_wpa_ie(mac_ctx, session_entry, req);
5157 	else if (lim_is_wapi_profile(session_entry))
5158 		lim_fill_wapi_ie(mac_ctx, session_entry, req);
5159 
5160 	lim_strip_rsnx_ie(mac_ctx, session_entry, req);
5161 
5162 	if (lim_is_rsn_profile(session_entry) &&
5163 	    !util_scan_entry_rsnxe(req->entry)) {
5164 		pe_debug("Bss bcn has no RSNXE, strip if has");
5165 		status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
5166 				      (uint16_t *)&req->assoc_ie.len,
5167 				      WLAN_ELEMID_RSNXE, ONE_BYTE,
5168 				      NULL, 0, NULL, 0);
5169 		if (QDF_IS_STATUS_ERROR(status))
5170 			pe_err("Strip RNSXE failed");
5171 	}
5172 
5173 	pe_debug("After stripping Assoc IE len: %d", req->assoc_ie.len);
5174 	if (req->assoc_ie.len)
5175 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
5176 				   req->assoc_ie.ptr, req->assoc_ie.len);
5177 	qdf_mem_copy(reassoc_req->addIEAssoc.addIEdata,
5178 		     req->assoc_ie.ptr, req->assoc_ie.len);
5179 	reassoc_req->addIEAssoc.length = req->assoc_ie.len;
5180 	/* update assoc ie to cm */
5181 	cm_update_session_assoc_ie(mac_ctx->psoc, vdev_id, &req->assoc_ie);
5182 	ucast_cipher = wlan_crypto_get_param(session_entry->vdev,
5183 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
5184 	auth_mode = wlan_crypto_get_param(session_entry->vdev,
5185 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
5186 	akm = wlan_crypto_get_param(session_entry->vdev,
5187 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
5188 	ap_cap_info = (tSirMacCapabilityInfo *)&req->entry->cap_info.value;
5189 
5190 	lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm,
5191 			ap_cap_info->privacy);
5192 
5193 	if (session_entry->vhtCapability) {
5194 		if (session_entry->opmode == QDF_STA_MODE) {
5195 			session_entry->vht_config.su_beam_formee =
5196 			    mac_ctx->mlme_cfg->vht_caps.vht_cap_info.su_bformee;
5197 		} else {
5198 			session_entry->vht_config.su_beam_formee = 0;
5199 		}
5200 		session_entry->enableVhtpAid =
5201 			mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_paid;
5202 		session_entry->enableVhtGid =
5203 			mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_gid;
5204 	}
5205 
5206 	if (session_entry->nss == 1)
5207 		session_entry->supported_nss_1x1 = true;
5208 
5209 	lim_check_oui_and_update_session(mac_ctx, session_entry, ie_struct);
5210 
5211 	session_entry->lim_reassoc_chan_freq = req->entry->channel.chan_freq;
5212 	cb_mode = wlan_get_cb_mode(mac_ctx,
5213 				  session_entry->lim_reassoc_chan_freq,
5214 				  ie_struct,
5215 				  session_entry);
5216 	session_entry->reAssocHtSupportedChannelWidthSet = cb_mode ? 1 : 0;
5217 	session_entry->reAssocHtRecommendedTxWidthSet =
5218 		session_entry->reAssocHtSupportedChannelWidthSet;
5219 	session_entry->reAssocHtSecondaryChannelOffset = cb_mode;
5220 
5221 	mac_ctx->mlme_cfg->power.local_power_constraint =
5222 		wlan_get_11h_power_constraint(mac_ctx,
5223 					      &ie_struct->PowerConstraints);
5224 	if (session_entry->dot11mode == MLME_DOT11_MODE_11B)
5225 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 0;
5226 	else
5227 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g =
5228 			mac_ctx->mlme_cfg->ht_caps.short_slot_time_enabled;
5229 	session_entry->enable_session_twt_support =
5230 					lim_enable_twt(mac_ctx, ie_struct);
5231 
5232 	qdf_mem_free(ie_struct);
5233 
5234 	session_entry->send_smps_action =
5235 		mac_ctx->roam.configParam.send_smps_action;
5236 	session_entry->lim_join_req = NULL;
5237 
5238 	/* Reassociate request is expected in link established state only. */
5239 	if (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE) {
5240 		if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) {
5241 			/*
5242 			 * May be from 11r FT pre-auth. So lets check it
5243 			 * before we bail out
5244 			 */
5245 			pe_debug("Session in reassoc state is %d",
5246 				 session_entry->peSessionId);
5247 
5248 			/* Make sure its our preauth bssid */
5249 			if (qdf_mem_cmp(req->entry->bssid.bytes,
5250 					session_entry->limReAssocbssId,
5251 					QDF_MAC_ADDR_SIZE)) {
5252 				pe_err("Requested BSSID: "QDF_MAC_ADDR_FMT " but bssId in reassoc state" QDF_MAC_ADDR_FMT,
5253 				       QDF_MAC_ADDR_REF(req->entry->bssid.bytes),
5254 				       QDF_MAC_ADDR_REF(session_entry->limReAssocbssId));
5255 				ret_code = eSIR_SME_INVALID_PARAMETERS;
5256 				goto end;
5257 			}
5258 
5259 			session_entry->vdev_id = vdev_id;
5260 			mlm_reassoc_req =
5261 				qdf_mem_malloc(sizeof(*mlm_reassoc_req));
5262 			if (!mlm_reassoc_req) {
5263 				ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5264 				goto end;
5265 			}
5266 
5267 			lim_dump_session_info(mac_ctx, session_entry);
5268 			lim_dump_he_info(mac_ctx, session_entry);
5269 			lim_dump_eht_info(session_entry);
5270 
5271 			/* Update PE sessionId */
5272 			mlm_reassoc_req->sessionId = session_entry->peSessionId;
5273 			status = lim_send_ft_reassoc_req(session_entry,
5274 							 mlm_reassoc_req);
5275 			if (QDF_IS_STATUS_ERROR(status)) {
5276 				qdf_mem_free(mlm_reassoc_req);
5277 				ret_code = eSIR_SME_REFUSED;
5278 				goto end;
5279 			}
5280 			return;
5281 		}
5282 		/*
5283 		 * Should not have received eWNI_SME_REASSOC_REQ
5284 		 */
5285 		pe_err("received unexpected SME_REASSOC_REQ in state %X",
5286 			session_entry->limSmeState);
5287 		lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState);
5288 
5289 		ret_code = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
5290 		goto end;
5291 	}
5292 
5293 	qdf_mem_copy(session_entry->limReAssocbssId, req->entry->bssid.bytes,
5294 		     sizeof(tSirMacAddr));
5295 
5296 	session_entry->limReassocBssCaps = req->entry->cap_info.value;
5297 	reg_max = wlan_reg_get_channel_reg_power_for_freq(
5298 		mac_ctx->pdev, session_entry->curr_op_freq);
5299 	local_pwr_constraint = reg_max;
5300 
5301 	lim_extract_ap_capability(mac_ctx, (uint8_t *)bss_desc->ieFields,
5302 				  lim_get_ielen_from_bss_description(bss_desc),
5303 				  &session_entry->limReassocBssQosCaps,
5304 				  &session_entry->gLimCurrentBssUapsd,
5305 				  &local_pwr_constraint, session_entry,
5306 				  &is_pwr_constraint);
5307 	if (is_pwr_constraint)
5308 		local_pwr_constraint = reg_max - local_pwr_constraint;
5309 
5310 	session_entry->maxTxPower = QDF_MIN(reg_max, (local_pwr_constraint));
5311 	session_entry->max_11h_pwr =
5312 		QDF_MIN(lim_get_cfg_max_tx_power(mac_ctx,
5313 						 bss_desc->chan_freq),
5314 			MAX_TX_PWR_CAP);
5315 	session_entry->min_11h_pwr = MIN_TX_PWR_CAP;
5316 	if (!session_entry->max_11h_pwr)
5317 		session_entry->max_11h_pwr = MAX_TX_PWR_CAP;
5318 
5319 	if (session_entry->max_11h_pwr > session_entry->maxTxPower)
5320 		session_entry->max_11h_pwr = session_entry->maxTxPower;
5321 
5322 	pe_info("Reg max = %d, local pwr constraint = %d, max tx = %d",
5323 		reg_max, local_pwr_constraint, session_entry->maxTxPower);
5324 	/* Copy the SSID from session entry to local variable */
5325 	session_entry->limReassocSSID.length = req->entry->ssid.length;
5326 	qdf_mem_copy(session_entry->limReassocSSID.ssId,
5327 		     req->entry->ssid.ssid,
5328 		     session_entry->limReassocSSID.length);
5329 
5330 	if (!session_entry->enable_session_twt_support) {
5331 		status = wlan_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode);
5332 		if (!QDF_IS_STATUS_SUCCESS(status)) {
5333 			pe_err("Get wmm_mode failed");
5334 			ret_code = eSIR_SME_INVALID_PARAMETERS;
5335 			goto end;
5336 		} else if (wmm_mode == 2) {
5337 			/*QoS not enabled in cfg file */
5338 			session_entry->gUapsdPerAcBitmask = 0;
5339 		} else {
5340 			/*QoS enabled, update uapsd mask from cfg file */
5341 			status = wlan_mlme_get_wmm_uapsd_mask(mac_ctx->psoc,
5342 							      &value);
5343 			if (QDF_IS_STATUS_ERROR(status)) {
5344 				pe_err("Get uapsd_mask failed");
5345 				ret_code = eSIR_SME_INVALID_PARAMETERS;
5346 				goto end;
5347 			} else
5348 				session_entry->gUapsdPerAcBitmask = value;
5349 		}
5350 	}
5351 
5352 	mlm_reassoc_req = qdf_mem_malloc(sizeof(tLimMlmReassocReq));
5353 	if (!mlm_reassoc_req) {
5354 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5355 		goto end;
5356 	}
5357 
5358 	qdf_mem_copy(mlm_reassoc_req->peerMacAddr,
5359 		     session_entry->limReAssocbssId, sizeof(tSirMacAddr));
5360 
5361 	if (lim_get_capability_info(mac_ctx, &caps, session_entry) !=
5362 	    QDF_STATUS_SUCCESS)
5363 		pe_err("could not retrieve Capabilities value");
5364 
5365 	lim_update_caps_info_for_bss(mac_ctx, &caps,
5366 				     req->entry->cap_info.value);
5367 	pe_debug("Capabilities info Reassoc: 0x%X", caps);
5368 
5369 	mlm_reassoc_req->capabilityInfo = caps;
5370 
5371 	/* Update PE session_id */
5372 	mlm_reassoc_req->sessionId = session_id;
5373 
5374 	/*
5375 	 * If telescopic beaconing is enabled, set listen interval to
5376 	 * CFG_TELE_BCN_MAX_LI
5377 	 */
5378 
5379 	tele_bcn_en = mac_ctx->mlme_cfg->sap_cfg.tele_bcn_wakeup_en;
5380 
5381 	if (tele_bcn_en)
5382 		val = mac_ctx->mlme_cfg->sap_cfg.tele_bcn_max_li;
5383 	else
5384 		val = mac_ctx->mlme_cfg->sap_cfg.listen_interval;
5385 
5386 	mlm_reassoc_req->listenInterval = (uint16_t) val;
5387 	if (mac_ctx->mlme_cfg->gen.enabled_11h &&
5388 	    ap_cap_info->spectrumMgt && bss_desc->nwType == eSIR_11A_NW_TYPE)
5389 		session_entry->spectrumMgtEnabled = true;
5390 
5391 	/* Enable the spectrum management if this is a DFS channel */
5392 	if (session_entry->country_info_present &&
5393 	    lim_isconnected_on_dfs_freq(
5394 		mac_ctx, session_entry->curr_op_freq))
5395 		session_entry->spectrumMgtEnabled = true;
5396 
5397 	session_entry->limPrevSmeState = session_entry->limSmeState;
5398 	session_entry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
5399 
5400 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, session_entry->peSessionId,
5401 			 session_entry->limSmeState));
5402 
5403 	lim_dump_session_info(mac_ctx, session_entry);
5404 	lim_dump_he_info(mac_ctx, session_entry);
5405 	lim_dump_eht_info(session_entry);
5406 
5407 	status = lim_send_reassoc_req(session_entry, mlm_reassoc_req);
5408 	if (QDF_IS_STATUS_ERROR(status)) {
5409 		qdf_mem_free(mlm_reassoc_req);
5410 		ret_code = eSIR_SME_REFUSED;
5411 		goto end;
5412 	}
5413 
5414 	return;
5415 end:
5416 	if (reassoc_req) {
5417 		qdf_mem_free(reassoc_req);
5418 		if (session_entry)
5419 			session_entry->pLimReAssocReq = NULL;
5420 	}
5421 
5422 	/*
5423 	 * Send Reassoc failure response to host
5424 	 * (note session_entry may be NULL, but that's OK)
5425 	 */
5426 	lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP,
5427 				      ret_code, STATUS_UNSPECIFIED_FAILURE,
5428 				      session_entry, vdev_id);
5429 }
5430 
5431 QDF_STATUS cm_process_reassoc_req(struct scheduler_msg *msg)
5432 {
5433 	struct cm_vdev_join_req *req;
5434 
5435 	if (!msg || !msg->bodyptr) {
5436 		mlme_err("msg or msg->bodyptr is NULL");
5437 		return QDF_STATUS_E_INVAL;
5438 	}
5439 
5440 	req = msg->bodyptr;
5441 
5442 	lim_handle_reassoc_req(req);
5443 
5444 	cm_free_join_req(req);
5445 
5446 	return QDF_STATUS_SUCCESS;
5447 }
5448 
5449 static QDF_STATUS
5450 lim_fill_preauth_req_dot11_mode(struct mac_context *mac_ctx,
5451 				tpSirFTPreAuthReq req,
5452 				uint8_t vdev_id)
5453 {
5454 	QDF_STATUS status;
5455 	tDot11fBeaconIEs *ie_struct;
5456 	enum mlme_dot11_mode self_dot11_mode;
5457 	enum mlme_dot11_mode bss_dot11_mode;
5458 	enum mlme_dot11_mode intersected_mode;
5459 	struct bss_description *bss_desc = req->pbssDescription;
5460 
5461 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5462 						     &ie_struct);
5463 	if (QDF_IS_STATUS_ERROR(status)) {
5464 		mlme_err("IE parsing failed");
5465 		return QDF_STATUS_E_FAILURE;
5466 	}
5467 
5468 	self_dot11_mode = lim_get_self_dot11_mode(mac_ctx, QDF_STA_MODE,
5469 						  vdev_id);
5470 	/* if user set dot11 mode by cmd, need to do intersect first */
5471 	self_dot11_mode =
5472 		   lim_intersect_user_dot11_mode(mac_ctx, QDF_STA_MODE,
5473 						 vdev_id, self_dot11_mode);
5474 
5475 	bss_dot11_mode = lim_get_bss_dot11_mode(mac_ctx, bss_desc, ie_struct);
5476 
5477 	status = lim_get_intersected_dot11_mode_sta_ap(mac_ctx, self_dot11_mode,
5478 						       bss_dot11_mode,
5479 						       &intersected_mode,
5480 						       ie_struct, bss_desc);
5481 	if (QDF_IS_STATUS_ERROR(status)) {
5482 		qdf_mem_free(ie_struct);
5483 		return status;
5484 	}
5485 
5486 	req->dot11mode = intersected_mode;
5487 	pe_debug("vdev %d self dot11mode %d bss_dot11 mode %d intersected_mode %d",
5488 		 vdev_id, self_dot11_mode, bss_dot11_mode, intersected_mode);
5489 
5490 	qdf_mem_free(ie_struct);
5491 	return status;
5492 }
5493 
5494 static QDF_STATUS lim_cm_handle_preauth_req(struct wlan_preauth_req *req)
5495 {
5496 	struct mac_context *mac_ctx;
5497 	struct wlan_objmgr_vdev *vdev;
5498 	struct scan_cache_entry *scan_entry;
5499 	struct bss_description *bss_desc = NULL;
5500 	uint32_t ie_len, bss_len;
5501 	uint8_t vdev_id;
5502 	struct mlme_legacy_priv *mlme_priv;
5503 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5504 	tpSirFTPreAuthReq preauth_req = NULL;
5505 	bool buf_consumed = true;
5506 
5507 	if (!req)
5508 		return QDF_STATUS_E_INVAL;
5509 
5510 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
5511 	if (!mac_ctx)
5512 		return QDF_STATUS_E_INVAL;
5513 
5514 	ie_len = util_scan_entry_ie_len(req->entry);
5515 	bss_len = (uint16_t)(offsetof(struct bss_description,
5516 			   ieFields[0]) + ie_len);
5517 
5518 	bss_desc = qdf_mem_malloc(sizeof(*bss_desc) + bss_len);
5519 	if (!bss_desc) {
5520 		status = QDF_STATUS_E_NOMEM;
5521 		goto end;
5522 	}
5523 
5524 	scan_entry = req->entry;
5525 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
5526 						    scan_entry);
5527 	if (QDF_IS_STATUS_ERROR(status))
5528 		goto end;
5529 
5530 	preauth_req = qdf_mem_malloc(sizeof(tSirFTPreAuthReq));
5531 	if (!preauth_req) {
5532 		status = QDF_STATUS_E_NOMEM;
5533 		goto end;
5534 	}
5535 
5536 	vdev_id = req->vdev_id;
5537 	preauth_req->pbssDescription = bss_desc;
5538 	status = lim_fill_preauth_req_dot11_mode(mac_ctx, preauth_req, vdev_id);
5539 	if (QDF_IS_STATUS_ERROR(status)) {
5540 		pe_err("dot11mode doesn't get proper filling");
5541 		goto end;
5542 	}
5543 
5544 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id,
5545 						    WLAN_MLME_CM_ID);
5546 	if (!vdev) {
5547 		status = QDF_STATUS_E_FAILURE;
5548 		goto end;
5549 	}
5550 
5551 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
5552 	if (!mlme_priv) {
5553 		status =  QDF_STATUS_E_FAILURE;
5554 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
5555 		goto end;
5556 	}
5557 	qdf_mem_copy(preauth_req->ft_ies,
5558 		     mlme_priv->connect_info.ft_info.auth_ft_ie,
5559 		     mlme_priv->connect_info.ft_info.auth_ie_len);
5560 	preauth_req->ft_ies_length =
5561 			mlme_priv->connect_info.ft_info.auth_ie_len;
5562 	preauth_req->pre_auth_channel_freq = scan_entry->channel.chan_freq;
5563 	wlan_mlme_get_bssid_vdev_id(
5564 			mac_ctx->pdev, vdev_id,
5565 			(struct qdf_mac_addr *)&preauth_req->currbssId);
5566 	qdf_mem_copy(&preauth_req->preAuthbssId,
5567 		     scan_entry->bssid.bytes, QDF_MAC_ADDR_SIZE);
5568 
5569 	wlan_vdev_obj_lock(vdev);
5570 	qdf_mem_copy(&preauth_req->self_mac_addr,
5571 		     wlan_vdev_mlme_get_macaddr(vdev), QDF_MAC_ADDR_SIZE);
5572 	wlan_vdev_obj_unlock(vdev);
5573 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
5574 
5575 	buf_consumed = lim_process_ft_pre_auth_req(mac_ctx, preauth_req);
5576 
5577 end:
5578 	if (buf_consumed) {
5579 		if (bss_desc)
5580 			qdf_mem_free(bss_desc);
5581 		if (preauth_req)
5582 			qdf_mem_free(preauth_req);
5583 	}
5584 
5585 	return status;
5586 }
5587 
5588 QDF_STATUS cm_process_preauth_req(struct scheduler_msg *msg)
5589 {
5590 	struct wlan_preauth_req *req;
5591 	QDF_STATUS status;
5592 
5593 	if (!msg || !msg->bodyptr) {
5594 		mlme_err("msg or msg->bodyptr is NULL");
5595 		return QDF_STATUS_E_INVAL;
5596 	}
5597 
5598 	req = msg->bodyptr;
5599 
5600 	status = lim_cm_handle_preauth_req(req);
5601 
5602 	cm_free_preauth_req(req);
5603 	return status;
5604 }
5605 #endif
5606 
5607 static uint8_t lim_get_num_tpe_octets(uint8_t max_transmit_power_count)
5608 {
5609 	if (!max_transmit_power_count)
5610 		return max_transmit_power_count;
5611 
5612 	return 1 << (max_transmit_power_count - 1);
5613 }
5614 
5615 void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session,
5616 		      tDot11fIEtransmit_power_env *tpe_ies, uint8_t num_tpe_ies,
5617 		      tDot11fIEhe_op *he_op, bool *has_tpe_updated)
5618 {
5619 	struct vdev_mlme_obj *vdev_mlme;
5620 	uint8_t i, local_tpe_count = 0, reg_tpe_count = 0, num_octets;
5621 	uint8_t psd_index = 0, non_psd_index = 0;
5622 	uint8_t bw_num;
5623 	uint16_t bw_val, ch_width;
5624 	qdf_freq_t curr_op_freq, curr_freq;
5625 	enum reg_6g_client_type client_mobility_type;
5626 	struct ch_params ch_params = {0};
5627 	tDot11fIEtransmit_power_env single_tpe, local_tpe, reg_tpe;
5628 	/*
5629 	 * PSD is power spectral density, incoming TPE could contain
5630 	 * non PSD info, or PSD info, or both, so need to keep track of them
5631 	 */
5632 	bool non_psd_set = false, psd_set = false;
5633 	bool both_tpe_present = false;
5634 	bool local_eirp_set = false, local_psd_set = false;
5635 	bool reg_eirp_set = false, reg_psd_set = false;
5636 	uint8_t local_eirp_idx = 0, local_psd_idx = 0;
5637 	uint8_t reg_eirp_idx = 0, reg_psd_idx = 0;
5638 	uint8_t min_count = 0;
5639 
5640 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
5641 	if (!vdev_mlme)
5642 		return;
5643 
5644 	if (session->sta_follows_sap_power) {
5645 		pe_debug_rl("STA operates in 6 GHz power of SAP, do not update STA power");
5646 		return;
5647 	}
5648 
5649 	vdev_mlme->reg_tpc_obj.num_pwr_levels = 0;
5650 	*has_tpe_updated = false;
5651 
5652 	wlan_reg_get_cur_6g_client_type(mac->pdev, &client_mobility_type);
5653 
5654 	for (i = 0; i < num_tpe_ies; i++) {
5655 		single_tpe = tpe_ies[i];
5656 		if (single_tpe.present &&
5657 		    (single_tpe.max_tx_pwr_category == client_mobility_type)) {
5658 			if (single_tpe.max_tx_pwr_interpret == LOCAL_EIRP ||
5659 			    single_tpe.max_tx_pwr_interpret == LOCAL_EIRP_PSD)
5660 				local_tpe_count++;
5661 			else if (single_tpe.max_tx_pwr_interpret ==
5662 				 REGULATORY_CLIENT_EIRP ||
5663 				 single_tpe.max_tx_pwr_interpret ==
5664 				 REGULATORY_CLIENT_EIRP_PSD)
5665 				reg_tpe_count++;
5666 		}
5667 	}
5668 
5669 	if (!reg_tpe_count && !local_tpe_count)
5670 		return;
5671 	else if (reg_tpe_count && local_tpe_count)
5672 		both_tpe_present = true;
5673 
5674 	for (i = 0; i < num_tpe_ies; i++) {
5675 		single_tpe = tpe_ies[i];
5676 		if (single_tpe.present &&
5677 		    (single_tpe.max_tx_pwr_category == client_mobility_type)) {
5678 			if (single_tpe.max_tx_pwr_interpret == LOCAL_EIRP) {
5679 				non_psd_index = i;
5680 				non_psd_set = true;
5681 				local_eirp_idx = non_psd_index;
5682 				local_eirp_set = non_psd_set;
5683 			} else if (single_tpe.max_tx_pwr_interpret ==
5684 				   LOCAL_EIRP_PSD) {
5685 				psd_index = i;
5686 				psd_set = true;
5687 				local_psd_idx = psd_index;
5688 				local_psd_set = psd_set;
5689 			} else if (single_tpe.max_tx_pwr_interpret ==
5690 				   REGULATORY_CLIENT_EIRP) {
5691 				non_psd_index = i;
5692 				non_psd_set = true;
5693 				reg_eirp_idx = non_psd_index;
5694 				reg_eirp_set = non_psd_set;
5695 			} else if (single_tpe.max_tx_pwr_interpret ==
5696 				   REGULATORY_CLIENT_EIRP_PSD) {
5697 				psd_index = i;
5698 				psd_set = true;
5699 				reg_psd_idx = psd_index;
5700 				reg_psd_set = psd_set;
5701 			}
5702 		}
5703 	}
5704 
5705 	curr_op_freq = session->curr_op_freq;
5706 	bw_val = wlan_reg_get_bw_value(session->ch_width);
5707 
5708 	if (non_psd_set && !psd_set) {
5709 		single_tpe = tpe_ies[non_psd_index];
5710 		vdev_mlme->reg_tpc_obj.is_psd_power = false;
5711 		vdev_mlme->reg_tpc_obj.eirp_power = 0;
5712 		bw_num = sizeof(get_next_higher_bw) /
5713 				sizeof(get_next_higher_bw[0]);
5714 		if (single_tpe.max_tx_pwr_count >= bw_num) {
5715 			pe_debug("tx pwr count: %d, larger than bw num: %d",
5716 				 single_tpe.max_tx_pwr_count, bw_num);
5717 			single_tpe.max_tx_pwr_count = bw_num - 1;
5718 		}
5719 		vdev_mlme->reg_tpc_obj.num_pwr_levels =
5720 					single_tpe.max_tx_pwr_count + 1;
5721 
5722 		ch_params.ch_width = CH_WIDTH_20MHZ;
5723 
5724 		for (i = 0; i < single_tpe.max_tx_pwr_count + 1 &&
5725 		     (ch_params.ch_width != CH_WIDTH_INVALID); i++) {
5726 			wlan_reg_set_channel_params_for_pwrmode(
5727 							mac->pdev,
5728 							curr_op_freq, 0,
5729 							&ch_params,
5730 							REG_CURRENT_PWR_MODE);
5731 			if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5732 			    single_tpe.tx_power[i] ||
5733 			    vdev_mlme->reg_tpc_obj.frequency[i] !=
5734 			    ch_params.mhz_freq_seg0)
5735 				*has_tpe_updated = true;
5736 			vdev_mlme->reg_tpc_obj.frequency[i] =
5737 							ch_params.mhz_freq_seg0;
5738 			vdev_mlme->reg_tpc_obj.tpe[i] = single_tpe.tx_power[i];
5739 			if (ch_params.ch_width != CH_WIDTH_INVALID)
5740 				ch_params.ch_width =
5741 					get_next_higher_bw[ch_params.ch_width];
5742 		}
5743 	}
5744 
5745 	if (psd_set) {
5746 		single_tpe = tpe_ies[psd_index];
5747 		vdev_mlme->reg_tpc_obj.is_psd_power = true;
5748 		num_octets =
5749 			lim_get_num_tpe_octets(single_tpe.max_tx_pwr_count);
5750 		vdev_mlme->reg_tpc_obj.num_pwr_levels = num_octets;
5751 
5752 		ch_params.ch_width = session->ch_width;
5753 		wlan_reg_set_channel_params_for_pwrmode(mac->pdev, curr_op_freq,
5754 							0, &ch_params,
5755 							REG_CURRENT_PWR_MODE);
5756 
5757 		if (ch_params.mhz_freq_seg1)
5758 			curr_freq = ch_params.mhz_freq_seg1 - bw_val / 2 + 10;
5759 		else
5760 			curr_freq = ch_params.mhz_freq_seg0 - bw_val / 2 + 10;
5761 
5762 		if (!num_octets) {
5763 			if (!he_op->oper_info_6g_present)
5764 				ch_width = session->ch_width;
5765 			else
5766 				ch_width = he_op->oper_info_6g.info.ch_width;
5767 			num_octets = lim_get_num_pwr_levels(true,
5768 							    session->ch_width);
5769 			vdev_mlme->reg_tpc_obj.num_pwr_levels = num_octets;
5770 			for (i = 0; i < num_octets; i++) {
5771 				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5772 				    single_tpe.tx_power[0] ||
5773 				    vdev_mlme->reg_tpc_obj.frequency[i] !=
5774 				    curr_freq)
5775 					*has_tpe_updated = true;
5776 				vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq;
5777 				curr_freq += 20;
5778 				vdev_mlme->reg_tpc_obj.tpe[i] =
5779 							single_tpe.tx_power[0];
5780 			}
5781 		} else {
5782 			for (i = 0; i < num_octets; i++) {
5783 				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5784 				    single_tpe.tx_power[i] ||
5785 				    vdev_mlme->reg_tpc_obj.frequency[i] !=
5786 				    curr_freq)
5787 					*has_tpe_updated = true;
5788 				vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq;
5789 				curr_freq += 20;
5790 				vdev_mlme->reg_tpc_obj.tpe[i] =
5791 							single_tpe.tx_power[i];
5792 			}
5793 		}
5794 	}
5795 
5796 	if (non_psd_set) {
5797 		single_tpe = tpe_ies[non_psd_index];
5798 		vdev_mlme->reg_tpc_obj.eirp_power =
5799 			single_tpe.tx_power[single_tpe.max_tx_pwr_count];
5800 		vdev_mlme->reg_tpc_obj.is_psd_power = false;
5801 	}
5802 
5803 	if (both_tpe_present) {
5804 		pe_debug("Local: eirp: %d psd: %d, Regulatory: eirp: %d psd %d",
5805 			 local_eirp_set, local_psd_set, reg_eirp_set,
5806 			 reg_psd_set);
5807 		if (local_eirp_set && reg_eirp_set) {
5808 			local_tpe = tpe_ies[local_eirp_idx];
5809 			reg_tpe = tpe_ies[reg_eirp_idx];
5810 		} else if (local_psd_set && reg_psd_set) {
5811 			local_tpe = tpe_ies[local_psd_idx];
5812 			reg_tpe = tpe_ies[reg_psd_idx];
5813 		} else {
5814 			return;
5815 		}
5816 
5817 		min_count = QDF_MIN(local_tpe.max_tx_pwr_count,
5818 				    reg_tpe.max_tx_pwr_count);
5819 		for (i = 0; i < min_count + 1; i++) {
5820 			if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5821 			    QDF_MIN(local_tpe.tx_power[i], reg_tpe.tx_power[i]))
5822 				*has_tpe_updated = true;
5823 			vdev_mlme->reg_tpc_obj.tpe[i] =
5824 						QDF_MIN(local_tpe.tx_power[i],
5825 							reg_tpe.tx_power[i]);
5826 			pe_debug("TPE: Local: %d, Reg: %d, power updated: %d",
5827 				 local_tpe.tx_power[i], reg_tpe.tx_power[i],
5828 				 *has_tpe_updated);
5829 		}
5830 	}
5831 }
5832 
5833 void lim_process_tpe_ie_from_beacon(struct mac_context *mac,
5834 				    struct pe_session *session,
5835 				    struct bss_description *bss_desc,
5836 				    bool *has_tpe_updated)
5837 {
5838 	tDot11fBeaconIEs *bcn_ie;
5839 	uint32_t buf_len;
5840 	uint8_t *buf;
5841 	int status;
5842 
5843 	bcn_ie = qdf_mem_malloc(sizeof(*bcn_ie));
5844 	if (!bcn_ie)
5845 		return;
5846 
5847 	buf_len = lim_get_ielen_from_bss_description(bss_desc);
5848 	buf = (uint8_t *)bss_desc->ieFields;
5849 	status = dot11f_unpack_beacon_i_es(mac, buf, buf_len, bcn_ie, false);
5850 	if (DOT11F_FAILED(status)) {
5851 		pe_err("Failed to parse Beacon IEs (0x%08x, %d bytes):",
5852 		       status, buf_len);
5853 		qdf_mem_free(bcn_ie);
5854 		return;
5855 	} else if (DOT11F_WARNED(status)) {
5856 		pe_debug("warnings (0x%08x, %d bytes):", status, buf_len);
5857 	}
5858 
5859 	status = lim_strip_and_decode_eht_op(buf, buf_len, &bcn_ie->eht_op,
5860 					     bcn_ie->VHTOperation,
5861 					     bcn_ie->he_op,
5862 					     bcn_ie->HTInfo);
5863 	if (status != QDF_STATUS_SUCCESS) {
5864 		pe_err("Failed to extract eht op");
5865 		return;
5866 	}
5867 
5868 	status = lim_strip_and_decode_eht_cap(buf, buf_len, &bcn_ie->eht_cap,
5869 					      bcn_ie->he_cap,
5870 					      session->curr_op_freq);
5871 	if (status != QDF_STATUS_SUCCESS) {
5872 		pe_err("Failed to extract eht cap");
5873 		return;
5874 	}
5875 
5876 	lim_parse_tpe_ie(mac, session, bcn_ie->transmit_power_env,
5877 			 bcn_ie->num_transmit_power_env, &bcn_ie->he_op,
5878 			 has_tpe_updated);
5879 	qdf_mem_free(bcn_ie);
5880 }
5881 
5882 uint32_t lim_get_num_pwr_levels(bool is_psd,
5883 				enum phy_ch_width ch_width)
5884 {
5885 	uint32_t num_pwr_levels = 0;
5886 
5887 	if (is_psd) {
5888 		switch (ch_width) {
5889 		case CH_WIDTH_20MHZ:
5890 			num_pwr_levels = 1;
5891 			break;
5892 		case CH_WIDTH_40MHZ:
5893 			num_pwr_levels = 2;
5894 			break;
5895 		case CH_WIDTH_80MHZ:
5896 			num_pwr_levels = 4;
5897 			break;
5898 		case CH_WIDTH_160MHZ:
5899 			num_pwr_levels = 8;
5900 			break;
5901 		case CH_WIDTH_320MHZ:
5902 			num_pwr_levels = 16;
5903 			break;
5904 		default:
5905 			pe_err_rl("Invalid channel width");
5906 			return 0;
5907 		}
5908 	} else {
5909 		switch (ch_width) {
5910 		case CH_WIDTH_20MHZ:
5911 			num_pwr_levels = 1;
5912 			break;
5913 		case CH_WIDTH_40MHZ:
5914 			num_pwr_levels = 2;
5915 			break;
5916 		case CH_WIDTH_80MHZ:
5917 			num_pwr_levels = 3;
5918 			break;
5919 		case CH_WIDTH_160MHZ:
5920 			num_pwr_levels = 4;
5921 			break;
5922 		case CH_WIDTH_320MHZ:
5923 			num_pwr_levels = 5;
5924 			break;
5925 		default:
5926 			pe_err_rl("Invalid channel width");
5927 			return 0;
5928 		}
5929 	}
5930 	return num_pwr_levels;
5931 }
5932 
5933 uint8_t lim_get_max_tx_power(struct mac_context *mac,
5934 			     struct vdev_mlme_obj *mlme_obj)
5935 {
5936 	uint8_t max_tx_power = 0;
5937 	uint8_t tx_power;
5938 
5939 	if (wlan_reg_get_fcc_constraint(mac->pdev,
5940 					mlme_obj->reg_tpc_obj.frequency[0]))
5941 		return mlme_obj->reg_tpc_obj.reg_max[0];
5942 
5943 	tx_power = QDF_MIN(mlme_obj->reg_tpc_obj.reg_max[0],
5944 			   mlme_obj->reg_tpc_obj.ap_constraint_power);
5945 
5946 	if (tx_power >= MIN_TX_PWR_CAP && tx_power <= MAX_TX_PWR_CAP)
5947 		max_tx_power = tx_power;
5948 	else if (tx_power < MIN_TX_PWR_CAP)
5949 		max_tx_power = MIN_TX_PWR_CAP;
5950 	else
5951 		max_tx_power = MAX_TX_PWR_CAP;
5952 
5953 	return max_tx_power;
5954 }
5955 
5956 void lim_calculate_tpc(struct mac_context *mac,
5957 		       struct pe_session *session)
5958 {
5959 	bool is_psd_power = false;
5960 	bool is_tpe_present = false, is_6ghz_freq = false;
5961 	uint8_t i = 0;
5962 	int8_t max_tx_power;
5963 	uint16_t reg_max = 0, psd_power = 0;
5964 	uint16_t tx_power_within_bw = 0, psd_power_within_bw = 0;
5965 	uint16_t local_constraint, bw_val = 0;
5966 	uint32_t num_pwr_levels, ap_power_type_6g = 0;
5967 	qdf_freq_t oper_freq, start_freq = 0;
5968 	struct ch_params ch_params = {0};
5969 	struct vdev_mlme_obj *mlme_obj;
5970 	int8_t tpe_power;
5971 	bool skip_tpe = false;
5972 	bool rf_test_mode = false;
5973 	bool safe_mode_enable = false;
5974 
5975 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
5976 	if (!mlme_obj) {
5977 		pe_err("vdev component object is NULL");
5978 		return;
5979 	}
5980 
5981 	if (session->sta_follows_sap_power) {
5982 		pe_debug_rl("STA operates in 6 GHz power of SAP, do not update STA power");
5983 		return;
5984 	}
5985 
5986 	oper_freq = session->curr_op_freq;
5987 	bw_val = wlan_reg_get_bw_value(session->ch_width);
5988 
5989 	ch_params.ch_width = session->ch_width;
5990 	/* start frequency calculation */
5991 	wlan_reg_set_channel_params_for_pwrmode(mac->pdev, oper_freq, 0,
5992 						&ch_params,
5993 						REG_CURRENT_PWR_MODE);
5994 	if (ch_params.mhz_freq_seg1)
5995 		start_freq = ch_params.mhz_freq_seg1 - bw_val / 2 + 10;
5996 	else
5997 		start_freq = ch_params.mhz_freq_seg0 - bw_val / 2 + 10;
5998 
5999 	if (!wlan_reg_is_6ghz_chan_freq(oper_freq)) {
6000 		reg_max = wlan_reg_get_channel_reg_power_for_freq(mac->pdev,
6001 								  oper_freq);
6002 		skip_tpe = wlan_mlme_skip_tpe(mac->psoc);
6003 	} else {
6004 		is_6ghz_freq = true;
6005 		/* Power mode calculation for 6 GHz STA*/
6006 		if (LIM_IS_STA_ROLE(session)) {
6007 			ap_power_type_6g = session->best_6g_power_type;
6008 			wlan_mlme_get_safe_mode_enable(mac->psoc,
6009 						       &safe_mode_enable);
6010 			wlan_mlme_is_rf_test_mode_enabled(mac->psoc,
6011 							  &rf_test_mode);
6012 			/*
6013 			 * set LPI power if safe mode is enabled OR RF test
6014 			 * mode is enabled.
6015 			 */
6016 			if (rf_test_mode || safe_mode_enable)
6017 				ap_power_type_6g = REG_INDOOR_AP;
6018 		}
6019 	}
6020 
6021 	if (mlme_obj->reg_tpc_obj.num_pwr_levels) {
6022 		is_tpe_present = true;
6023 		num_pwr_levels = mlme_obj->reg_tpc_obj.num_pwr_levels;
6024 		is_psd_power = mlme_obj->reg_tpc_obj.is_psd_power;
6025 	} else {
6026 		/**
6027 		 * Set is_psd_power based on reg channel list if it is a 6 GHz
6028 		 * channel and TPE IE is absent.
6029 		 */
6030 		if (is_6ghz_freq)
6031 			is_psd_power = wlan_reg_is_6g_psd_power(mac->pdev);
6032 		num_pwr_levels = lim_get_num_pwr_levels(is_psd_power,
6033 							session->ch_width);
6034 	}
6035 
6036 	if (num_pwr_levels > MAX_NUM_PWR_LEVELS) {
6037 		pe_debug("reset num_pwr_levels %d to MAX_NUM_PWR_LEVELS %d",
6038 			 num_pwr_levels, MAX_NUM_PWR_LEVELS);
6039 		num_pwr_levels = MAX_NUM_PWR_LEVELS;
6040 	}
6041 
6042 	ch_params.ch_width = CH_WIDTH_20MHZ;
6043 
6044 	for (i = 0;
6045 		i < num_pwr_levels && (ch_params.ch_width != CH_WIDTH_INVALID);
6046 		i++) {
6047 		if (is_tpe_present) {
6048 			if (is_6ghz_freq) {
6049 				if (is_psd_power) {
6050 					wlan_reg_get_client_power_for_connecting_ap(
6051 					mac->pdev, ap_power_type_6g,
6052 					mlme_obj->reg_tpc_obj.frequency[i],
6053 					is_psd_power, &reg_max, &psd_power);
6054 				} else {
6055 					wlan_reg_get_client_power_for_connecting_ap(
6056 					mac->pdev, ap_power_type_6g, oper_freq,
6057 					is_psd_power, &reg_max, &psd_power);
6058 				}
6059 			}
6060 		} else {
6061 			/* center frequency calculation */
6062 			if (is_psd_power) {
6063 				mlme_obj->reg_tpc_obj.frequency[i] =
6064 						start_freq + (20 * i);
6065 			} else {
6066 				/* Use operating frequency to fetch EIRP pwr */
6067 				mlme_obj->reg_tpc_obj.frequency[i] = oper_freq;
6068 			}
6069 			if (is_6ghz_freq) {
6070 				if (LIM_IS_STA_ROLE(session)) {
6071 					wlan_reg_get_client_power_for_connecting_ap
6072 					(mac->pdev, ap_power_type_6g,
6073 					 mlme_obj->reg_tpc_obj.frequency[i],
6074 					 is_psd_power, &reg_max, &psd_power);
6075 				} else {
6076 					if (wlan_reg_decide_6ghz_power_within_bw_for_freq(
6077 							mac->pdev, oper_freq,
6078 							session->ch_width,
6079 							&is_psd_power,
6080 							&tx_power_within_bw,
6081 							&psd_power_within_bw,
6082 							&ap_power_type_6g,
6083 							REG_BEST_PWR_MODE,
6084 							NO_SCHANS_PUNC) ==
6085 							QDF_STATUS_SUCCESS) {
6086 						pe_debug("get pwr attr from secondary list");
6087 						reg_max = tx_power_within_bw;
6088 						psd_power = psd_power_within_bw;
6089 					} else {
6090 						wlan_reg_get_cur_6g_ap_pwr_type(
6091 							mac->pdev,
6092 							&ap_power_type_6g);
6093 						wlan_reg_get_6g_chan_ap_power(
6094 							mac->pdev,
6095 							mlme_obj->reg_tpc_obj.
6096 							frequency[i],
6097 							&is_psd_power,
6098 							&reg_max,
6099 							&psd_power);
6100 					}
6101 				}
6102 			}
6103 		}
6104 		/* Check for regulatory channel power. If it is zero due to
6105 		 * invalid frequency or other inputs, then assign the regulatory
6106 		 * power of operating frequency to reg_max.
6107 		 */
6108 		if (reg_max) {
6109 			mlme_obj->reg_tpc_obj.reg_max[i] = reg_max;
6110 		} else {
6111 			pe_debug("Reg power due to invalid freq: %d",
6112 				 mlme_obj->reg_tpc_obj.frequency[i]);
6113 			reg_max = mlme_obj->reg_tpc_obj.reg_max[0];
6114 			mlme_obj->reg_tpc_obj.reg_max[i] = reg_max;
6115 		}
6116 
6117 		mlme_obj->reg_tpc_obj.chan_power_info[i].chan_cfreq =
6118 					mlme_obj->reg_tpc_obj.frequency[i];
6119 
6120 		/* max tx power calculation */
6121 		max_tx_power = mlme_obj->reg_tpc_obj.reg_max[i];
6122 		/* If AP local power constraint is present */
6123 		if (mlme_obj->reg_tpc_obj.ap_constraint_power) {
6124 			local_constraint =
6125 				mlme_obj->reg_tpc_obj.ap_constraint_power;
6126 			pe_debug("local constraint: %d power constraint absolute %d",
6127 				 local_constraint,
6128 				 mlme_obj->reg_tpc_obj.is_power_constraint_abs);
6129 			if (mlme_obj->reg_tpc_obj.is_power_constraint_abs)
6130 				max_tx_power = QDF_MIN(reg_max,
6131 						       local_constraint);
6132 			else
6133 				max_tx_power = reg_max - local_constraint;
6134 		}
6135 		/* If TPE is present */
6136 		if (is_tpe_present && !skip_tpe) {
6137 			if (!is_psd_power && mlme_obj->reg_tpc_obj.eirp_power)
6138 				tpe_power =  mlme_obj->reg_tpc_obj.eirp_power;
6139 			else
6140 				tpe_power = mlme_obj->reg_tpc_obj.tpe[i];
6141 			/**
6142 			 * AP advertises TPE IE tx power as 8-bit unsigned int.
6143 			 * STA needs to convert it into an 8-bit 2s complement
6144 			 * signed integer in the range –64 dBm to 63 dBm with a
6145 			 * 0.5 dB step
6146 			 */
6147 			tpe_power /= 2;
6148 			max_tx_power = QDF_MIN(max_tx_power, tpe_power);
6149 			pe_debug("TPE: %d", tpe_power);
6150 		}
6151 
6152 		if (is_psd_power)
6153 			mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power =
6154 						(uint8_t)psd_power;
6155 		else
6156 			mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power =
6157 						(uint8_t)max_tx_power;
6158 
6159 		pe_debug("freq: %d reg power: %d, max_tx_power(eirp/psd): %d",
6160 			 mlme_obj->reg_tpc_obj.frequency[i], reg_max,
6161 			 mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power);
6162 	}
6163 
6164 	mlme_obj->reg_tpc_obj.num_pwr_levels = num_pwr_levels;
6165 	mlme_obj->reg_tpc_obj.eirp_power = reg_max;
6166 	mlme_obj->reg_tpc_obj.power_type_6g = ap_power_type_6g;
6167 	mlme_obj->reg_tpc_obj.is_psd_power = is_psd_power;
6168 
6169 	pe_debug("num_pwr_levels: %d, is_psd_power: %d, total eirp_power: %d, ap_pwr_type: %d",
6170 		 num_pwr_levels, is_psd_power, reg_max, ap_power_type_6g);
6171 }
6172 
6173 /**
6174  * lim_mlo_sap_validate_and_update_ra() - Validate peer address for ML SAP
6175  * management frames.
6176  * @session: pe_session
6177  * @peer_addr: address of the peer
6178  *
6179  * Check if address pointed by @peer_addr is MLD of the client,
6180  * if so, replace the address with link address of the client
6181  * to send the management packet over the air.
6182  *
6183  * Return: void
6184  */
6185 #ifdef WLAN_FEATURE_11BE_MLO
6186 static void lim_mlo_sap_validate_and_update_ra(struct pe_session *session,
6187 					       struct qdf_mac_addr *peer_addr)
6188 {
6189 	uint8_t i;
6190 	struct wlan_mlo_dev_context *ml_ctx;
6191 	struct wlan_mlo_peer_list *mlo_peer_list;
6192 	struct wlan_mlo_peer_context *ml_peer;
6193 	struct wlan_mlo_link_peer_entry *link_peer;
6194 
6195 	if (!wlan_vdev_mlme_is_mlo_ap(session->vdev))
6196 		return;
6197 
6198 	ml_ctx = session->vdev->mlo_dev_ctx;
6199 	mlo_peer_list = &ml_ctx->mlo_peer_list;
6200 
6201 	ml_peerlist_lock_acquire(mlo_peer_list);
6202 	ml_peer = mlo_get_mlpeer(ml_ctx, peer_addr);
6203 	if (!ml_peer) {
6204 		ml_peerlist_lock_release(mlo_peer_list);
6205 		return;
6206 	}
6207 
6208 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
6209 		link_peer = &ml_peer->peer_list[i];
6210 		if (link_peer->is_primary &&
6211 		    !qdf_is_macaddr_equal(peer_addr, &link_peer->link_addr)) {
6212 			qdf_copy_macaddr(peer_addr, &link_peer->link_addr);
6213 			break;
6214 		}
6215 	}
6216 	ml_peerlist_lock_release(mlo_peer_list);
6217 }
6218 #else
6219 static inline void
6220 lim_mlo_sap_validate_and_update_ra(struct pe_session *session,
6221 				   struct qdf_mac_addr *peer_addr)
6222 {
6223 }
6224 #endif
6225 
6226 bool send_disassoc_frame = 1;
6227 /**
6228  * __lim_process_sme_disassoc_req()
6229  *
6230  ***FUNCTION:
6231  * This function is called to process SME_DISASSOC_REQ message
6232  * from HDD or upper layer application.
6233  *
6234  ***LOGIC:
6235  *
6236  ***ASSUMPTIONS:
6237  *
6238  ***NOTE:
6239  *
6240  * @param  mac      Pointer to Global MAC structure
6241  * @param  *msg_buf  A pointer to the SME message buffer
6242  * @return None
6243  */
6244 
6245 static void __lim_process_sme_disassoc_req(struct mac_context *mac,
6246 					   uint32_t *msg_buf)
6247 {
6248 	uint16_t disassocTrigger, reasonCode;
6249 	tLimMlmDisassocReq *pMlmDisassocReq;
6250 	tSirResultCodes retCode = eSIR_SME_SUCCESS;
6251 	struct disassoc_req smeDisassocReq;
6252 	struct pe_session *pe_session = NULL;
6253 	uint8_t sessionId;
6254 	uint8_t smesessionId;
6255 
6256 	if (!msg_buf) {
6257 		pe_err("Buffer is Pointing to NULL");
6258 		return;
6259 	}
6260 
6261 	qdf_mem_copy(&smeDisassocReq, msg_buf, sizeof(struct disassoc_req));
6262 	smesessionId = smeDisassocReq.sessionId;
6263 	if (!lim_is_sme_disassoc_req_valid(mac,
6264 					   &smeDisassocReq,
6265 					   pe_session)) {
6266 		pe_err("received invalid SME_DISASSOC_REQ message");
6267 		if (mac->lim.gLimRspReqd) {
6268 			mac->lim.gLimRspReqd = false;
6269 
6270 			retCode = eSIR_SME_INVALID_PARAMETERS;
6271 			disassocTrigger = eLIM_HOST_DISASSOC;
6272 			goto sendDisassoc;
6273 		}
6274 
6275 		return;
6276 	}
6277 
6278 	pe_session = pe_find_session_by_bssid_and_vdev_id(mac,
6279 				smeDisassocReq.bssid.bytes,
6280 				smeDisassocReq.sessionId,
6281 				&sessionId);
6282 	if (!pe_session) {
6283 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
6284 		       QDF_MAC_ADDR_REF(smeDisassocReq.bssid.bytes));
6285 		retCode = eSIR_SME_INVALID_PARAMETERS;
6286 		disassocTrigger = eLIM_HOST_DISASSOC;
6287 		goto sendDisassoc;
6288 	}
6289 	pe_debug("vdev %d (%d) opmode %d Reason: %u SmeState: %d limMlmState %d ho fail %d send OTA %d to: " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT,
6290 		 pe_session->vdev_id, pe_session->peSessionId,
6291 		 pe_session->opmode, smeDisassocReq.reasonCode,
6292 		 pe_session->limSmeState, pe_session->limMlmState,
6293 		 smeDisassocReq.process_ho_fail,
6294 		 smeDisassocReq.doNotSendOverTheAir,
6295 		 QDF_MAC_ADDR_REF(smeDisassocReq.peer_macaddr.bytes),
6296 		 QDF_MAC_ADDR_REF(smeDisassocReq.bssid.bytes));
6297 
6298 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
6299 	lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, pe_session,
6300 			      0, smeDisassocReq.reasonCode);
6301 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
6302 
6303 	pe_session->smeSessionId = smesessionId;
6304 	pe_session->process_ho_fail = smeDisassocReq.process_ho_fail;
6305 
6306 	switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
6307 	case eLIM_STA_ROLE:
6308 		switch (pe_session->limSmeState) {
6309 		case eLIM_SME_ASSOCIATED_STATE:
6310 		case eLIM_SME_LINK_EST_STATE:
6311 			pe_session->limPrevSmeState =
6312 				pe_session->limSmeState;
6313 			pe_session->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
6314 			/* Delete all TDLS peers connected before leaving BSS */
6315 			lim_delete_tdls_peers(mac, pe_session);
6316 			MTRACE(mac_trace(mac, TRACE_CODE_SME_STATE,
6317 				pe_session->peSessionId,
6318 				pe_session->limSmeState));
6319 			break;
6320 
6321 		case eLIM_SME_WT_DEAUTH_STATE:
6322 			/* PE shall still process the DISASSOC_REQ and proceed with
6323 			 * link tear down even if it had already sent a DEAUTH_IND to
6324 			 * to SME. mac->lim.gLimPrevSmeState shall remain the same as
6325 			 * its been set when PE entered WT_DEAUTH_STATE.
6326 			 */
6327 			pe_session->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
6328 			MTRACE(mac_trace
6329 				       (mac, TRACE_CODE_SME_STATE,
6330 				       pe_session->peSessionId,
6331 				       pe_session->limSmeState));
6332 			break;
6333 
6334 		case eLIM_SME_WT_DISASSOC_STATE:
6335 			/* PE Received a Disassoc frame. Normally it gets DISASSOC_CNF but it
6336 			 * received DISASSOC_REQ. Which means host is also trying to disconnect.
6337 			 * PE can continue processing DISASSOC_REQ and send the response instead
6338 			 * of failing the request. SME will anyway ignore DEAUTH_IND that was sent
6339 			 * for disassoc frame.
6340 			 *
6341 			 * It will send a disassoc, which is ok. However, we can use the global flag
6342 			 * sendDisassoc to not send disassoc frame.
6343 			 */
6344 			break;
6345 
6346 		case eLIM_SME_JOIN_FAILURE_STATE: {
6347 			/* Already in Disconnected State, return success */
6348 			if (mac->lim.gLimRspReqd) {
6349 				retCode = eSIR_SME_SUCCESS;
6350 				disassocTrigger = eLIM_HOST_DISASSOC;
6351 				goto sendDisassoc;
6352 			}
6353 		}
6354 		break;
6355 		default:
6356 			/**
6357 			 * STA is not currently associated.
6358 			 * Log error and send response to host
6359 			 */
6360 			pe_err("received unexpected SME_DISASSOC_REQ in state %X",
6361 				pe_session->limSmeState);
6362 			lim_print_sme_state(mac, LOGE,
6363 				pe_session->limSmeState);
6364 
6365 			if (mac->lim.gLimRspReqd) {
6366 				if (pe_session->limSmeState !=
6367 				    eLIM_SME_WT_ASSOC_STATE)
6368 					mac->lim.gLimRspReqd = false;
6369 
6370 				retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
6371 				disassocTrigger = eLIM_HOST_DISASSOC;
6372 				goto sendDisassoc;
6373 			}
6374 
6375 			return;
6376 		}
6377 
6378 		break;
6379 
6380 	case eLIM_AP_ROLE:
6381 		/* Check if MAC address is MLD of the client and
6382 		 * change it to primary link address to send OTA.
6383 		 */
6384 		lim_mlo_sap_validate_and_update_ra(
6385 				pe_session, &smeDisassocReq.peer_macaddr);
6386 		break;
6387 
6388 	default:
6389 		/* eLIM_UNKNOWN_ROLE */
6390 		pe_err("received unexpected SME_DISASSOC_REQ for role %d",
6391 			GET_LIM_SYSTEM_ROLE(pe_session));
6392 
6393 		retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
6394 		disassocTrigger = eLIM_HOST_DISASSOC;
6395 		goto sendDisassoc;
6396 	} /* end switch (mac->lim.gLimSystemRole) */
6397 
6398 	disassocTrigger = eLIM_HOST_DISASSOC;
6399 	reasonCode = smeDisassocReq.reasonCode;
6400 
6401 	if (smeDisassocReq.doNotSendOverTheAir)
6402 		send_disassoc_frame = 0;
6403 
6404 	pMlmDisassocReq = qdf_mem_malloc(sizeof(tLimMlmDisassocReq));
6405 	if (!pMlmDisassocReq)
6406 		return;
6407 
6408 	qdf_copy_macaddr(&pMlmDisassocReq->peer_macaddr,
6409 			 &smeDisassocReq.peer_macaddr);
6410 
6411 	pMlmDisassocReq->reasonCode = reasonCode;
6412 	pMlmDisassocReq->disassocTrigger = disassocTrigger;
6413 
6414 	/* Update PE session ID */
6415 	pMlmDisassocReq->sessionId = sessionId;
6416 
6417 	lim_post_mlm_message(mac,
6418 			     LIM_MLM_DISASSOC_REQ, (uint32_t *) pMlmDisassocReq);
6419 	return;
6420 
6421 sendDisassoc:
6422 	if (pe_session)
6423 		lim_send_sme_disassoc_ntf(mac,
6424 					  smeDisassocReq.peer_macaddr.bytes,
6425 					  retCode,
6426 					  disassocTrigger,
6427 					  1, smesessionId,
6428 					  pe_session);
6429 	else
6430 		lim_send_sme_disassoc_ntf(mac,
6431 					  smeDisassocReq.peer_macaddr.bytes,
6432 					  retCode, disassocTrigger, 1,
6433 					  smesessionId, NULL);
6434 
6435 } /*** end __lim_process_sme_disassoc_req() ***/
6436 
6437 /** -----------------------------------------------------------------
6438    \brief __lim_process_sme_disassoc_cnf() - Process SME_DISASSOC_CNF
6439 
6440    This function is called to process SME_DISASSOC_CNF message
6441    from HDD or upper layer application.
6442 
6443    \param mac - global mac structure
6444    \param sta - station dph hash node
6445    \return none
6446    \sa
6447    ----------------------------------------------------------------- */
6448 void __lim_process_sme_disassoc_cnf(struct mac_context *mac, uint32_t *msg_buf)
6449 {
6450 	struct disassoc_cnf smeDisassocCnf;
6451 	uint16_t aid;
6452 	tpDphHashNode sta;
6453 	struct pe_session *pe_session;
6454 	uint8_t sessionId;
6455 	uint32_t *msg = NULL;
6456 	QDF_STATUS status;
6457 
6458 	qdf_mem_copy(&smeDisassocCnf, msg_buf, sizeof(smeDisassocCnf));
6459 
6460 	pe_session = pe_find_session_by_bssid_and_vdev_id(mac,
6461 				smeDisassocCnf.bssid.bytes,
6462 				smeDisassocCnf.vdev_id,
6463 				&sessionId);
6464 	if (!pe_session) {
6465 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
6466 		       QDF_MAC_ADDR_REF(smeDisassocCnf.bssid.bytes));
6467 		status = lim_prepare_disconnect_done_ind(mac, &msg,
6468 						smeDisassocCnf.vdev_id,
6469 						eSIR_SME_INVALID_SESSION,
6470 						NULL);
6471 		if (QDF_IS_STATUS_SUCCESS(status))
6472 			lim_send_sme_disassoc_deauth_ntf(mac,
6473 							 QDF_STATUS_SUCCESS,
6474 							 (uint32_t *)msg);
6475 		return;
6476 	}
6477 
6478 	if (!lim_is_sme_disassoc_cnf_valid(mac, &smeDisassocCnf, pe_session)) {
6479 		pe_err("received invalid SME_DISASSOC_CNF message");
6480 		status = lim_prepare_disconnect_done_ind(
6481 					mac, &msg,
6482 					pe_session->smeSessionId,
6483 					eSIR_SME_INVALID_PARAMETERS,
6484 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6485 		if (QDF_IS_STATUS_SUCCESS(status))
6486 			lim_send_sme_disassoc_deauth_ntf(mac,
6487 							 QDF_STATUS_SUCCESS,
6488 							 (uint32_t *)msg);
6489 		return;
6490 	}
6491 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
6492 	if (smeDisassocCnf.messageType == eWNI_SME_DISASSOC_CNF)
6493 		lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_CNF_EVENT,
6494 				      pe_session,
6495 				      (uint16_t)smeDisassocCnf.status_code, 0);
6496 	else if (smeDisassocCnf.messageType == eWNI_SME_DEAUTH_CNF)
6497 		lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_CNF_EVENT,
6498 				      pe_session,
6499 				      (uint16_t)smeDisassocCnf.status_code, 0);
6500 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
6501 	pe_debug("vdev %d (%d) opmode %d SmeState: %d limMlmState %d from: " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT,
6502 		 pe_session->vdev_id, pe_session->peSessionId,
6503 		 pe_session->opmode, pe_session->limSmeState,
6504 		 pe_session->limMlmState,
6505 		 QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes),
6506 		 QDF_MAC_ADDR_REF(smeDisassocCnf.bssid.bytes));
6507 
6508 	switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
6509 	case eLIM_STA_ROLE:
6510 		if ((pe_session->limSmeState != eLIM_SME_IDLE_STATE) &&
6511 		    (pe_session->limSmeState != eLIM_SME_WT_DISASSOC_STATE)
6512 		    && (pe_session->limSmeState !=
6513 			eLIM_SME_WT_DEAUTH_STATE)) {
6514 			pe_err("received unexp SME_DISASSOC_CNF in state %X",
6515 				pe_session->limSmeState);
6516 			lim_print_sme_state(mac, LOGE,
6517 					    pe_session->limSmeState);
6518 			status = lim_prepare_disconnect_done_ind(
6519 					mac, &msg,
6520 					pe_session->smeSessionId,
6521 					eSIR_SME_INVALID_STATE,
6522 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6523 			if (QDF_IS_STATUS_SUCCESS(status))
6524 				lim_send_sme_disassoc_deauth_ntf(mac,
6525 							QDF_STATUS_SUCCESS,
6526 							(uint32_t *)msg);
6527 			return;
6528 		}
6529 		break;
6530 
6531 	case eLIM_AP_ROLE:
6532 		break;
6533 	default:                /* eLIM_UNKNOWN_ROLE */
6534 		pe_err("received unexpected SME_DISASSOC_CNF role %d",
6535 			GET_LIM_SYSTEM_ROLE(pe_session));
6536 		status = lim_prepare_disconnect_done_ind(
6537 					mac, &msg,
6538 					pe_session->smeSessionId,
6539 					eSIR_SME_INVALID_STATE,
6540 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6541 		if (QDF_IS_STATUS_SUCCESS(status))
6542 			lim_send_sme_disassoc_deauth_ntf(mac,
6543 							 QDF_STATUS_SUCCESS,
6544 							 (uint32_t *)msg);
6545 		return;
6546 	}
6547 
6548 	if ((pe_session->limSmeState == eLIM_SME_WT_DISASSOC_STATE) ||
6549 	    (pe_session->limSmeState == eLIM_SME_WT_DEAUTH_STATE) ||
6550 	    LIM_IS_AP_ROLE(pe_session)) {
6551 		sta = dph_lookup_hash_entry(mac,
6552 				smeDisassocCnf.peer_macaddr.bytes, &aid,
6553 				&pe_session->dph.dphHashTable);
6554 		if (!sta) {
6555 			pe_err("DISASSOC_CNF for a STA with no context, addr= "
6556 				QDF_MAC_ADDR_FMT,
6557 				QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes));
6558 			status = lim_prepare_disconnect_done_ind(
6559 					mac, &msg,
6560 					pe_session->smeSessionId,
6561 					eSIR_SME_INVALID_PARAMETERS,
6562 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6563 			if (QDF_IS_STATUS_SUCCESS(status))
6564 				lim_send_sme_disassoc_deauth_ntf(mac,
6565 							QDF_STATUS_SUCCESS,
6566 							(uint32_t *)msg);
6567 			return;
6568 		}
6569 
6570 		if ((sta->mlmStaContext.mlmState ==
6571 				eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
6572 			(sta->mlmStaContext.mlmState ==
6573 				eLIM_MLM_WT_DEL_BSS_RSP_STATE)) {
6574 			pe_err("No need of cleanup for addr:" QDF_MAC_ADDR_FMT "as MLM state is %d",
6575 				QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes),
6576 				sta->mlmStaContext.mlmState);
6577 			status = lim_prepare_disconnect_done_ind(mac, &msg,
6578 						pe_session->smeSessionId,
6579 						eSIR_SME_SUCCESS,
6580 						NULL);
6581 			if (QDF_IS_STATUS_SUCCESS(status))
6582 				lim_send_sme_disassoc_deauth_ntf(mac,
6583 							QDF_STATUS_SUCCESS,
6584 							(uint32_t *)msg);
6585 			return;
6586 		}
6587 
6588 		lim_mlo_notify_peer_disconn(pe_session, sta);
6589 
6590 		/* Delete FT session if there exists one */
6591 		lim_ft_cleanup_pre_auth_info(mac, pe_session);
6592 		lim_cleanup_rx_path(mac, sta, pe_session, true);
6593 
6594 		lim_clean_up_disassoc_deauth_req(mac,
6595 				 (char *)&smeDisassocCnf.peer_macaddr, 0);
6596 	}
6597 
6598 	return;
6599 }
6600 
6601 /**
6602  * __lim_process_sme_deauth_req() - process sme deauth req
6603  * @mac_ctx: Pointer to Global MAC structure
6604  * @msg_buf: pointer to the SME message buffer
6605  *
6606  * This function is called to process SME_DEAUTH_REQ message
6607  * from HDD or upper layer application.
6608  *
6609  * Return: None
6610  */
6611 
6612 static void __lim_process_sme_deauth_req(struct mac_context *mac_ctx,
6613 		uint32_t *msg_buf)
6614 {
6615 	uint16_t deauth_trigger, reason_code;
6616 	tLimMlmDeauthReq *mlm_deauth_req;
6617 	struct deauth_req sme_deauth_req;
6618 	tSirResultCodes ret_code = eSIR_SME_SUCCESS;
6619 	struct pe_session *session_entry;
6620 	uint8_t session_id;      /* PE sessionId */
6621 	uint8_t vdev_id;
6622 
6623 	qdf_mem_copy(&sme_deauth_req, msg_buf, sizeof(sme_deauth_req));
6624 	vdev_id = sme_deauth_req.vdev_id;
6625 
6626 	/*
6627 	 * We need to get a session first but we don't even know
6628 	 * if the message is correct.
6629 	 */
6630 	session_entry = pe_find_session_by_bssid_and_vdev_id(mac_ctx,
6631 					sme_deauth_req.bssid.bytes,
6632 					sme_deauth_req.vdev_id,
6633 					&session_id);
6634 	if (!session_entry) {
6635 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
6636 		       QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes));
6637 		ret_code = eSIR_SME_INVALID_PARAMETERS;
6638 		deauth_trigger = eLIM_HOST_DEAUTH;
6639 		goto send_deauth;
6640 	}
6641 
6642 	if (!lim_is_sme_deauth_req_valid(mac_ctx, &sme_deauth_req,
6643 				session_entry)) {
6644 		pe_err("received invalid SME_DEAUTH_REQ message");
6645 		mac_ctx->lim.gLimRspReqd = false;
6646 
6647 		ret_code = eSIR_SME_INVALID_PARAMETERS;
6648 		deauth_trigger = eLIM_HOST_DEAUTH;
6649 		goto send_deauth;
6650 	}
6651 	pe_debug("vdev %d (%d) opmode %d reasoncode %u limSmestate %d limMlmState %d to " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT,
6652 		 vdev_id, session_entry->peSessionId,
6653 		 session_entry->opmode, sme_deauth_req.reasonCode,
6654 		 session_entry->limSmeState, session_entry->limMlmState,
6655 		 QDF_MAC_ADDR_REF(sme_deauth_req.peer_macaddr.bytes),
6656 		 QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes));
6657 
6658 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
6659 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_DEAUTH_REQ_EVENT,
6660 			session_entry, 0, sme_deauth_req.reasonCode);
6661 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
6662 
6663 	session_entry->vdev_id = vdev_id;
6664 
6665 	switch (GET_LIM_SYSTEM_ROLE(session_entry)) {
6666 	case eLIM_STA_ROLE:
6667 		switch (session_entry->limSmeState) {
6668 		case eLIM_SME_ASSOCIATED_STATE:
6669 		case eLIM_SME_LINK_EST_STATE:
6670 			/* Delete all TDLS peers connected before leaving BSS */
6671 			lim_delete_tdls_peers(mac_ctx, session_entry);
6672 			fallthrough;
6673 		case eLIM_SME_WT_ASSOC_STATE:
6674 		case eLIM_SME_JOIN_FAILURE_STATE:
6675 		case eLIM_SME_IDLE_STATE:
6676 			session_entry->limPrevSmeState =
6677 				session_entry->limSmeState;
6678 			session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
6679 			MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
6680 				       session_entry->peSessionId,
6681 				       session_entry->limSmeState));
6682 			/* Send Deauthentication request to MLM below */
6683 			break;
6684 		case eLIM_SME_WT_DEAUTH_STATE:
6685 		case eLIM_SME_WT_DISASSOC_STATE:
6686 			/*
6687 			 * PE Received a Deauth/Disassoc frame. Normally it get
6688 			 * DEAUTH_CNF/DISASSOC_CNF but it received DEAUTH_REQ.
6689 			 * Which means host is also trying to disconnect.
6690 			 * PE can continue processing DEAUTH_REQ and send
6691 			 * the response instead of failing the request.
6692 			 * SME will anyway ignore DEAUTH_IND/DISASSOC_IND that
6693 			 * was sent for deauth/disassoc frame.
6694 			 */
6695 			session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
6696 			break;
6697 		default:
6698 			/*
6699 			 * STA is not in a state to deauthenticate with
6700 			 * peer. Log error and send response to host.
6701 			 */
6702 			pe_err("received unexp SME_DEAUTH_REQ in state %X",
6703 				session_entry->limSmeState);
6704 			lim_print_sme_state(mac_ctx, LOGE,
6705 					    session_entry->limSmeState);
6706 
6707 			if (mac_ctx->lim.gLimRspReqd) {
6708 				mac_ctx->lim.gLimRspReqd = false;
6709 
6710 				ret_code = eSIR_SME_STA_NOT_AUTHENTICATED;
6711 				deauth_trigger = eLIM_HOST_DEAUTH;
6712 
6713 				/*
6714 				 * here we received deauth request from AP so
6715 				 * sme state is eLIM_SME_WT_DEAUTH_STATE.if we
6716 				 * have ISSUED delSta then mlm state should be
6717 				 * eLIM_MLM_WT_DEL_STA_RSP_STATE and ifwe got
6718 				 * delBSS rsp then mlm state should be
6719 				 * eLIM_MLM_IDLE_STATE so the below condition
6720 				 * captures the state where delSta not done
6721 				 * and firmware still in connected state.
6722 				 */
6723 				if (session_entry->limSmeState ==
6724 					eLIM_SME_WT_DEAUTH_STATE &&
6725 					session_entry->limMlmState !=
6726 					eLIM_MLM_IDLE_STATE &&
6727 					session_entry->limMlmState !=
6728 					eLIM_MLM_WT_DEL_STA_RSP_STATE)
6729 					ret_code = eSIR_SME_DEAUTH_STATUS;
6730 				goto send_deauth;
6731 			}
6732 			return;
6733 		}
6734 		break;
6735 	case eLIM_AP_ROLE:
6736 		/* Check if MAC address is MLD of the client and
6737 		 * change it to primary link address to send OTA.
6738 		 */
6739 		lim_mlo_sap_validate_and_update_ra(
6740 				session_entry, &sme_deauth_req.peer_macaddr);
6741 		break;
6742 	default:
6743 		pe_err("received unexpected SME_DEAUTH_REQ for role %X",
6744 			GET_LIM_SYSTEM_ROLE(session_entry));
6745 		if (mac_ctx->lim.gLimRspReqd) {
6746 			mac_ctx->lim.gLimRspReqd = false;
6747 			ret_code = eSIR_SME_INVALID_PARAMETERS;
6748 			deauth_trigger = eLIM_HOST_DEAUTH;
6749 			goto send_deauth;
6750 		}
6751 		return;
6752 	} /* end switch (mac_ctx->lim.gLimSystemRole) */
6753 
6754 	if (sme_deauth_req.reasonCode == eLIM_LINK_MONITORING_DEAUTH &&
6755 	    session_entry->limSystemRole == eLIM_STA_ROLE) {
6756 		/* Deauthentication is triggered by Link Monitoring */
6757 		pe_debug("** Lost link with AP **");
6758 		deauth_trigger = eLIM_LINK_MONITORING_DEAUTH;
6759 		reason_code = REASON_UNSPEC_FAILURE;
6760 	} else {
6761 		deauth_trigger = eLIM_HOST_DEAUTH;
6762 		reason_code = sme_deauth_req.reasonCode;
6763 	}
6764 
6765 	/* Trigger Deauthentication frame to peer MAC entity */
6766 	mlm_deauth_req = qdf_mem_malloc(sizeof(tLimMlmDeauthReq));
6767 	if (!mlm_deauth_req) {
6768 		if (mac_ctx->lim.gLimRspReqd) {
6769 			mac_ctx->lim.gLimRspReqd = false;
6770 			ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
6771 			deauth_trigger = eLIM_HOST_DEAUTH;
6772 			goto send_deauth;
6773 		}
6774 		return;
6775 	}
6776 
6777 	qdf_copy_macaddr(&mlm_deauth_req->peer_macaddr,
6778 			 &sme_deauth_req.peer_macaddr);
6779 
6780 	mlm_deauth_req->reasonCode = reason_code;
6781 	mlm_deauth_req->deauthTrigger = deauth_trigger;
6782 
6783 	/* Update PE session Id */
6784 	mlm_deauth_req->sessionId = session_id;
6785 	lim_process_mlm_deauth_req(mac_ctx, (uint32_t *)mlm_deauth_req);
6786 
6787 	return;
6788 
6789 send_deauth:
6790 	lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peer_macaddr.bytes,
6791 				ret_code, deauth_trigger, 1, vdev_id);
6792 }
6793 
6794 /**
6795  * __lim_counter_measures()
6796  *
6797  * FUNCTION:
6798  * This function is called to "implement" MIC counter measure
6799  * and is *temporary* only
6800  *
6801  * LOGIC: on AP, disassoc all STA associated thru TKIP,
6802  * we don't do the proper STA disassoc sequence since the
6803  * BSS will be stopped anyway
6804  *
6805  ***ASSUMPTIONS:
6806  *
6807  ***NOTE:
6808  *
6809  * @param  mac      Pointer to Global MAC structure
6810  * @return None
6811  */
6812 
6813 static void __lim_counter_measures(struct mac_context *mac, struct pe_session *pe_session)
6814 {
6815 	tSirMacAddr mac_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
6816 
6817 	if (LIM_IS_AP_ROLE(pe_session))
6818 		lim_send_disassoc_mgmt_frame(mac, REASON_MIC_FAILURE,
6819 					     mac_addr, pe_session, false);
6820 };
6821 
6822 void lim_send_stop_bss_failure_resp(struct mac_context *mac_ctx,
6823 				    struct pe_session *session)
6824 {
6825 	session->limSmeState = session->limPrevSmeState;
6826 
6827 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, session->peSessionId,
6828 			  session->limSmeState));
6829 	lim_send_stop_bss_response(mac_ctx, session->vdev_id,
6830 				   eSIR_SME_STOP_BSS_FAILURE);
6831 }
6832 
6833 static void lim_flush_all_peer_from_serialization_queue(
6834 				struct mac_context *mac_ctx,
6835 				struct pe_session *session)
6836 {
6837 	struct wlan_serialization_queued_cmd_info cmd = {0};
6838 	struct wlan_objmgr_vdev *vdev;
6839 
6840 	vdev = session->vdev;
6841 	if (!vdev) {
6842 		pe_err("vdev is null");
6843 		return;
6844 	}
6845 
6846 	pe_debug("vdev id is %d for disconnect/deauth cmd", session->vdev_id);
6847 
6848 	/* Flush any pending NB peer deauth command */
6849 	cmd.vdev = vdev;
6850 	cmd.cmd_type = WLAN_SER_CMD_FORCE_DEAUTH_STA;
6851 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
6852 	cmd.requestor = WLAN_UMAC_COMP_MLME;
6853 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
6854 
6855 	wlan_serialization_cancel_request(&cmd);
6856 
6857 	/* Flush any pending NB peer disassoc command */
6858 	qdf_mem_zero(&cmd, sizeof(cmd));
6859 	cmd.vdev = vdev;
6860 	cmd.cmd_type = WLAN_SER_CMD_FORCE_DISASSOC_STA;
6861 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
6862 	cmd.requestor = WLAN_UMAC_COMP_MLME;
6863 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
6864 
6865 	wlan_serialization_cancel_request(&cmd);
6866 
6867 	/* Flush any pending SB peer deauth/disconnect command */
6868 	qdf_mem_zero(&cmd, sizeof(cmd));
6869 	cmd.vdev = vdev;
6870 	cmd.cmd_type = WLAN_SER_CMD_WM_STATUS_CHANGE;
6871 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
6872 	cmd.requestor = WLAN_UMAC_COMP_MLME;
6873 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
6874 
6875 	wlan_serialization_cancel_request(&cmd);
6876 }
6877 
6878 void lim_delete_all_peers(struct pe_session *session)
6879 {
6880 	uint8_t i = 0;
6881 	struct mac_context *mac_ctx = session->mac_ctx;
6882 	tpDphHashNode sta_ds = NULL;
6883 	QDF_STATUS status;
6884 	tSirMacAddr bc_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
6885 
6886 	/* IBSS and NDI doesn't send Disassoc frame */
6887 	if (!LIM_IS_NDI_ROLE(session)) {
6888 		pe_debug("stop_bss_reason: %d", session->stop_bss_reason);
6889 		if (session->stop_bss_reason == eSIR_SME_MIC_COUNTER_MEASURES)
6890 			__lim_counter_measures(mac_ctx, session);
6891 		else
6892 			lim_send_disassoc_mgmt_frame(mac_ctx,
6893 				REASON_DEAUTH_NETWORK_LEAVING,
6894 				bc_addr, session, false);
6895 	}
6896 
6897 	for (i = 1; i < session->dph.dphHashTable.size; i++) {
6898 		sta_ds = dph_get_hash_entry(mac_ctx, i,
6899 					    &session->dph.dphHashTable);
6900 		if (!sta_ds)
6901 			continue;
6902 		lim_mlo_notify_peer_disconn(session, sta_ds);
6903 		status = lim_del_sta(mac_ctx, sta_ds, false, session);
6904 		if (QDF_STATUS_SUCCESS == status) {
6905 			lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr,
6906 						  sta_ds->assocId, session);
6907 			if (lim_is_mlo_conn(session, sta_ds))
6908 				lim_release_mlo_conn_idx(mac_ctx,
6909 							 sta_ds->assocId,
6910 							 session, false);
6911 			else
6912 				lim_release_peer_idx(mac_ctx, sta_ds->assocId,
6913 						     session);
6914 		} else {
6915 			pe_err("lim_del_sta failed with Status: %d", status);
6916 			QDF_ASSERT(0);
6917 		}
6918 	}
6919 
6920 	/**
6921 	 * Scenario: CSA happens and south bound disconnection got queued
6922 	 * in serialization parallelly.
6923 	 * As part of CSA, remove all peer from serialization, so that when
6924 	 * south bound disconnection becomes active, it should not lead to a
6925 	 * race where the peer is trying to connect and the driver is trying
6926 	 * to disconnect the same peer, leading to an active command timeout
6927 	 */
6928 	lim_flush_all_peer_from_serialization_queue(mac_ctx, session);
6929 
6930 	lim_disconnect_complete(session, false);
6931 	if (mac_ctx->del_peers_ind_cb)
6932 		mac_ctx->del_peers_ind_cb(mac_ctx->psoc, session->vdev_id);
6933 }
6934 
6935 QDF_STATUS lim_sta_send_del_bss(struct pe_session *session)
6936 {
6937 	struct mac_context *mac_ctx = session->mac_ctx;
6938 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
6939 	tpDphHashNode sta_ds = NULL;
6940 
6941 	sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
6942 				    &session->dph.dphHashTable);
6943 	if (!sta_ds) {
6944 		pe_err("DPH Entry for STA is missing, failed to send delbss");
6945 		goto end;
6946 	}
6947 
6948 	status = lim_del_bss(mac_ctx, sta_ds, 0, session);
6949 	if (QDF_IS_STATUS_ERROR(status))
6950 		pe_err("delBss failed for bss %d", session->vdev_id);
6951 
6952 end:
6953 	return status;
6954 }
6955 
6956 QDF_STATUS lim_send_vdev_stop(struct pe_session *session)
6957 {
6958 	struct mac_context *mac_ctx = session->mac_ctx;
6959 	QDF_STATUS status;
6960 
6961 	status = lim_del_bss(mac_ctx, NULL, session->vdev_id, session);
6962 
6963 	if (QDF_IS_STATUS_ERROR(status)) {
6964 		pe_err("delBss failed for bss %d", session->vdev_id);
6965 		lim_send_stop_bss_failure_resp(mac_ctx, session);
6966 	}
6967 
6968 	return status;
6969 }
6970 
6971 /**
6972  * lim_delete_peers_and_send_vdev_stop() -delete peers and send vdev stop
6973  * @session: session pointer
6974  *
6975  * Return None
6976  */
6977 static void lim_delete_peers_and_send_vdev_stop(struct pe_session *session)
6978 {
6979 	struct mac_context *mac_ctx = session->mac_ctx;
6980 	QDF_STATUS status;
6981 
6982 	if (QDF_IS_STATUS_SUCCESS(
6983 	    wlan_vdev_is_restart_progress(session->vdev)))
6984 		status =
6985 		 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
6986 					       WLAN_VDEV_SM_EV_RESTART_REQ_FAIL,
6987 					       sizeof(*session), session);
6988 	else
6989 		status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
6990 						       WLAN_VDEV_SM_EV_DOWN,
6991 						       sizeof(*session),
6992 						       session);
6993 	if (QDF_IS_STATUS_ERROR(status))
6994 		lim_send_stop_bss_failure_resp(mac_ctx, session);
6995 }
6996 
6997 static void
6998 __lim_handle_sme_stop_bss_request(struct mac_context *mac, uint32_t *msg_buf)
6999 {
7000 	struct stop_bss_req stop_bss_req;
7001 	tLimSmeStates prevState;
7002 	struct pe_session *pe_session;
7003 	struct qdf_mac_addr bssid;
7004 	uint8_t vdev_id;
7005 	uint8_t session_id;
7006 
7007 	qdf_mem_copy(&stop_bss_req, msg_buf, sizeof(stop_bss_req));
7008 	vdev_id = stop_bss_req.vdev_id;
7009 	wlan_mlme_get_mac_vdev_id(mac->pdev, vdev_id, &bssid);
7010 
7011 	pe_session = pe_find_session_by_bssid(mac, bssid.bytes,
7012 					       &session_id);
7013 	if (!pe_session) {
7014 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
7015 		       QDF_MAC_ADDR_REF(bssid.bytes));
7016 		lim_send_stop_bss_response(mac, vdev_id,
7017 					   eSIR_SME_INVALID_PARAMETERS);
7018 		return;
7019 	}
7020 
7021 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
7022 	lim_diag_event_report(mac, WLAN_PE_DIAG_STOP_BSS_REQ_EVENT, pe_session,
7023 			      0, 0);
7024 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
7025 
7026 	if (pe_session->limSmeState != eLIM_SME_NORMAL_STATE ||    /* Added For BT -AMP Support */
7027 	    LIM_IS_STA_ROLE(pe_session)) {
7028 		/**
7029 		 * Should not have received STOP_BSS_REQ in states
7030 		 * other than 'normal' state or on STA in Infrastructure
7031 		 * mode. Log error and return response to host.
7032 		 */
7033 		pe_err("received unexpected SME_STOP_BSS_REQ in state %X, for role %d",
7034 			pe_session->limSmeState,
7035 			GET_LIM_SYSTEM_ROLE(pe_session));
7036 		lim_print_sme_state(mac, LOGE, pe_session->limSmeState);
7037 		/* / Send Stop BSS response to host */
7038 		lim_send_stop_bss_response(mac, vdev_id,
7039 					   eSIR_SME_UNEXPECTED_REQ_RESULT_CODE);
7040 		return;
7041 	}
7042 
7043 	if (LIM_IS_AP_ROLE(pe_session))
7044 		lim_wpspbc_close(mac, pe_session);
7045 
7046 	prevState = pe_session->limSmeState;
7047 	pe_session->limPrevSmeState = prevState;
7048 
7049 	pe_session->limSmeState = eLIM_SME_IDLE_STATE;
7050 	MTRACE(mac_trace
7051 		       (mac, TRACE_CODE_SME_STATE, pe_session->peSessionId,
7052 		       pe_session->limSmeState));
7053 
7054 	pe_session->smeSessionId = vdev_id;
7055 	pe_session->stop_bss_reason = 0;
7056 
7057 	if (!LIM_IS_NDI_ROLE(pe_session)) {
7058 		/* Free the buffer allocated in START_BSS_REQ */
7059 		qdf_mem_free(pe_session->add_ie_params.probeRespData_buff);
7060 		pe_session->add_ie_params.probeRespDataLen = 0;
7061 		pe_session->add_ie_params.probeRespData_buff = NULL;
7062 
7063 		qdf_mem_free(pe_session->add_ie_params.assocRespData_buff);
7064 		pe_session->add_ie_params.assocRespDataLen = 0;
7065 		pe_session->add_ie_params.assocRespData_buff = NULL;
7066 
7067 		qdf_mem_free(pe_session->add_ie_params.probeRespBCNData_buff);
7068 		pe_session->add_ie_params.probeRespBCNDataLen = 0;
7069 		pe_session->add_ie_params.probeRespBCNData_buff = NULL;
7070 	}
7071 
7072 	lim_delete_peers_and_send_vdev_stop(pe_session);
7073 
7074 }
7075 
7076 /**
7077  * __lim_process_sme_stop_bss_req() - Process STOP_BSS from SME
7078  * @mac: Global MAC context
7079  * @pMsg: Message from SME
7080  *
7081  * Wrapper for the function __lim_handle_sme_stop_bss_request
7082  * This message will be deferred until softmac come out of
7083  * scan mode. Message should be handled even if we have
7084  * detected radar in the current operating channel.
7085  *
7086  * Return: true - If we consumed the buffer
7087  *         false - If have deferred the message.
7088  */
7089 
7090 static bool __lim_process_sme_stop_bss_req(struct mac_context *mac,
7091 					   struct scheduler_msg *pMsg)
7092 {
7093 	__lim_handle_sme_stop_bss_request(mac, (uint32_t *) pMsg->bodyptr);
7094 	return true;
7095 } /*** end __lim_process_sme_stop_bss_req() ***/
7096 
7097 void lim_process_sme_del_bss_rsp(struct mac_context *mac,
7098 				 struct pe_session *pe_session)
7099 {
7100 	SET_LIM_PROCESS_DEFD_MESGS(mac, true);
7101 	dph_hash_table_init(mac, &pe_session->dph.dphHashTable);
7102 	lim_delete_pre_auth_list(mac);
7103 	lim_send_stop_bss_response(mac, pe_session->vdev_id,
7104 				   eSIR_SME_SUCCESS);
7105 	return;
7106 }
7107 
7108 /**
7109  * __lim_process_sme_assoc_cnf_new() - process sme assoc/reassoc cnf
7110  *
7111  * @mac_ctx: pointer to mac context
7112  * @msg_type: message type
7113  * @msg_buf: pointer to the SME message buffer
7114  *
7115  * This function handles SME_ASSOC_CNF/SME_REASSOC_CNF
7116  * in BTAMP AP.
7117  *
7118  * Return: None
7119  */
7120 
7121 void __lim_process_sme_assoc_cnf_new(struct mac_context *mac_ctx, uint32_t msg_type,
7122 				uint32_t *msg_buf)
7123 {
7124 	struct assoc_cnf assoc_cnf;
7125 	tpDphHashNode sta_ds = NULL;
7126 	struct pe_session *session_entry = NULL;
7127 	uint8_t session_id;
7128 	tpSirAssocReq assoc_req;
7129 
7130 	if (!msg_buf) {
7131 		pe_err("msg_buf is NULL");
7132 		return;
7133 	}
7134 
7135 	qdf_mem_copy(&assoc_cnf, msg_buf, sizeof(assoc_cnf));
7136 	if (!__lim_is_sme_assoc_cnf_valid(&assoc_cnf)) {
7137 		pe_err("Received invalid SME_RE(ASSOC)_CNF message");
7138 		goto end;
7139 	}
7140 
7141 	session_entry = pe_find_session_by_bssid(mac_ctx, assoc_cnf.bssid.bytes,
7142 			&session_id);
7143 	if (!session_entry) {
7144 		pe_err("session does not exist for given bssId");
7145 		goto end;
7146 	}
7147 
7148 	if ((!LIM_IS_AP_ROLE(session_entry)) ||
7149 	    (session_entry->limSmeState != eLIM_SME_NORMAL_STATE)) {
7150 		pe_err("Rcvd unexpected msg %X in state %X, in role %X",
7151 			msg_type, session_entry->limSmeState,
7152 			GET_LIM_SYSTEM_ROLE(session_entry));
7153 		goto end;
7154 	}
7155 	sta_ds = dph_get_hash_entry(mac_ctx, assoc_cnf.aid,
7156 			&session_entry->dph.dphHashTable);
7157 	if (!sta_ds) {
7158 		pe_err("Rcvd invalid msg %X due to no STA ctx, aid %d, peer "QDF_MAC_ADDR_FMT,
7159 		       msg_type, assoc_cnf.aid,
7160 		       QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes));
7161 
7162 		/*
7163 		 * send a DISASSOC_IND message to WSM to make sure
7164 		 * the state in WSM and LIM is the same
7165 		 */
7166 		lim_send_sme_disassoc_ntf(mac_ctx, assoc_cnf.peer_macaddr.bytes,
7167 				eSIR_SME_STA_NOT_ASSOCIATED,
7168 				eLIM_PEER_ENTITY_DISASSOC, assoc_cnf.aid,
7169 				session_entry->smeSessionId,
7170 				session_entry);
7171 		goto end;
7172 	}
7173 	if (qdf_mem_cmp((uint8_t *)sta_ds->staAddr,
7174 				(uint8_t *) assoc_cnf.peer_macaddr.bytes,
7175 				QDF_MAC_ADDR_SIZE)) {
7176 		pe_debug("peerMacAddr mismatched for aid %d, peer "QDF_MAC_ADDR_FMT,
7177 			 assoc_cnf.aid,
7178 			 QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes));
7179 		goto end;
7180 	}
7181 
7182 	if ((sta_ds->mlmStaContext.mlmState != eLIM_MLM_WT_ASSOC_CNF_STATE) ||
7183 		((sta_ds->mlmStaContext.subType == LIM_ASSOC) &&
7184 		 (msg_type != eWNI_SME_ASSOC_CNF)) ||
7185 		((sta_ds->mlmStaContext.subType == LIM_REASSOC) &&
7186 		 (msg_type != eWNI_SME_ASSOC_CNF))) {
7187 		pe_debug("peer " QDF_MAC_ADDR_FMT " not in WT_ASSOC_CNF_STATE, for aid %d, sta mlmstate %d",
7188 			 QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes),
7189 			 assoc_cnf.aid, sta_ds->mlmStaContext.mlmState);
7190 		goto end;
7191 	}
7192 	/*
7193 	 * Deactivate/delete CNF_WAIT timer since ASSOC_CNF
7194 	 * has been received
7195 	 */
7196 	pe_debug("Received SME_ASSOC_CNF. Delete Timer");
7197 	lim_deactivate_and_change_per_sta_id_timer(mac_ctx,
7198 			eLIM_CNF_WAIT_TIMER, sta_ds->assocId);
7199 
7200 	if (assoc_cnf.status_code == eSIR_SME_SUCCESS) {
7201 		/*
7202 		 * In BTAMP-AP, PE already finished the WMA_ADD_STA sequence
7203 		 * when it had received Assoc Request frame. Now, PE just needs
7204 		 * to send association rsp frame to the requesting BTAMP-STA.
7205 		 */
7206 		sta_ds->mlmStaContext.mlmState =
7207 			eLIM_MLM_LINK_ESTABLISHED_STATE;
7208 		sta_ds->mlmStaContext.owe_ie = assoc_cnf.owe_ie;
7209 		sta_ds->mlmStaContext.owe_ie_len = assoc_cnf.owe_ie_len;
7210 		sta_ds->mlmStaContext.ft_ie = assoc_cnf.ft_ie;
7211 		sta_ds->mlmStaContext.ft_ie_len = assoc_cnf.ft_ie_len;
7212 		pe_debug("sending Assoc Rsp frame to STA assoc id=%d, tx cb %d",
7213 			 sta_ds->assocId, assoc_cnf.need_assoc_rsp_tx_cb);
7214 		lim_send_assoc_rsp_mgmt_frame(
7215 					mac_ctx, QDF_STATUS_SUCCESS,
7216 					sta_ds->assocId, sta_ds->staAddr,
7217 					sta_ds->mlmStaContext.subType, sta_ds,
7218 					session_entry,
7219 					assoc_cnf.need_assoc_rsp_tx_cb);
7220 		sta_ds->mlmStaContext.owe_ie = NULL;
7221 		sta_ds->mlmStaContext.owe_ie_len = 0;
7222 		sta_ds->mlmStaContext.ft_ie = NULL;
7223 		sta_ds->mlmStaContext.ft_ie_len = 0;
7224 		goto end;
7225 	} else {
7226 		uint8_t add_pre_auth_context = true;
7227 		/*
7228 		 * SME_ASSOC_CNF status is non-success, so STA is not allowed
7229 		 * to be associated since the HAL sta entry is created for
7230 		 * denied STA we need to remove this HAL entry.
7231 		 * So to do that set updateContext to 1
7232 		 */
7233 		enum wlan_status_code mac_status_code =
7234 					STATUS_UNSPECIFIED_FAILURE;
7235 
7236 		if (!sta_ds->mlmStaContext.updateContext)
7237 			sta_ds->mlmStaContext.updateContext = 1;
7238 		pe_debug("Recv Assoc Cnf, status Code : %d(assoc id=%d) Reason code: %d",
7239 			 assoc_cnf.status_code, sta_ds->assocId,
7240 			 assoc_cnf.mac_status_code);
7241 		if (assoc_cnf.mac_status_code)
7242 			mac_status_code = assoc_cnf.mac_status_code;
7243 		if (assoc_cnf.mac_status_code == STATUS_INVALID_PMKID ||
7244 		    assoc_cnf.mac_status_code ==
7245 			STATUS_NOT_SUPPORTED_AUTH_ALG)
7246 			add_pre_auth_context = false;
7247 
7248 		lim_reject_association(mac_ctx, sta_ds->staAddr,
7249 				       sta_ds->mlmStaContext.subType,
7250 				       add_pre_auth_context,
7251 				       sta_ds->mlmStaContext.authType,
7252 				       sta_ds->assocId, true,
7253 				       mac_status_code,
7254 				       session_entry);
7255 	}
7256 end:
7257 	if (((session_entry) && (sta_ds)) &&
7258 		(session_entry->parsedAssocReq[sta_ds->assocId]) &&
7259 		!assoc_cnf.need_assoc_rsp_tx_cb) {
7260 		assoc_req = (tpSirAssocReq)
7261 			session_entry->parsedAssocReq[sta_ds->assocId];
7262 		lim_free_assoc_req_frm_buf(assoc_req);
7263 		qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
7264 		session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
7265 	}
7266 	qdf_mem_free(assoc_cnf.owe_ie);
7267 	qdf_mem_free(assoc_cnf.ft_ie);
7268 }
7269 
7270 static void
7271 __lim_process_sme_addts_req(struct mac_context *mac, uint32_t *msg_buf)
7272 {
7273 	tpDphHashNode sta;
7274 	tSirMacAddr peerMac;
7275 	tpSirAddtsReq pSirAddts;
7276 	uint32_t timeout;
7277 	struct pe_session *pe_session;
7278 	uint8_t sessionId;      /* PE sessionId */
7279 	uint8_t smesessionId;
7280 
7281 	if (!msg_buf) {
7282 		pe_err("Buffer is Pointing to NULL");
7283 		return;
7284 	}
7285 
7286 	pSirAddts = (tpSirAddtsReq) msg_buf;
7287 	smesessionId = pSirAddts->sessionId;
7288 	pe_session = pe_find_session_by_bssid(mac, pSirAddts->bssid.bytes,
7289 						 &sessionId);
7290 	if (!pe_session) {
7291 		pe_err("Session Does not exist for given bssId");
7292 		lim_send_sme_addts_rsp(mac, pSirAddts->rspReqd,
7293 				       QDF_STATUS_E_FAILURE,
7294 				       NULL, pSirAddts->req.tspec,
7295 				       smesessionId);
7296 		return;
7297 	}
7298 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
7299 	lim_diag_event_report(mac, WLAN_PE_DIAG_ADDTS_REQ_EVENT, pe_session, 0,
7300 			      0);
7301 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
7302 
7303 	/* if sta
7304 	 *  - verify assoc state
7305 	 *  - send addts request to ap
7306 	 *  - wait for addts response from ap
7307 	 * if ap, just ignore with error log
7308 	 */
7309 	pe_debug("Received SME_ADDTS_REQ (TSid %d, UP %d)",
7310 		pSirAddts->req.tspec.tsinfo.traffic.tsid,
7311 		pSirAddts->req.tspec.tsinfo.traffic.userPrio);
7312 
7313 	if (!LIM_IS_STA_ROLE(pe_session)) {
7314 		pe_err("AddTs received on AP - ignoring");
7315 		goto send_failure_addts_rsp;
7316 	}
7317 
7318 	sta =
7319 		dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
7320 				   &pe_session->dph.dphHashTable);
7321 
7322 	if (!sta) {
7323 		pe_err("Cannot find AP context for addts req");
7324 		goto send_failure_addts_rsp;
7325 	}
7326 
7327 	if ((!sta->valid) || (sta->mlmStaContext.mlmState !=
7328 	    eLIM_MLM_LINK_ESTABLISHED_STATE)) {
7329 		pe_err("AddTs received in invalid MLM state");
7330 		goto send_failure_addts_rsp;
7331 	}
7332 
7333 	pSirAddts->req.wsmTspecPresent = 0;
7334 	pSirAddts->req.wmeTspecPresent = 0;
7335 	pSirAddts->req.lleTspecPresent = 0;
7336 
7337 	if ((sta->wsmEnabled) &&
7338 	    (pSirAddts->req.tspec.tsinfo.traffic.accessPolicy !=
7339 	     SIR_MAC_ACCESSPOLICY_EDCA))
7340 		pSirAddts->req.wsmTspecPresent = 1;
7341 	else if (sta->wmeEnabled)
7342 		pSirAddts->req.wmeTspecPresent = 1;
7343 	else if (sta->lleEnabled)
7344 		pSirAddts->req.lleTspecPresent = 1;
7345 	else {
7346 		pe_warn("ADDTS_REQ ignore - qos is disabled");
7347 		goto send_failure_addts_rsp;
7348 	}
7349 
7350 	if ((pe_session->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
7351 	    (pe_session->limSmeState != eLIM_SME_LINK_EST_STATE)) {
7352 		pe_err("AddTs received in invalid LIMsme state (%d)",
7353 			pe_session->limSmeState);
7354 		goto send_failure_addts_rsp;
7355 	}
7356 
7357 	if (mac->lim.gLimAddtsSent) {
7358 		pe_err("Addts (token %d, tsid %d, up %d) is still pending",
7359 			mac->lim.gLimAddtsReq.req.dialogToken,
7360 			mac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid,
7361 			mac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.
7362 			userPrio);
7363 		goto send_failure_addts_rsp;
7364 	}
7365 
7366 	sir_copy_mac_addr(peerMac, pe_session->bssId);
7367 
7368 	/* save the addts request */
7369 	mac->lim.gLimAddtsSent = true;
7370 	qdf_mem_copy((uint8_t *) &mac->lim.gLimAddtsReq,
7371 		     (uint8_t *) pSirAddts, sizeof(tSirAddtsReq));
7372 
7373 	/* ship out the message now */
7374 	lim_send_addts_req_action_frame(mac, peerMac, &pSirAddts->req,
7375 					pe_session);
7376 	pe_debug("Sent ADDTS request");
7377 	/* start a timer to wait for the response */
7378 	if (pSirAddts->timeout)
7379 		timeout = pSirAddts->timeout;
7380 	else
7381 		timeout = mac->mlme_cfg->timeouts.addts_rsp_timeout;
7382 
7383 	timeout = SYS_MS_TO_TICKS(timeout);
7384 	if (tx_timer_change(&mac->lim.lim_timers.gLimAddtsRspTimer, timeout, 0)
7385 	    != TX_SUCCESS) {
7386 		pe_err("AddtsRsp timer change failed!");
7387 		goto send_failure_addts_rsp;
7388 	}
7389 	mac->lim.gLimAddtsRspTimerCount++;
7390 	if (tx_timer_change_context(&mac->lim.lim_timers.gLimAddtsRspTimer,
7391 				    mac->lim.gLimAddtsRspTimerCount) !=
7392 	    TX_SUCCESS) {
7393 		pe_err("AddtsRsp timer change failed!");
7394 		goto send_failure_addts_rsp;
7395 	}
7396 	MTRACE(mac_trace
7397 		       (mac, TRACE_CODE_TIMER_ACTIVATE, pe_session->peSessionId,
7398 		       eLIM_ADDTS_RSP_TIMER));
7399 
7400 	/* add the sessionId to the timer object */
7401 	mac->lim.lim_timers.gLimAddtsRspTimer.sessionId = sessionId;
7402 	if (tx_timer_activate(&mac->lim.lim_timers.gLimAddtsRspTimer) !=
7403 	    TX_SUCCESS) {
7404 		pe_err("AddtsRsp timer activation failed!");
7405 		goto send_failure_addts_rsp;
7406 	}
7407 	return;
7408 
7409 send_failure_addts_rsp:
7410 	lim_send_sme_addts_rsp(mac, pSirAddts->rspReqd, QDF_STATUS_E_FAILURE,
7411 			       pe_session, pSirAddts->req.tspec,
7412 			       smesessionId);
7413 }
7414 
7415 #ifdef WLAN_FEATURE_MSCS
7416 static void
7417 __lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf)
7418 {
7419 	struct qdf_mac_addr peer_mac;
7420 	struct mscs_req_info *mscs_req;
7421 	struct pe_session *pe_session;
7422 	uint8_t pe_session_id;
7423 
7424 	if (!msg_buf) {
7425 		pe_err("Buffer is Pointing to NULL");
7426 		return;
7427 	}
7428 
7429 	mscs_req = (struct mscs_req_info *) msg_buf;
7430 	pe_session = pe_find_session_by_bssid(mac, mscs_req->bssid.bytes,
7431 					      &pe_session_id);
7432 	if (!pe_session) {
7433 		pe_err("Session Does not exist for bssid: " QDF_MAC_ADDR_FMT,
7434 			QDF_MAC_ADDR_REF(mscs_req->bssid.bytes));
7435 		return;
7436 	}
7437 
7438 	if (!LIM_IS_STA_ROLE(pe_session)) {
7439 		pe_err("MSCS req received on AP - ignoring");
7440 		return;
7441 	}
7442 
7443 	if (QDF_IS_STATUS_ERROR(wlan_vdev_mlme_is_active(pe_session->vdev))) {
7444 		pe_err("mscs req in unexpected vdev SM state:%d",
7445 		       wlan_vdev_mlme_get_state(pe_session->vdev));
7446 		return;
7447 	}
7448 
7449 	if (mscs_req->is_mscs_req_sent) {
7450 		pe_err("MSCS req already sent");
7451 		return;
7452 	}
7453 
7454 	qdf_mem_copy(peer_mac.bytes, pe_session->bssId, QDF_MAC_ADDR_SIZE);
7455 
7456 	/* save the mscs request */
7457 	mscs_req->is_mscs_req_sent = true;
7458 
7459 	/* ship out the message now */
7460 	lim_send_mscs_req_action_frame(mac, peer_mac, mscs_req,
7461 				       pe_session);
7462 }
7463 #else
7464 static inline void
7465 __lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf)
7466 {
7467 	return;
7468 }
7469 
7470 #endif
7471 
7472 static void
7473 __lim_process_sme_delts_req(struct mac_context *mac, uint32_t *msg_buf)
7474 {
7475 	tSirMacAddr peerMacAddr;
7476 	uint8_t ac;
7477 	struct mac_ts_info *pTsinfo;
7478 	tpSirDeltsReq pDeltsReq = (tpSirDeltsReq) msg_buf;
7479 	tpDphHashNode sta = NULL;
7480 	struct pe_session *pe_session;
7481 	uint8_t sessionId;
7482 	uint32_t status = QDF_STATUS_SUCCESS;
7483 	uint8_t smesessionId;
7484 
7485 	smesessionId = pDeltsReq->sessionId;
7486 
7487 	pe_session = pe_find_session_by_bssid(mac,
7488 				pDeltsReq->bssid.bytes,
7489 				&sessionId);
7490 	if (!pe_session) {
7491 		pe_err("Session Does not exist for given bssId");
7492 		status = QDF_STATUS_E_FAILURE;
7493 		goto end;
7494 	}
7495 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
7496 	lim_diag_event_report(mac, WLAN_PE_DIAG_DELTS_REQ_EVENT, pe_session, 0,
7497 			      0);
7498 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
7499 
7500 	if (QDF_STATUS_SUCCESS !=
7501 	    lim_validate_delts_req(mac, pDeltsReq, peerMacAddr, pe_session)) {
7502 		pe_err("lim_validate_delts_req failed");
7503 		status = QDF_STATUS_E_FAILURE;
7504 		lim_send_sme_delts_rsp(mac, pDeltsReq, QDF_STATUS_E_FAILURE,
7505 				       pe_session, smesessionId);
7506 		return;
7507 	}
7508 
7509 	pe_debug("Sent DELTS request to station with assocId = %d MacAddr = "
7510 		QDF_MAC_ADDR_FMT,
7511 		pDeltsReq->aid, QDF_MAC_ADDR_REF(peerMacAddr));
7512 
7513 	lim_send_delts_req_action_frame(mac, peerMacAddr,
7514 					pDeltsReq->req.wmeTspecPresent,
7515 					&pDeltsReq->req.tsinfo,
7516 					&pDeltsReq->req.tspec, pe_session);
7517 
7518 	pTsinfo =
7519 		pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.
7520 		tsinfo : &pDeltsReq->req.tsinfo;
7521 
7522 	/* We've successfully send DELTS frame to AP. Update the
7523 	 * dynamic UAPSD mask. The AC for this TSPEC to be deleted
7524 	 * is no longer trigger enabled or delivery enabled
7525 	 */
7526 	lim_set_tspec_uapsd_mask_per_session(mac, pe_session,
7527 					     pTsinfo, CLEAR_UAPSD_MASK);
7528 
7529 	/* We're deleting the TSPEC, so this particular AC is no longer
7530 	 * admitted.  PE needs to downgrade the EDCA
7531 	 * parameters(for the AC for which TS is being deleted) to the
7532 	 * next best AC for which ACM is not enabled, and send the
7533 	 * updated values to HAL.
7534 	 */
7535 	ac = upToAc(pTsinfo->traffic.userPrio);
7536 
7537 	if (pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) {
7538 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
7539 			~(1 << ac);
7540 	} else if (pTsinfo->traffic.direction ==
7541 		   SIR_MAC_DIRECTION_DNLINK) {
7542 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
7543 			~(1 << ac);
7544 	} else if (pTsinfo->traffic.direction ==
7545 		   SIR_MAC_DIRECTION_BIDIR) {
7546 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
7547 			~(1 << ac);
7548 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
7549 			~(1 << ac);
7550 	}
7551 
7552 	lim_set_active_edca_params(mac, pe_session->gLimEdcaParams,
7553 				   pe_session);
7554 
7555 	sta =
7556 		dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
7557 				   &pe_session->dph.dphHashTable);
7558 	if (sta) {
7559 		lim_send_edca_params(mac, pe_session->gLimEdcaParamsActive,
7560 				     pe_session->vdev_id, false);
7561 		status = QDF_STATUS_SUCCESS;
7562 	} else {
7563 		pe_err("Self entry missing in Hash Table");
7564 		status = QDF_STATUS_E_FAILURE;
7565 	}
7566 #ifdef FEATURE_WLAN_ESE
7567 	lim_send_sme_tsm_ie_ind(mac, pe_session, 0, 0, 0);
7568 #endif
7569 
7570 	/* send an sme response back */
7571 end:
7572 	lim_send_sme_delts_rsp(mac, pDeltsReq, QDF_STATUS_SUCCESS, pe_session,
7573 			       smesessionId);
7574 }
7575 
7576 void lim_process_sme_addts_rsp_timeout(struct mac_context *mac, uint32_t param)
7577 {
7578 	/* fetch the pe_session based on the sessionId */
7579 	struct pe_session *pe_session;
7580 
7581 	pe_session = pe_find_session_by_session_id(mac,
7582 				mac->lim.lim_timers.gLimAddtsRspTimer.
7583 				sessionId);
7584 	if (!pe_session) {
7585 		pe_err("Session Does not exist for given sessionID");
7586 		return;
7587 	}
7588 
7589 	if (!LIM_IS_STA_ROLE(pe_session)) {
7590 		pe_warn("AddtsRspTimeout in non-Sta role (%d)",
7591 			GET_LIM_SYSTEM_ROLE(pe_session));
7592 		mac->lim.gLimAddtsSent = false;
7593 		return;
7594 	}
7595 
7596 	if (!mac->lim.gLimAddtsSent) {
7597 		pe_warn("AddtsRspTimeout but no AddtsSent");
7598 		return;
7599 	}
7600 
7601 	if (param != mac->lim.gLimAddtsRspTimerCount) {
7602 		pe_err("Invalid AddtsRsp Timer count %d (exp %d)", param,
7603 			mac->lim.gLimAddtsRspTimerCount);
7604 		return;
7605 	}
7606 	/* this a real response timeout */
7607 	mac->lim.gLimAddtsSent = false;
7608 	mac->lim.gLimAddtsRspTimerCount++;
7609 
7610 	lim_send_sme_addts_rsp(mac, true, eSIR_SME_ADDTS_RSP_TIMEOUT,
7611 			       pe_session, mac->lim.gLimAddtsReq.req.tspec,
7612 			       pe_session->smeSessionId);
7613 }
7614 
7615 #ifdef FEATURE_WLAN_ESE
7616 /**
7617  * __lim_process_sme_get_tsm_stats_request() - get tsm stats request
7618  *
7619  * @mac: Pointer to Global MAC structure
7620  * @msg_buf: A pointer to the SME message buffer
7621  *
7622  * Return: None
7623  */
7624 static void __lim_process_sme_get_tsm_stats_request(struct mac_context *mac,
7625 						    uint32_t *msg_buf)
7626 {
7627 	struct scheduler_msg msgQ = {0};
7628 
7629 	msgQ.type = WMA_TSM_STATS_REQ;
7630 	msgQ.reserved = 0;
7631 	msgQ.bodyptr = msg_buf;
7632 	msgQ.bodyval = 0;
7633 	MTRACE(mac_trace_msg_tx(mac, NO_SESSION, msgQ.type));
7634 
7635 	if (QDF_STATUS_SUCCESS != (wma_post_ctrl_msg(mac, &msgQ))) {
7636 		qdf_mem_free(msg_buf);
7637 		msg_buf = NULL;
7638 		pe_err("Unable to forward request");
7639 		return;
7640 	}
7641 }
7642 #endif /* FEATURE_WLAN_ESE */
7643 
7644 static void lim_process_sme_set_addba_accept(struct mac_context *mac_ctx,
7645 		struct sme_addba_accept *msg)
7646 {
7647 	if (!msg) {
7648 		pe_err("Msg Buffer is NULL");
7649 		return;
7650 	}
7651 	if (!msg->addba_accept)
7652 		mac_ctx->reject_addba_req = 1;
7653 	else
7654 		mac_ctx->reject_addba_req = 0;
7655 }
7656 
7657 static void lim_process_sme_update_edca_params(struct mac_context *mac_ctx,
7658 					       uint32_t vdev_id)
7659 {
7660 	struct pe_session *pe_session;
7661 	tpDphHashNode sta_ds_ptr;
7662 
7663 	pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7664 	if (!pe_session) {
7665 		pe_err("Session does not exist: vdev_id %d", vdev_id);
7666 		return;
7667 	}
7668 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_BE].no_ack =
7669 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BE];
7670 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_BK].no_ack =
7671 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BK];
7672 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_VI].no_ack =
7673 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VI];
7674 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_VO].no_ack =
7675 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VO];
7676 	sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
7677 					&pe_session->dph.dphHashTable);
7678 	if (sta_ds_ptr)
7679 		lim_send_edca_params(mac_ctx,
7680 				     pe_session->gLimEdcaParamsActive,
7681 				     pe_session->vdev_id, false);
7682 	else
7683 		pe_err("Self entry missing in Hash Table");
7684 }
7685 
7686 /**
7687  * lim_process_sme_update_session_edca_txq_params()
7688  * Update the edca tx queue parameters for the vdev
7689  *
7690  * @mac_ctx: Pointer to Global MAC structure
7691  * @msg_buf: Pointer to SME message buffer
7692  *
7693  * Return: None
7694  */
7695 static void
7696 lim_process_sme_update_session_edca_txq_params(struct mac_context *mac_ctx,
7697 					       uint32_t *msg_buf)
7698 {
7699 	struct sir_update_session_txq_edca_param *msg;
7700 	struct pe_session *pe_session;
7701 	uint8_t ac;
7702 
7703 	if (!msg_buf) {
7704 		pe_err("Buffer is Pointing to NULL");
7705 		return;
7706 	}
7707 
7708 	msg = (struct sir_update_session_txq_edca_param *)msg_buf;
7709 
7710 	pe_session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
7711 	if (!pe_session) {
7712 		pe_warn("Session does not exist for given vdev_id %d",
7713 			msg->vdev_id);
7714 		return;
7715 	}
7716 
7717 	ac = msg->txq_edca_params.aci.aci;
7718 	pe_debug("received SME Session tx queue update for vdev %d queue %d",
7719 		 msg->vdev_id, ac);
7720 
7721 	if ((!LIM_IS_AP_ROLE(pe_session)) ||
7722 	    (pe_session->limSmeState != eLIM_SME_NORMAL_STATE)) {
7723 		pe_err("Rcvd edca update req in state %X, in role %X",
7724 		       pe_session->limSmeState,
7725 		       GET_LIM_SYSTEM_ROLE(pe_session));
7726 		return;
7727 	}
7728 
7729 	pe_session->gLimEdcaParams[ac].cw.min =
7730 			msg->txq_edca_params.cw.min;
7731 	pe_session->gLimEdcaParams[ac].cw.max =
7732 			msg->txq_edca_params.cw.max;
7733 	pe_session->gLimEdcaParams[ac].aci.aci =
7734 			msg->txq_edca_params.aci.aci;
7735 	pe_session->gLimEdcaParams[ac].aci.aifsn =
7736 			msg->txq_edca_params.aci.aifsn;
7737 	pe_session->gLimEdcaParams[ac].txoplimit =
7738 			msg->txq_edca_params.txoplimit;
7739 
7740 	lim_send_edca_params(mac_ctx,
7741 			     pe_session->gLimEdcaParams,
7742 			     pe_session->vdev_id, false);
7743 }
7744 
7745 static void lim_process_sme_update_mu_edca_params(struct mac_context *mac_ctx,
7746 						  uint32_t vdev_id)
7747 {
7748 	struct pe_session *pe_session;
7749 	tpDphHashNode sta_ds_ptr;
7750 
7751 	pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7752 	if (!pe_session) {
7753 		pe_err("Session does not exist: vdev_id %d", vdev_id);
7754 		return;
7755 	}
7756 	sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
7757 					&pe_session->dph.dphHashTable);
7758 	if (sta_ds_ptr)
7759 		lim_send_edca_params(mac_ctx, mac_ctx->usr_mu_edca_params,
7760 				     pe_session->vdev_id, true);
7761 	else
7762 		pe_err("Self entry missing in Hash Table");
7763 }
7764 
7765 static void
7766 lim_process_sme_cfg_action_frm_in_tb_ppdu(struct mac_context *mac_ctx,
7767 					  struct  sir_cfg_action_frm_tb_ppdu
7768 					  *msg)
7769 {
7770 	if (!msg) {
7771 		pe_err("Buffer is NULL");
7772 		return;
7773 	}
7774 
7775 	lim_send_action_frm_tb_ppdu_cfg(mac_ctx, msg->vdev_id, msg->cfg);
7776 }
7777 
7778 static void
7779 lim_process_sme_send_vdev_pause(struct mac_context *mac_ctx,
7780 				struct sme_vdev_pause *msg)
7781 {
7782 	struct pe_session *session;
7783 	uint16_t vdev_pause_dur_ms;
7784 
7785 	if (!msg) {
7786 		pe_err("Buffer is NULL");
7787 		return;
7788 	}
7789 
7790 	session = pe_find_session_by_vdev_id(mac_ctx, msg->session_id);
7791 	if (!session) {
7792 		pe_warn("Session does not exist for given BSSID");
7793 		return;
7794 	}
7795 
7796 	if (!(wlan_vdev_mlme_get_opmode(session->vdev) == QDF_STA_MODE) &&
7797 	    wlan_vdev_mlme_is_mlo_vdev(session->vdev)) {
7798 		pe_err("vdev is not ML STA");
7799 		return;
7800 	}
7801 
7802 	vdev_pause_dur_ms = session->beaconParams.beaconInterval *
7803 						msg->vdev_pause_duration;
7804 	wlan_mlo_send_vdev_pause(mac_ctx->psoc, session->vdev,
7805 				 msg->session_id, vdev_pause_dur_ms);
7806 }
7807 
7808 static void lim_process_sme_update_config(struct mac_context *mac_ctx,
7809 					  struct update_config *msg)
7810 {
7811 	struct pe_session *pe_session;
7812 
7813 	pe_debug("received eWNI_SME_UPDATE_HT_CONFIG message");
7814 	if (!msg) {
7815 		pe_err("Buffer is Pointing to NULL");
7816 		return;
7817 	}
7818 
7819 	pe_session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
7820 	if (!pe_session) {
7821 		pe_warn("Session does not exist for given BSSID");
7822 		return;
7823 	}
7824 
7825 	switch (msg->capab) {
7826 	case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
7827 		pe_session->ht_config.adv_coding_cap = msg->value;
7828 		break;
7829 	case WNI_CFG_HT_CAP_INFO_TX_STBC:
7830 		pe_session->ht_config.tx_stbc = msg->value;
7831 		break;
7832 	case WNI_CFG_HT_CAP_INFO_RX_STBC:
7833 		pe_session->ht_config.rx_stbc = msg->value;
7834 		break;
7835 	case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
7836 		pe_session->ht_config.short_gi_20_mhz = msg->value;
7837 		break;
7838 	case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
7839 		pe_session->ht_config.short_gi_40_mhz = msg->value;
7840 		break;
7841 	}
7842 
7843 	if (LIM_IS_AP_ROLE(pe_session)) {
7844 		sch_set_fixed_beacon_fields(mac_ctx, pe_session);
7845 		lim_send_beacon_ind(mac_ctx, pe_session, REASON_CONFIG_UPDATE);
7846 	}
7847 }
7848 
7849 void
7850 lim_send_vdev_restart(struct mac_context *mac,
7851 		      struct pe_session *pe_session, uint8_t sessionId)
7852 {
7853 	struct vdev_mlme_obj *mlme_obj;
7854 
7855 	if (!pe_session) {
7856 		pe_err("Invalid parameters");
7857 		return;
7858 	}
7859 
7860 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
7861 	if (!mlme_obj) {
7862 		pe_err("vdev component object is NULL");
7863 		return;
7864 	}
7865 
7866 	mlme_obj->mgmt.ap.hidden_ssid = pe_session->ssidHidden ? true : false;
7867 
7868 	vdev_mgr_start_send(mlme_obj,  true);
7869 }
7870 
7871 static void lim_handle_update_ssid_hidden(struct mac_context *mac_ctx,
7872 				struct pe_session *session, uint8_t ssid_hidden)
7873 {
7874 	pe_debug("rcvd HIDE_SSID message old HIDE_SSID: %d new HIDE_SSID: %d",
7875 			session->ssidHidden, ssid_hidden);
7876 
7877 	if (ssid_hidden != session->ssidHidden) {
7878 		session->ssidHidden = ssid_hidden;
7879 	} else {
7880 		pe_debug("Dont process HIDE_SSID msg with existing setting");
7881 		return;
7882 	}
7883 
7884 	ap_mlme_set_hidden_ssid_restart_in_progress(session->vdev, true);
7885 	wlan_vdev_mlme_sm_deliver_evt(session->vdev,
7886 				      WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
7887 				      sizeof(*session), session);
7888 }
7889 
7890 /**
7891  * __lim_process_sme_session_update - process SME session update msg
7892  *
7893  * @mac_ctx: Pointer to global mac context
7894  * @msg_buf: Pointer to the received message buffer
7895  *
7896  * Return: None
7897  */
7898 static void __lim_process_sme_session_update(struct mac_context *mac_ctx,
7899 						uint32_t *msg_buf)
7900 {
7901 	struct sir_update_session_param *msg;
7902 	struct pe_session *session;
7903 
7904 	if (!msg_buf) {
7905 		pe_err("Buffer is Pointing to NULL");
7906 		return;
7907 	}
7908 
7909 	msg = (struct sir_update_session_param *) msg_buf;
7910 
7911 	session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
7912 	if (!session) {
7913 		pe_warn("Session does not exist for given vdev_id %d",
7914 			msg->vdev_id);
7915 		return;
7916 	}
7917 
7918 	pe_debug("received SME Session update for %d val %d",
7919 			msg->param_type, msg->param_val);
7920 	switch (msg->param_type) {
7921 	case SIR_PARAM_SSID_HIDDEN:
7922 		lim_handle_update_ssid_hidden(mac_ctx, session, msg->param_val);
7923 		break;
7924 	default:
7925 		pe_err("Unknown session param");
7926 		break;
7927 	}
7928 }
7929 
7930 /*
7931    Update the beacon Interval dynamically if beaconInterval is different in MCC
7932  */
7933 static void __lim_process_sme_change_bi(struct mac_context *mac,
7934 					uint32_t *msg_buf)
7935 {
7936 	struct wlan_change_bi *pChangeBIParams;
7937 	struct pe_session *pe_session;
7938 	uint8_t sessionId = 0;
7939 	tUpdateBeaconParams beaconParams;
7940 
7941 	pe_debug("received Update Beacon Interval message");
7942 
7943 	if (!msg_buf) {
7944 		pe_err("Buffer is Pointing to NULL");
7945 		return;
7946 	}
7947 
7948 	qdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams));
7949 	pChangeBIParams = (struct wlan_change_bi *)msg_buf;
7950 
7951 	pe_session = pe_find_session_by_bssid(mac,
7952 				pChangeBIParams->bssid.bytes,
7953 				&sessionId);
7954 	if (!pe_session) {
7955 		pe_err("Session does not exist for given BSSID");
7956 		return;
7957 	}
7958 
7959 	/*Update pe_session Beacon Interval */
7960 	if (pe_session->beaconParams.beaconInterval !=
7961 	    pChangeBIParams->beacon_interval) {
7962 		pe_session->beaconParams.beaconInterval =
7963 			pChangeBIParams->beacon_interval;
7964 	}
7965 
7966 	/*Update sch beaconInterval */
7967 	if (mac->sch.beacon_interval !=
7968 	    pChangeBIParams->beacon_interval) {
7969 		mac->sch.beacon_interval =
7970 			pChangeBIParams->beacon_interval;
7971 
7972 		pe_debug("LIM send update BeaconInterval Indication: %d",
7973 			pChangeBIParams->beacon_interval);
7974 
7975 		if (false == mac->sap.SapDfsInfo.is_dfs_cac_timer_running) {
7976 			/* Update beacon */
7977 			sch_set_fixed_beacon_fields(mac, pe_session);
7978 
7979 			beaconParams.bss_idx = pe_session->vdev_id;
7980 			/* Set change in beacon Interval */
7981 			beaconParams.beaconInterval =
7982 				pChangeBIParams->beacon_interval;
7983 			beaconParams.paramChangeBitmap =
7984 				PARAM_BCN_INTERVAL_CHANGED;
7985 			lim_send_beacon_params(mac, &beaconParams, pe_session);
7986 		}
7987 	}
7988 
7989 	return;
7990 } /*** end __lim_process_sme_change_bi() ***/
7991 
7992 #ifdef QCA_HT_2040_COEX
7993 static void __lim_process_sme_set_ht2040_mode(struct mac_context *mac,
7994 					      uint32_t *msg_buf)
7995 {
7996 	struct set_ht2040_mode *pSetHT2040Mode;
7997 	struct pe_session *pe_session;
7998 	uint8_t sessionId = 0;
7999 	struct scheduler_msg msg = {0};
8000 	tUpdateVHTOpMode *pHtOpMode = NULL;
8001 	uint16_t staId = 0;
8002 	tpDphHashNode sta = NULL;
8003 
8004 	pe_debug("received Set HT 20/40 mode message");
8005 	if (!msg_buf) {
8006 		pe_err("Buffer is Pointing to NULL");
8007 		return;
8008 	}
8009 
8010 	pSetHT2040Mode = (struct set_ht2040_mode *)msg_buf;
8011 
8012 	pe_session = pe_find_session_by_bssid(mac,
8013 				pSetHT2040Mode->bssid.bytes,
8014 				&sessionId);
8015 	if (!pe_session) {
8016 		pe_debug("Session does not exist for given BSSID: "QDF_MAC_ADDR_FMT,
8017 			 QDF_MAC_ADDR_REF(pSetHT2040Mode->bssid.bytes));
8018 		return;
8019 	}
8020 
8021 	pe_debug("Update session entry for cbMod=%d",
8022 		pSetHT2040Mode->cbMode);
8023 	/*Update pe_session HT related fields */
8024 	switch (pSetHT2040Mode->cbMode) {
8025 	case PHY_SINGLE_CHANNEL_CENTERED:
8026 		pe_session->htSecondaryChannelOffset =
8027 			PHY_SINGLE_CHANNEL_CENTERED;
8028 		pe_session->htRecommendedTxWidthSet = 0;
8029 		if (pSetHT2040Mode->obssEnabled)
8030 			pe_session->htSupportedChannelWidthSet
8031 					= eHT_CHANNEL_WIDTH_40MHZ;
8032 		else
8033 			pe_session->htSupportedChannelWidthSet
8034 					= eHT_CHANNEL_WIDTH_20MHZ;
8035 		break;
8036 	case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
8037 		pe_session->htSecondaryChannelOffset =
8038 			PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
8039 		pe_session->htRecommendedTxWidthSet = 1;
8040 		break;
8041 	case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
8042 		pe_session->htSecondaryChannelOffset =
8043 			PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
8044 		pe_session->htRecommendedTxWidthSet = 1;
8045 		break;
8046 	default:
8047 		pe_err("Invalid cbMode");
8048 		return;
8049 	}
8050 
8051 	/* Update beacon */
8052 	sch_set_fixed_beacon_fields(mac, pe_session);
8053 	lim_send_beacon_ind(mac, pe_session, REASON_SET_HT2040);
8054 
8055 	/* update OP Mode for each associated peer */
8056 	for (staId = 0; staId < pe_session->dph.dphHashTable.size; staId++) {
8057 		sta = dph_get_hash_entry(mac, staId,
8058 				&pe_session->dph.dphHashTable);
8059 		if (!sta)
8060 			continue;
8061 
8062 		if (sta->valid && sta->htSupportedChannelWidthSet) {
8063 			pHtOpMode = qdf_mem_malloc(sizeof(tUpdateVHTOpMode));
8064 			if (!pHtOpMode)
8065 				return;
8066 			pHtOpMode->opMode =
8067 				(pe_session->htSecondaryChannelOffset ==
8068 				 PHY_SINGLE_CHANNEL_CENTERED) ?
8069 				eHT_CHANNEL_WIDTH_20MHZ : eHT_CHANNEL_WIDTH_40MHZ;
8070 			qdf_mem_copy(pHtOpMode->peer_mac, &sta->staAddr,
8071 				     sizeof(tSirMacAddr));
8072 			pHtOpMode->smesessionId = pe_session->smeSessionId;
8073 
8074 			msg.type = WMA_UPDATE_OP_MODE;
8075 			msg.reserved = 0;
8076 			msg.bodyptr = pHtOpMode;
8077 			if (!QDF_IS_STATUS_SUCCESS
8078 				    (scheduler_post_message(QDF_MODULE_ID_PE,
8079 							    QDF_MODULE_ID_WMA,
8080 							    QDF_MODULE_ID_WMA,
8081 							    &msg))) {
8082 				pe_err("Not able to post WMA_UPDATE_OP_MODE message to WMA");
8083 				qdf_mem_free(pHtOpMode);
8084 				return;
8085 			}
8086 			pe_debug("Notified FW about OP mode: %d",
8087 				pHtOpMode->opMode);
8088 
8089 		} else
8090 			pe_debug("station does not support HT40");
8091 	}
8092 
8093 	return;
8094 }
8095 #endif
8096 
8097 /* -------------------------------------------------------------------- */
8098 /**
8099  * __lim_process_report_message
8100  *
8101  * FUNCTION:  Processes the next received Radio Resource Management message
8102  *
8103  * LOGIC:
8104  *
8105  * ASSUMPTIONS:
8106  *
8107  * NOTE:
8108  *
8109  * @param None
8110  * @return None
8111  */
8112 
8113 static void __lim_process_report_message(struct mac_context *mac,
8114 					 struct scheduler_msg *pMsg)
8115 {
8116 	switch (pMsg->type) {
8117 	case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
8118 		rrm_process_neighbor_report_req(mac, pMsg->bodyptr);
8119 		break;
8120 	case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
8121 		rrm_process_beacon_report_xmit(mac, pMsg->bodyptr);
8122 		break;
8123 	case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND:
8124 		rrm_process_chan_load_report_xmit(mac, pMsg->bodyptr);
8125 		break;
8126 	default:
8127 		pe_err("Invalid msg type: %d", pMsg->type);
8128 	}
8129 }
8130 
8131 /* -------------------------------------------------------------------- */
8132 /**
8133  * lim_send_set_max_tx_power_req
8134  *
8135  * FUNCTION:  Send SIR_HAL_SET_MAX_TX_POWER_REQ message to change the max tx power.
8136  *
8137  * LOGIC:
8138  *
8139  * ASSUMPTIONS:
8140  *
8141  * NOTE:
8142  *
8143  * @param txPower txPower to be set.
8144  * @param pe_session session entry.
8145  * @return None
8146  */
8147 QDF_STATUS
8148 lim_send_set_max_tx_power_req(struct mac_context *mac, int8_t txPower,
8149 			      struct pe_session *pe_session)
8150 {
8151 	tpMaxTxPowerParams pMaxTxParams = NULL;
8152 	QDF_STATUS retCode = QDF_STATUS_SUCCESS;
8153 	struct scheduler_msg msgQ = {0};
8154 
8155 	if (!pe_session) {
8156 		pe_err("Invalid parameters");
8157 		return QDF_STATUS_E_FAILURE;
8158 	}
8159 
8160 	pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams));
8161 	if (!pMaxTxParams)
8162 		return QDF_STATUS_E_NOMEM;
8163 	pMaxTxParams->power = txPower;
8164 	qdf_mem_copy(pMaxTxParams->bssId.bytes, pe_session->bssId,
8165 		     QDF_MAC_ADDR_SIZE);
8166 	qdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes,
8167 			pe_session->self_mac_addr,
8168 			QDF_MAC_ADDR_SIZE);
8169 
8170 	msgQ.type = WMA_SET_MAX_TX_POWER_REQ;
8171 	msgQ.bodyptr = pMaxTxParams;
8172 	msgQ.bodyval = 0;
8173 	pe_debug("Post WMA_SET_MAX_TX_POWER_REQ to WMA");
8174 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type));
8175 	retCode = wma_post_ctrl_msg(mac, &msgQ);
8176 	if (QDF_STATUS_SUCCESS != retCode) {
8177 		pe_err("wma_post_ctrl_msg() failed");
8178 		qdf_mem_free(pMaxTxParams);
8179 	}
8180 	return retCode;
8181 }
8182 
8183 /**
8184  * __lim_process_sme_register_mgmt_frame_req() - process sme reg mgmt frame req
8185  *
8186  * @mac_ctx: Pointer to Global MAC structure
8187  * @msg_buf: pointer to the SME message buffer
8188  *
8189  * This function is called to process eWNI_SME_REGISTER_MGMT_FRAME_REQ message
8190  * from SME. It Register this information within PE.
8191  *
8192  * Return: None
8193  */
8194 static void __lim_process_sme_register_mgmt_frame_req(struct mac_context *mac_ctx,
8195 		uint32_t *msg_buf)
8196 {
8197 	QDF_STATUS qdf_status;
8198 	struct register_mgmt_frame *sme_req =
8199 					(struct register_mgmt_frame *)msg_buf;
8200 	struct mgmt_frm_reg_info *lim_mgmt_regn = NULL;
8201 	struct mgmt_frm_reg_info *next = NULL;
8202 	bool match = false;
8203 
8204 	pe_nofl_debug("Register Frame: register %d, type %d, match length %d",
8205 		      sme_req->registerFrame, sme_req->frameType,
8206 		      sme_req->matchLen);
8207 	/* First check whether entry exists already */
8208 	qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
8209 	qdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
8210 			    (qdf_list_node_t **) &lim_mgmt_regn);
8211 	qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
8212 
8213 	while (lim_mgmt_regn) {
8214 		if (lim_mgmt_regn->frameType != sme_req->frameType)
8215 			goto skip_match;
8216 		if (sme_req->matchLen) {
8217 			if ((lim_mgmt_regn->matchLen == sme_req->matchLen) &&
8218 				(!qdf_mem_cmp(lim_mgmt_regn->matchData,
8219 					sme_req->matchData,
8220 					lim_mgmt_regn->matchLen))) {
8221 					/* found match! */
8222 					match = true;
8223 					break;
8224 			}
8225 		} else {
8226 			/* found match! */
8227 			match = true;
8228 			break;
8229 		}
8230 skip_match:
8231 		qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
8232 		qdf_status = qdf_list_peek_next(
8233 				&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
8234 				(qdf_list_node_t *)lim_mgmt_regn,
8235 				(qdf_list_node_t **)&next);
8236 		qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
8237 		lim_mgmt_regn = next;
8238 		next = NULL;
8239 	}
8240 	if (match) {
8241 		qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
8242 		if (QDF_STATUS_SUCCESS ==
8243 				qdf_list_remove_node(
8244 				&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
8245 				(qdf_list_node_t *)lim_mgmt_regn))
8246 			qdf_mem_free(lim_mgmt_regn);
8247 		qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
8248 	}
8249 
8250 	if (sme_req->registerFrame) {
8251 		lim_mgmt_regn =
8252 			qdf_mem_malloc(sizeof(struct mgmt_frm_reg_info) +
8253 					sme_req->matchLen);
8254 		if (lim_mgmt_regn) {
8255 			lim_mgmt_regn->frameType = sme_req->frameType;
8256 			lim_mgmt_regn->matchLen = sme_req->matchLen;
8257 			lim_mgmt_regn->sessionId = sme_req->sessionId;
8258 			if (sme_req->matchLen) {
8259 				qdf_mem_copy(lim_mgmt_regn->matchData,
8260 					     sme_req->matchData,
8261 					     sme_req->matchLen);
8262 			}
8263 			qdf_mutex_acquire(
8264 					&mac_ctx->lim.lim_frame_register_lock);
8265 			qdf_list_insert_front(&mac_ctx->lim.
8266 					      gLimMgmtFrameRegistratinQueue,
8267 					      &lim_mgmt_regn->node);
8268 			qdf_mutex_release(
8269 					&mac_ctx->lim.lim_frame_register_lock);
8270 		}
8271 	}
8272 	return;
8273 }
8274 
8275 /**
8276  * lim_register_mgmt_frame_ind_cb() - Save the Management frame
8277  * indication callback in PE.
8278  * @mac_ptr: Mac pointer
8279  * @msg_buf: Msg pointer containing the callback
8280  *
8281  * This function is used save the Management frame
8282  * indication callback in PE.
8283  *
8284  * Return: None
8285  */
8286 static void lim_register_mgmt_frame_ind_cb(struct mac_context *mac_ctx,
8287 							uint32_t *msg_buf)
8288 {
8289 	struct sir_sme_mgmt_frame_cb_req *sme_req =
8290 		(struct sir_sme_mgmt_frame_cb_req *)msg_buf;
8291 
8292 	if (!msg_buf) {
8293 		pe_err("msg_buf is null");
8294 		return;
8295 	}
8296 	if (sme_req->callback)
8297 		mac_ctx->mgmt_frame_ind_cb =
8298 			(sir_mgmt_frame_ind_callback)sme_req->callback;
8299 	else
8300 		pe_err("sme_req->callback is null");
8301 }
8302 
8303 /**
8304  *__lim_process_send_disassoc_frame() - processes send disassoc frame request
8305  * @mac_ctx: pointer to mac context
8306  * @msg_buf: request message buffer
8307  *
8308  * Process a request from SME to send a disassoc frame
8309  *
8310  * Return: none
8311  */
8312 static void __lim_process_send_disassoc_frame(struct mac_context *mac_ctx,
8313 					      void *msg_buf)
8314 {
8315 	struct sme_send_disassoc_frm_req *req = msg_buf;
8316 	struct pe_session *session_entry;
8317 
8318 	if (!req) {
8319 		pe_err("NULL req");
8320 		return;
8321 	}
8322 
8323 	if ((IEEE80211_IS_MULTICAST(req->peer_mac) &&
8324 	     !QDF_IS_ADDR_BROADCAST(req->peer_mac))) {
8325 		pe_err("received invalid SME_DISASSOC_REQ message");
8326 		return;
8327 	}
8328 
8329 	session_entry = pe_find_session_by_vdev_id(mac_ctx, req->vdev_id);
8330 	if (!session_entry) {
8331 		pe_err("session does not exist for given bssId "
8332 		       QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(req->peer_mac));
8333 		return;
8334 	}
8335 
8336 	/* Check if MAC address is MLD of the client and
8337 	 * change it to primary link address to send OTA.
8338 	 */
8339 	lim_mlo_sap_validate_and_update_ra(
8340 			session_entry, (struct qdf_mac_addr *)req->peer_mac);
8341 
8342 	pe_debug("msg_type %d len %d vdev_id %d mac: " QDF_MAC_ADDR_FMT " reason %d wait_for_ack %d",
8343 		 req->msg_type, req->length,  req->vdev_id,
8344 		 QDF_MAC_ADDR_REF(req->peer_mac), req->reason, req->wait_for_ack);
8345 
8346 	lim_send_disassoc_mgmt_frame(mac_ctx, req->reason, req->peer_mac,
8347 				     session_entry, req->wait_for_ack);
8348 }
8349 
8350 /**
8351  * lim_set_pdev_ht_ie() - sends the set HT IE req to FW
8352  * @mac_ctx: Pointer to Global MAC structure
8353  * @pdev_id: pdev id to set the IE.
8354  * @nss: Nss values to prepare the HT IE.
8355  *
8356  * Prepares the HT IE with self capabilities for different
8357  * Nss values and sends the set HT IE req to FW.
8358  *
8359  * Return: None
8360  */
8361 static void lim_set_pdev_ht_ie(struct mac_context *mac_ctx, uint8_t pdev_id,
8362 		uint8_t nss)
8363 {
8364 	struct set_ie_param *ie_params;
8365 	struct scheduler_msg msg = {0};
8366 	QDF_STATUS rc = QDF_STATUS_SUCCESS;
8367 	const uint8_t *p_ie = NULL;
8368 	tHtCaps *p_ht_cap;
8369 	int i;
8370 
8371 	for (i = 1; i <= nss; i++) {
8372 		ie_params = qdf_mem_malloc(sizeof(*ie_params));
8373 		if (!ie_params)
8374 			return;
8375 		ie_params->nss = i;
8376 		ie_params->pdev_id = pdev_id;
8377 		ie_params->ie_type = DOT11_HT_IE;
8378 		/* 2 for IE len and EID */
8379 		ie_params->ie_len = 2 + sizeof(tHtCaps);
8380 		ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len);
8381 		if (!ie_params->ie_ptr) {
8382 			qdf_mem_free(ie_params);
8383 			return;
8384 		}
8385 		*ie_params->ie_ptr = WLAN_ELEMID_HTCAP_ANA;
8386 		*(ie_params->ie_ptr + 1) = ie_params->ie_len - 2;
8387 		lim_set_ht_caps(mac_ctx, ie_params->ie_ptr,
8388 				ie_params->ie_len);
8389 
8390 		if (NSS_1x1_MODE == i) {
8391 			p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_HTCAPS,
8392 					ie_params->ie_ptr, ie_params->ie_len);
8393 			if (!p_ie) {
8394 				qdf_mem_free(ie_params->ie_ptr);
8395 				qdf_mem_free(ie_params);
8396 				pe_err("failed to get IE ptr");
8397 				return;
8398 			}
8399 			p_ht_cap = (tHtCaps *)&p_ie[2];
8400 			p_ht_cap->supportedMCSSet[1] = 0;
8401 			p_ht_cap->txSTBC = 0;
8402 		}
8403 
8404 		msg.type = WMA_SET_PDEV_IE_REQ;
8405 		msg.bodyptr = ie_params;
8406 		msg.bodyval = 0;
8407 
8408 		rc = wma_post_ctrl_msg(mac_ctx, &msg);
8409 		if (rc != QDF_STATUS_SUCCESS) {
8410 			pe_err("wma_post_ctrl_msg() return failure");
8411 			qdf_mem_free(ie_params->ie_ptr);
8412 			qdf_mem_free(ie_params);
8413 			return;
8414 		}
8415 	}
8416 }
8417 
8418 /**
8419  * lim_set_pdev_vht_ie() - sends the set VHT IE to req FW
8420  * @mac_ctx: Pointer to Global MAC structure
8421  * @pdev_id: pdev id to set the IE.
8422  * @nss: Nss values to prepare the VHT IE.
8423  *
8424  * Prepares the VHT IE with self capabilities for different
8425  * Nss values and sends the set VHT IE req to FW.
8426  *
8427  * Return: None
8428  */
8429 static void lim_set_pdev_vht_ie(struct mac_context *mac_ctx, uint8_t pdev_id,
8430 		uint8_t nss)
8431 {
8432 	struct set_ie_param *ie_params;
8433 	struct scheduler_msg msg = {0};
8434 	QDF_STATUS rc = QDF_STATUS_SUCCESS;
8435 	const uint8_t *p_ie = NULL;
8436 	tSirMacVHTCapabilityInfo *vht_cap;
8437 	int i;
8438 	tSirVhtMcsInfo *vht_mcs;
8439 
8440 	for (i = 1; i <= nss; i++) {
8441 		ie_params = qdf_mem_malloc(sizeof(*ie_params));
8442 		if (!ie_params)
8443 			return;
8444 		ie_params->nss = i;
8445 		ie_params->pdev_id = pdev_id;
8446 		ie_params->ie_type = DOT11_VHT_IE;
8447 		/* 2 for IE len and EID */
8448 		ie_params->ie_len = 2 + sizeof(tSirMacVHTCapabilityInfo) +
8449 			sizeof(tSirVhtMcsInfo);
8450 		ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len);
8451 		if (!ie_params->ie_ptr) {
8452 			qdf_mem_free(ie_params);
8453 			return;
8454 		}
8455 		*ie_params->ie_ptr = WLAN_ELEMID_VHTCAP;
8456 		*(ie_params->ie_ptr + 1) = ie_params->ie_len - 2;
8457 		lim_set_vht_caps(mac_ctx, ie_params->ie_ptr, ie_params->ie_len);
8458 
8459 		if (NSS_1x1_MODE == i) {
8460 			p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_VHTCAPS,
8461 					ie_params->ie_ptr, ie_params->ie_len);
8462 			if (!p_ie) {
8463 				qdf_mem_free(ie_params->ie_ptr);
8464 				qdf_mem_free(ie_params);
8465 				pe_err("failed to get IE ptr");
8466 				return;
8467 			}
8468 			vht_cap = (tSirMacVHTCapabilityInfo *)&p_ie[2];
8469 			vht_cap->txSTBC = 0;
8470 			vht_mcs =
8471 				(tSirVhtMcsInfo *)&p_ie[2 +
8472 				sizeof(tSirMacVHTCapabilityInfo)];
8473 			vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS;
8474 			vht_mcs->rxHighest =
8475 				VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
8476 			vht_mcs->txMcsMap |= DISABLE_NSS2_MCS;
8477 			vht_mcs->txHighest =
8478 				VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
8479 		}
8480 		msg.type = WMA_SET_PDEV_IE_REQ;
8481 		msg.bodyptr = ie_params;
8482 		msg.bodyval = 0;
8483 
8484 		rc = wma_post_ctrl_msg(mac_ctx, &msg);
8485 		if (rc != QDF_STATUS_SUCCESS) {
8486 			pe_err("wma_post_ctrl_msg failure");
8487 			qdf_mem_free(ie_params->ie_ptr);
8488 			qdf_mem_free(ie_params);
8489 			return;
8490 		}
8491 	}
8492 }
8493 
8494 /**
8495  * lim_process_set_vdev_ies_per_band() - process the set vdev IE req
8496  * @mac_ctx: Pointer to Global MAC structure
8497  * @msg_buf: Pointer to the SME message buffer
8498  *
8499  * This function is called by limProcessMessageQueue(). This function sets the
8500  * VDEV IEs to the FW.
8501  *
8502  * Return: None
8503  */
8504 static void lim_process_set_vdev_ies_per_band(struct mac_context *mac_ctx,
8505 					      uint32_t *msg_buf)
8506 {
8507 	struct sir_set_vdev_ies_per_band *p_msg =
8508 				(struct sir_set_vdev_ies_per_band *)msg_buf;
8509 
8510 	if (!p_msg) {
8511 		pe_err("NULL p_msg");
8512 		return;
8513 	}
8514 
8515 	pe_debug("rcvd set vdev ie per band req vdev_id = %d",
8516 		p_msg->vdev_id);
8517 
8518 	if (lim_send_ies_per_band(mac_ctx, p_msg->vdev_id,
8519 				  p_msg->dot11_mode, p_msg->device_mode) !=
8520 	    QDF_STATUS_SUCCESS)
8521 		pe_err("Unable to send HT/VHT Cap to FW");
8522 }
8523 
8524 /**
8525  * lim_process_set_pdev_IEs() - process the set pdev IE req
8526  * @mac_ctx: Pointer to Global MAC structure
8527  * @msg_buf: Pointer to the SME message buffer
8528  *
8529  * This function is called by limProcessMessageQueue(). This
8530  * function sets the PDEV IEs to the FW.
8531  *
8532  * Return: None
8533  */
8534 static void lim_process_set_pdev_IEs(struct mac_context *mac_ctx, uint32_t *msg_buf)
8535 {
8536 	struct sir_set_ht_vht_cfg *ht_vht_cfg;
8537 
8538 	ht_vht_cfg = (struct sir_set_ht_vht_cfg *)msg_buf;
8539 
8540 	if (!ht_vht_cfg) {
8541 		pe_err("NULL ht_vht_cfg");
8542 		return;
8543 	}
8544 
8545 	pe_debug("rcvd set pdev ht vht ie req with nss = %d",
8546 			ht_vht_cfg->nss);
8547 	lim_set_pdev_ht_ie(mac_ctx, ht_vht_cfg->pdev_id, ht_vht_cfg->nss);
8548 
8549 	if (IS_DOT11_MODE_VHT(ht_vht_cfg->dot11mode))
8550 		lim_set_pdev_vht_ie(mac_ctx, ht_vht_cfg->pdev_id,
8551 				ht_vht_cfg->nss);
8552 }
8553 
8554 /**
8555  * lim_process_sme_update_access_policy_vendor_ie: function updates vendor IE
8556  *
8557  * access policy
8558  * @mac_ctx: pointer to mac context
8559  * @msg: message buffer
8560  *
8561  * function processes vendor IE and access policy from SME and updates PE
8562  *
8563  * session entry
8564  *
8565  * return: none
8566 */
8567 static void lim_process_sme_update_access_policy_vendor_ie(
8568 						struct mac_context *mac_ctx,
8569 						uint32_t *msg)
8570 {
8571 	struct sme_update_access_policy_vendor_ie *update_vendor_ie;
8572 	struct pe_session *pe_session_entry;
8573 	uint16_t num_bytes;
8574 
8575 	if (!msg) {
8576 		pe_err("Buffer is Pointing to NULL");
8577 		return;
8578 	}
8579 	update_vendor_ie = (struct sme_update_access_policy_vendor_ie *) msg;
8580 	pe_session_entry = pe_find_session_by_vdev_id(mac_ctx,
8581 					update_vendor_ie->vdev_id);
8582 
8583 	if (!pe_session_entry) {
8584 		pe_err("Session does not exist for given vdev_id %d",
8585 			update_vendor_ie->vdev_id);
8586 		return;
8587 	}
8588 	if (pe_session_entry->access_policy_vendor_ie)
8589 		qdf_mem_free(pe_session_entry->access_policy_vendor_ie);
8590 
8591 	num_bytes = update_vendor_ie->ie[1] + 2;
8592 	pe_session_entry->access_policy_vendor_ie = qdf_mem_malloc(num_bytes);
8593 	if (!pe_session_entry->access_policy_vendor_ie)
8594 		return;
8595 	qdf_mem_copy(pe_session_entry->access_policy_vendor_ie,
8596 		&update_vendor_ie->ie[0], num_bytes);
8597 
8598 	pe_session_entry->access_policy = update_vendor_ie->access_policy;
8599 }
8600 
8601 QDF_STATUS lim_sta_mlme_vdev_disconnect_bss(struct vdev_mlme_obj *vdev_mlme,
8602 					    uint16_t data_len, void *data)
8603 {
8604 	struct mac_context *mac_ctx;
8605 	struct scheduler_msg *msg = (struct scheduler_msg *)data;
8606 
8607 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
8608 	if (!mac_ctx) {
8609 		if (data)
8610 			qdf_mem_free(data);
8611 		return QDF_STATUS_E_INVAL;
8612 	}
8613 	pe_debug("Vdev %d: disconnect bss callback type:(%d)",
8614 		 wlan_vdev_get_id(vdev_mlme->vdev), msg->type);
8615 
8616 	switch (msg->type) {
8617 	case eWNI_SME_DEAUTH_REQ:
8618 		__lim_process_sme_deauth_req(mac_ctx,
8619 					     (uint32_t *)msg->bodyptr);
8620 		break;
8621 	case eWNI_SME_DISASSOC_CNF:
8622 	case eWNI_SME_DEAUTH_CNF:
8623 		__lim_process_sme_disassoc_cnf(mac_ctx,
8624 					       (uint32_t *)msg->bodyptr);
8625 		break;
8626 	case eWNI_SME_DISASSOC_REQ:
8627 		__lim_process_sme_disassoc_req(mac_ctx,
8628 					       (uint32_t *)msg->bodyptr);
8629 		break;
8630 	default:
8631 		pe_err("Vdev %d Wrong message type received %d",
8632 		       wlan_vdev_get_id(vdev_mlme->vdev), msg->type);
8633 	}
8634 	return QDF_STATUS_SUCCESS;
8635 }
8636 
8637 static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx,
8638 					 struct scheduler_msg *msg)
8639 {
8640 	struct disassoc_cnf sme_disassoc_cnf;
8641 	struct pe_session *session;
8642 	uint8_t session_id;
8643 	uint32_t *err_msg = NULL;
8644 	QDF_STATUS status;
8645 
8646 	qdf_mem_copy(&sme_disassoc_cnf, msg->bodyptr, sizeof(sme_disassoc_cnf));
8647 
8648 	session = pe_find_session_by_bssid(mac_ctx,
8649 					   sme_disassoc_cnf.bssid.bytes,
8650 					   &session_id);
8651 	if (!session) {
8652 		pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT,
8653 		       QDF_MAC_ADDR_REF(sme_disassoc_cnf.bssid.bytes));
8654 		status = lim_prepare_disconnect_done_ind
8655 						(mac_ctx, &err_msg,
8656 						sme_disassoc_cnf.vdev_id,
8657 						eSIR_SME_INVALID_SESSION,
8658 						NULL);
8659 
8660 		if (QDF_IS_STATUS_SUCCESS(status))
8661 			lim_send_sme_disassoc_deauth_ntf(mac_ctx,
8662 							 QDF_STATUS_SUCCESS,
8663 							 err_msg);
8664 		return;
8665 	}
8666 
8667 	__lim_process_sme_disassoc_cnf(mac_ctx, (uint32_t *)msg->bodyptr);
8668 }
8669 
8670 static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx,
8671 					 struct scheduler_msg *msg)
8672 {
8673 	struct disassoc_req disassoc_req;
8674 	struct pe_session *session;
8675 	uint8_t session_id;
8676 
8677 	qdf_mem_copy(&disassoc_req, msg->bodyptr, sizeof(struct disassoc_req));
8678 
8679 	session = pe_find_session_by_bssid(mac_ctx,
8680 					   disassoc_req.bssid.bytes,
8681 					   &session_id);
8682 	if (!session) {
8683 		pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT,
8684 		       QDF_MAC_ADDR_REF(disassoc_req.bssid.bytes));
8685 		lim_send_sme_disassoc_ntf(mac_ctx,
8686 					  disassoc_req.peer_macaddr.bytes,
8687 					  eSIR_SME_INVALID_PARAMETERS,
8688 					  eLIM_HOST_DISASSOC, 1,
8689 					  disassoc_req.sessionId, NULL);
8690 
8691 		return;
8692 	}
8693 
8694 	__lim_process_sme_disassoc_req(mac_ctx, (uint32_t *)msg->bodyptr);
8695 }
8696 
8697 static void lim_process_sme_deauth_req(struct mac_context *mac_ctx,
8698 				       struct scheduler_msg *msg)
8699 {
8700 	struct deauth_req sme_deauth_req;
8701 	struct pe_session *session;
8702 	uint8_t session_id;
8703 
8704 	qdf_mem_copy(&sme_deauth_req, msg->bodyptr, sizeof(sme_deauth_req));
8705 
8706 	session = pe_find_session_by_bssid(mac_ctx,
8707 					   sme_deauth_req.bssid.bytes,
8708 					   &session_id);
8709 	if (!session) {
8710 		pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT,
8711 		       QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes));
8712 		lim_send_sme_deauth_ntf(mac_ctx,
8713 					sme_deauth_req.peer_macaddr.bytes,
8714 					eSIR_SME_INVALID_PARAMETERS,
8715 					eLIM_HOST_DEAUTH, 1,
8716 					sme_deauth_req.vdev_id);
8717 
8718 		return;
8719 	}
8720 
8721 	__lim_process_sme_deauth_req(mac_ctx, (uint32_t *)msg->bodyptr);
8722 }
8723 
8724 void lim_send_bcn_rsp(struct mac_context *mac_ctx, tpSendbeaconParams rsp)
8725 {
8726 	if (!rsp) {
8727 		pe_err("rsp is NULL");
8728 		return;
8729 	}
8730 
8731 	/* Success case response is sent from beacon_tx completion/timeout */
8732 	if (rsp->reason == REASON_CH_WIDTH_UPDATE &&
8733 	    QDF_IS_STATUS_SUCCESS(rsp->status))
8734 		return;
8735 
8736 	pe_debug("Send beacon resp status %d for reason %d",
8737 		 rsp->status, rsp->reason);
8738 
8739 	lim_nss_or_ch_width_update_rsp(mac_ctx, rsp->vdev_id,
8740 				       rsp->status, rsp->reason);
8741 }
8742 
8743 static void
8744 lim_update_bcn_with_new_ch_width(struct mac_context *mac_ctx,
8745 				 struct pe_session *session,
8746 				 enum phy_ch_width ch_width)
8747 {
8748 	QDF_STATUS status;
8749 
8750 	session->gLimOperatingMode.present = 1;
8751 	session->gLimOperatingMode.chanWidth = ch_width;
8752 
8753 	pe_debug("ch width %d",
8754 		 session->gLimOperatingMode.chanWidth);
8755 
8756 	session->bw_update_include_ch_sw_ie = true;
8757 	status = qdf_mc_timer_start(&session->ap_ecsa_timer,
8758 				    MAX_WAIT_FOR_CH_WIDTH_UPDATE_COMPLETE);
8759 	if (QDF_IS_STATUS_ERROR(status))
8760 		pe_err("cannot start ap_ecsa_timer");
8761 
8762 	/* Send nss update request from here */
8763 	status = sch_set_fixed_beacon_fields(mac_ctx, session);
8764 	if (QDF_IS_STATUS_ERROR(status)) {
8765 		pe_err("Unable to set op mode IE in beacon");
8766 		goto end;
8767 	}
8768 
8769 	status = lim_send_beacon_ind(mac_ctx, session,
8770 				     REASON_CH_WIDTH_UPDATE);
8771 	if (QDF_IS_STATUS_SUCCESS(status))
8772 		return;
8773 
8774 	pe_err("Unable to send beacon");
8775 end:
8776 	/*
8777 	 * send resp only in case of failure,
8778 	 * success case response will be from wma.
8779 	 */
8780 	lim_nss_or_ch_width_update_rsp(mac_ctx, session->vdev_id, status,
8781 				       REASON_CH_WIDTH_UPDATE);
8782 }
8783 
8784 static enum phy_ch_width
8785 lim_calculate_peer_ch_width(struct pe_session *session,
8786 			    uint8_t *mac_addr,
8787 			    enum phy_ch_width new_ch_width)
8788 {
8789 	enum phy_ch_width peer_org_bw, updated_bw;
8790 	struct peer_oper_mode_event data = {0};
8791 	QDF_STATUS status;
8792 
8793 	peer_org_bw = wlan_mlme_get_peer_ch_width(
8794 				wlan_vdev_get_psoc(session->vdev), mac_addr);
8795 
8796 	updated_bw = new_ch_width;
8797 
8798 	qdf_mem_copy(&data.peer_mac_address.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
8799 	status = wlan_mlme_get_peer_indicated_ch_width(
8800 				wlan_vdev_get_psoc(session->vdev), &data);
8801 	if (QDF_IS_STATUS_SUCCESS(status))
8802 		updated_bw = data.new_bw;
8803 
8804 	pe_debug("Peer: " QDF_MAC_ADDR_FMT " original bw: %d, updated bw: %d, new bw: %d",
8805 		 QDF_MAC_ADDR_REF(mac_addr), peer_org_bw, updated_bw,
8806 		 new_ch_width);
8807 
8808 	return qdf_min(peer_org_bw, qdf_min(updated_bw, new_ch_width));
8809 }
8810 
8811 static void
8812 lim_update_new_ch_width_to_fw(struct mac_context *mac_ctx,
8813 			      struct pe_session *session,
8814 			      enum phy_ch_width ch_bandwidth)
8815 {
8816 	uint8_t i;
8817 	tpDphHashNode psta;
8818 	tUpdateVHTOpMode params;
8819 
8820 	for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) {
8821 		psta = session->dph.dphHashTable.pDphNodeArray + i;
8822 		if (!psta || !psta->added)
8823 			continue;
8824 
8825 		params.opMode = lim_calculate_peer_ch_width(session,
8826 					psta->staAddr, ch_bandwidth);
8827 		params.smesessionId = session->smeSessionId;
8828 		qdf_mem_copy(params.peer_mac, psta->staAddr,
8829 			     sizeof(tSirMacAddr));
8830 
8831 		lim_send_mode_update(mac_ctx, &params, session);
8832 	}
8833 }
8834 
8835 /**
8836  * lim_process_sap_ch_width_update() - process sme nss update req
8837  *
8838  * @mac_ctx: Pointer to Global MAC structure
8839  * @msg_buf: pointer to the SME message buffer
8840  *
8841  * This function processes SME request messages from HDD or upper layer
8842  * application.
8843  *
8844  * Return: None
8845  */
8846 static void
8847 lim_process_sap_ch_width_update(struct mac_context *mac_ctx,
8848 				uint32_t *msg_buf)
8849 {
8850 	struct sir_sap_ch_width_update *req;
8851 	struct pe_session *session = NULL;
8852 	uint8_t vdev_id;
8853 	struct sir_bcn_update_rsp *param;
8854 	struct scheduler_msg msg_return = {0};
8855 	uint8_t primary_channel;
8856 	struct ch_params ch_params = {0};
8857 
8858 	if (!msg_buf) {
8859 		pe_err("Buffer is Pointing to NULL");
8860 		return;
8861 	}
8862 
8863 	req = (struct sir_sap_ch_width_update *)msg_buf;
8864 	vdev_id = req->vdev_id;
8865 	session = pe_find_session_by_vdev_id(mac_ctx, req->vdev_id);
8866 	if (!session) {
8867 		pe_err("vdev %d session not found", req->vdev_id);
8868 		goto fail;
8869 	}
8870 
8871 	if (session->opmode != QDF_SAP_MODE) {
8872 		pe_err("Invalid opmode %d", session->opmode);
8873 		goto fail;
8874 	}
8875 
8876 	ch_params.ch_width = req->ch_width;
8877 	wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
8878 						session->curr_op_freq,
8879 						0,
8880 						&ch_params,
8881 						REG_CURRENT_PWR_MODE);
8882 
8883 	session->gLimChannelSwitch.switchCount = 1;
8884 	session->gLimChannelSwitch.sw_target_freq = session->curr_op_freq;
8885 	primary_channel = wlan_reg_freq_to_chan(mac_ctx->pdev,
8886 						session->curr_op_freq);
8887 	session->gLimChannelSwitch.primaryChannel = primary_channel;
8888 	session->gLimChannelSwitch.ch_width = req->ch_width;
8889 	session->gLimChannelSwitch.ch_center_freq_seg0 =
8890 						ch_params.center_freq_seg0;
8891 	session->gLimChannelSwitch.ch_center_freq_seg1 =
8892 						ch_params.center_freq_seg1;
8893 
8894 	wlan_mlme_set_ap_oper_ch_width(session->vdev, req->ch_width);
8895 
8896 	/* Send ECSA to the peers */
8897 	send_extended_chan_switch_action_frame(mac_ctx,
8898 				       session->curr_op_freq,
8899 				       req->ch_width, session);
8900 
8901 	/* Send beacon template to firmware */
8902 	lim_update_bcn_with_new_ch_width(mac_ctx, session, req->ch_width);
8903 	/* Send updated bw info of each peer to firmware */
8904 	lim_update_new_ch_width_to_fw(mac_ctx, session, req->ch_width);
8905 
8906 	/*
8907 	 * Release the SER command only after this, otherwise it may cause
8908 	 * out of sync issues if any other WMI commands go to fw
8909 	 */
8910 	return;
8911 
8912 fail:
8913 	pe_err("vdev %d: send bandwidth update fail", vdev_id);
8914 	param = qdf_mem_malloc(sizeof(*param));
8915 	if (param) {
8916 		param->status = QDF_STATUS_E_FAILURE;
8917 		param->vdev_id = INVALID_VDEV_ID;
8918 		param->reason = REASON_CH_WIDTH_UPDATE;
8919 	}
8920 	msg_return.type = eWNI_SME_SAP_CH_WIDTH_UPDATE_RSP;
8921 	msg_return.bodyptr = param;
8922 	msg_return.bodyval = 0;
8923 	sys_process_mmh_msg(mac_ctx, &msg_return);
8924 }
8925 
8926 /**
8927  * lim_process_sme_req_messages()
8928  *
8929  ***FUNCTION:
8930  * This function is called by limProcessMessageQueue(). This
8931  * function processes SME request messages from HDD or upper layer
8932  * application.
8933  *
8934  ***LOGIC:
8935  *
8936  ***ASSUMPTIONS:
8937  *
8938  ***NOTE:
8939  *
8940  * @param  mac      Pointer to Global MAC structure
8941  * @param  msgType   Indicates the SME message type
8942  * @param  *msg_buf  A pointer to the SME message buffer
8943  * @return Boolean - true - if msg_buf is consumed and can be freed.
8944  *                   false - if msg_buf is not to be freed.
8945  */
8946 
8947 bool lim_process_sme_req_messages(struct mac_context *mac,
8948 				  struct scheduler_msg *pMsg)
8949 {
8950 	/*
8951 	 * Set this flag to false within case block of any following message,
8952 	 * that doesn't want msg_buf to be freed.
8953 	 */
8954 	bool bufConsumed = true;
8955 	uint32_t *msg_buf = pMsg->bodyptr;
8956 
8957 	pe_nofl_debug("LIM handle SME Msg %s(%d)",
8958 		      lim_msg_str(pMsg->type), pMsg->type);
8959 
8960 	/* If no insert NOA required then execute the code below */
8961 
8962 	switch (pMsg->type) {
8963 	case eWNI_SME_SYS_READY_IND:
8964 		bufConsumed = __lim_process_sme_sys_ready_ind(mac, msg_buf);
8965 		break;
8966 
8967 	case eWNI_SME_START_BSS_REQ:
8968 		bufConsumed = __lim_process_sme_start_bss_req(mac, pMsg);
8969 		break;
8970 	case eWNI_SME_DISASSOC_REQ:
8971 		lim_process_sme_disassoc_req(mac, pMsg);
8972 		break;
8973 
8974 	case eWNI_SME_DISASSOC_CNF:
8975 	case eWNI_SME_DEAUTH_CNF:
8976 		lim_process_sme_disassoc_cnf(mac, pMsg);
8977 		break;
8978 
8979 	case eWNI_SME_DEAUTH_REQ:
8980 		lim_process_sme_deauth_req(mac, pMsg);
8981 		break;
8982 
8983 	case eWNI_SME_SEND_DISASSOC_FRAME:
8984 		__lim_process_send_disassoc_frame(mac, msg_buf);
8985 		break;
8986 
8987 	case eWNI_SME_STOP_BSS_REQ:
8988 		bufConsumed = __lim_process_sme_stop_bss_req(mac, pMsg);
8989 		break;
8990 
8991 	case eWNI_SME_ASSOC_CNF:
8992 		if (pMsg->type == eWNI_SME_ASSOC_CNF)
8993 			pe_debug("Received ASSOC_CNF message");
8994 			__lim_process_sme_assoc_cnf_new(mac, pMsg->type,
8995 							msg_buf);
8996 		break;
8997 
8998 	case eWNI_SME_ADDTS_REQ:
8999 		pe_debug("Received ADDTS_REQ message");
9000 		__lim_process_sme_addts_req(mac, msg_buf);
9001 		break;
9002 
9003 	case eWNI_SME_MSCS_REQ:
9004 		pe_debug("Received MSCS_REQ message");
9005 		__lim_process_sme_mscs_req(mac, msg_buf);
9006 		break;
9007 
9008 	case eWNI_SME_DELTS_REQ:
9009 		pe_debug("Received DELTS_REQ message");
9010 		__lim_process_sme_delts_req(mac, msg_buf);
9011 		break;
9012 
9013 	case SIR_LIM_ADDTS_RSP_TIMEOUT:
9014 		pe_debug("Received SIR_LIM_ADDTS_RSP_TIMEOUT message");
9015 		lim_process_sme_addts_rsp_timeout(mac, pMsg->bodyval);
9016 		break;
9017 
9018 #ifdef FEATURE_WLAN_ESE
9019 	case eWNI_SME_GET_TSM_STATS_REQ:
9020 		__lim_process_sme_get_tsm_stats_request(mac, msg_buf);
9021 		bufConsumed = false;
9022 		break;
9023 #endif /* FEATURE_WLAN_ESE */
9024 	case eWNI_SME_SESSION_UPDATE_PARAM:
9025 		__lim_process_sme_session_update(mac, msg_buf);
9026 		break;
9027 	case eWNI_SME_CHNG_MCC_BEACON_INTERVAL:
9028 		/* Update the beaconInterval */
9029 		__lim_process_sme_change_bi(mac, msg_buf);
9030 		break;
9031 
9032 #ifdef QCA_HT_2040_COEX
9033 	case eWNI_SME_SET_HT_2040_MODE:
9034 		__lim_process_sme_set_ht2040_mode(mac, msg_buf);
9035 		break;
9036 #endif
9037 
9038 	case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
9039 	case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
9040 	case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND:
9041 		__lim_process_report_message(mac, pMsg);
9042 		break;
9043 	case eWNI_SME_FT_AGGR_QOS_REQ:
9044 		lim_process_ft_aggr_qos_req(mac, msg_buf);
9045 		break;
9046 
9047 	case eWNI_SME_REGISTER_MGMT_FRAME_REQ:
9048 		__lim_process_sme_register_mgmt_frame_req(mac, msg_buf);
9049 		break;
9050 #ifdef FEATURE_WLAN_TDLS
9051 	case eWNI_SME_TDLS_SEND_MGMT_REQ:
9052 		lim_process_sme_tdls_mgmt_send_req(mac, msg_buf);
9053 		break;
9054 	case eWNI_SME_TDLS_ADD_STA_REQ:
9055 		lim_process_sme_tdls_add_sta_req(mac, msg_buf);
9056 		break;
9057 	case eWNI_SME_TDLS_DEL_STA_REQ:
9058 		lim_process_sme_tdls_del_sta_req(mac, msg_buf);
9059 		break;
9060 #endif
9061 	case eWNI_SME_CHANNEL_CHANGE_REQ:
9062 		lim_process_sme_channel_change_request(mac, msg_buf);
9063 		break;
9064 
9065 	case eWNI_SME_START_BEACON_REQ:
9066 		lim_process_sme_start_beacon_req(mac, msg_buf);
9067 		break;
9068 
9069 	case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ:
9070 		lim_process_sme_dfs_csa_ie_request(mac, msg_buf);
9071 		break;
9072 
9073 	case eWNI_SME_UPDATE_ADDITIONAL_IES:
9074 		lim_process_update_add_ies(mac, msg_buf);
9075 		break;
9076 
9077 	case eWNI_SME_MODIFY_ADDITIONAL_IES:
9078 		lim_process_modify_add_ies(mac, msg_buf);
9079 		break;
9080 	case eWNI_SME_SET_HW_MODE_REQ:
9081 		lim_process_set_hw_mode(mac, msg_buf);
9082 		break;
9083 	case eWNI_SME_NSS_UPDATE_REQ:
9084 		lim_process_nss_update_request(mac, msg_buf);
9085 		break;
9086 	case eWNI_SME_SET_DUAL_MAC_CFG_REQ:
9087 		lim_process_set_dual_mac_cfg_req(mac, msg_buf);
9088 		break;
9089 	case eWNI_SME_SET_IE_REQ:
9090 		lim_process_set_ie_req(mac, msg_buf);
9091 		break;
9092 	case eWNI_SME_REGISTER_MGMT_FRAME_CB:
9093 		lim_register_mgmt_frame_ind_cb(mac, msg_buf);
9094 		break;
9095 	case eWNI_SME_EXT_CHANGE_CHANNEL:
9096 		lim_process_ext_change_channel(mac, msg_buf);
9097 		break;
9098 	case eWNI_SME_SET_ANTENNA_MODE_REQ:
9099 		lim_process_set_antenna_mode_req(mac, msg_buf);
9100 		break;
9101 	case eWNI_SME_PDEV_SET_HT_VHT_IE:
9102 		lim_process_set_pdev_IEs(mac, msg_buf);
9103 		break;
9104 	case eWNI_SME_SET_VDEV_IES_PER_BAND:
9105 		lim_process_set_vdev_ies_per_band(mac, msg_buf);
9106 		break;
9107 	case eWNI_SME_UPDATE_ACCESS_POLICY_VENDOR_IE:
9108 		lim_process_sme_update_access_policy_vendor_ie(mac, msg_buf);
9109 		break;
9110 	case eWNI_SME_UPDATE_CONFIG:
9111 		lim_process_sme_update_config(mac,
9112 					(struct update_config *)msg_buf);
9113 		break;
9114 	case eWNI_SME_SET_ADDBA_ACCEPT:
9115 		lim_process_sme_set_addba_accept(mac,
9116 					(struct sme_addba_accept *)msg_buf);
9117 		break;
9118 	case eWNI_SME_UPDATE_EDCA_PROFILE:
9119 		lim_process_sme_update_edca_params(mac, pMsg->bodyval);
9120 		break;
9121 	case WNI_SME_UPDATE_MU_EDCA_PARAMS:
9122 		lim_process_sme_update_mu_edca_params(mac, pMsg->bodyval);
9123 		break;
9124 	case eWNI_SME_UPDATE_SESSION_EDCA_TXQ_PARAMS:
9125 		lim_process_sme_update_session_edca_txq_params(mac, msg_buf);
9126 		break;
9127 	case WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU:
9128 		lim_process_sme_cfg_action_frm_in_tb_ppdu(mac,
9129 				(struct  sir_cfg_action_frm_tb_ppdu *)msg_buf);
9130 		break;
9131 	case eWNI_SME_VDEV_PAUSE_IND:
9132 		lim_process_sme_send_vdev_pause(mac,
9133 					(struct sme_vdev_pause *)msg_buf);
9134 		break;
9135 	case eWNI_SME_SAP_CH_WIDTH_UPDATE_REQ:
9136 		lim_process_sap_ch_width_update(mac, msg_buf);
9137 		break;
9138 	default:
9139 		qdf_mem_free((void *)pMsg->bodyptr);
9140 		pMsg->bodyptr = NULL;
9141 		break;
9142 	} /* switch (msgType) */
9143 
9144 	return bufConsumed;
9145 } /*** end lim_process_sme_req_messages() ***/
9146 
9147 /**
9148  * lim_process_sme_start_beacon_req()
9149  *
9150  ***FUNCTION:
9151  * This function is called by limProcessMessageQueue(). This
9152  * function processes SME request messages from HDD or upper layer
9153  * application.
9154  *
9155  ***LOGIC:
9156  *
9157  ***ASSUMPTIONS:
9158  *
9159  ***NOTE:
9160  *
9161  * @param  mac      Pointer to Global MAC structure
9162  * @param  msgType   Indicates the SME message type
9163  * @param  *msg_buf  A pointer to the SME message buffer
9164  * @return Boolean - true - if msg_buf is consumed and can be freed.
9165  *                   false - if msg_buf is not to be freed.
9166  */
9167 static void lim_process_sme_start_beacon_req(struct mac_context *mac, uint32_t *pMsg)
9168 {
9169 	tpSirStartBeaconIndication pBeaconStartInd;
9170 	struct pe_session *pe_session;
9171 	uint8_t sessionId;      /* PE sessionID */
9172 
9173 	if (!pMsg) {
9174 		pe_err("Buffer is Pointing to NULL");
9175 		return;
9176 	}
9177 
9178 	pBeaconStartInd = (tpSirStartBeaconIndication) pMsg;
9179 	pe_session = pe_find_session_by_bssid(mac,
9180 				pBeaconStartInd->bssid,
9181 				&sessionId);
9182 	if (!pe_session) {
9183 		pe_err("Session does not exist for given bssId: "QDF_MAC_ADDR_FMT,
9184 		       QDF_MAC_ADDR_REF(pBeaconStartInd->bssid));
9185 		return;
9186 	}
9187 
9188 	if (pBeaconStartInd->beaconStartStatus == true) {
9189 		/*
9190 		 * Currently this Indication comes from SAP
9191 		 * to start Beacon Tx on a DFS channel
9192 		 * since beaconing has to be done on DFS
9193 		 * channel only after CAC WAIT is completed.
9194 		 * On a DFS Channel LIM does not start beacon
9195 		 * Tx right after the WMA_ADD_BSS_RSP.
9196 		 */
9197 		lim_apply_configuration(mac, pe_session);
9198 		pe_debug("Start Beacon with ssid " QDF_SSID_FMT " Ch freq %d",
9199 			 QDF_SSID_REF(pe_session->ssId.length,
9200 				      pe_session->ssId.ssId),
9201 			 pe_session->curr_op_freq);
9202 		lim_send_beacon(mac, pe_session);
9203 		lim_enable_obss_detection_config(mac, pe_session);
9204 		lim_send_obss_color_collision_cfg(mac, pe_session,
9205 					OBSS_COLOR_COLLISION_DETECTION);
9206 	} else {
9207 		pe_err("Invalid Beacon Start Indication");
9208 		return;
9209 	}
9210 }
9211 
9212 static void lim_mon_change_channel(
9213 	struct mac_context *mac_ctx,
9214 	struct pe_session *session_entry)
9215 {
9216 	if (wlan_vdev_mlme_get_state(session_entry->vdev) == WLAN_VDEV_S_INIT)
9217 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9218 					      WLAN_VDEV_SM_EV_START,
9219 					      sizeof(*session_entry),
9220 					      session_entry);
9221 	else if (wlan_vdev_mlme_get_state(session_entry->vdev) ==
9222 		 WLAN_VDEV_S_UP) {
9223 		mlme_set_chan_switch_in_progress(session_entry->vdev, true);
9224 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9225 					      WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
9226 					      sizeof(*session_entry),
9227 					      session_entry);
9228 	} else {
9229 		pe_err("Invalid vdev state to change channel");
9230 	}
9231 }
9232 
9233 static void lim_change_channel(
9234 	struct mac_context *mac_ctx,
9235 	struct pe_session *session_entry)
9236 {
9237 	if (session_entry->bssType == eSIR_MONITOR_MODE)
9238 		return lim_mon_change_channel(mac_ctx, session_entry);
9239 
9240 	mlme_set_chan_switch_in_progress(session_entry->vdev, true);
9241 
9242 	if (wlan_vdev_mlme_get_state(session_entry->vdev) ==
9243 	    WLAN_VDEV_S_DFS_CAC_WAIT)
9244 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9245 					      WLAN_VDEV_SM_EV_RADAR_DETECTED,
9246 					      sizeof(*session_entry),
9247 					      session_entry);
9248 	else
9249 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9250 					      WLAN_VDEV_SM_EV_CSA_COMPLETE,
9251 					      sizeof(*session_entry),
9252 					      session_entry);
9253 }
9254 
9255 #ifdef WLAN_FEATURE_11BE
9256 static bool
9257 lim_is_puncture_bitmap_changed(struct pe_session *session,
9258 			       struct channel_change_req *ch_change_req)
9259 {
9260 	uint16_t ori_puncture_bitmap;
9261 
9262 	ori_puncture_bitmap =
9263 		*(uint16_t *)session->eht_op.disabled_sub_chan_bitmap;
9264 
9265 	return ori_puncture_bitmap != ch_change_req->target_punc_bitmap;
9266 }
9267 #else
9268 static inline bool
9269 lim_is_puncture_bitmap_changed(struct pe_session *session,
9270 			       struct channel_change_req *ch_change_req)
9271 {
9272 	return false;
9273 }
9274 #endif
9275 
9276 /**
9277  * lim_abort_channel_change() - Abort channel change
9278  *
9279  * @mac_ctx : Pointer to pe_session
9280  * @vdev_id: vdev ID
9281  *
9282  * This function is called to abort channel change request after CSA
9283  * countdown and allow SAP/GO to operate on current channel without
9284  * vdev restart.
9285  *
9286  * Return: None
9287  */
9288 static void lim_abort_channel_change(struct mac_context *mac_ctx,
9289 				     uint8_t vdev_id)
9290 {
9291 	struct qdf_mac_addr bssid;
9292 	struct pe_session *session_entry;
9293 	uint8_t session_id;
9294 	QDF_STATUS status;
9295 	struct scheduler_msg sch_msg = {0};
9296 	struct sSirChanChangeResponse *chan_change_rsp;
9297 
9298 	status = wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, vdev_id, &bssid);
9299 	if (!QDF_IS_STATUS_SUCCESS(status)) {
9300 		pe_err("Failed to get vdev ID");
9301 		return;
9302 	}
9303 
9304 	session_entry = pe_find_session_by_bssid(mac_ctx, bssid.bytes,
9305 						 &session_id);
9306 	if (!session_entry) {
9307 		pe_err("Session does not exist for bssid " QDF_MAC_ADDR_FMT,
9308 		       QDF_MAC_ADDR_REF(bssid.bytes));
9309 		return;
9310 	}
9311 
9312 	session_entry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_SAP_DFS;
9313 	mac_ctx->sap.SapDfsInfo.target_chan_freq =
9314 					session_entry->curr_op_freq;
9315 	mac_ctx->sap.SapDfsInfo.new_chanWidth = session_entry->ch_width;
9316 	mac_ctx->sap.SapDfsInfo.new_ch_params.ch_width =
9317 						session_entry->ch_width;
9318 
9319 	wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9320 				      WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED,
9321 				      sizeof(*session_entry), session_entry);
9322 
9323 	chan_change_rsp = qdf_mem_malloc(sizeof(struct sSirChanChangeResponse));
9324 	if (!chan_change_rsp) {
9325 		pe_err("Failed to allocate chan_change_rsp");
9326 		return;
9327 	}
9328 
9329 	chan_change_rsp->new_op_freq = session_entry->curr_op_freq;
9330 	chan_change_rsp->channelChangeStatus = QDF_STATUS_SUCCESS;
9331 	chan_change_rsp->sessionId = session_id;
9332 	sch_msg.type = eWNI_SME_CHANNEL_CHANGE_RSP;
9333 	sch_msg.bodyptr = (void *)chan_change_rsp;
9334 	sch_msg.bodyval = 0;
9335 
9336 	lim_sys_process_mmh_msg_api(mac_ctx, &sch_msg);
9337 }
9338 
9339 /**
9340  * lim_process_sme_channel_change_request() - process sme ch change req
9341  *
9342  * @mac_ctx: Pointer to Global MAC structure
9343  * @msg_buf: pointer to the SME message buffer
9344  *
9345  * This function is called to process SME_CHANNEL_CHANGE_REQ message
9346  *
9347  * Return: None
9348  */
9349 static void lim_process_sme_channel_change_request(struct mac_context *mac_ctx,
9350 		uint32_t *msg_buf)
9351 {
9352 	struct channel_change_req *ch_change_req;
9353 	struct qdf_mac_addr bssid;
9354 	struct pe_session *session_entry;
9355 	uint8_t session_id;      /* PE session_id */
9356 	int8_t max_tx_pwr;
9357 	uint32_t target_freq;
9358 	bool is_curr_ch_2g, is_new_ch_2g, update_he_cap, update_eht_cap;
9359 
9360 	if (!msg_buf) {
9361 		pe_err("msg_buf is NULL");
9362 		return;
9363 	}
9364 	ch_change_req = (struct channel_change_req *)msg_buf;
9365 	target_freq = ch_change_req->target_chan_freq;
9366 
9367 	max_tx_pwr = wlan_reg_get_channel_reg_power_for_freq(
9368 				mac_ctx->pdev, target_freq);
9369 	if (max_tx_pwr == WMA_MAX_TXPOWER_INVALID) {
9370 		pe_err("Invalid max tx power");
9371 		return;
9372 	}
9373 	wlan_mlme_get_mac_vdev_id(mac_ctx->pdev,
9374 				  ch_change_req->vdev_id, &bssid);
9375 	session_entry = pe_find_session_by_bssid(mac_ctx, bssid.bytes,
9376 						 &session_id);
9377 	if (!session_entry) {
9378 		pe_err("Session does not exist for bssid " QDF_MAC_ADDR_FMT,
9379 		       QDF_MAC_ADDR_REF(bssid.bytes));
9380 		return;
9381 	}
9382 
9383 	/*
9384 	 * The scenario here is, existing SAP/GO is operating on non-DFS chan
9385 	 * and STA connects to a DFS AP which creates MCC. This will then
9386 	 * trigger SCC enforcement logic. Now during CSA countdown (before
9387 	 * GO/SAP actually moves to STA's channel), if STA disconnects, then
9388 	 * moving GO / SAP to DFS channel will lead to FCC violation if radar
9389 	 * detection is disabled
9390 	 *
9391 	 * Hence to handle this scenario, better to stop current GO/SAP's
9392 	 * movement to this DFS channel and allow to operate on current channel
9393 	 * only, STA associated to GO/SAP's will find that SAP/GO didn't beacon
9394 	 * on new channel so Heartbeat failure will happen and they will scan
9395 	 * and connect again.
9396 	 */
9397 
9398 	if (LIM_IS_AP_ROLE(session_entry) &&
9399 	    !policy_mgr_is_sap_allowed_on_dfs_freq(mac_ctx->pdev, session_id,
9400 						   target_freq)) {
9401 		lim_abort_channel_change(mac_ctx, ch_change_req->vdev_id);
9402 		return;
9403 	} else if ((session_entry->curr_op_freq == target_freq &&
9404 		    session_entry->ch_width == ch_change_req->ch_width) &&
9405 		   (!IS_DOT11_MODE_EHT(session_entry->dot11mode) ||
9406 		    !lim_is_puncture_bitmap_changed(session_entry,
9407 						    ch_change_req))) {
9408 		pe_err("Target channel and mode is same as current channel and mode channel freq %d and mode %d",
9409 		       session_entry->curr_op_freq, session_entry->ch_width);
9410 		return;
9411 	}
9412 
9413 	if (LIM_IS_AP_ROLE(session_entry))
9414 		session_entry->channelChangeReasonCode =
9415 			LIM_SWITCH_CHANNEL_SAP_DFS;
9416 	else
9417 		session_entry->channelChangeReasonCode =
9418 			LIM_SWITCH_CHANNEL_MONITOR;
9419 
9420 	pe_nofl_debug("SAP CSA: %d ---> %d, ch_bw %d, nw_type %d, dot11mode %d",
9421 		      session_entry->curr_op_freq, target_freq,
9422 		      ch_change_req->ch_width, ch_change_req->nw_type,
9423 		      ch_change_req->dot11mode);
9424 
9425 	if (IS_DOT11_MODE_HE(ch_change_req->dot11mode) &&
9426 		((QDF_MONITOR_MODE == session_entry->opmode) ||
9427 		lim_is_session_he_capable(session_entry))) {
9428 		lim_update_session_he_capable_chan_switch
9429 			(mac_ctx, session_entry, target_freq);
9430 		is_new_ch_2g = wlan_reg_is_24ghz_ch_freq(target_freq);
9431 		is_curr_ch_2g = wlan_reg_is_24ghz_ch_freq(
9432 					session_entry->curr_op_freq);
9433 		if ((is_new_ch_2g && !is_curr_ch_2g) ||
9434 		    (!is_new_ch_2g && is_curr_ch_2g))
9435 			update_he_cap = true;
9436 		else
9437 			update_he_cap = false;
9438 		if (!update_he_cap) {
9439 			if ((session_entry->ch_width !=
9440 			     ch_change_req->ch_width) &&
9441 			    (session_entry->ch_width > CH_WIDTH_80MHZ ||
9442 			     ch_change_req->ch_width > CH_WIDTH_80MHZ))
9443 				update_he_cap = true;
9444 		}
9445 		if (update_he_cap) {
9446 			session_entry->curr_op_freq = target_freq;
9447 			session_entry->ch_width = ch_change_req->ch_width;
9448 			lim_copy_bss_he_cap(session_entry);
9449 			lim_update_he_bw_cap_mcs(session_entry, NULL);
9450 		}
9451 	} else if (wlan_reg_is_6ghz_chan_freq(target_freq)) {
9452 		pe_debug("Invalid target_freq %d for dot11mode %d cur HE %d",
9453 			 target_freq, ch_change_req->dot11mode,
9454 			 lim_is_session_he_capable(session_entry));
9455 		return;
9456 	}
9457 
9458 	if (IS_DOT11_MODE_EHT(ch_change_req->dot11mode) &&
9459 	    ((QDF_MONITOR_MODE == session_entry->opmode) ||
9460 	     lim_is_session_eht_capable(session_entry))) {
9461 		lim_update_session_eht_capable_chan_switch(
9462 				mac_ctx, session_entry, target_freq);
9463 		is_new_ch_2g = wlan_reg_is_24ghz_ch_freq(target_freq);
9464 		is_curr_ch_2g = wlan_reg_is_24ghz_ch_freq(
9465 					session_entry->curr_op_freq);
9466 		if ((is_new_ch_2g && !is_curr_ch_2g) ||
9467 		    (!is_new_ch_2g && is_curr_ch_2g))
9468 			update_eht_cap = true;
9469 		else
9470 			update_eht_cap = false;
9471 		if (!update_eht_cap) {
9472 			if ((session_entry->ch_width !=
9473 			     ch_change_req->ch_width) &&
9474 			    (session_entry->ch_width > CH_WIDTH_80MHZ ||
9475 			     ch_change_req->ch_width > CH_WIDTH_80MHZ))
9476 				update_eht_cap = true;
9477 		}
9478 		if (update_eht_cap) {
9479 			session_entry->curr_op_freq = target_freq;
9480 			session_entry->ch_width = ch_change_req->ch_width;
9481 			lim_copy_bss_eht_cap(session_entry);
9482 			lim_update_eht_bw_cap_mcs(session_entry, NULL);
9483 		}
9484 	}
9485 
9486 	/* Store the New Channel Params in session_entry */
9487 	session_entry->ch_width = ch_change_req->ch_width;
9488 	session_entry->ch_center_freq_seg0 =
9489 			 ch_change_req->center_freq_seg0;
9490 	session_entry->ch_center_freq_seg1 =
9491 			ch_change_req->center_freq_seg1;
9492 	session_entry->htSecondaryChannelOffset = ch_change_req->sec_ch_offset;
9493 	session_entry->htSupportedChannelWidthSet =
9494 		(ch_change_req->ch_width ? 1 : 0);
9495 	session_entry->htRecommendedTxWidthSet =
9496 		session_entry->htSupportedChannelWidthSet;
9497 	session_entry->curr_op_freq = target_freq;
9498 	session_entry->limRFBand = lim_get_rf_band(
9499 		session_entry->curr_op_freq);
9500 	if (mlme_get_cac_required(session_entry->vdev))
9501 		session_entry->cac_duration_ms = ch_change_req->cac_duration_ms;
9502 	else
9503 		session_entry->cac_duration_ms = 0;
9504 	session_entry->dfs_regdomain = ch_change_req->dfs_regdomain;
9505 	session_entry->maxTxPower = max_tx_pwr;
9506 
9507 	/* Update the global beacon filter */
9508 	lim_update_bcn_probe_filter(mac_ctx, session_entry);
9509 
9510 	/* Initialize 11h Enable Flag */
9511 	if (CHAN_HOP_ALL_BANDS_ENABLE ||
9512 	    session_entry->limRFBand != REG_BAND_2G)
9513 		session_entry->lim11hEnable =
9514 			mac_ctx->mlme_cfg->gen.enabled_11h;
9515 	else
9516 		session_entry->lim11hEnable = 0;
9517 
9518 	session_entry->dot11mode = ch_change_req->dot11mode;
9519 	session_entry->nwType = ch_change_req->nw_type;
9520 	qdf_mem_copy(&session_entry->rateSet,
9521 		     &ch_change_req->opr_rates,
9522 		     sizeof(session_entry->rateSet));
9523 	qdf_mem_copy(&session_entry->extRateSet,
9524 		     &ch_change_req->ext_rates,
9525 		     sizeof(session_entry->extRateSet));
9526 	lim_change_channel(mac_ctx, session_entry);
9527 	lim_check_conc_power_for_csa(mac_ctx, session_entry);
9528 
9529 	lim_dump_session_info(mac_ctx, session_entry);
9530 	lim_dump_he_info(mac_ctx, session_entry);
9531 	lim_dump_eht_info(session_entry);
9532 }
9533 
9534 /******************************************************************************
9535 * lim_start_bss_update_add_ie_buffer()
9536 *
9537 ***FUNCTION:
9538 * This function checks the src buffer and its length and then malloc for
9539 * dst buffer update the same
9540 *
9541 ***LOGIC:
9542 *
9543 ***ASSUMPTIONS:
9544 *
9545 ***NOTE:
9546 *
9547 * @param  mac      Pointer to Global MAC structure
9548 * @param  **pDstData_buff  A pointer to pointer of  uint8_t dst buffer
9549 * @param  *pDstDataLen  A pointer to pointer of  uint16_t dst buffer length
9550 * @param  *pSrcData_buff  A pointer of  uint8_t  src buffer
9551 * @param  srcDataLen  src buffer length
9552 ******************************************************************************/
9553 
9554 static void
9555 lim_start_bss_update_add_ie_buffer(struct mac_context *mac,
9556 				   uint8_t **pDstData_buff,
9557 				   uint16_t *pDstDataLen,
9558 				   uint8_t *pSrcData_buff, uint16_t srcDataLen)
9559 {
9560 
9561 	if (srcDataLen > 0 && pSrcData_buff) {
9562 		*pDstDataLen = srcDataLen;
9563 
9564 		*pDstData_buff = qdf_mem_malloc(*pDstDataLen);
9565 		if (!*pDstData_buff)
9566 			return;
9567 		qdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen);
9568 	} else {
9569 		*pDstData_buff = NULL;
9570 		*pDstDataLen = 0;
9571 	}
9572 }
9573 
9574 /******************************************************************************
9575 * lim_update_add_ie_buffer()
9576 *
9577 ***FUNCTION:
9578 * This function checks the src buffer and length if src buffer length more
9579 * than dst buffer length then free the dst buffer and malloc for the new src
9580 * length, and update the dst buffer and length. But if dst buffer is bigger
9581 * than src buffer length then it just update the dst buffer and length
9582 *
9583 ***LOGIC:
9584 *
9585 ***ASSUMPTIONS:
9586 *
9587 ***NOTE:
9588 *
9589 * @param  mac      Pointer to Global MAC structure
9590 * @param  **pDstData_buff  A pointer to pointer of  uint8_t dst buffer
9591 * @param  *pDstDataLen  A pointer to pointer of  uint16_t dst buffer length
9592 * @param  *pSrcData_buff  A pointer of  uint8_t  src buffer
9593 * @param  srcDataLen  src buffer length
9594 ******************************************************************************/
9595 
9596 static void
9597 lim_update_add_ie_buffer(struct mac_context *mac,
9598 			 uint8_t **pDstData_buff,
9599 			 uint16_t *pDstDataLen,
9600 			 uint8_t *pSrcData_buff, uint16_t srcDataLen)
9601 {
9602 
9603 	if (!pSrcData_buff) {
9604 		pe_err("src buffer is null");
9605 		return;
9606 	}
9607 
9608 	if (srcDataLen > *pDstDataLen) {
9609 		*pDstDataLen = srcDataLen;
9610 		/* free old buffer */
9611 		qdf_mem_free(*pDstData_buff);
9612 		/* allocate a new */
9613 		*pDstData_buff = qdf_mem_malloc(*pDstDataLen);
9614 		if (!*pDstData_buff) {
9615 			*pDstDataLen = 0;
9616 			return;
9617 		}
9618 	}
9619 
9620 	/* copy the content of buffer into dst buffer
9621 	 */
9622 	*pDstDataLen = srcDataLen;
9623 	qdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen);
9624 
9625 }
9626 
9627 /*
9628 * lim_process_modify_add_ies() - process modify additional IE req.
9629 *
9630 * @mac_ctx: Pointer to Global MAC structure
9631 * @msg_buf: pointer to the SME message buffer
9632 *
9633 * This function update the PE buffers for additional IEs.
9634 *
9635 * Return: None
9636 */
9637 static void lim_process_modify_add_ies(struct mac_context *mac_ctx,
9638 		uint32_t *msg_buf)
9639 {
9640 	tpSirModifyIEsInd modify_add_ies;
9641 	struct pe_session *session_entry;
9642 	uint8_t session_id;
9643 	bool ret = false;
9644 	struct add_ie_params *add_ie_params;
9645 
9646 	if (!msg_buf) {
9647 		pe_err("msg_buf is NULL");
9648 		return;
9649 	}
9650 
9651 	modify_add_ies = (tpSirModifyIEsInd)msg_buf;
9652 	/* Incoming message has smeSession, use BSSID to find PE session */
9653 	session_entry = pe_find_session_by_bssid(mac_ctx,
9654 			modify_add_ies->modifyIE.bssid.bytes, &session_id);
9655 
9656 	if (!session_entry) {
9657 		pe_err("Session not found for given bssid"
9658 					QDF_MAC_ADDR_FMT,
9659 		QDF_MAC_ADDR_REF(modify_add_ies->modifyIE.bssid.bytes));
9660 		goto end;
9661 	}
9662 	if ((0 == modify_add_ies->modifyIE.ieBufferlength) ||
9663 		(0 == modify_add_ies->modifyIE.ieIDLen) ||
9664 		(!modify_add_ies->modifyIE.pIEBuffer)) {
9665 		pe_err("Invalid request pIEBuffer %pK ieBufferlength %d ieIDLen %d ieID %d. update Type %d",
9666 				modify_add_ies->modifyIE.pIEBuffer,
9667 				modify_add_ies->modifyIE.ieBufferlength,
9668 				modify_add_ies->modifyIE.ieID,
9669 				modify_add_ies->modifyIE.ieIDLen,
9670 				modify_add_ies->updateType);
9671 		goto end;
9672 	}
9673 	add_ie_params = &session_entry->add_ie_params;
9674 	switch (modify_add_ies->updateType) {
9675 	case eUPDATE_IE_PROBE_RESP:
9676 		/* Probe resp */
9677 		break;
9678 	case eUPDATE_IE_ASSOC_RESP:
9679 		/* assoc resp IE */
9680 		if (!add_ie_params->assocRespDataLen)
9681 			pe_err("assoc resp add ie not present");
9682 		/* search through the buffer and modify the IE */
9683 		break;
9684 	case eUPDATE_IE_PROBE_BCN:
9685 		/*probe beacon IE */
9686 		if (ret == true && modify_add_ies->modifyIE.notify) {
9687 			lim_handle_param_update(mac_ctx,
9688 					modify_add_ies->updateType);
9689 		}
9690 		break;
9691 	default:
9692 		pe_err("unhandled buffer type %d",
9693 				modify_add_ies->updateType);
9694 		break;
9695 	}
9696 end:
9697 	qdf_mem_free(modify_add_ies->modifyIE.pIEBuffer);
9698 	modify_add_ies->modifyIE.pIEBuffer = NULL;
9699 }
9700 
9701 /*
9702 * lim_process_update_add_ies() - process additional IE update req
9703 *
9704 * @mac_ctx: Pointer to Global MAC structure
9705 * @msg_buf: pointer to the SME message buffer
9706 *
9707 * This function update the PE buffers for additional IEs.
9708 *
9709 * Return: None
9710 */
9711 static void lim_process_update_add_ies(struct mac_context *mac_ctx,
9712 		uint32_t *msg_buf)
9713 {
9714 	tpSirUpdateIEsInd update_add_ies = (tpSirUpdateIEsInd)msg_buf;
9715 	uint8_t session_id;
9716 	struct pe_session *session_entry;
9717 	struct add_ie_params *addn_ie;
9718 	uint16_t new_length = 0;
9719 	uint8_t *new_ptr = NULL;
9720 	tSirUpdateIE *update_ie;
9721 
9722 	if (!msg_buf) {
9723 		pe_err("msg_buf is NULL");
9724 		return;
9725 	}
9726 	update_ie = &update_add_ies->updateIE;
9727 	/* incoming message has smeSession, use BSSID to find PE session */
9728 	session_entry = pe_find_session_by_bssid(mac_ctx,
9729 			update_ie->bssid.bytes, &session_id);
9730 
9731 	if (!session_entry) {
9732 		pe_debug("Session not found for given bssid"
9733 			 QDF_MAC_ADDR_FMT,
9734 			 QDF_MAC_ADDR_REF(update_ie->bssid.bytes));
9735 		goto end;
9736 	}
9737 	addn_ie = &session_entry->add_ie_params;
9738 	/* if len is 0, upper layer requested freeing of buffer */
9739 	if (0 == update_ie->ieBufferlength) {
9740 		switch (update_add_ies->updateType) {
9741 		case eUPDATE_IE_PROBE_RESP:
9742 			qdf_mem_free(addn_ie->probeRespData_buff);
9743 			addn_ie->probeRespData_buff = NULL;
9744 			addn_ie->probeRespDataLen = 0;
9745 			break;
9746 		case eUPDATE_IE_ASSOC_RESP:
9747 			qdf_mem_free(addn_ie->assocRespData_buff);
9748 			addn_ie->assocRespData_buff = NULL;
9749 			addn_ie->assocRespDataLen = 0;
9750 			break;
9751 		case eUPDATE_IE_PROBE_BCN:
9752 			qdf_mem_free(addn_ie->probeRespBCNData_buff);
9753 			addn_ie->probeRespBCNData_buff = NULL;
9754 			addn_ie->probeRespBCNDataLen = 0;
9755 
9756 			if (update_ie->notify)
9757 				lim_handle_param_update(mac_ctx,
9758 						update_add_ies->updateType);
9759 			break;
9760 		default:
9761 			break;
9762 		}
9763 		return;
9764 	}
9765 	switch (update_add_ies->updateType) {
9766 	case eUPDATE_IE_PROBE_RESP:
9767 		if (update_ie->append) {
9768 			/*
9769 			 * In case of append, allocate new memory
9770 			 * with combined length.
9771 			 * Multiple back to back append commands
9772 			 * can lead to a huge length.So, check
9773 			 * for the validity of the length.
9774 			 */
9775 			if (addn_ie->probeRespDataLen >
9776 				(USHRT_MAX - update_ie->ieBufferlength)) {
9777 				pe_err("IE Length overflow, curr:%d, new:%d",
9778 					addn_ie->probeRespDataLen,
9779 					update_ie->ieBufferlength);
9780 				goto end;
9781 			}
9782 			new_length = update_ie->ieBufferlength +
9783 				addn_ie->probeRespDataLen;
9784 			new_ptr = qdf_mem_malloc(new_length);
9785 			if (!new_ptr)
9786 				goto end;
9787 			/* append buffer to end of local buffers */
9788 			qdf_mem_copy(new_ptr, addn_ie->probeRespData_buff,
9789 					addn_ie->probeRespDataLen);
9790 			qdf_mem_copy(&new_ptr[addn_ie->probeRespDataLen],
9791 				     update_ie->pAdditionIEBuffer,
9792 				     update_ie->ieBufferlength);
9793 			/* free old memory */
9794 			qdf_mem_free(addn_ie->probeRespData_buff);
9795 			/* adjust length accordingly */
9796 			addn_ie->probeRespDataLen = new_length;
9797 			/* save reference of local buffer in PE session */
9798 			addn_ie->probeRespData_buff = new_ptr;
9799 			goto end;
9800 		}
9801 		lim_update_add_ie_buffer(mac_ctx, &addn_ie->probeRespData_buff,
9802 				&addn_ie->probeRespDataLen,
9803 				update_ie->pAdditionIEBuffer,
9804 				update_ie->ieBufferlength);
9805 		break;
9806 	case eUPDATE_IE_ASSOC_RESP:
9807 		/* assoc resp IE */
9808 		lim_update_add_ie_buffer(mac_ctx, &addn_ie->assocRespData_buff,
9809 				&addn_ie->assocRespDataLen,
9810 				update_ie->pAdditionIEBuffer,
9811 				update_ie->ieBufferlength);
9812 		break;
9813 	case eUPDATE_IE_PROBE_BCN:
9814 		/* probe resp Bcn IE */
9815 		lim_update_add_ie_buffer(mac_ctx,
9816 				&addn_ie->probeRespBCNData_buff,
9817 				&addn_ie->probeRespBCNDataLen,
9818 				update_ie->pAdditionIEBuffer,
9819 				update_ie->ieBufferlength);
9820 		if (update_ie->notify)
9821 			lim_handle_param_update(mac_ctx,
9822 					update_add_ies->updateType);
9823 		break;
9824 	default:
9825 		pe_err("unhandled buffer type %d", update_add_ies->updateType);
9826 		break;
9827 	}
9828 end:
9829 	qdf_mem_free(update_ie->pAdditionIEBuffer);
9830 	update_ie->pAdditionIEBuffer = NULL;
9831 }
9832 
9833 void send_extended_chan_switch_action_frame(struct mac_context *mac_ctx,
9834 					    uint16_t new_channel_freq,
9835 					    enum phy_ch_width ch_bandwidth,
9836 					    struct pe_session *session_entry)
9837 {
9838 	uint8_t op_class = 0;
9839 	uint8_t switch_mode = 0, i;
9840 	tpDphHashNode psta;
9841 	uint8_t new_channel = 0;
9842 	enum phy_ch_width ch_width;
9843 	tLimChannelSwitchInfo *ch_switch = &session_entry->gLimChannelSwitch;
9844 
9845 	op_class =
9846 		lim_op_class_from_bandwidth(mac_ctx, new_channel_freq,
9847 					    ch_bandwidth,
9848 					    ch_switch->sec_ch_offset);
9849 	new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq);
9850 	if (LIM_IS_AP_ROLE(session_entry) &&
9851 		(mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false))
9852 		switch_mode = ch_switch->switchMode;
9853 
9854 	if (LIM_IS_AP_ROLE(session_entry)) {
9855 		for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) {
9856 			psta =
9857 			  session_entry->dph.dphHashTable.pDphNodeArray + i;
9858 			if (!psta || !psta->added)
9859 				continue;
9860 			ch_width = lim_calculate_peer_ch_width(session_entry,
9861 							       psta->staAddr,
9862 							       ch_bandwidth);
9863 			op_class = lim_op_class_from_bandwidth(mac_ctx,
9864 						new_channel_freq, ch_width,
9865 						ch_switch->sec_ch_offset);
9866 			lim_send_extended_chan_switch_action_frame(
9867 					mac_ctx, psta->staAddr,
9868 					switch_mode, op_class, new_channel,
9869 					ch_switch->switchCount, session_entry);
9870 		}
9871 	} else if (LIM_IS_STA_ROLE(session_entry)) {
9872 		lim_send_extended_chan_switch_action_frame(mac_ctx,
9873 					session_entry->bssId,
9874 					switch_mode, op_class, new_channel,
9875 					ch_switch->switchCount,
9876 					session_entry);
9877 	}
9878 
9879 }
9880 
9881 void lim_send_chan_switch_action_frame(struct mac_context *mac_ctx,
9882 				       uint16_t new_channel_freq,
9883 				       enum phy_ch_width ch_bandwidth,
9884 				       struct pe_session *session_entry)
9885 {
9886 	uint8_t op_class = 0, new_channel;
9887 	uint8_t switch_mode = 0, i;
9888 	uint8_t switch_count;
9889 	tpDphHashNode psta;
9890 	tpDphHashNode dph_node_array_ptr;
9891 
9892 	dph_node_array_ptr = session_entry->dph.dphHashTable.pDphNodeArray;
9893 	op_class =
9894 		lim_op_class_from_bandwidth(mac_ctx, new_channel_freq,
9895 					    ch_bandwidth,
9896 					    session_entry->gLimChannelSwitch.sec_ch_offset);
9897 	new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq);
9898 
9899 	if (LIM_IS_AP_ROLE(session_entry) &&
9900 	    (false == mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch))
9901 		switch_mode = session_entry->gLimChannelSwitch.switchMode;
9902 
9903 	switch_count = session_entry->gLimChannelSwitch.switchCount;
9904 
9905 	if (LIM_IS_AP_ROLE(session_entry)) {
9906 		for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) {
9907 			psta = dph_node_array_ptr + i;
9908 			if (!(psta && psta->added))
9909 				continue;
9910 			if (session_entry->lim_non_ecsa_cap_num == 0)
9911 				lim_send_extended_chan_switch_action_frame
9912 					(mac_ctx, psta->staAddr, switch_mode,
9913 					 op_class, new_channel, switch_count,
9914 					 session_entry);
9915 			else
9916 				lim_send_channel_switch_mgmt_frame
9917 					(mac_ctx, psta->staAddr, switch_mode,
9918 					 new_channel, switch_count,
9919 					 session_entry);
9920 		}
9921 	} else if (LIM_IS_STA_ROLE(session_entry)) {
9922 		lim_send_extended_chan_switch_action_frame
9923 			(mac_ctx, session_entry->bssId, switch_mode, op_class,
9924 			 new_channel, switch_count, session_entry);
9925 	}
9926 }
9927 
9928 /**
9929  * lim_process_sme_dfs_csa_ie_request() - process sme dfs csa ie req
9930  *
9931  * @mac_ctx: Pointer to Global MAC structure
9932  * @msg_buf: pointer to the SME message buffer
9933  *
9934  * This function processes SME request messages from HDD or upper layer
9935  * application.
9936  *
9937  * Return: None
9938  */
9939 static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx,
9940 		uint32_t *msg_buf)
9941 {
9942 	tpSirDfsCsaIeRequest dfs_csa_ie_req;
9943 	struct pe_session *session_entry = NULL;
9944 	uint8_t session_id;
9945 	tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch;
9946 	QDF_STATUS status;
9947 	enum phy_ch_width ch_width;
9948 	uint32_t target_ch_freq;
9949 	bool is_vdev_ll_lt_sap = false;
9950 	uint8_t peer_count;
9951 	uint16_t max_wait_for_bcn_tx_complete;
9952 
9953 	if (!msg_buf) {
9954 		pe_err("Buffer is Pointing to NULL");
9955 		return;
9956 	}
9957 
9958 	dfs_csa_ie_req = (tSirDfsCsaIeRequest *)msg_buf;
9959 	session_entry = pe_find_session_by_bssid(mac_ctx,
9960 			dfs_csa_ie_req->bssid, &session_id);
9961 	if (!session_entry) {
9962 		pe_err("Session not found for given BSSID" QDF_MAC_ADDR_FMT,
9963 			QDF_MAC_ADDR_REF(dfs_csa_ie_req->bssid));
9964 		return;
9965 	}
9966 
9967 	if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
9968 		pe_err("Invalid SystemRole %d",
9969 			GET_LIM_SYSTEM_ROLE(session_entry));
9970 		return;
9971 	}
9972 
9973 	/* target channel */
9974 	session_entry->gLimChannelSwitch.primaryChannel =
9975 		wlan_reg_freq_to_chan(mac_ctx->pdev,
9976 				      dfs_csa_ie_req->target_chan_freq);
9977 	session_entry->gLimChannelSwitch.sw_target_freq =
9978 		dfs_csa_ie_req->target_chan_freq;
9979 	target_ch_freq = dfs_csa_ie_req->target_chan_freq;
9980 	/* Channel switch announcement needs to be included in beacon */
9981 	session_entry->dfsIncludeChanSwIe = true;
9982 
9983 	wlan_reg_set_create_punc_bitmap(&dfs_csa_ie_req->ch_params, false);
9984 	wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
9985 						dfs_csa_ie_req->target_chan_freq,
9986 						0,
9987 						&dfs_csa_ie_req->ch_params,
9988 						REG_CURRENT_PWR_MODE);
9989 
9990 	ch_width = dfs_csa_ie_req->ch_params.ch_width;
9991 	if (ch_width >= CH_WIDTH_160MHZ &&
9992 	    wma_get_vht_ch_width() < WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
9993 		ch_width = CH_WIDTH_80MHZ;
9994 	}
9995 	session_entry->gLimChannelSwitch.ch_width = ch_width;
9996 	session_entry->gLimChannelSwitch.sec_ch_offset =
9997 				 dfs_csa_ie_req->ch_params.sec_ch_offset;
9998 
9999 	is_vdev_ll_lt_sap = policy_mgr_is_vdev_ll_lt_sap(
10000 						mac_ctx->psoc,
10001 						session_entry->vdev_id);
10002 
10003 	if (is_vdev_ll_lt_sap) {
10004 		session_entry->gLimChannelSwitch.switchCount = 1;
10005 		session_entry->gLimChannelSwitch.switchMode = 0;
10006 	} else {
10007 		session_entry->gLimChannelSwitch.switchCount =
10008 			dfs_csa_ie_req->ch_switch_beacon_cnt;
10009 		if (!mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch)
10010 			session_entry->gLimChannelSwitch.switchMode =
10011 					dfs_csa_ie_req->ch_switch_mode;
10012 	}
10013 
10014 	/*
10015 	 * Validate if SAP is operating HT or VHT/HE mode and set the Channel
10016 	 * Switch Wrapper element with the Wide Band Switch subelement.
10017 	 */
10018 	if (!(session_entry->vhtCapability ||
10019 	      lim_is_session_he_capable(session_entry)))
10020 		goto skip_vht;
10021 
10022 	/* Now encode the Wider Ch BW element depending on the ch width */
10023 	wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch;
10024 	switch (ch_width) {
10025 	case CH_WIDTH_20MHZ:
10026 		/*
10027 		 * Wide channel BW sublement in channel wrapper element is not
10028 		 * required in case of 20 Mhz operation. Currently It is set
10029 		 * only set in case of 40/80 Mhz Operation.
10030 		 */
10031 		session_entry->dfsIncludeChanWrapperIe = false;
10032 		wider_bw_ch_switch->newChanWidth =
10033 			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
10034 		break;
10035 	case CH_WIDTH_40MHZ:
10036 		session_entry->dfsIncludeChanWrapperIe = false;
10037 		wider_bw_ch_switch->newChanWidth =
10038 			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
10039 		break;
10040 	case CH_WIDTH_80MHZ:
10041 		session_entry->dfsIncludeChanWrapperIe = true;
10042 		wider_bw_ch_switch->newChanWidth =
10043 			WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
10044 		break;
10045 	case CH_WIDTH_160MHZ:
10046 		session_entry->dfsIncludeChanWrapperIe = true;
10047 		wider_bw_ch_switch->newChanWidth =
10048 			WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
10049 		break;
10050 	case CH_WIDTH_80P80MHZ:
10051 		session_entry->dfsIncludeChanWrapperIe = true;
10052 		wider_bw_ch_switch->newChanWidth =
10053 			WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
10054 		/*
10055 		 * This is not applicable for 20/40/80 Mhz.
10056 		 * Only used when we support 80+80 Mhz operation.
10057 		 * In case of 80+80 Mhz, this parameter indicates
10058 		 * center channel frequency index of 80 Mhz channel of
10059 		 * frequency segment 1.
10060 		 */
10061 		wider_bw_ch_switch->newCenterChanFreq1 =
10062 			dfs_csa_ie_req->ch_params.center_freq_seg1;
10063 		break;
10064 	default:
10065 		session_entry->dfsIncludeChanWrapperIe = false;
10066 		/*
10067 		 * Need to handle 80+80 Mhz Scenario. When 80+80 is supported
10068 		 * set the gLimWiderBWChannelSwitch.newChanWidth to 3
10069 		 */
10070 		pe_err("Invalid Channel Width");
10071 		break;
10072 	}
10073 	/* Fetch the center channel based on the channel width */
10074 	wider_bw_ch_switch->newCenterChanFreq0 =
10075 		dfs_csa_ie_req->ch_params.center_freq_seg0;
10076 skip_vht:
10077 
10078 	/* Take a wakelock for CSA for 5 seconds and release in vdev start */
10079 
10080 	qdf_wake_lock_timeout_acquire(&session_entry->ap_ecsa_wakelock,
10081 				      MAX_WAKELOCK_FOR_CSA);
10082 	qdf_runtime_pm_prevent_suspend(&session_entry->ap_ecsa_runtime_lock);
10083 
10084 	session_entry->cac_duration_ms = dfs_csa_ie_req->new_chan_cac_ms;
10085 	wlan_util_vdev_mgr_set_cac_timeout_for_vdev(
10086 		session_entry->vdev, dfs_csa_ie_req->new_chan_cac_ms);
10087 
10088 	peer_count = wlan_vdev_get_peer_sta_count(session_entry->vdev);
10089 
10090 	if (is_vdev_ll_lt_sap && !peer_count) {
10091 		pe_debug("Peer count is 0 for LL_LT_SAP, continue CSA directly");
10092 		/* initiate vdev restart if no peer connected on XPAN */
10093 		lim_send_csa_tx_complete(session_entry->vdev_id);
10094 		/* Clear CSA IE count and update beacon */
10095 		lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry);
10096 		return;
10097 	}
10098 
10099 	/* Send CSA IE request from here */
10100 	lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry);
10101 
10102 	/*
10103 	 * Wait for max_wait_for_bcn_tx_complete ms for tx complete for beacon.
10104 	 * If tx complete for beacon is received before this timer expire,
10105 	 * stop this timer and then this will be restarted for every beacon
10106 	 * interval until switchCount become 0 and bcn template with new
10107 	 * switchCount will be sent to firmware.
10108 	 * OR
10109 	 * If no tx complete for beacon is received till this timer expire
10110 	 * this will be restarted for every beacon interval until switchCount
10111 	 * become 0 and bcn template with new switchCount will be sent to
10112 	 * firmware.
10113 	 */
10114 	if (is_vdev_ll_lt_sap)
10115 		max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE_FOR_LL_SAP;
10116 	else
10117 		max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE;
10118 
10119 	status = qdf_mc_timer_start(&session_entry->ap_ecsa_timer,
10120 				    max_wait_for_bcn_tx_complete);
10121 
10122 	if (QDF_IS_STATUS_ERROR(status))
10123 		pe_err("cannot start ap_ecsa_timer");
10124 
10125 	pe_debug("IE count:%d chan:%d freq %d width:%d wrapper:%d ch_offset:%d",
10126 		 session_entry->gLimChannelSwitch.switchCount,
10127 		 session_entry->gLimChannelSwitch.primaryChannel,
10128 		 session_entry->gLimChannelSwitch.sw_target_freq,
10129 		 session_entry->gLimChannelSwitch.ch_width,
10130 		 session_entry->dfsIncludeChanWrapperIe,
10131 		 session_entry->gLimChannelSwitch.sec_ch_offset);
10132 
10133 	/*
10134 	 * Send ECSA/CSA Action frame after updating the beacon.
10135 	 * For LL_LT_SAP, send ECSA action frame only
10136 	 */
10137 	if (CHAN_HOP_ALL_BANDS_ENABLE &&
10138 	    session_entry->lim_non_ecsa_cap_num &&
10139 	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(target_ch_freq) &&
10140 	    !is_vdev_ll_lt_sap)
10141 		lim_send_chan_switch_action_frame
10142 			(mac_ctx,
10143 			 session_entry->gLimChannelSwitch.primaryChannel,
10144 			 ch_width, session_entry);
10145 	else
10146 		send_extended_chan_switch_action_frame
10147 			(mac_ctx, target_ch_freq, ch_width,
10148 			 session_entry);
10149 }
10150 
10151 /**
10152  * lim_process_ext_change_channel()- function to send ECSA
10153  * action frame for STA/CLI .
10154  * @mac_ctx: pointer to global mac structure
10155  * @msg: params from sme for new channel.
10156  *
10157  * This function is called to send ECSA frame for STA/CLI.
10158  *
10159  * Return: void
10160  */
10161 
10162 static void lim_process_ext_change_channel(struct mac_context *mac_ctx,
10163 							uint32_t *msg)
10164 {
10165 	struct sir_sme_ext_cng_chan_req *ext_chng_channel =
10166 				(struct sir_sme_ext_cng_chan_req *) msg;
10167 	struct pe_session *session_entry = NULL;
10168 
10169 	if (!msg) {
10170 		pe_err("Buffer is Pointing to NULL");
10171 		return;
10172 	}
10173 	session_entry =
10174 		pe_find_session_by_vdev_id(mac_ctx, ext_chng_channel->vdev_id);
10175 	if (!session_entry) {
10176 		pe_err("Session not found for given vdev_id %d",
10177 			ext_chng_channel->vdev_id);
10178 		return;
10179 	}
10180 	if (LIM_IS_AP_ROLE(session_entry)) {
10181 		pe_err("not an STA/CLI session");
10182 		return;
10183 	}
10184 	session_entry->gLimChannelSwitch.sec_ch_offset = 0;
10185 	send_extended_chan_switch_action_frame(mac_ctx,
10186 					       ext_chng_channel->new_ch_freq, 0,
10187 					       session_entry);
10188 }
10189 
10190 /**
10191  * lim_process_nss_update_request() - process sme nss update req
10192  *
10193  * @mac_ctx: Pointer to Global MAC structure
10194  * @msg_buf: pointer to the SME message buffer
10195  *
10196  * This function processes SME request messages from HDD or upper layer
10197  * application.
10198  *
10199  * Return: None
10200  */
10201 static void lim_process_nss_update_request(struct mac_context *mac_ctx,
10202 		uint32_t *msg_buf)
10203 {
10204 	struct sir_nss_update_request *nss_update_req_ptr;
10205 	struct pe_session *session_entry = NULL;
10206 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
10207 	uint8_t vdev_id;
10208 
10209 	if (!msg_buf) {
10210 		pe_err("Buffer is Pointing to NULL");
10211 		return;
10212 	}
10213 
10214 	nss_update_req_ptr = (struct sir_nss_update_request *)msg_buf;
10215 	vdev_id = nss_update_req_ptr->vdev_id;
10216 	session_entry = pe_find_session_by_vdev_id(mac_ctx,
10217 						   nss_update_req_ptr->vdev_id);
10218 	if (!session_entry) {
10219 		pe_err("Session not found for given session_id %d",
10220 			nss_update_req_ptr->vdev_id);
10221 		goto end;
10222 	}
10223 
10224 	if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
10225 		pe_err("Invalid SystemRole %d",
10226 			GET_LIM_SYSTEM_ROLE(session_entry));
10227 		goto end;
10228 	}
10229 
10230 	/* populate nss field in the beacon */
10231 	session_entry->gLimOperatingMode.present = 1;
10232 	session_entry->gLimOperatingMode.rxNSS = nss_update_req_ptr->new_nss;
10233 	session_entry->gLimOperatingMode.chanWidth = session_entry->ch_width;
10234 
10235 	if ((nss_update_req_ptr->new_nss == NSS_1x1_MODE) &&
10236 			(session_entry->ch_width > CH_WIDTH_80MHZ))
10237 		session_entry->gLimOperatingMode.chanWidth = CH_WIDTH_80MHZ;
10238 	if (session_entry->gLimOperatingMode.chanWidth <= CH_WIDTH_160MHZ &&
10239 	    nss_update_req_ptr->ch_width <
10240 			session_entry->gLimOperatingMode.chanWidth)
10241 		session_entry->gLimOperatingMode.chanWidth =
10242 			nss_update_req_ptr->ch_width;
10243 
10244 	pe_debug("ch width %d Rx NSS %d",
10245 		 session_entry->gLimOperatingMode.chanWidth,
10246 		 session_entry->gLimOperatingMode.rxNSS);
10247 
10248 	/* Send nss update request from here */
10249 	status = sch_set_fixed_beacon_fields(mac_ctx, session_entry);
10250 	if (QDF_IS_STATUS_ERROR(status)) {
10251 		pe_err("Unable to set op mode IE in beacon");
10252 		goto end;
10253 	}
10254 
10255 	status = lim_send_beacon_ind(mac_ctx, session_entry, REASON_NSS_UPDATE);
10256 	if (QDF_IS_STATUS_SUCCESS(status))
10257 		return;
10258 
10259 	pe_err("Unable to send beacon");
10260 end:
10261 	/*
10262 	 * send resp only in case of failure,
10263 	 * success case response will be from wma.
10264 	 */
10265 	lim_nss_or_ch_width_update_rsp(mac_ctx, vdev_id, status,
10266 				       REASON_NSS_UPDATE);
10267 }
10268 
10269 /**
10270  * lim_process_set_ie_req() - process sme set IE request
10271  *
10272  * @mac_ctx: Pointer to Global MAC structure
10273  * @msg_buf: pointer to the SME message buffer
10274  *
10275  * This function processes SME request messages from HDD or upper layer
10276  * application.
10277  *
10278  * Return: None
10279  */
10280 static void lim_process_set_ie_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
10281 {
10282 	struct send_extcap_ie *msg;
10283 	QDF_STATUS status;
10284 	tDot11fIEExtCap extra_ext_cap = {0};
10285 	uint16_t vdev_id;
10286 	struct wlan_objmgr_vdev *vdev = NULL;
10287 	struct mlme_legacy_priv *mlme_priv;
10288 	struct s_ext_cap *p_ext_cap;
10289 
10290 	if (!msg_buf) {
10291 		pe_err("Buffer is Pointing to NULL");
10292 		return;
10293 	}
10294 
10295 	msg = (struct send_extcap_ie *)msg_buf;
10296 	vdev_id = msg->session_id;
10297 
10298 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
10299 						    vdev_id,
10300 						    WLAN_LEGACY_SME_ID);
10301 	if (!vdev)
10302 		return;
10303 
10304 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
10305 	if (!mlme_priv) {
10306 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
10307 		return;
10308 	}
10309 
10310 	if (!mlme_priv->connect_info.ext_cap_ie[0])
10311 		goto send_ie;
10312 
10313 	lim_update_extcap_struct(mac_ctx,
10314 				 mlme_priv->connect_info.ext_cap_ie,
10315 				 &extra_ext_cap);
10316 	p_ext_cap = (struct s_ext_cap *)extra_ext_cap.bytes;
10317 	if (p_ext_cap->interworking_service)
10318 		p_ext_cap->qos_map = 1;
10319 	extra_ext_cap.num_bytes =
10320 		lim_compute_ext_cap_ie_length(&extra_ext_cap);
10321 send_ie:
10322 	status = lim_send_ext_cap_ie(mac_ctx, msg->session_id, &extra_ext_cap,
10323 				     true);
10324 	if (QDF_IS_STATUS_ERROR(status))
10325 		pe_err("Unable to send ExtCap to FW");
10326 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
10327 }
10328 
10329 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
10330 
10331 /**
10332  * obss_color_collision_process_color_disable() - Disable bss color
10333  * @mac_ctx: Pointer to Global MAC structure
10334  * @session: pointer to session
10335  *
10336  * This function will disable bss color.
10337  *
10338  * Return: None
10339  */
10340 static void obss_color_collision_process_color_disable(struct mac_context *mac_ctx,
10341 						       struct pe_session *session)
10342 {
10343 	tUpdateBeaconParams beacon_params;
10344 
10345 	if (!session) {
10346 		pe_err("Invalid session");
10347 		return;
10348 	}
10349 
10350 	if (session->valid && !LIM_IS_AP_ROLE(session)) {
10351 		pe_err("Invalid SystemRole %d",
10352 		       GET_LIM_SYSTEM_ROLE(session));
10353 		return;
10354 	}
10355 
10356 	if (session->bss_color_changing == 1) {
10357 		pe_warn("%d: color change in progress", session->smeSessionId);
10358 		/* Continue color collision detection */
10359 		lim_send_obss_color_collision_cfg(mac_ctx, session,
10360 				OBSS_COLOR_COLLISION_DETECTION);
10361 		return;
10362 	}
10363 
10364 	if (session->he_op.bss_col_disabled == 1) {
10365 		pe_warn("%d: bss color already disabled",
10366 			session->smeSessionId);
10367 		/* Continue free color detection */
10368 		lim_send_obss_color_collision_cfg(mac_ctx, session,
10369 				OBSS_COLOR_FREE_SLOT_AVAILABLE);
10370 		return;
10371 	}
10372 
10373 	qdf_mem_zero(&beacon_params, sizeof(beacon_params));
10374 	beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED;
10375 	session->he_op.bss_col_disabled = 1;
10376 	beacon_params.bss_color_disabled = 1;
10377 	beacon_params.bss_color = session->he_op.bss_color;
10378 
10379 	if (sch_set_fixed_beacon_fields(mac_ctx, session) !=
10380 	    QDF_STATUS_SUCCESS) {
10381 		pe_err("Unable to set op mode IE in beacon");
10382 		return;
10383 	}
10384 
10385 	lim_send_beacon_params(mac_ctx, &beacon_params, session);
10386 	lim_send_obss_color_collision_cfg(mac_ctx, session,
10387 					  OBSS_COLOR_FREE_SLOT_AVAILABLE);
10388 }
10389 
10390 /**
10391  * obss_color_collision_process_color_change() - Process bss color change
10392  * @mac_ctx: Pointer to Global MAC structure
10393  * @session: pointer to session
10394  * @obss_color_info: obss color collision/free slot indication info
10395  *
10396  * This function selects new color ib case of bss color collision.
10397  *
10398  * Return: None
10399  */
10400 static void obss_color_collision_process_color_change(struct mac_context *mac_ctx,
10401 		struct pe_session *session,
10402 		struct wmi_obss_color_collision_info *obss_color_info)
10403 {
10404 	int i, num_bss_color = 0;
10405 	uint32_t bss_color_bitmap;
10406 	uint8_t bss_color_index_array[MAX_BSS_COLOR_VALUE];
10407 	uint32_t rand_byte = 0;
10408 	struct sir_set_he_bss_color he_bss_color;
10409 	bool is_color_collision = false;
10410 
10411 
10412 	if (session->bss_color_changing == 1) {
10413 		pe_err("%d: color change in progress", session->smeSessionId);
10414 		return;
10415 	}
10416 
10417 	if (!session->he_op.bss_col_disabled) {
10418 		if (session->he_op.bss_color < 32)
10419 			is_color_collision = (obss_color_info->
10420 					     obss_color_bitmap_bit0to31 >>
10421 					     session->he_op.bss_color) & 0x01;
10422 		else
10423 			is_color_collision = (obss_color_info->
10424 					     obss_color_bitmap_bit32to63 >>
10425 					     (session->he_op.bss_color -
10426 					      32)) & 0x01;
10427 		if (!is_color_collision) {
10428 			pe_err("%d: color collision not found, curr_color: %d",
10429 			       session->smeSessionId,
10430 			       session->he_op.bss_color);
10431 			return;
10432 		}
10433 	}
10434 
10435 	bss_color_bitmap = obss_color_info->obss_color_bitmap_bit0to31;
10436 
10437 	/* Skip color zero */
10438 	bss_color_bitmap = bss_color_bitmap >> 1;
10439 	for (i = 0; (i < 31) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) {
10440 		if (!(bss_color_bitmap & 0x01)) {
10441 			bss_color_index_array[num_bss_color] = i + 1;
10442 			num_bss_color++;
10443 		}
10444 		bss_color_bitmap = bss_color_bitmap >> 1;
10445 	}
10446 
10447 	bss_color_bitmap = obss_color_info->obss_color_bitmap_bit32to63;
10448 	for (i = 0; (i < 32) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) {
10449 		if (!(bss_color_bitmap & 0x01)) {
10450 			bss_color_index_array[num_bss_color] = i + 32;
10451 			num_bss_color++;
10452 		}
10453 		bss_color_bitmap = bss_color_bitmap >> 1;
10454 	}
10455 
10456 	if (num_bss_color) {
10457 		qdf_get_random_bytes((void *) &rand_byte, 1);
10458 		i = (rand_byte + qdf_mc_timer_get_system_ticks()) %
10459 		    num_bss_color;
10460 		pe_debug("New bss color = %d", bss_color_index_array[i]);
10461 		he_bss_color.vdev_id = obss_color_info->vdev_id;
10462 		he_bss_color.bss_color = bss_color_index_array[i];
10463 
10464 		/* Take the wakelock for 2 sec, release it after color change */
10465 		wma_prevent_suspend_on_obss_color_collision(session->vdev);
10466 
10467 		lim_process_set_he_bss_color(mac_ctx,
10468 					     (uint32_t *)&he_bss_color);
10469 	} else {
10470 		pe_err("Unable to find bss color from bitmasp");
10471 		if (obss_color_info->evt_type ==
10472 		    OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY &&
10473 		    session->obss_color_collision_dec_evt ==
10474 		    OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY)
10475 			/* In dot11BSSColorCollisionAPPeriod and
10476 			 * timer expired, time to disable bss color.
10477 			 */
10478 			obss_color_collision_process_color_disable(mac_ctx,
10479 								   session);
10480 		else
10481 			/*
10482 			 * Enter dot11BSSColorCollisionAPPeriod period.
10483 			 */
10484 			lim_send_obss_color_collision_cfg(mac_ctx, session,
10485 					OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY);
10486 	}
10487 }
10488 
10489 void lim_process_set_he_bss_color(struct mac_context *mac_ctx, uint32_t *msg_buf)
10490 {
10491 	struct sir_set_he_bss_color *bss_color;
10492 	struct pe_session *session_entry = NULL;
10493 	tUpdateBeaconParams beacon_params;
10494 
10495 	if (!msg_buf) {
10496 		pe_err("Buffer is Pointing to NULL");
10497 		return;
10498 	}
10499 
10500 	bss_color = (struct sir_set_he_bss_color *)msg_buf;
10501 	session_entry = pe_find_session_by_vdev_id(mac_ctx, bss_color->vdev_id);
10502 	if (!session_entry) {
10503 		pe_err("Session not found for given vdev_id %d",
10504 			bss_color->vdev_id);
10505 		return;
10506 	}
10507 
10508 	if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
10509 		pe_err("Invalid SystemRole %d",
10510 			GET_LIM_SYSTEM_ROLE(session_entry));
10511 		return;
10512 	}
10513 
10514 	if (bss_color->bss_color == session_entry->he_op.bss_color) {
10515 		pe_err("No change in  BSS color, current BSS color %d",
10516 			bss_color->bss_color);
10517 		return;
10518 	}
10519 	qdf_mem_zero(&beacon_params, sizeof(beacon_params));
10520 	beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED;
10521 	session_entry->he_op.bss_col_disabled = 1;
10522 	session_entry->he_bss_color_change.countdown =
10523 		BSS_COLOR_SWITCH_COUNTDOWN;
10524 	session_entry->he_bss_color_change.new_color = bss_color->bss_color;
10525 	beacon_params.bss_color_disabled = 1;
10526 	beacon_params.bss_color = session_entry->he_op.bss_color;
10527 	session_entry->bss_color_changing = 1;
10528 
10529 	if (wlan_vdev_mlme_get_he_spr_enabled(session_entry->vdev))
10530 		/* Disable spatial reuse during BSS color change */
10531 		wlan_spatial_reuse_config_set(session_entry->vdev, 0, 0);
10532 
10533 	if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) !=
10534 			QDF_STATUS_SUCCESS) {
10535 		pe_err("Unable to set op mode IE in beacon");
10536 		return;
10537 	}
10538 
10539 	lim_send_beacon_params(mac_ctx, &beacon_params, session_entry);
10540 	lim_send_obss_color_collision_cfg(mac_ctx, session_entry,
10541 			OBSS_COLOR_COLLISION_DETECTION_DISABLE);
10542 }
10543 
10544 void lim_reconfig_obss_scan_param(struct mac_context *mac_ctx,
10545 				  uint32_t *msg_buf)
10546 {
10547 	struct sir_cfg_obss_scan *obss_scan_param;
10548 	struct pe_session *session = NULL;
10549 	struct wmi_obss_color_collision_cfg_param *cfg_param;
10550 	struct scheduler_msg msg = {0};
10551 
10552 	if (!msg_buf) {
10553 		pe_err("Buffer is Pointing to NULL");
10554 		return;
10555 	}
10556 
10557 	obss_scan_param = (struct sir_cfg_obss_scan *)msg_buf;
10558 	session = pe_find_session_by_vdev_id(mac_ctx, obss_scan_param->vdev_id);
10559 	if (!session) {
10560 		pe_err("Session not found for given vdev_id %d",
10561 		       obss_scan_param->vdev_id);
10562 		return;
10563 	}
10564 
10565 	if (!session->he_capable ||
10566 	    !session->is_session_obss_color_collision_det_enabled ||
10567 	    session->obss_color_collision_dec_evt ==
10568 				OBSS_COLOR_COLLISION_DETECTION_DISABLE) {
10569 		pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d event_type:%d",
10570 			 session->smeSessionId, session->he_capable,
10571 			 session->is_session_obss_color_collision_det_enabled,
10572 			 mac_ctx->mlme_cfg->obss_ht40.obss_color_collision_offload_enabled,
10573 			 session->obss_color_collision_dec_evt);
10574 		return;
10575 	}
10576 
10577 	cfg_param = qdf_mem_malloc(sizeof(*cfg_param));
10578 	if (!cfg_param)
10579 		return;
10580 
10581 	pe_debug("vdev_id %d: sending event:%d scan_reconfig:%d",
10582 		 session->smeSessionId, session->obss_color_collision_dec_evt,
10583 		 obss_scan_param->is_scan_reconfig);
10584 	cfg_param->vdev_id = session->smeSessionId;
10585 	cfg_param->evt_type = session->obss_color_collision_dec_evt;
10586 	cfg_param->current_bss_color = session->he_op.bss_color;
10587 
10588 	if (obss_scan_param->is_scan_reconfig)
10589 		cfg_param->detection_period_ms =
10590 				OBSS_COLOR_COLLISION_DETECTION_NDP_PERIOD_MS;
10591 	else
10592 		cfg_param->detection_period_ms =
10593 				OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS;
10594 	cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS;
10595 
10596 	if (session->obss_color_collision_dec_evt ==
10597 	    OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY)
10598 		cfg_param->free_slot_expiry_time_ms =
10599 			OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS;
10600 
10601 	msg.type = WMA_OBSS_COLOR_COLLISION_REQ;
10602 	msg.bodyptr = cfg_param;
10603 	msg.reserved = 0;
10604 
10605 	if (QDF_IS_STATUS_ERROR(scheduler_post_message(QDF_MODULE_ID_PE,
10606 						       QDF_MODULE_ID_WMA,
10607 						       QDF_MODULE_ID_WMA,
10608 						       &msg))) {
10609 		qdf_mem_free(cfg_param);
10610 	}
10611 }
10612 
10613 void lim_send_obss_color_collision_cfg(struct mac_context *mac_ctx,
10614 				       struct pe_session *session,
10615 				       enum wmi_obss_color_collision_evt_type
10616 				       event_type)
10617 {
10618 	struct wmi_obss_color_collision_cfg_param *cfg_param;
10619 	struct scheduler_msg msg = {0};
10620 
10621 	if (!session) {
10622 		pe_err("Invalid session");
10623 		return;
10624 	}
10625 
10626 	if (!session->he_capable ||
10627 	    !session->is_session_obss_color_collision_det_enabled) {
10628 		pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d",
10629 			 session->smeSessionId, session->he_capable,
10630 			 session->is_session_obss_color_collision_det_enabled,
10631 			 mac_ctx->mlme_cfg->obss_ht40.
10632 			 obss_color_collision_offload_enabled);
10633 		return;
10634 	}
10635 
10636 	cfg_param = qdf_mem_malloc(sizeof(*cfg_param));
10637 	if (!cfg_param)
10638 		return;
10639 
10640 	pe_debug("%d: sending event:%d", session->smeSessionId, event_type);
10641 	qdf_mem_zero(cfg_param, sizeof(*cfg_param));
10642 	cfg_param->vdev_id = session->smeSessionId;
10643 	cfg_param->evt_type = event_type;
10644 	cfg_param->current_bss_color = session->he_op.bss_color;
10645 	if (LIM_IS_AP_ROLE(session))
10646 		cfg_param->detection_period_ms =
10647 			OBSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS;
10648 	else
10649 		cfg_param->detection_period_ms =
10650 			OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS;
10651 
10652 	cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS;
10653 	if (event_type == OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY)
10654 		cfg_param->free_slot_expiry_time_ms =
10655 			OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS;
10656 
10657 	msg.type = WMA_OBSS_COLOR_COLLISION_REQ;
10658 	msg.bodyptr = cfg_param;
10659 	msg.reserved = 0;
10660 
10661 	if (QDF_IS_STATUS_ERROR(scheduler_post_message(QDF_MODULE_ID_PE,
10662 						       QDF_MODULE_ID_WMA,
10663 						       QDF_MODULE_ID_WMA,
10664 						       &msg))) {
10665 		qdf_mem_free(cfg_param);
10666 	} else {
10667 		session->obss_color_collision_dec_evt = event_type;
10668 	}
10669 }
10670 
10671 void lim_process_obss_color_collision_info(struct mac_context *mac_ctx,
10672 					   uint32_t *msg_buf)
10673 {
10674 	struct wmi_obss_color_collision_info *obss_color_info;
10675 	struct pe_session *session;
10676 
10677 	if (!msg_buf) {
10678 		pe_err("Buffer is Pointing to NULL");
10679 		return;
10680 	}
10681 
10682 	obss_color_info = (struct wmi_obss_color_collision_info *)msg_buf;
10683 	session = pe_find_session_by_vdev_id(mac_ctx, obss_color_info->vdev_id);
10684 	if (!session) {
10685 		pe_err("Session not found for given session_id %d",
10686 			obss_color_info->vdev_id);
10687 		return;
10688 	}
10689 
10690 	pe_debug("vdev_id:%d, evt:%d:%d, 0to31:0x%x, 32to63:0x%x, cap:%d:%d:%d",
10691 		 obss_color_info->vdev_id,
10692 		 obss_color_info->evt_type,
10693 		 session->obss_color_collision_dec_evt,
10694 		 obss_color_info->obss_color_bitmap_bit0to31,
10695 		 obss_color_info->obss_color_bitmap_bit32to63,
10696 		 session->he_capable,
10697 		 session->is_session_obss_color_collision_det_enabled,
10698 		 mac_ctx->mlme_cfg->obss_ht40.
10699 		 obss_color_collision_offload_enabled);
10700 
10701 	if (!session->he_capable ||
10702 	    !session->is_session_obss_color_collision_det_enabled) {
10703 		return;
10704 	}
10705 
10706 	switch (obss_color_info->evt_type) {
10707 	case OBSS_COLOR_COLLISION_DETECTION_DISABLE:
10708 		pe_err("%d: FW disabled obss color det. he_cap:%d, sup:%d:%d",
10709 		       session->smeSessionId, session->he_capable,
10710 		       session->is_session_obss_color_collision_det_enabled,
10711 		       mac_ctx->mlme_cfg->obss_ht40.
10712 		       obss_color_collision_offload_enabled);
10713 		session->is_session_obss_color_collision_det_enabled = false;
10714 		return;
10715 	case OBSS_COLOR_FREE_SLOT_AVAILABLE:
10716 	case OBSS_COLOR_COLLISION_DETECTION:
10717 	case OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY:
10718 		if (session->valid && !LIM_IS_AP_ROLE(session)) {
10719 			pe_debug("Invalid System Role %d",
10720 				 GET_LIM_SYSTEM_ROLE(session));
10721 			return;
10722 		}
10723 
10724 		if (session->obss_color_collision_dec_evt !=
10725 		    obss_color_info->evt_type) {
10726 			pe_debug("%d: Wrong event: %d, skipping",
10727 				 obss_color_info->vdev_id,
10728 				 obss_color_info->evt_type);
10729 			return;
10730 		}
10731 		obss_color_collision_process_color_change(mac_ctx, session,
10732 							  obss_color_info);
10733 		break;
10734 	default:
10735 		pe_err("%d: Invalid event type %d",
10736 		       obss_color_info->vdev_id, obss_color_info->evt_type);
10737 		return;
10738 	}
10739 }
10740 #endif
10741 
10742 void lim_send_csa_restart_req(struct mac_context *mac_ctx, uint8_t vdev_id)
10743 {
10744 	struct pe_session *session;
10745 
10746 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
10747 	if (!session) {
10748 		pe_err("session not found for vdev id %d", vdev_id);
10749 		return;
10750 	}
10751 
10752 	wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10753 				      WLAN_VDEV_SM_EV_CSA_RESTART,
10754 				      sizeof(*session), session);
10755 }
10756 
10757 void lim_continue_sta_csa_req(struct mac_context *mac_ctx, uint8_t vdev_id)
10758 {
10759 	pe_info("Continue CSA for STA vdev id %d", vdev_id);
10760 	lim_process_channel_switch(mac_ctx, vdev_id);
10761 }
10762