xref: /wlan-driver/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * 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  */
lim_process_set_hw_mode(struct mac_context * mac,uint32_t * msg)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  */
lim_process_set_dual_mac_cfg_req(struct mac_context * mac,uint32_t * msg)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
lim_is_ese_enabled(struct mac_context * mac_ctx)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
lim_is_ese_enabled(struct mac_context * mac_ctx)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  */
lim_process_set_antenna_mode_req(struct mac_context * mac,uint32_t * msg)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  */
__lim_is_sme_assoc_cnf_valid(struct assoc_cnf * assoc_cnf)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
__lim_is_deferred_msg_for_radar(struct mac_context * mac_ctx,struct scheduler_msg * message)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 
__lim_process_sme_sys_ready_ind(struct mac_context * mac,uint32_t * msg_buf)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
lim_configure_ap_start_bss_session(struct mac_context * mac_ctx,struct pe_session * session,struct start_bss_config * sme_start_bss_req)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 
lim_set_privacy(struct mac_context * mac_ctx,int32_t ucast_cipher,int32_t auth_mode,int32_t akm,bool ap_privacy)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
lim_send_start_vdev_req(struct pe_session * session,tLimMlmStartReq * mlm_start_req)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
lim_strip_eht_ies_from_add_ies(struct mac_context * mac_ctx,struct pe_session * session)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
lim_strip_eht_ies_from_add_ies(struct mac_context * mac_ctx,struct pe_session * session)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
lim_strip_he_ies_from_add_ies(struct mac_context * mac_ctx,struct pe_session * session)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
lim_strip_he_ies_from_add_ies(struct mac_context * mac_ctx,struct pe_session * session)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 
lim_strip_wapi_ies_from_add_ies(struct mac_context * mac_ctx,struct pe_session * session)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
lim_strip_wapi_ies_from_add_ies(struct mac_context * mac_ctx,struct pe_session * session)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  */
lim_set_ldpc_exception(struct mac_context * mac_ctx,struct vdev_mlme_obj * vdev_mlme,uint32_t ch_freq)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  */
lim_revise_req_vht_cap_per_band(struct pe_session * session)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 
lim_start_bss_update_ht_vht_caps(struct mac_context * mac_ctx,struct pe_session * session)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
lim_fill_cc_mode(struct mac_context * mac_ctx,struct pe_session * session)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
lim_fill_cc_mode(struct mac_context * mac_ctx,struct pe_session * session)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
lim_save_max_mcs_idx(struct mac_context * mac_ctx,struct pe_session * session)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
lim_save_max_mcs_idx(struct mac_context * mac_ctx,struct pe_session * session)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
__lim_handle_sme_start_bss_request(struct mac_context * mac_ctx,uint32_t * msg_buf)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  */
__lim_process_sme_start_bss_req(struct mac_context * mac,struct scheduler_msg * pMsg)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  */
lim_get_random_bssid(struct mac_context * mac,uint8_t * data)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  */
lim_send_join_req(struct pe_session * session,tLimMlmJoinReq * mlm_join_req)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  */
lim_send_reassoc_req(struct pe_session * session,tLimMlmReassocReq * reassoc_req)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  */
lim_send_ft_reassoc_req(struct pe_session * session,tLimMlmReassocReq * reassoc_req)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 
lim_join_req_update_ht_vht_caps(struct mac_context * mac,struct pe_session * session,struct bss_description * bss_desc,tDot11fBeaconIEs * bcn_ie)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
lim_get_vdev_rmf_capable(struct mac_context * mac,struct pe_session * session)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
lim_get_nss_supported_by_sta_and_ap(tDot11fIEVHTCaps * vht_caps,tDot11fIEHTCaps * ht_caps,tDot11fIEhe_cap * he_cap,enum mlme_dot11_mode dot11_mode)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
lim_check_vendor_ap_3_present(struct mac_context * mac_ctx,uint8_t * ie,uint16_t ie_len)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
lim_handle_iot_ap_no_common_he_rates(struct mac_context * mac,struct pe_session * session,tDot11fBeaconIEs * ies)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
lim_handle_iot_ap_no_common_he_rates(struct mac_context * mac,struct pe_session * session,tDot11fBeaconIEs * ies)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
lim_update_he_caps_htc(struct pe_session * session,bool val)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
lim_update_he_caps_htc(struct pe_session * session,bool val)1707 lim_update_he_caps_htc(struct pe_session *session,  bool val)
1708 {
1709 }
1710 #endif
1711 
1712 #ifdef WLAN_FEATURE_11BE
1713 void
lim_update_eht_caps_mcs(struct mac_context * mac,struct pe_session * session)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 
lim_check_oui_and_update_session(struct mac_context * mac_ctx,struct pe_session * session,tDot11fBeaconIEs * ie_struct)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 = {0};
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
lim_get_user_dot11_mode(struct wlan_objmgr_vdev * vdev)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
lim_intersect_user_dot11_mode(struct mac_context * mac_ctx,enum QDF_OPMODE opmode,uint8_t vdev_id,enum mlme_dot11_mode self_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
lim_get_self_dot11_mode(struct mac_context * mac_ctx,enum QDF_OPMODE opmode,uint8_t vdev_id)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
lim_get_bss_11be_mode_allowed(struct mac_context * mac_ctx,struct bss_description * bss_desc,tDot11fBeaconIEs * ie_struct)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, false);
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
lim_get_bss_dot11_mode(struct mac_context * mac_ctx,struct bss_description * bss_desc,tDot11fBeaconIEs * ie_struct)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
lim_handle_11abg_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,struct bss_description * bss_desc)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
lim_handle_11a_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,struct bss_description * bss_desc)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
lim_handle_11b_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,struct bss_description * bss_desc)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
lim_handle_11g_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,struct bss_description * bss_desc)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
lim_handle_11n_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,tDot11fBeaconIEs * ie_struct,struct bss_description * bss_desc)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
lim_handle_11ac_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,tDot11fBeaconIEs * ie_struct,struct bss_description * bss_desc)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
lim_handle_11ax_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,tDot11fBeaconIEs * ie_struct,struct bss_description * bss_desc)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
lim_handle_11be_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode)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
lim_handle_11g_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,struct bss_description * bss_desc)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
lim_handle_11n_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,tDot11fBeaconIEs * ie_struct,struct bss_description * bss_desc)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
lim_handle_11ac_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,tDot11fBeaconIEs * ie_struct,struct bss_description * bss_desc)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
lim_handle_11ax_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,tDot11fBeaconIEs * ie_struct)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
lim_handle_11be_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode)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
lim_get_intersected_dot11_mode_sta_ap(struct mac_context * mac_ctx,enum mlme_dot11_mode self_dot11_mode,enum mlme_dot11_mode bss_dot11_mode,enum mlme_dot11_mode * intersected_mode,tDot11fBeaconIEs * ie_struct,struct bss_description * bss_desc)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
lim_verify_dot11_mode_with_crypto(struct pe_session * session)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
lim_fill_dot11_mode(struct mac_context * mac_ctx,struct pe_session * session,tDot11fBeaconIEs * ie_struct)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
lim_enable_twt(struct mac_context * mac_ctx,tDot11fBeaconIEs * ie)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
lim_enable_twt(struct mac_context * mac_ctx,tDot11fBeaconIEs * ie)2845 lim_enable_twt(struct mac_context *mac_ctx, tDot11fBeaconIEs *ie)
2846 {
2847 	return false;
2848 }
2849 #endif
2850 
lim_get_cfg_max_tx_power(struct mac_context * mac,uint32_t ch_freq)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
lim_fill_rssi(struct pe_session * session,struct bss_description * bss_desc)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
lim_fill_rssi(struct pe_session * session,struct bss_description * bss_desc)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
lim_update_sae_single_pmk_ap_cap(struct mac_context * mac,struct pe_session * session)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 	     QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) &&
2889 	    mac->mlme_cfg->lfr.sae_single_pmk_feature_enabled)
2890 		wlan_mlme_set_sae_single_pmk_bss_cap(mac->psoc,
2891 			session->vdev_id,
2892 			session->lim_join_req->bssDescription.is_single_pmk);
2893 
2894 }
2895 #else
2896 static inline void
lim_update_sae_single_pmk_ap_cap(struct mac_context * mac,struct pe_session * session)2897 lim_update_sae_single_pmk_ap_cap(struct mac_context *mac,
2898 				  struct pe_session *session)
2899 {
2900 }
2901 #endif
2902 
2903 #ifdef WLAN_FEATURE_11BE_MLO
lim_get_mld_peer(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * bssid)2904 static void lim_get_mld_peer(struct wlan_objmgr_vdev *vdev,
2905 			     struct qdf_mac_addr *bssid)
2906 {
2907 	struct wlan_objmgr_peer *peer;
2908 
2909 	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
2910 		return;
2911 
2912 	peer = wlan_vdev_get_bsspeer(vdev);
2913 	if (!peer)
2914 		return;
2915 
2916 	qdf_mem_copy(bssid->bytes, peer->mldaddr, QDF_MAC_ADDR_SIZE);
2917 }
2918 #else
lim_get_mld_peer(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * bssid)2919 static void lim_get_mld_peer(struct wlan_objmgr_vdev *vdev,
2920 			     struct qdf_mac_addr *bssid)
2921 {
2922 }
2923 #endif
2924 
2925 #ifdef WLAN_FEATURE_SAE
lim_update_sae_config(struct mac_context * mac,struct pe_session * session)2926 static void lim_update_sae_config(struct mac_context *mac,
2927 				  struct pe_session *session)
2928 {
2929 	struct wlan_crypto_pmksa *pmksa;
2930 	struct qdf_mac_addr bssid;
2931 
2932 	qdf_mem_copy(bssid.bytes, session->bssId,
2933 		     QDF_MAC_ADDR_SIZE);
2934 
2935 	/* For MLO connection, override BSSID with peer mldaddr */
2936 	lim_get_mld_peer(session->vdev, &bssid);
2937 
2938 	pmksa = wlan_crypto_get_pmksa(session->vdev, &bssid);
2939 	if (!pmksa)
2940 		return;
2941 
2942 	session->sae_pmk_cached = true;
2943 	pe_debug("PMKSA Found for BSSID=" QDF_MAC_ADDR_FMT,
2944 		 QDF_MAC_ADDR_REF(bssid.bytes));
2945 }
2946 #else
lim_update_sae_config(struct mac_context * mac,struct pe_session * session)2947 static inline void lim_update_sae_config(struct mac_context *mac,
2948 					 struct pe_session *session)
2949 { }
2950 #endif
2951 
2952 static void
lim_fill_11r_params(struct mac_context * mac_ctx,struct pe_session * session,bool ese_version_present)2953 lim_fill_11r_params(struct mac_context *mac_ctx, struct pe_session *session,
2954 		    bool ese_version_present)
2955 {
2956 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2957 
2958 	mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc);
2959 	if (!mlme_obj)
2960 		return;
2961 	if (wlan_cm_is_auth_type_11r(mlme_obj, session->vdev,
2962 	    session->lim_join_req->bssDescription.mdiePresent) &&
2963 	    !cm_ese_open_present(session->vdev, mlme_obj, ese_version_present))
2964 		session->is11Rconnection = true;
2965 }
2966 
2967 #ifdef FEATURE_WLAN_ESE
2968 static void
lim_fill_ese_params(struct mac_context * mac_ctx,struct pe_session * session,bool ese_version_present)2969 lim_fill_ese_params(struct mac_context *mac_ctx, struct pe_session *session,
2970 		    bool ese_version_present)
2971 {
2972 	wlan_cm_set_ese_assoc(mac_ctx->pdev, session->vdev_id,
2973 			      cm_is_ese_connection(session->vdev,
2974 			      ese_version_present));
2975 }
2976 #else
2977 static inline void
lim_fill_ese_params(struct mac_context * mac_ctx,struct pe_session * session,bool ese_version_present)2978 lim_fill_ese_params(struct mac_context *mac_ctx, struct pe_session *session,
2979 		    bool ese_version_present)
2980 {
2981 }
2982 #endif
2983 
lim_get_basic_rates(tSirMacRateSet * b_rates,uint32_t chan_freq)2984 void lim_get_basic_rates(tSirMacRateSet *b_rates, uint32_t chan_freq)
2985 {
2986 	/*
2987 	 * Some IOT APs don't send supported rates in
2988 	 * probe resp, hence add BSS basic rates in
2989 	 * supported rates IE of assoc request.
2990 	 */
2991 	if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq))
2992 		wlan_populate_basic_rates(b_rates, false, true);
2993 	else if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq))
2994 		wlan_populate_basic_rates(b_rates, true, true);
2995 }
2996 
2997 /*
2998  * lim_iterate_triplets() - Iterate the country IE to validate it
2999  * @country_ie: country IE to iterate through
3000  *
3001  * This function always returns success because connection should not be failed
3002  * in the case of missing elements in the country IE
3003  *
3004  * Return: QDF_STATUS
3005  */
lim_iterate_triplets(tDot11fIECountry country_ie)3006 static QDF_STATUS lim_iterate_triplets(tDot11fIECountry country_ie)
3007 {
3008 	u_int8_t i;
3009 
3010 	if (country_ie.first_triplet[0] > OP_CLASS_ID_200) {
3011 		if (country_ie.more_triplets[0][0] <= OP_CLASS_ID_200)
3012 			return QDF_STATUS_SUCCESS;
3013 	}
3014 
3015 	for (i = 0; i < country_ie.num_more_triplets; i++) {
3016 		if ((country_ie.more_triplets[i][0] > OP_CLASS_ID_200) &&
3017 		    (i < country_ie.num_more_triplets - 1)) {
3018 			if (country_ie.more_triplets[i + 1][0] <=
3019 			    OP_CLASS_ID_200)
3020 				return QDF_STATUS_SUCCESS;
3021 		}
3022 	}
3023 	pe_debug("No operating class triplet followed by sub-band triplet");
3024 
3025 	return QDF_STATUS_SUCCESS;
3026 }
3027 
lim_is_bss_description_wme(struct mac_context * mac,tDot11fBeaconIEs * ie_struct)3028 static bool lim_is_bss_description_wme(struct mac_context *mac,
3029 				       tDot11fBeaconIEs *ie_struct)
3030 {
3031 
3032 	if (!(ie_struct->WMMParams.present || ie_struct->WMMInfoAp.present))
3033 		return false;
3034 	if (mac->roam.configParam.WMMSupportMode == WMM_USER_MODE_NO_QOS &&
3035 	    !ie_struct->HTCaps.present)
3036 		return false;
3037 
3038 	return true;
3039 }
3040 
3041 static enum medium_access_type
lim_get_qos_from_bss_desc(struct mac_context * mac_ctx,struct bss_description * bss_desc,tDot11fBeaconIEs * ie_struct)3042 lim_get_qos_from_bss_desc(struct mac_context *mac_ctx,
3043 			  struct bss_description *bss_desc,
3044 			  tDot11fBeaconIEs *ie_struct)
3045 {
3046 	enum medium_access_type qos_type = MEDIUM_ACCESS_DCF;
3047 	tSirMacCapabilityInfo *ap_cap_info;
3048 
3049 	/*
3050 	 * If we find WMM in the Bss Description, then we let this
3051 	 * override and use WMM.
3052 	 */
3053 	if (lim_is_bss_description_wme(mac_ctx, ie_struct))
3054 		return MEDIUM_ACCESS_WMM_EDCF_DSCP;
3055 
3056 	ap_cap_info = (tSirMacCapabilityInfo *)&bss_desc->capabilityInfo;
3057 	/* If the QoS bit is on, then the AP is advertising 11E QoS. */
3058 	if (ap_cap_info->qos)
3059 		qos_type = MEDIUM_ACCESS_11E_EDCF;
3060 
3061 	if (qos_type == MEDIUM_ACCESS_11E_EDCF &&
3062 	    !mac_ctx->roam.configParam.Is11eSupportEnabled)
3063 		qos_type = MEDIUM_ACCESS_DCF;
3064 
3065 	return qos_type;
3066 }
3067 
lim_set_qos_to_cfg(struct pe_session * session,enum medium_access_type qos_type)3068 static void lim_set_qos_to_cfg(struct pe_session *session,
3069 			       enum medium_access_type qos_type)
3070 {
3071 	bool qos_enabled;
3072 	bool wme_enabled;
3073 
3074 	switch (qos_type) {
3075 	case MEDIUM_ACCESS_WMM_EDCF_DSCP:
3076 		qos_enabled = false;
3077 		wme_enabled = true;
3078 		break;
3079 	case MEDIUM_ACCESS_11E_EDCF:
3080 		qos_enabled = true;
3081 		wme_enabled = false;
3082 		break;
3083 	default:
3084 	case MEDIUM_ACCESS_DCF:
3085 		qos_enabled = false;
3086 		wme_enabled = false;
3087 		break;
3088 	}
3089 
3090 	session->limWmeEnabled = wme_enabled;
3091 	session->limQosEnabled = qos_enabled;
3092 }
3093 
lim_update_qos(struct mac_context * mac_ctx,struct pe_session * session,struct bss_description * bss_desc,tDot11fBeaconIEs * ie_struct)3094 static void lim_update_qos(struct mac_context *mac_ctx,
3095 			   struct pe_session *session,
3096 			   struct bss_description *bss_desc,
3097 			   tDot11fBeaconIEs *ie_struct)
3098 {
3099 	struct mlme_legacy_priv *mlme_priv;
3100 	enum medium_access_type qos_type;
3101 
3102 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
3103 	if (!mlme_priv)
3104 		return;
3105 
3106 	qos_type = lim_get_qos_from_bss_desc(mac_ctx, bss_desc, ie_struct);
3107 
3108 	if ((session->dot11mode != MLME_DOT11_MODE_11N) &&
3109 	    (mac_ctx->roam.configParam.WMMSupportMode ==
3110 	     WMM_USER_MODE_NO_QOS)) {
3111 		/*
3112 		 * Joining BSS is not 11n capable and WMM is disabled on client.
3113 		 * Disable QoS and WMM
3114 		 */
3115 		qos_type = MEDIUM_ACCESS_DCF;
3116 	}
3117 
3118 	if ((session->dot11mode == MLME_DOT11_MODE_11N ||
3119 	     session->dot11mode == MLME_DOT11_MODE_11AC) &&
3120 	     (qos_type != MEDIUM_ACCESS_WMM_EDCF_DSCP &&
3121 	      qos_type != MEDIUM_ACCESS_11E_EDCF)) {
3122 		/*
3123 		 * Joining BSS is 11n capable and WMM is disabled on AP.
3124 		 * Assume all HT AP's are QOS AP's and enable WMM
3125 		 */
3126 		qos_type = MEDIUM_ACCESS_WMM_EDCF_DSCP;
3127 	}
3128 
3129 	lim_set_qos_to_cfg(session, qos_type);
3130 	mlme_priv->connect_info.qos_enabled = session->limWmeEnabled;
3131 	pe_debug("qos_type %d QOS %d WMM %d", qos_type,
3132 		 session->limQosEnabled,
3133 		 session->limWmeEnabled);
3134 }
3135 
lim_reset_self_ocv_caps(struct pe_session * session)3136 static void lim_reset_self_ocv_caps(struct pe_session *session)
3137 {
3138 	uint16_t self_rsn_cap;
3139 
3140 	self_rsn_cap = wlan_crypto_get_param(session->vdev,
3141 					     WLAN_CRYPTO_PARAM_RSN_CAP);
3142 	if (self_rsn_cap == -1)
3143 		return;
3144 
3145 	self_rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED;
3146 
3147 	/* Update the new rsn caps */
3148 	wlan_crypto_set_vdev_param(session->vdev, WLAN_CRYPTO_PARAM_RSN_CAP,
3149 				   self_rsn_cap);
3150 
3151 }
3152 
lim_enable_cts_to_self_for_exempted_iot_ap(struct mac_context * mac_ctx,struct pe_session * session,uint8_t * ie_ptr,uint16_t ie_len)3153 bool lim_enable_cts_to_self_for_exempted_iot_ap(
3154 				       struct mac_context *mac_ctx,
3155 				       struct pe_session *session,
3156 				       uint8_t *ie_ptr,
3157 				       uint16_t ie_len)
3158 {
3159 	struct action_oui_search_attr vendor_ap_search_attr = {0};
3160 
3161 	vendor_ap_search_attr.ie_data = ie_ptr;
3162 	vendor_ap_search_attr.ie_length = ie_len;
3163 
3164 	if (wlan_action_oui_search(mac_ctx->psoc, &vendor_ap_search_attr,
3165 				   ACTION_OUI_ENABLE_CTS2SELF)) {
3166 		pe_debug("vdev %d: enable cts to self", session->vdev_id);
3167 		wma_cli_set_command(session->vdev_id,
3168 				    wmi_vdev_param_enable_rtscts,
3169 				    FW_CTS2SELF_PROFILE, VDEV_CMD);
3170 		return true;
3171 	}
3172 	return false;
3173 }
3174 
3175 /**
3176  * lim_disable_bformee_for_iot_ap() - disable bformee for iot ap
3177  *@mac_ctx: mac context
3178  *@session: pe session
3179  *@bss_desc: bss descriptor
3180  *
3181  * When connect IoT AP with BW 160MHz and NSS 2, disable Beamformee
3182  *
3183  * Return: None
3184  */
3185 static void
lim_disable_bformee_for_iot_ap(struct mac_context * mac_ctx,struct pe_session * session,struct bss_description * bss_desc)3186 lim_disable_bformee_for_iot_ap(struct mac_context *mac_ctx,
3187 			       struct pe_session *session,
3188 			       struct bss_description *bss_desc)
3189 {
3190 	struct action_oui_search_attr vendor_ap_search_attr = {0};
3191 	uint16_t ie_len;
3192 
3193 	ie_len = wlan_get_ielen_from_bss_description(bss_desc);
3194 
3195 	vendor_ap_search_attr.ie_data = (uint8_t *)&bss_desc->ieFields[0];
3196 	vendor_ap_search_attr.ie_length = ie_len;
3197 
3198 	if (wlan_action_oui_search(mac_ctx->psoc,
3199 				   &vendor_ap_search_attr,
3200 				   ACTION_OUI_DISABLE_BFORMEE) &&
3201 	    session->nss == 2 && CH_WIDTH_160MHZ == session->ch_width) {
3202 		session->vht_config.su_beam_formee = 0;
3203 		session->vht_config.mu_beam_formee = 0;
3204 		pe_debug("IoT ap with BW 160 MHz NSS 2, disable Beamformee");
3205 	}
3206 }
3207 
3208 QDF_STATUS
lim_fill_pe_session(struct mac_context * mac_ctx,struct pe_session * session,struct bss_description * bss_desc)3209 lim_fill_pe_session(struct mac_context *mac_ctx, struct pe_session *session,
3210 		    struct bss_description *bss_desc)
3211 {
3212 	uint8_t bss_chan_id;
3213 	tDot11fBeaconIEs *ie_struct;
3214 	QDF_STATUS status;
3215 	ePhyChanBondState cb_mode;
3216 	const uint8_t *vendor_ie;
3217 	uint16_t ie_len;
3218 	int8_t local_power_constraint = 0;
3219 	struct vdev_mlme_obj *mlme_obj;
3220 	bool is_pwr_constraint = false;
3221 	tSirMacCapabilityInfo *ap_cap_info;
3222 	uint8_t wmm_mode, value;
3223 	struct wlan_mlme_lfr_cfg *lfr = &mac_ctx->mlme_cfg->lfr;
3224 	struct cm_roam_values_copy config = {};
3225 	bool ese_ver_present;
3226 	int8_t reg_max;
3227 	struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info;
3228 	struct ps_params *ps_param =
3229 				&ps_global_info->ps_params[session->vdev_id];
3230 	uint32_t timeout;
3231 	enum reg_6g_ap_type power_type_6g;
3232 	struct cm_roam_values_copy temp;
3233 	uint32_t neighbor_lookup_threshold;
3234 	uint32_t hi_rssi_scan_rssi_delta;
3235 
3236 	/*
3237 	 * Update the capability here itself as this is used in
3238 	 * lim_extract_ap_capability() below. If not updated issues
3239 	 * like not honoring power constraint on 1st association after
3240 	 * driver loading might occur.
3241 	 */
3242 	lim_update_rrm_capability(mac_ctx);
3243 	bss_chan_id = wlan_reg_freq_to_chan(mac_ctx->pdev,
3244 					    bss_desc->chan_freq);
3245 
3246 	lim_update_sae_config(mac_ctx, session);
3247 	lim_update_sae_single_pmk_ap_cap(mac_ctx, session);
3248 
3249 	/* Update the beacon/probe filter in mac_ctx */
3250 	lim_set_bcn_probe_filter(mac_ctx, session,
3251 				 bss_chan_id);
3252 	session->max_amsdu_num =
3253 			mac_ctx->mlme_cfg->ht_caps.max_num_amsdu;
3254 	/* Store beaconInterval */
3255 	session->beaconParams.beaconInterval =
3256 		bss_desc->beaconInterval;
3257 	/* Copy oper freq to the session Table */
3258 	session->curr_op_freq = bss_desc->chan_freq;
3259 
3260 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
3261 						     &ie_struct);
3262 	if (QDF_IS_STATUS_ERROR(status)) {
3263 		pe_err("IE parsing failed vdev id %d",
3264 		       session->vdev_id);
3265 		return QDF_STATUS_E_FAILURE;
3266 	}
3267 
3268 	qdf_mem_zero(&session->wmm_params, sizeof(tDot11fIEWMMParams));
3269 	if (ie_struct->WMMParams.present)
3270 		qdf_mem_copy(&session->wmm_params, &ie_struct->WMMParams,
3271 			     sizeof(tDot11fIEWMMParams));
3272 
3273 	mac_ctx->mlme_cfg->power.local_power_constraint =
3274 		wlan_get_11h_power_constraint(mac_ctx,
3275 					      &ie_struct->PowerConstraints);
3276 
3277 	session->enable_session_twt_support =
3278 					lim_enable_twt(mac_ctx, ie_struct);
3279 	status = lim_fill_dot11_mode(mac_ctx, session, ie_struct);
3280 	if (QDF_IS_STATUS_ERROR(status)) {
3281 		status = QDF_STATUS_E_FAILURE;
3282 		goto send;
3283 	}
3284 	cb_mode = wlan_get_cb_mode(mac_ctx, session->curr_op_freq, ie_struct,
3285 				   session);
3286 
3287 	if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
3288 	    wlan_cm_get_force_20mhz_in_24ghz(session->vdev))
3289 		cb_mode = PHY_SINGLE_CHANNEL_CENTERED;
3290 
3291 	status = wlan_get_rate_set(mac_ctx, ie_struct, session);
3292 	if (QDF_IS_STATUS_ERROR(status)) {
3293 		pe_err("Get rate failed vdev id %d", session->vdev_id);
3294 		lim_get_basic_rates(&session->rateSet, bss_desc->chan_freq);
3295 	}
3296 
3297 	if (session->dot11mode == MLME_DOT11_MODE_11B)
3298 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 0;
3299 	else
3300 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g =
3301 			mac_ctx->mlme_cfg->ht_caps.short_slot_time_enabled;
3302 
3303 	/*
3304 	 * Join timeout: if we find a BeaconInterval in the BssDescription,
3305 	 * then set the Join Timeout to be 10 x the BeaconInterval.
3306 	 *
3307 	 * 10 * BeaconInterval should be greater than the minimum join
3308 	 * timeout and lesser than the configured timeout.
3309 	 */
3310 	timeout = mac_ctx->mlme_cfg->timeouts.join_failure_timeout_ori;
3311 	if (bss_desc->beaconInterval)
3312 		timeout = QDF_MAX(10 * bss_desc->beaconInterval,
3313 				  cfg_min(CFG_JOIN_FAILURE_TIMEOUT));
3314 
3315 	mac_ctx->mlme_cfg->timeouts.join_failure_timeout =
3316 		QDF_MIN(timeout,
3317 			mac_ctx->mlme_cfg->timeouts.join_failure_timeout_ori);
3318 	/*
3319 	 * Calculate probe request retry timeout,
3320 	 * Change probe req retry to MAX_JOIN_PROBE_REQ if sta freq
3321 	 * can cause MCC
3322 	 */
3323 	timeout = JOIN_PROBE_REQ_TIMER_MS;
3324 	if (policy_mgr_will_freq_lead_to_mcc(mac_ctx->psoc,
3325 					     bss_desc->chan_freq)) {
3326 		 /* Send MAX_JOIN_PROBE_REQ probe req during join timeout */
3327 		timeout = mac_ctx->mlme_cfg->timeouts.join_failure_timeout/
3328 							MAX_JOIN_PROBE_REQ;
3329 		timeout = QDF_MAX(JOIN_PROBE_REQ_TIMER_MS, timeout);
3330 	}
3331 	mac_ctx->mlme_cfg->timeouts.probe_req_retry_timeout = timeout;
3332 
3333 	lim_join_req_update_ht_vht_caps(mac_ctx, session, bss_desc,
3334 					ie_struct);
3335 
3336 	lim_check_oui_and_update_session(mac_ctx, session, ie_struct);
3337 	ese_ver_present = ie_struct->ESEVersion.present;
3338 
3339 	/* Copying of bssId is already done, while creating session */
3340 	sir_copy_mac_addr(session->self_mac_addr,
3341 			  wlan_vdev_mlme_get_macaddr(session->vdev));
3342 
3343 	session->statypeForBss = STA_ENTRY_PEER;
3344 
3345 	lim_update_qos(mac_ctx, session, bss_desc, ie_struct);
3346 
3347 	if (session->lim_join_req->bssDescription.adaptive_11r_ap)
3348 		session->is_adaptive_11r_connection =
3349 				wlan_get_adaptive_11r_enabled(lfr);
3350 	config.bool_value = session->is_adaptive_11r_connection;
3351 	wlan_cm_roam_cfg_set_value(mac_ctx->psoc, session->vdev_id,
3352 				   ADAPTIVE_11R_CONNECTION,
3353 				   &config);
3354 	lim_fill_11r_params(mac_ctx, session , ese_ver_present);
3355 	lim_fill_ese_params(mac_ctx, session, ese_ver_present);
3356 
3357 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session->vdev_id,
3358 				   NEIGHBOUR_LOOKUP_THRESHOLD, &temp);
3359 	neighbor_lookup_threshold = temp.uint_value;
3360 
3361 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session->vdev_id,
3362 				   HI_RSSI_SCAN_RSSI_DELTA, &temp);
3363 	hi_rssi_scan_rssi_delta = temp.uint_value;
3364 
3365 	/*
3366 	 * Firmware will take care of checking hi_scan rssi delta, take care of
3367 	 * legacy -> legacy hi-rssi roam also if this feature flag is
3368 	 * advertised.
3369 	 */
3370 	if (wlan_cm_is_self_mld_roam_supported(mac_ctx->psoc)) {
3371 		wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id,
3372 					    false);
3373 	} else if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
3374 	    (abs(bss_desc->rssi) >
3375 	     (neighbor_lookup_threshold - hi_rssi_scan_rssi_delta))) {
3376 		pe_debug("Enabling HI_RSSI, rssi: %d lookup_th: %d, delta:%d",
3377 			 bss_desc->rssi, neighbor_lookup_threshold,
3378 			 hi_rssi_scan_rssi_delta);
3379 		wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id,
3380 					    false);
3381 	} else {
3382 		wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id,
3383 					    true);
3384 		pe_debug("Disabling HI_RSSI, AP freq=%d, rssi=%d",
3385 			  bss_desc->chan_freq, bss_desc->rssi);
3386 	}
3387 
3388 	if (session->opmode == QDF_STA_MODE)
3389 		session->enable_bcast_probe_rsp =
3390 			mac_ctx->mlme_cfg->oce.enable_bcast_probe_rsp;
3391 
3392 	/* Store vendor specific IE for CISCO AP */
3393 	ie_len = (bss_desc->length + sizeof(bss_desc->length) -
3394 		 GET_FIELD_OFFSET(struct bss_description, ieFields));
3395 
3396 	vendor_ie = wlan_get_vendor_ie_ptr_from_oui(
3397 			SIR_MAC_CISCO_OUI, SIR_MAC_CISCO_OUI_SIZE,
3398 			((uint8_t *)&bss_desc->ieFields), ie_len);
3399 
3400 	if (vendor_ie)
3401 		session->isCiscoVendorAP = true;
3402 	else
3403 		session->isCiscoVendorAP = false;
3404 
3405 	session->nwType = bss_desc->nwType;
3406 	session->enableAmpduPs =
3407 		mac_ctx->mlme_cfg->ht_caps.enable_ampdu_ps;
3408 	session->send_smps_action =
3409 		mac_ctx->roam.configParam.send_smps_action;
3410 	session->vhtCapability =
3411 		IS_DOT11_MODE_VHT(session->dot11mode);
3412 	if (session->vhtCapability) {
3413 		session->enableVhtpAid =
3414 		   mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_paid;
3415 		session->enableVhtGid =
3416 		   mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_gid;
3417 	}
3418 	/*Phy mode */
3419 	session->gLimPhyMode = bss_desc->nwType;
3420 	handle_ht_capabilityand_ht_info(mac_ctx, session);
3421 
3422 	session->htSupportedChannelWidthSet = cb_mode ? 1 : 0;
3423 	session->htRecommendedTxWidthSet =
3424 		session->htSupportedChannelWidthSet;
3425 	session->htSecondaryChannelOffset = cb_mode;
3426 
3427 	if (cb_mode == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) {
3428 		session->ch_center_freq_seg0 =
3429 			wlan_reg_freq_to_chan(
3430 			mac_ctx->pdev, session->curr_op_freq) - 2;
3431 		session->ch_width = CH_WIDTH_40MHZ;
3432 	} else if (cb_mode == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) {
3433 		session->ch_center_freq_seg0 =
3434 			wlan_reg_freq_to_chan(
3435 			mac_ctx->pdev, session->curr_op_freq) + 2;
3436 		session->ch_width = CH_WIDTH_40MHZ;
3437 	} else {
3438 		session->ch_center_freq_seg0 = 0;
3439 		session->ch_width = CH_WIDTH_20MHZ;
3440 	}
3441 	session->ap_ch_width = session->ch_width;
3442 
3443 	if (IS_DOT11_MODE_HE(session->dot11mode)) {
3444 		lim_update_session_he_capable(mac_ctx, session);
3445 		lim_copy_join_req_he_cap(session);
3446 	}
3447 
3448 	if (IS_DOT11_MODE_EHT(session->dot11mode)) {
3449 		lim_update_session_eht_capable(mac_ctx, session);
3450 		lim_reset_self_ocv_caps(session);
3451 		lim_copy_join_req_eht_cap(session);
3452 	}
3453 
3454 	/* Record if management frames need to be protected */
3455 	session->limRmfEnabled =
3456 		lim_get_vdev_rmf_capable(mac_ctx, session);
3457 
3458 	session->txLdpcIniFeatureEnabled =
3459 		mac_ctx->mlme_cfg->ht_caps.tx_ldpc_enable;
3460 
3461 	session->limSystemRole = eLIM_STA_ROLE;
3462 	if (session->nss == 1)
3463 		session->supported_nss_1x1 = true;
3464 
3465 	session->limCurrentBssCaps = bss_desc->capabilityInfo;
3466 
3467 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
3468 	if (!mlme_obj) {
3469 		status =  QDF_STATUS_E_FAILURE;
3470 		goto send;
3471 	}
3472 
3473 	lim_extract_ap_capability(mac_ctx,
3474 		(uint8_t *)bss_desc->ieFields,
3475 		lim_get_ielen_from_bss_description(bss_desc),
3476 		&session->limCurrentBssQosCaps,
3477 		&session->gLimCurrentBssUapsd,
3478 		&local_power_constraint, session, &is_pwr_constraint);
3479 
3480 	lim_disable_bformee_for_iot_ap(mac_ctx, session, bss_desc);
3481 
3482 	mlme_obj->reg_tpc_obj.is_power_constraint_abs =
3483 						!is_pwr_constraint;
3484 
3485 	if (wlan_reg_is_6ghz_chan_freq(bss_desc->chan_freq)) {
3486 		if (!ie_struct->Country.present)
3487 			pe_debug("Channel is 6G but country IE not present");
3488 		status = wlan_reg_get_best_6g_power_type(
3489 				mac_ctx->psoc, mac_ctx->pdev,
3490 				&power_type_6g,
3491 				session->ap_defined_power_type_6g,
3492 				bss_desc->chan_freq);
3493 		if (QDF_IS_STATUS_ERROR(status)) {
3494 			status = QDF_STATUS_E_NOSUPPORT;
3495 			goto send;
3496 		}
3497 		session->best_6g_power_type = power_type_6g;
3498 		mlme_set_best_6g_power_type(session->vdev, power_type_6g);
3499 
3500 		lim_iterate_triplets(ie_struct->Country);
3501 
3502 		if (!ie_struct->num_transmit_power_env ||
3503 		    !ie_struct->transmit_power_env[0].present)
3504 			pe_debug("TPE not present for 6G channel");
3505 	}
3506 
3507 	if (wlan_reg_is_ext_tpc_supported(mac_ctx->psoc)) {
3508 		mlme_obj->reg_tpc_obj.ap_constraint_power =
3509 						local_power_constraint;
3510 	} else {
3511 		reg_max = wlan_reg_get_channel_reg_power_for_freq(
3512 				mac_ctx->pdev, session->curr_op_freq);
3513 		if (is_pwr_constraint)
3514 			local_power_constraint = reg_max -
3515 						local_power_constraint;
3516 		if (!local_power_constraint)
3517 			local_power_constraint = reg_max;
3518 
3519 		mlme_obj->reg_tpc_obj.reg_max[0] = reg_max;
3520 		mlme_obj->reg_tpc_obj.ap_constraint_power =
3521 						local_power_constraint;
3522 		mlme_obj->reg_tpc_obj.frequency[0] = session->curr_op_freq;
3523 
3524 		session->maxTxPower = lim_get_max_tx_power(mac_ctx, mlme_obj);
3525 		session->def_max_tx_pwr = session->maxTxPower;
3526 	}
3527 
3528 	/*
3529 	 * for mdm platform which QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
3530 	 * will not call from android framework every 3 seconds, and tx
3531 	 * power will never update. So we use iw dev get tx power need
3532 	 * set maxTxPower non-zero value, that firmware can calc a non-zero
3533 	 * tx power, and update to host driver.
3534 	 */
3535 	if (LIM_IS_STA_ROLE(session) && session->maxTxPower == 0)
3536 		session->maxTxPower =
3537 			wlan_reg_get_channel_reg_power_for_freq(mac_ctx->pdev,
3538 							session->curr_op_freq);
3539 
3540 	session->limRFBand = lim_get_rf_band(session->curr_op_freq);
3541 
3542 	/* Initialize 11h Enable Flag */
3543 	if (session->limRFBand != REG_BAND_2G)
3544 		session->lim11hEnable =
3545 			mac_ctx->mlme_cfg->gen.enabled_11h;
3546 	else
3547 		session->lim11hEnable = 0;
3548 
3549 	session->limPrevSmeState = session->limSmeState;
3550 	session->limSmeState = eLIM_SME_WT_JOIN_STATE;
3551 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
3552 			session->peSessionId,
3553 			session->limSmeState));
3554 
3555 	/* Enable MBSSID only for station */
3556 	session->is_mbssid_enabled = wma_is_mbssid_enabled();
3557 
3558 	/* Enable the spectrum management if this is a DFS channel */
3559 	if (session->country_info_present &&
3560 	    lim_isconnected_on_dfs_freq(
3561 			mac_ctx,
3562 			session->curr_op_freq))
3563 		session->spectrumMgtEnabled = true;
3564 
3565 	ap_cap_info = (tSirMacCapabilityInfo *)&bss_desc->capabilityInfo;
3566 
3567 	/*
3568 	 * tell the target AP my 11H capability only if both AP and STA
3569 	 * support
3570 	 * 11H and the channel being used is 11a
3571 	 */
3572 	if (mac_ctx->mlme_cfg->gen.enabled_11h &&
3573 	    ap_cap_info->spectrumMgt && bss_desc->nwType == eSIR_11A_NW_TYPE)
3574 		session->spectrumMgtEnabled = true;
3575 
3576 	/*
3577 	 * This is required for 11k test VoWiFi Ent: Test 2.
3578 	 * We need the power capabilities for Assoc Req.
3579 	 * This macro is provided by the halPhyCfg.h. We pick our
3580 	 * max and min capability by the halPhy provided macros
3581 	 * Any change in this power cap IE should also be done
3582 	 * in csr_update_driver_assoc_ies() which would send
3583 	 * assoc IE's to FW which is used for LFR3 roaming
3584 	 * ie. used in reassociation requests from FW.
3585 	 */
3586 	session->max_11h_pwr =
3587 		QDF_MIN(lim_get_cfg_max_tx_power(mac_ctx,
3588 						 bss_desc->chan_freq),
3589 			MAX_TX_PWR_CAP);
3590 
3591 	if (!session->max_11h_pwr)
3592 		session->max_11h_pwr = MAX_TX_PWR_CAP;
3593 
3594 	if (session->max_11h_pwr > session->maxTxPower)
3595 		session->max_11h_pwr = session->maxTxPower;
3596 
3597 	session->min_11h_pwr = MIN_TX_PWR_CAP;
3598 
3599 	if (!session->enable_session_twt_support) {
3600 		status = wlan_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode);
3601 		if (!QDF_IS_STATUS_SUCCESS(status)) {
3602 			pe_err("Get wmm_mode failed");
3603 			status = QDF_STATUS_E_INVAL;
3604 			goto send;
3605 		}
3606 		if (wmm_mode == 2 || !(LIM_IS_QOS_BSS(ie_struct)) ||
3607 		    !(LIM_IS_UAPSD_BSS(ie_struct))) {
3608 			/*QoS not enabled in cfg file or in BSS*/
3609 			session->gUapsdPerAcBitmask = 0;
3610 		} else {
3611 			/*QoS enabled, update uapsd mask from cfg file */
3612 			status = wlan_mlme_get_wmm_uapsd_mask(mac_ctx->psoc,
3613 							      &value);
3614 			if (QDF_IS_STATUS_ERROR(status)) {
3615 				pe_err("Get uapsd_mask failed");
3616 				status = QDF_STATUS_E_INVAL;
3617 				goto send;
3618 			}
3619 			session->gUapsdPerAcBitmask = value;
3620 		}
3621 		ps_param->uapsd_per_ac_bit_mask = session->gUapsdPerAcBitmask;
3622 	}
3623 
3624 	if (session->gLimCurrentBssUapsd) {
3625 		/* resetting the dynamic uapsd mask  */
3626 		session->gUapsdPerAcDeliveryEnableMask = 0;
3627 		session->gUapsdPerAcTriggerEnableMask = 0;
3628 	}
3629 
3630 	lim_fill_cc_mode(mac_ctx, session);
3631 	lim_fill_rssi(session, bss_desc);
3632 
3633 	status = QDF_STATUS_SUCCESS;
3634 
3635 send:
3636 	qdf_mem_free(ie_struct);
3637 	return status;
3638 
3639 }
3640 
3641 static QDF_STATUS
lim_send_connect_req_to_mlm(struct pe_session * session)3642 lim_send_connect_req_to_mlm(struct pe_session *session)
3643 {
3644 	tLimMlmJoinReq *mlm_join_req;
3645 	uint32_t len;
3646 	QDF_STATUS status;
3647 
3648 	len = sizeof(tLimMlmJoinReq) +
3649 			session->lim_join_req->bssDescription.length + 2;
3650 	mlm_join_req = qdf_mem_malloc(len);
3651 	if (!mlm_join_req)
3652 		return QDF_STATUS_E_FAILURE;
3653 
3654 	/* PE SessionId is stored as a part of JoinReq */
3655 	mlm_join_req->sessionId = session->peSessionId;
3656 
3657 	mlm_join_req->bssDescription.length =
3658 		session->lim_join_req->bssDescription.length;
3659 
3660 	qdf_mem_copy((uint8_t *) &mlm_join_req->bssDescription.bssId,
3661 		(uint8_t *)
3662 		&session->lim_join_req->bssDescription.bssId,
3663 		session->lim_join_req->bssDescription.length + 2);
3664 
3665 	/* Issue LIM_MLM_JOIN_REQ to MLM */
3666 	status = lim_send_join_req(session, mlm_join_req);
3667 	if (QDF_IS_STATUS_ERROR(status)) {
3668 		qdf_mem_free(mlm_join_req);
3669 		return QDF_STATUS_E_FAILURE;
3670 	}
3671 
3672 	return QDF_STATUS_SUCCESS;
3673 }
3674 
3675 static struct pe_session *
lim_cm_create_session(struct mac_context * mac_ctx,struct cm_vdev_join_req * req)3676 lim_cm_create_session(struct mac_context *mac_ctx, struct cm_vdev_join_req *req)
3677 {
3678 	struct pe_session *pe_session;
3679 	uint8_t session_id;
3680 
3681 	pe_session = pe_find_session_by_bssid(mac_ctx, req->entry->bssid.bytes,
3682 					      &session_id);
3683 
3684 	if (pe_session) {
3685 		pe_err("vdev_id: %d cm_id 0x%x :pe-session(%d (vdev %d)) already exists for BSSID: "
3686 		       QDF_MAC_ADDR_FMT " in lim_sme_state = %X",
3687 		       req->vdev_id, req->cm_id, session_id,
3688 		       pe_session->vdev_id,
3689 		       QDF_MAC_ADDR_REF(req->entry->bssid.bytes),
3690 		       pe_session->limSmeState);
3691 
3692 		qdf_trigger_self_recovery(mac_ctx->psoc,
3693 					  QDF_VDEV_SM_OUT_OF_SYNC);
3694 		return NULL;
3695 	}
3696 
3697 	pe_session = pe_create_session(mac_ctx, req->entry->bssid.bytes,
3698 			&session_id,
3699 			mac_ctx->lim.max_sta_of_pe_session,
3700 			eSIR_INFRASTRUCTURE_MODE,
3701 			req->vdev_id);
3702 	if (!pe_session)
3703 		pe_err("vdev_id: %d cm_id 0x%x : pe_session create failed BSSID"
3704 		       QDF_MAC_ADDR_FMT, req->vdev_id, req->cm_id,
3705 		       QDF_MAC_ADDR_REF(req->entry->bssid.bytes));
3706 
3707 	return pe_session;
3708 }
3709 
3710 static bool
lim_is_wpa_profile(struct pe_session * session)3711 lim_is_wpa_profile(struct pe_session *session)
3712 {
3713 	int32_t ucast_cipher;
3714 	int32_t auth_mode;
3715 
3716 	ucast_cipher = wlan_crypto_get_param(session->vdev,
3717 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
3718 
3719 	auth_mode = wlan_crypto_get_param(session->vdev,
3720 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
3721 
3722 	if (auth_mode == -1 || ucast_cipher == -1)
3723 		return false;
3724 
3725 	if (!QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_WPA))
3726 		return false;
3727 
3728 	if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) ||
3729 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) ||
3730 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104)) ||
3731 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) ||
3732 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) ||
3733 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_OCB)) ||
3734 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256))))
3735 		return true;
3736 
3737 	return false;
3738 }
3739 
3740 static bool
lim_is_wapi_profile(struct pe_session * session)3741 lim_is_wapi_profile(struct pe_session *session)
3742 {
3743 	int32_t ucast_cipher;
3744 	int32_t auth_mode;
3745 
3746 	ucast_cipher = wlan_crypto_get_param(session->vdev,
3747 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
3748 
3749 	auth_mode = wlan_crypto_get_param(session->vdev,
3750 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
3751 
3752 	if (auth_mode == -1 || ucast_cipher == -1)
3753 		return false;
3754 
3755 	if (!QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_WAPI))
3756 		return false;
3757 
3758 	if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WAPI_GCM4)) ||
3759 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WAPI_SMS4))))
3760 		return true;
3761 
3762 	return false;
3763 }
3764 
3765 static bool
lim_is_rsn_profile(struct pe_session * session)3766 lim_is_rsn_profile(struct pe_session *session)
3767 {
3768 	int32_t ucast_cipher;
3769 	int32_t auth_mode;
3770 	bool is_rsn = false;
3771 
3772 	ucast_cipher = wlan_crypto_get_param(session->vdev,
3773 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
3774 
3775 	auth_mode = wlan_crypto_get_param(session->vdev,
3776 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
3777 
3778 	if (auth_mode == -1 || ucast_cipher == -1)
3779 		return false;
3780 
3781 	if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_8021X) ||
3782 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_RSNA) ||
3783 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_CCKM) ||
3784 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_SAE) ||
3785 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_FILS_SK))
3786 		is_rsn = true;
3787 
3788 	if (!is_rsn)
3789 		return false;
3790 
3791 	if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) ||
3792 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) ||
3793 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104)) ||
3794 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) ||
3795 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) ||
3796 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_OCB)) ||
3797 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256)) ||
3798 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM_256)) ||
3799 	     (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM))))
3800 		return true;
3801 
3802 	return false;
3803 }
3804 
lim_get_encrypt_ed_type(int32_t ucast_cipher)3805 tAniEdType lim_get_encrypt_ed_type(int32_t ucast_cipher)
3806 {
3807 	if (ucast_cipher == -1)
3808 		return eSIR_ED_NONE;
3809 
3810 	if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM_256))
3811 		return eSIR_ED_GCMP_256;
3812 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM))
3813 		return eSIR_ED_GCMP;
3814 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM) ||
3815 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_OCB) ||
3816 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM_256))
3817 		return eSIR_ED_CCMP;
3818 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_TKIP))
3819 		return eSIR_ED_TKIP;
3820 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CMAC) ||
3821 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CMAC_256))
3822 		return eSIR_ED_AES_128_CMAC;
3823 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_GCM4) ||
3824 		 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_SMS4))
3825 		return eSIR_ED_WPI;
3826 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GMAC))
3827 		return eSIR_ED_AES_GMAC_128;
3828 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GMAC_256))
3829 		return eSIR_ED_AES_GMAC_256;
3830 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP))
3831 		return eSIR_ED_WEP40;
3832 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_40))
3833 		return eSIR_ED_WEP40;
3834 	else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_104))
3835 		return eSIR_ED_WEP104;
3836 
3837 	return eSIR_ED_NONE;
3838 }
3839 
3840 static enum ani_akm_type
lim_get_wpa_akm(uint32_t akm)3841 lim_get_wpa_akm(uint32_t akm)
3842 {
3843 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X))
3844 		return ANI_AKM_TYPE_WPA;
3845 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK))
3846 		return ANI_AKM_TYPE_WPA_PSK;
3847 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM))
3848 		return ANI_AKM_TYPE_CCKM;
3849 	else
3850 		return ANI_AKM_TYPE_UNKNOWN;
3851 }
3852 
3853 static enum ani_akm_type
lim_get_rsn_akm(uint32_t akm)3854 lim_get_rsn_akm(uint32_t akm)
3855 {
3856 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384))
3857 		return ANI_AKM_TYPE_FT_FILS_SHA384;
3858 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256))
3859 		return ANI_AKM_TYPE_FT_FILS_SHA256;
3860 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384))
3861 		return ANI_AKM_TYPE_FILS_SHA384;
3862 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256))
3863 		return ANI_AKM_TYPE_FILS_SHA256;
3864 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY))
3865 		return ANI_AKM_TYPE_FT_SAE_EXT_KEY;
3866 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE))
3867 		return ANI_AKM_TYPE_FT_SAE;
3868 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE))
3869 		return ANI_AKM_TYPE_SAE;
3870 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_DPP))
3871 		return ANI_AKM_TYPE_DPP_RSN;
3872 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OSEN))
3873 		return ANI_AKM_TYPE_OSEN;
3874 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE))
3875 		return ANI_AKM_TYPE_OWE;
3876 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X))
3877 		return ANI_AKM_TYPE_FT_RSN;
3878 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK))
3879 		return ANI_AKM_TYPE_FT_RSN_PSK;
3880 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X))
3881 		return ANI_AKM_TYPE_RSN;
3882 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK))
3883 		return ANI_AKM_TYPE_RSN_PSK;
3884 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM))
3885 		return ANI_AKM_TYPE_CCKM;
3886 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256))
3887 		return ANI_AKM_TYPE_RSN_PSK_SHA256;
3888 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256))
3889 		return ANI_AKM_TYPE_RSN_8021X_SHA256;
3890 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B))
3891 		return ANI_AKM_TYPE_SUITEB_EAP_SHA256;
3892 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192))
3893 		return ANI_AKM_TYPE_SUITEB_EAP_SHA384;
3894 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384))
3895 		return ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384;
3896 	else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))
3897 		return ANI_AKM_TYPE_SAE_EXT_KEY;
3898 	else
3899 		return ANI_AKM_TYPE_NONE;
3900 }
3901 
3902 enum ani_akm_type
lim_get_connected_akm(struct pe_session * session,int32_t ucast_cipher,int32_t auth_mode,int32_t akm)3903 lim_get_connected_akm(struct pe_session *session, int32_t ucast_cipher,
3904 		      int32_t auth_mode, int32_t akm)
3905 {
3906 	if (auth_mode == -1 || ucast_cipher == -1 || akm == -1)
3907 		return ANI_AKM_TYPE_NONE;
3908 
3909 	if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_NONE) ||
3910 	    QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_OPEN))
3911 		return ANI_AKM_TYPE_NONE;
3912 
3913 	if (lim_is_rsn_profile(session))
3914 		return lim_get_rsn_akm(akm);
3915 
3916 	if (lim_is_wpa_profile(session))
3917 		return lim_get_wpa_akm(akm);
3918 
3919 	if (lim_is_wapi_profile(session))
3920 		return ANI_AKM_TYPE_UNKNOWN;
3921 
3922 	return ANI_AKM_TYPE_NONE;
3923 }
3924 
3925 #ifdef WLAN_FEATURE_FILS_SK
3926 /**
3927  * lim_update_pmksa_to_profile() - update pmk and pmkid to profile which will be
3928  * used in case of fils session
3929  * @vdev: vdev
3930  * @pmkid_cache: pmksa cache
3931  *
3932  * Return: None
3933  */
lim_update_pmksa_to_profile(struct wlan_objmgr_vdev * vdev,struct wlan_crypto_pmksa * pmksa)3934 static inline void lim_update_pmksa_to_profile(struct wlan_objmgr_vdev *vdev,
3935 					       struct wlan_crypto_pmksa *pmksa)
3936 {
3937 	struct mlme_legacy_priv *mlme_priv;
3938 
3939 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
3940 	if (!mlme_priv) {
3941 		pe_err("vdev legacy private object is NULL");
3942 		return;
3943 	}
3944 	if (!mlme_priv->connect_info.fils_con_info)
3945 		return;
3946 	mlme_priv->connect_info.fils_con_info->pmk_len = pmksa->pmk_len;
3947 	qdf_mem_copy(mlme_priv->connect_info.fils_con_info->pmk,
3948 		     pmksa->pmk, pmksa->pmk_len);
3949 	qdf_mem_copy(mlme_priv->connect_info.fils_con_info->pmkid,
3950 		     pmksa->pmkid, PMKID_LEN);
3951 }
3952 #else
lim_update_pmksa_to_profile(struct wlan_objmgr_vdev * vdev,struct wlan_crypto_pmksa * pmksa)3953 static inline void lim_update_pmksa_to_profile(struct wlan_objmgr_vdev *vdev,
3954 					       struct wlan_crypto_pmksa *pmksa)
3955 {
3956 }
3957 #endif
3958 
3959 /*
3960  * lim_is_non_default_rsnxe_cap_set() - Check if non-default userspace RSNXE
3961  * CAP is set
3962  *
3963  * @mac_ctx: pointer to mac contetx
3964  * @req: join request
3965  *
3966  * Return: Non default cap set
3967  */
3968 static inline bool
lim_is_non_default_rsnxe_cap_set(struct mac_context * mac_ctx,struct cm_vdev_join_req * req)3969 lim_is_non_default_rsnxe_cap_set(struct mac_context *mac_ctx,
3970 				 struct cm_vdev_join_req *req)
3971 {
3972 	const uint8_t *rsnxe, *rsnxe_cap;
3973 	uint8_t cap_len = 0, cap_index;
3974 	uint32_t cap_mask;
3975 
3976 	rsnxe = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE,
3977 					 req->assoc_ie.ptr,
3978 					 req->assoc_ie.len);
3979 	if (!rsnxe)
3980 		return false;
3981 
3982 	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe, &cap_len);
3983 	if (!rsnxe_cap || (rsnxe[SIR_MAC_IE_LEN_OFFSET] > (cap_len + 1))) {
3984 		mlme_err("RSNXE caps not present/unknown caps present. Cap len %d",
3985 			 cap_len);
3986 		return true;
3987 	}
3988 
3989 	/*
3990 	 * Below is the definition of RSNXE capabilities defined
3991 	 * in (IEEE Std 802.11-2020, 9.4.2.241, Table 9-780).
3992 	 * The Extended RSN Capabilities field, except its first 4 bits, is a
3993 	 * bit field indicating the extended RSN capabilities being advertised
3994 	 * by the STA transmitting the element. The length of the Extended
3995 	 * RSN Capabilities field is a variable n, in octets, as indicated by
3996 	 * the first 4 bits in the field.
3997 	 * Let's consider a uint32_t cap_mask which can accommodate 28(32-4)
3998 	 * bits to check if those bits are set or not. This is to keep it
3999 	 * simple as current supported bits are only 11.
4000 	 * TODO: If spec supports more than this range in future, this needs to
4001 	 * be an array to hold the complete bitmap/bitmask.
4002 	 */
4003 	cap_mask = ~(0xF | WLAN_CRYPTO_RSNX_CAP_SAE_H2E |
4004 		     WLAN_CRYPTO_RSNX_CAP_SAE_PK |
4005 		     WLAN_CRYPTO_RSNX_CAP_SECURE_LTF |
4006 		     WLAN_CRYPTO_RSNX_CAP_SECURE_RTT |
4007 		     WLAN_CRYPTO_RSNX_CAP_URNM_MFPR);
4008 
4009 	/* Check if any other bits are set than cap_mask */
4010 	for (cap_index = 0; cap_index <= cap_len; cap_index++) {
4011 		if (rsnxe_cap[cap_index] & (cap_mask & 0xFF))
4012 			return true;
4013 		cap_mask >>= 8;
4014 	}
4015 
4016 	return false;
4017 }
4018 
4019 /*
4020  * lim_rebuild_rsnxe_cap() - Rebuild the RSNXE CAP for STA
4021  *
4022  * @rsnx_ie: RSNX IE
4023  * @length: length of extended RSN cap field
4024  *
4025  * This API is used to truncate/rebuild the RSNXE based on the length
4026  * provided. This length marks the length of the extended RSN cap field.
4027  *
4028  * Return: Newly constructed RSNX IE
4029  */
lim_rebuild_rsnxe_cap(uint8_t * rsnx_ie,uint8_t length)4030 static inline uint8_t *lim_rebuild_rsnxe_cap(uint8_t *rsnx_ie, uint8_t length)
4031 {
4032 	const uint8_t *rsnxe_cap;
4033 	uint8_t cap_len;
4034 	uint8_t *new_rsnxe = NULL;
4035 
4036 	if (length < SIR_MAC_RSNX_CAP_MIN_LEN ||
4037 	    length > SIR_MAC_RSNX_CAP_MAX_LEN) {
4038 		pe_err("Invalid length %d", length);
4039 		return NULL;
4040 	}
4041 
4042 	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnx_ie, &cap_len);
4043 	if (!rsnxe_cap)
4044 		return NULL;
4045 
4046 	new_rsnxe = qdf_mem_malloc(length + SIR_MAC_IE_TYPE_LEN_SIZE);
4047 	if (!new_rsnxe)
4048 		return NULL;
4049 
4050 	new_rsnxe[SIR_MAC_IE_TYPE_OFFSET] = WLAN_ELEMID_RSNXE;
4051 	new_rsnxe[SIR_MAC_IE_LEN_OFFSET] = length;
4052 	qdf_mem_copy(&new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE], rsnxe_cap, length);
4053 
4054 	/* Now update the new field length in octet 0 for the new length*/
4055 	new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE] =
4056 		(new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE] & 0xF0) | (length - 1);
4057 
4058 	pe_debug("New RSNXE length %d", length);
4059 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
4060 			   new_rsnxe, length + SIR_MAC_IE_TYPE_LEN_SIZE);
4061 	return new_rsnxe;
4062 }
4063 
4064 /*
4065  * lim_append_rsnxe_to_assoc_ie() - Append the new RSNXE to the
4066  * assoc ie buffer
4067  *
4068  * @req: join request
4069  * @new_rsnxe: new rsnxe to be appended
4070  *
4071  * Return: QDF_STATUS
4072  */
4073 static inline QDF_STATUS
lim_append_rsnxe_to_assoc_ie(struct cm_vdev_join_req * req,uint8_t * new_rsnxe)4074 lim_append_rsnxe_to_assoc_ie(struct cm_vdev_join_req *req,
4075 			     uint8_t *new_rsnxe)
4076 {
4077 	uint8_t *assoc_ie = NULL;
4078 	uint8_t assoc_ie_len;
4079 
4080 	assoc_ie = qdf_mem_malloc(req->assoc_ie.len +
4081 				  new_rsnxe[SIR_MAC_IE_LEN_OFFSET] +
4082 				  SIR_MAC_IE_TYPE_LEN_SIZE);
4083 	if (!assoc_ie)
4084 		return QDF_STATUS_E_FAILURE;
4085 
4086 	qdf_mem_copy(assoc_ie, req->assoc_ie.ptr, req->assoc_ie.len);
4087 	assoc_ie_len = req->assoc_ie.len;
4088 	qdf_mem_copy(&assoc_ie[assoc_ie_len], new_rsnxe,
4089 		     new_rsnxe[SIR_MAC_IE_LEN_OFFSET] +
4090 		     SIR_MAC_IE_TYPE_LEN_SIZE);
4091 	assoc_ie_len += new_rsnxe[SIR_MAC_IE_LEN_OFFSET] +
4092 			SIR_MAC_IE_TYPE_LEN_SIZE;
4093 
4094 	/* Replace the assoc ie with new assoc_ie */
4095 	qdf_mem_free(req->assoc_ie.ptr);
4096 	req->assoc_ie.ptr = &assoc_ie[0];
4097 	req->assoc_ie.len = assoc_ie_len;
4098 	return QDF_STATUS_SUCCESS;
4099 }
4100 
4101 static inline QDF_STATUS
lim_strip_rsnx_ie(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * req)4102 lim_strip_rsnx_ie(struct mac_context *mac_ctx,
4103 		  struct pe_session *session,
4104 		  struct cm_vdev_join_req *req)
4105 {
4106 	int32_t akm;
4107 	uint8_t ap_rsnxe_len = 0, len = 0;
4108 	uint8_t *rsnxe = NULL, *new_rsnxe = NULL;
4109 	uint8_t *ap_rsnxe = NULL;
4110 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4111 
4112 	akm = wlan_crypto_get_param(session->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
4113 	if (akm == -1 ||
4114 	    !(WLAN_CRYPTO_IS_WPA_WPA2(akm) || WLAN_CRYPTO_IS_WPA3(akm)))
4115 		return status;
4116 
4117 	if (!wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, req->assoc_ie.ptr,
4118 				      req->assoc_ie.len))
4119 		return status;
4120 
4121 	/*
4122 	 * Userspace may send RSNXE also in connect request irrespective
4123 	 * of the connecting AP capabilities. This allows the driver to chose
4124 	 * best candidate based on score. But the chosen candidate may
4125 	 * not support the RSNXE feature and may not advertise RSNXE
4126 	 * in beacon/probe response. Station is not supposed to include
4127 	 * the RSNX IE in assoc request in such cases as legacy APs
4128 	 * may misbahave due to the new IE. It's observed that few
4129 	 * legacy APs which don't support the RSNXE reject the
4130 	 * connection at EAPOL stage.
4131 	 *
4132 	 * Modify the RSNXE only when known capability bits are set.
4133 	 * i.e., don't strip when bits other than SAE_H2E, SAE_PK, SECURE_LTF,
4134 	 * SECURE_RTT, PROT_RANGE_NEGOTIOATION are set by userspace.
4135 	 *
4136 	 */
4137 	if (lim_is_non_default_rsnxe_cap_set(mac_ctx, req)) {
4138 		pe_debug("Do not strip RSNXE, unknown caps are set");
4139 		return status;
4140 	}
4141 
4142 	ap_rsnxe = util_scan_entry_rsnxe(req->entry);
4143 	if (!ap_rsnxe)
4144 		ap_rsnxe_len = 0;
4145 	else
4146 		ap_rsnxe_len = ap_rsnxe[SIR_MAC_IE_LEN_OFFSET];
4147 
4148 	/*
4149 	 * Do not modify userspace RSNXE if either:
4150 	 * a) AP supports RSNXE cap with more than 1 bytes
4151 	 * b) AP has zero length RSNXE.
4152 	 */
4153 
4154 	if (ap_rsnxe_len > 1 || (ap_rsnxe && ap_rsnxe_len == 0))
4155 		return QDF_STATUS_SUCCESS;
4156 
4157 	rsnxe = qdf_mem_malloc(WLAN_MAX_IE_LEN + SIR_MAC_IE_TYPE_LEN_SIZE);
4158 	if (!rsnxe)
4159 		return QDF_STATUS_E_FAILURE;
4160 
4161 	lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4162 		     (uint16_t *)&req->assoc_ie.len, WLAN_ELEMID_RSNXE,
4163 		     ONE_BYTE, NULL, 0, rsnxe, WLAN_MAX_IE_LEN);
4164 
4165 	if (!rsnxe[0])
4166 		goto end;
4167 
4168 	switch (ap_rsnxe_len) {
4169 	case 0:
4170 		/*
4171 		 * AP doesn't broadcast RSNXE/invalid RSNXE:
4172 		 * For WPA2 - Strip the RSNXE
4173 		 * For WPA3 - Retain only SAE caps: H2E and PK in the 1st octet
4174 		 */
4175 		if (WLAN_CRYPTO_IS_WPA_WPA2(akm)) {
4176 			mlme_debug("Strip RSNXE as it is not supported by AP");
4177 			goto end;
4178 		}
4179 		if (WLAN_CRYPTO_IS_WPA3(akm)) {
4180 			len = 1;
4181 			goto rebuild_rsnxe;
4182 		}
4183 		break;
4184 	case 1:
4185 		/*
4186 		 * In some IOT cases, APs do not recognize more than 1 octet of
4187 		 * RSNXE. This leads to connectivity failures.
4188 		 * Therefore, restrict the self RSNXE to 1 octet if AP supports
4189 		 * only 1 octet
4190 		 */
4191 		len = 1;
4192 		goto rebuild_rsnxe;
4193 	default:
4194 		break;
4195 	}
4196 
4197 	pe_err("Error in handling RSNXE. Length AP: %d SELF: %d",
4198 	       ap_rsnxe_len, rsnxe[SIR_MAC_IE_LEN_OFFSET]);
4199 	status = QDF_STATUS_E_FAILURE;
4200 	goto end;
4201 
4202 rebuild_rsnxe:
4203 	/* Build the new RSNXE */
4204 	new_rsnxe = lim_rebuild_rsnxe_cap(rsnxe, len);
4205 	if (!new_rsnxe) {
4206 		status = QDF_STATUS_E_FAILURE;
4207 		goto end;
4208 	} else if (!new_rsnxe[1]) {
4209 		qdf_mem_free(new_rsnxe);
4210 		status = QDF_STATUS_E_FAILURE;
4211 		goto end;
4212 	}
4213 
4214 	/* Append the new RSNXE to the assoc ie */
4215 	status = lim_append_rsnxe_to_assoc_ie(req, new_rsnxe);
4216 	qdf_mem_free(new_rsnxe);
4217 
4218 end:
4219 	qdf_mem_free(rsnxe);
4220 	return status;
4221 }
4222 
4223 void
lim_update_connect_rsn_ie(struct pe_session * session,uint8_t * rsn_ie_buf,struct wlan_crypto_pmksa * pmksa)4224 lim_update_connect_rsn_ie(struct pe_session *session,
4225 			  uint8_t *rsn_ie_buf, struct wlan_crypto_pmksa *pmksa)
4226 {
4227 	uint8_t *rsn_ie_end;
4228 	uint16_t rsn_ie_len = 0;
4229 
4230 	rsn_ie_end = wlan_crypto_build_rsnie_with_pmksa(session->vdev,
4231 							rsn_ie_buf, pmksa);
4232 	if (!rsn_ie_end) {
4233 		pe_debug("Build RSN IE failed");
4234 		return;
4235 	}
4236 
4237 	rsn_ie_len = rsn_ie_end - rsn_ie_buf;
4238 	session->lim_join_req->rsnIE.length = rsn_ie_len;
4239 	qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4240 		     rsn_ie_buf, rsn_ie_len);
4241 }
4242 
4243 static QDF_STATUS
lim_fill_rsn_ie(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * req)4244 lim_fill_rsn_ie(struct mac_context *mac_ctx, struct pe_session *session,
4245 		struct cm_vdev_join_req *req)
4246 {
4247 	QDF_STATUS status;
4248 	uint8_t *rsn_ie;
4249 	uint8_t rsn_ie_len = 0;
4250 	struct wlan_crypto_pmksa pmksa, *pmksa_peer;
4251 	struct bss_description *bss_desc;
4252 
4253 	rsn_ie = qdf_mem_malloc(DOT11F_IE_RSN_MAX_LEN + 2);
4254 	if (!rsn_ie)
4255 		return QDF_STATUS_E_NOMEM;
4256 
4257 	status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4258 			      (uint16_t *)&req->assoc_ie.len,
4259 			      WLAN_ELEMID_RSN, ONE_BYTE,
4260 			      NULL, 0, rsn_ie, DOT11F_IE_RSN_MAX_LEN);
4261 
4262 	if (req->force_rsne_override && QDF_IS_STATUS_SUCCESS(status)) {
4263 		rsn_ie_len = rsn_ie[1] + 2;
4264 		if (rsn_ie_len < DOT11F_IE_RSN_MIN_LEN ||
4265 		    rsn_ie_len > DOT11F_IE_RSN_MAX_LEN) {
4266 			pe_err("RSN length %d not within limits", rsn_ie_len);
4267 			qdf_mem_free(rsn_ie);
4268 			return QDF_STATUS_E_FAILURE;
4269 		}
4270 
4271 		session->lim_join_req->rsnIE.length = rsn_ie_len;
4272 		qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4273 			     rsn_ie, rsn_ie_len);
4274 
4275 		qdf_mem_free(rsn_ie);
4276 		return QDF_STATUS_SUCCESS;
4277 	}
4278 
4279 	bss_desc = &session->lim_join_req->bssDescription;
4280 
4281 	qdf_mem_zero(&pmksa, sizeof(pmksa));
4282 	if (bss_desc->fils_info_element.is_cache_id_present) {
4283 		pmksa.ssid_len = session->ssId.length;
4284 		qdf_mem_copy(pmksa.ssid, session->ssId.ssId,
4285 			     session->ssId.length);
4286 		qdf_mem_copy(pmksa.cache_id,
4287 			     bss_desc->fils_info_element.cache_id,
4288 			     CACHE_ID_LEN);
4289 		pe_debug("FILS: vdev %d Cache id =0x%x 0x%x ssid: " QDF_SSID_FMT,
4290 			 session->vdev_id, pmksa.cache_id[0], pmksa.cache_id[1],
4291 			 QDF_SSID_REF(pmksa.ssid_len, pmksa.ssid));
4292 	} else {
4293 		qdf_mem_copy(&pmksa.bssid, session->bssId, QDF_MAC_ADDR_SIZE);
4294 		/* For MLO connection, override BSSID with peer mldaddr */
4295 		lim_get_mld_peer(session->vdev, &pmksa.bssid);
4296 	}
4297 
4298 	pmksa_peer = wlan_crypto_get_peer_pmksa(session->vdev, &pmksa);
4299 	if (pmksa_peer)
4300 		pe_debug("PMKSA found");
4301 
4302 	lim_update_connect_rsn_ie(session, rsn_ie, pmksa_peer);
4303 	qdf_mem_free(rsn_ie);
4304 
4305 	/*
4306 	 * If a PMK cache is found for the BSSID, then
4307 	 * update the PMK in CSR session also as this
4308 	 * will be sent to the FW during RSO.
4309 	 */
4310 	if (pmksa_peer) {
4311 		wlan_cm_set_psk_pmk(mac_ctx->pdev, session->vdev_id,
4312 				    pmksa_peer->pmk, pmksa_peer->pmk_len);
4313 		lim_update_pmksa_to_profile(session->vdev, pmksa_peer);
4314 	}
4315 
4316 	return QDF_STATUS_SUCCESS;
4317 }
4318 
4319 static QDF_STATUS
lim_fill_wpa_ie(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * req)4320 lim_fill_wpa_ie(struct mac_context *mac_ctx, struct pe_session *session,
4321 		struct cm_vdev_join_req *req)
4322 {
4323 	QDF_STATUS status;
4324 	uint8_t *wpa_ie;
4325 	uint8_t ie_len = 0;
4326 	uint8_t *wpa_ie_end = NULL;
4327 
4328 	wpa_ie = qdf_mem_malloc(DOT11F_IE_WPA_MAX_LEN + 2);
4329 	if (!wpa_ie)
4330 		return QDF_STATUS_E_NOMEM;
4331 
4332 	status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4333 			      (uint16_t *)&req->assoc_ie.len,
4334 			      DOT11F_EID_WPA, ONE_BYTE,
4335 			      "\x00\x50\xf2", 3, NULL, 0);
4336 
4337 	wpa_ie_end = wlan_crypto_build_wpaie(session->vdev, wpa_ie);
4338 	if (wpa_ie_end)
4339 		ie_len = wpa_ie_end - wpa_ie;
4340 
4341 	session->lim_join_req->rsnIE.length = ie_len;
4342 	qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4343 		     wpa_ie, ie_len);
4344 
4345 	qdf_mem_free(wpa_ie);
4346 
4347 	return QDF_STATUS_SUCCESS;
4348 }
4349 
4350 #ifdef FEATURE_WLAN_WAPI
4351 static QDF_STATUS
lim_fill_wapi_ie(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * req)4352 lim_fill_wapi_ie(struct mac_context *mac_ctx, struct pe_session *session,
4353 		 struct cm_vdev_join_req *req)
4354 {
4355 	QDF_STATUS status;
4356 	uint8_t *wapi_ie;
4357 	uint8_t ie_len = 0;
4358 	uint8_t *wapi_ie_end = NULL;
4359 
4360 	wapi_ie = qdf_mem_malloc(DOT11F_IE_WAPI_MAX_LEN + 2);
4361 	if (!wapi_ie)
4362 		return QDF_STATUS_E_NOMEM;
4363 
4364 	status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
4365 			      (uint16_t *)&req->assoc_ie.len,
4366 			      WLAN_ELEMID_WAPI, ONE_BYTE,
4367 			      NULL, 0, NULL, 0);
4368 
4369 	wapi_ie_end = wlan_crypto_build_wapiie(session->vdev, wapi_ie);
4370 	if (wapi_ie_end)
4371 		ie_len = wapi_ie_end - wapi_ie;
4372 
4373 	session->lim_join_req->rsnIE.length = ie_len;
4374 	qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata,
4375 		     wapi_ie, ie_len);
4376 
4377 	qdf_mem_free(wapi_ie);
4378 
4379 	return QDF_STATUS_SUCCESS;
4380 }
4381 #else
4382 static inline QDF_STATUS
lim_fill_wapi_ie(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * req)4383 lim_fill_wapi_ie(struct mac_context *mac_ctx, struct pe_session *session,
4384 		 struct cm_vdev_join_req *req)
4385 {
4386 	return QDF_STATUS_SUCCESS;
4387 }
4388 #endif
4389 
lim_fill_crypto_params(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * req)4390 static QDF_STATUS lim_fill_crypto_params(struct mac_context *mac_ctx,
4391 					 struct pe_session *session,
4392 					 struct cm_vdev_join_req *req)
4393 {
4394 	int32_t ucast_cipher;
4395 	int32_t auth_mode;
4396 	int32_t akm;
4397 	tSirMacCapabilityInfo *ap_cap_info;
4398 	QDF_STATUS status;
4399 
4400 	ucast_cipher = wlan_crypto_get_param(session->vdev,
4401 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
4402 	auth_mode = wlan_crypto_get_param(session->vdev,
4403 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
4404 	akm = wlan_crypto_get_param(session->vdev,
4405 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
4406 	ap_cap_info = (tSirMacCapabilityInfo *)
4407 			&session->lim_join_req->bssDescription.capabilityInfo;
4408 
4409 	lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm,
4410 			ap_cap_info->privacy);
4411 	session->encryptType = lim_get_encrypt_ed_type(ucast_cipher);
4412 	session->connected_akm = lim_get_connected_akm(session, ucast_cipher,
4413 						       auth_mode, akm);
4414 
4415 	session->wps_registration = req->is_wps_connection;
4416 	session->isOSENConnection = req->is_osen_connection;
4417 
4418 	if (lim_is_rsn_profile(session))
4419 		lim_fill_rsn_ie(mac_ctx, session, req);
4420 	else if (lim_is_wpa_profile(session))
4421 		lim_fill_wpa_ie(mac_ctx, session, req);
4422 	else if (lim_is_wapi_profile(session))
4423 		lim_fill_wapi_ie(mac_ctx, session, req);
4424 
4425 	status = lim_strip_rsnx_ie(mac_ctx, session, req);
4426 	if (QDF_IS_STATUS_ERROR(status))
4427 		return status;
4428 
4429 	lim_update_fils_config(mac_ctx, session, req);
4430 	return QDF_STATUS_SUCCESS;
4431 }
4432 
4433 #ifdef WLAN_FEATURE_11BE_MLO
lim_fill_ml_info(struct cm_vdev_join_req * req,struct join_req * pe_join_req)4434 static void lim_fill_ml_info(struct cm_vdev_join_req *req,
4435 			     struct join_req *pe_join_req)
4436 {
4437 	uint8_t idx, num_links = 0;
4438 	struct mlo_partner_info *partner_info = NULL;
4439 
4440 	partner_info = &pe_join_req->partner_info;
4441 	if (!partner_info)
4442 		return;
4443 
4444 	num_links = req->partner_info.num_partner_links;
4445 	if (num_links > WLAN_UMAC_MLO_MAX_VDEVS)
4446 		num_links = WLAN_UMAC_MLO_MAX_VDEVS;
4447 
4448 	partner_info->num_partner_links = num_links;
4449 
4450 	for (idx = 0; idx < num_links; idx++) {
4451 		partner_info->partner_link_info[idx].link_id =
4452 			req->partner_info.partner_link_info[idx].link_id;
4453 		qdf_copy_macaddr(
4454 			&partner_info->partner_link_info[idx].link_addr,
4455 			&req->partner_info.partner_link_info[idx].link_addr);
4456 		partner_info->partner_link_info[idx].chan_freq =
4457 			req->partner_info.partner_link_info[idx].chan_freq;
4458 	}
4459 	pe_join_req->assoc_link_id = req->assoc_link_id;
4460 }
4461 
lim_copy_ml_partner_info_to_session(struct pe_session * session,struct cm_vdev_join_req * req)4462 static void lim_copy_ml_partner_info_to_session(struct pe_session *session,
4463 						struct cm_vdev_join_req *req)
4464 {
4465 	session->ml_partner_info = req->partner_info;
4466 }
4467 
lim_set_emlsr_caps(struct mac_context * mac_ctx,struct pe_session * session)4468 void lim_set_emlsr_caps(struct mac_context *mac_ctx, struct pe_session *session)
4469 {
4470 	bool emlsr_cap, emlsr_allowed, emlsr_band_check, emlsr_enabled = false;
4471 
4472 	/* Check if HW supports eMLSR mode */
4473 	emlsr_cap = policy_mgr_is_hw_emlsr_capable(mac_ctx->psoc);
4474 	if (!emlsr_cap)
4475 		return;
4476 
4477 	/* Check if vendor command chooses eMLSR mode */
4478 	wlan_mlme_get_emlsr_mode_enabled(mac_ctx->psoc, &emlsr_enabled);
4479 
4480 	/* Check if ML links are in 5 GHz + 6 GHz combination */
4481 	emlsr_band_check = lim_is_emlsr_band_supported(session);
4482 
4483 	emlsr_allowed = emlsr_cap && emlsr_enabled && emlsr_band_check;
4484 
4485 	if (emlsr_allowed) {
4486 		wlan_vdev_obj_lock(session->vdev);
4487 		wlan_vdev_mlme_cap_set(session->vdev, WLAN_VDEV_C_EMLSR_CAP);
4488 		wlan_vdev_obj_unlock(session->vdev);
4489 	} else {
4490 		wlan_vdev_obj_lock(session->vdev);
4491 		wlan_vdev_mlme_cap_clear(session->vdev, WLAN_VDEV_C_EMLSR_CAP);
4492 		wlan_vdev_obj_unlock(session->vdev);
4493 	}
4494 }
4495 #else
lim_fill_ml_info(struct cm_vdev_join_req * req,struct join_req * pe_join_req)4496 static void lim_fill_ml_info(struct cm_vdev_join_req *req,
4497 			     struct join_req *pe_join_req)
4498 {
4499 }
4500 
4501 static void
lim_copy_ml_partner_info_to_session(struct pe_session * session,struct cm_vdev_join_req * req)4502 lim_copy_ml_partner_info_to_session(struct pe_session *session,
4503 				    struct cm_vdev_join_req *req)
4504 {}
4505 #endif
4506 
4507 static QDF_STATUS
lim_fill_session_params(struct mac_context * mac_ctx,struct pe_session * session,struct cm_vdev_join_req * req)4508 lim_fill_session_params(struct mac_context *mac_ctx,
4509 			struct pe_session *session,
4510 			struct cm_vdev_join_req *req)
4511 {
4512 	QDF_STATUS status;
4513 	struct bss_description *bss_desc;
4514 	uint32_t ie_len;
4515 	uint32_t bss_len;
4516 	struct join_req *pe_join_req;
4517 	int32_t akm;
4518 	struct mlme_legacy_priv *mlme_priv;
4519 	uint32_t assoc_ie_len;
4520 	bool eht_capab;
4521 
4522 	ie_len = util_scan_entry_ie_len(req->entry);
4523 	bss_len = (uint16_t)(offsetof(struct bss_description,
4524 			   ieFields[0]) + ie_len);
4525 
4526 	session->lim_join_req = qdf_mem_malloc(sizeof(*session->lim_join_req) +
4527 					       bss_len);
4528 	if (!session->lim_join_req)
4529 		return QDF_STATUS_E_NOMEM;
4530 
4531 	pe_join_req = session->lim_join_req;
4532 	bss_desc = &session->lim_join_req->bssDescription;
4533 	mgmt_txrx_frame_hex_dump(util_scan_entry_frame_ptr(req->entry),
4534 				 util_scan_entry_frame_len(req->entry),
4535 				 false);
4536 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
4537 						    req->entry);
4538 	if (QDF_IS_STATUS_ERROR(status)) {
4539 		qdf_mem_free(session->lim_join_req);
4540 		session->lim_join_req = NULL;
4541 		return QDF_STATUS_E_FAILURE;
4542 	}
4543 
4544 	akm = wlan_crypto_get_param(session->vdev,
4545 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
4546 	if (!req->entry->ssid.length &&
4547 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE) &&
4548 	    req->owe_trans_ssid.length) {
4549 		req->entry->ssid = req->owe_trans_ssid;
4550 		pe_debug("OWE transition ssid is " QDF_SSID_FMT,
4551 			 QDF_SSID_REF(req->entry->ssid.length,
4552 				      req->entry->ssid.ssid));
4553 	}
4554 
4555 	/* Copy the SSID from req to session entry  */
4556 	session->ssId.length = req->entry->ssid.length;
4557 	qdf_mem_copy(session->ssId.ssId, req->entry->ssid.ssid,
4558 		     session->ssId.length);
4559 	session->ssidHidden = req->is_ssid_hidden;
4560 
4561 	status = lim_fill_pe_session(mac_ctx, session, bss_desc);
4562 	if (QDF_IS_STATUS_ERROR(status)) {
4563 		pe_err("Failed to fill pe session vdev id %d",
4564 		       session->vdev_id);
4565 		qdf_mem_free(session->lim_join_req);
4566 		session->lim_join_req = NULL;
4567 		return QDF_STATUS_E_FAILURE;
4568 	}
4569 
4570 	lim_copy_ml_partner_info_to_session(session, req);
4571 
4572 	pe_debug("Assoc IE len: %d", req->assoc_ie.len);
4573 	if (req->assoc_ie.len)
4574 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
4575 				   req->assoc_ie.ptr, req->assoc_ie.len);
4576 
4577 	assoc_ie_len = req->assoc_ie.len;
4578 	status = lim_fill_crypto_params(mac_ctx, session, req);
4579 	if (QDF_IS_STATUS_ERROR(status)) {
4580 		pe_err("Error in handling RSNXE");
4581 		qdf_mem_free(session->lim_join_req);
4582 		session->lim_join_req = NULL;
4583 		return QDF_STATUS_E_FAILURE;
4584 	}
4585 
4586 	/* Reset the SPMK global cache for non-SAE connection */
4587 	if (session->connected_akm != ANI_AKM_TYPE_SAE) {
4588 		wlan_mlme_set_sae_single_pmk_bss_cap(mac_ctx->psoc,
4589 						     session->vdev_id,
4590 						     false);
4591 		wlan_mlme_clear_sae_single_pmk_info(session->vdev,
4592 						    NULL);
4593 	}
4594 
4595 	if (assoc_ie_len != req->assoc_ie.len) {
4596 		pe_debug("After stripping Assoc IE len: %d", req->assoc_ie.len);
4597 		if (req->assoc_ie.len)
4598 			QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
4599 					   QDF_TRACE_LEVEL_DEBUG,
4600 					   req->assoc_ie.ptr,
4601 					   req->assoc_ie.len);
4602 	}
4603 
4604 	qdf_mem_copy(pe_join_req->addIEAssoc.addIEdata,
4605 		     req->assoc_ie.ptr, req->assoc_ie.len);
4606 	/* update assoc ie to cm */
4607 	cm_update_session_assoc_ie(mac_ctx->psoc, session->vdev_id,
4608 				   &req->assoc_ie);
4609 	pe_join_req->addIEAssoc.length = req->assoc_ie.len;
4610 	qdf_mem_copy(pe_join_req->addIEScan.addIEdata,
4611 		     req->scan_ie.ptr, req->scan_ie.len);
4612 	pe_join_req->addIEScan.length = req->scan_ie.len;
4613 
4614 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
4615 	if (!mlme_priv) {
4616 		pe_err("Invalid mlme priv object");
4617 		qdf_mem_free(session->lim_join_req);
4618 		session->lim_join_req = NULL;
4619 		return QDF_STATUS_E_FAILURE;
4620 	}
4621 	qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie,
4622 		     DOT11F_IE_EXTCAP_MAX_LEN + 2);
4623 
4624 	if (session->lim_join_req->addIEAssoc.length) {
4625 		uint8_t *add_ie = NULL;
4626 		uint16_t add_ie_len;
4627 
4628 		add_ie_len = session->lim_join_req->addIEAssoc.length;
4629 		add_ie = qdf_mem_malloc(add_ie_len);
4630 		if (!add_ie) {
4631 			qdf_mem_free(session->lim_join_req);
4632 			session->lim_join_req = NULL;
4633 			return QDF_STATUS_E_FAILURE;
4634 		}
4635 		qdf_mem_copy(add_ie,
4636 			     session->lim_join_req->addIEAssoc.addIEdata,
4637 			     add_ie_len);
4638 
4639 		status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
4640 				      DOT11F_EID_EXTCAP, ONE_BYTE,
4641 				      NULL, 0,
4642 				      mlme_priv->connect_info.ext_cap_ie,
4643 				      DOT11F_IE_EXTCAP_MAX_LEN);
4644 		qdf_mem_free(add_ie);
4645 
4646 		if (QDF_IS_STATUS_ERROR(status)) {
4647 			pe_err("Parsing of ext cap failed with status : %d",
4648 			       status);
4649 			qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie,
4650 				     DOT11F_IE_EXTCAP_MAX_LEN + 2);
4651 			qdf_mem_free(session->lim_join_req);
4652 			session->lim_join_req = NULL;
4653 			return QDF_STATUS_E_FAILURE;
4654 		}
4655 	}
4656 
4657 	if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
4658 		if (!lim_is_session_he_capable(session)) {
4659 			pe_err("JOIN_REQ with invalid 6G security");
4660 			qdf_mem_free(session->lim_join_req);
4661 			session->lim_join_req = NULL;
4662 			return QDF_STATUS_E_FAILURE;
4663 		}
4664 	}
4665 
4666 	wlan_psoc_mlme_get_11be_capab(mac_ctx->psoc, &eht_capab);
4667 	if (eht_capab && wlan_vdev_mlme_is_mlo_vdev(session->vdev))
4668 		lim_fill_ml_info(req, pe_join_req);
4669 
4670 	lim_set_emlsr_caps(mac_ctx, session);
4671 
4672 	return QDF_STATUS_SUCCESS;
4673 }
4674 
4675 static QDF_STATUS
lim_cm_handle_join_req(struct cm_vdev_join_req * req)4676 lim_cm_handle_join_req(struct cm_vdev_join_req *req)
4677 {
4678 	struct mac_context *mac_ctx;
4679 	struct pe_session *pe_session;
4680 	QDF_STATUS status;
4681 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4682 
4683 	if (!wma)
4684 		return QDF_STATUS_E_INVAL;
4685 
4686 	if (!req)
4687 		return QDF_STATUS_E_INVAL;
4688 
4689 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
4690 
4691 	if (!mac_ctx)
4692 		return QDF_STATUS_E_INVAL;
4693 
4694 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0);
4695 
4696 	pe_session = lim_cm_create_session(mac_ctx, req);
4697 	if (!pe_session)
4698 		goto fail;
4699 
4700 	pe_session->cm_id = req->cm_id;
4701 	status = lim_fill_session_params(mac_ctx, pe_session, req);
4702 
4703 	if (QDF_IS_STATUS_ERROR(status))
4704 		goto fail;
4705 
4706 	lim_dump_session_info(mac_ctx, pe_session);
4707 	lim_dump_he_info(mac_ctx, pe_session);
4708 	lim_dump_eht_info(pe_session);
4709 
4710 	if (lim_connect_skip_join_for_gc(pe_session)) {
4711 		pe_session->beacon =
4712 			qdf_mem_malloc(util_scan_entry_frame_len(req->entry));
4713 		if (!pe_session->beacon)
4714 			goto fail;
4715 		pe_session->bcnLen = util_scan_entry_frame_len(req->entry);
4716 		qdf_mem_copy(pe_session->beacon,
4717 			     util_scan_entry_frame_ptr(req->entry),
4718 			     pe_session->bcnLen);
4719 	}
4720 
4721 	status = lim_send_connect_req_to_mlm(pe_session);
4722 	if (QDF_IS_STATUS_ERROR(status)) {
4723 		pe_err("Failed to send mlm req vdev id %d",
4724 		       pe_session->vdev_id);
4725 		goto fail;
4726 	}
4727 
4728 	if (!wlan_vdev_mlme_is_mlo_link_vdev(pe_session->vdev))
4729 		lim_send_mlo_caps_ie(mac_ctx, pe_session->vdev,
4730 				     QDF_STA_MODE,
4731 				     pe_session->vdev_id);
4732 
4733 	return QDF_STATUS_SUCCESS;
4734 
4735 fail:
4736 	if (pe_session)
4737 		pe_delete_session(mac_ctx, pe_session);
4738 	status = wma_remove_bss_peer_before_join(wma, req->vdev_id, req);
4739 	if (status == QDF_STATUS_E_PENDING)
4740 		return status;
4741 	lim_cm_send_connect_rsp(mac_ctx, NULL, req, CM_GENERIC_FAILURE,
4742 					QDF_STATUS_E_FAILURE, 0, false);
4743 
4744 	return status;
4745 }
4746 
cm_process_join_req(struct scheduler_msg * msg)4747 QDF_STATUS cm_process_join_req(struct scheduler_msg *msg)
4748 {
4749 	struct cm_vdev_join_req *req;
4750 	QDF_STATUS status;
4751 
4752 	if (!msg || !msg->bodyptr) {
4753 		pe_err("msg or msg->bodyptr is NULL");
4754 		return QDF_STATUS_E_INVAL;
4755 	}
4756 
4757 	req = msg->bodyptr;
4758 
4759 	status = lim_cm_handle_join_req(req);
4760 	if (status != QDF_STATUS_E_PENDING)
4761 		cm_free_join_req(req);
4762 
4763 	return status;
4764 }
4765 
lim_process_disconnect_sta(struct pe_session * session,struct scheduler_msg * msg)4766 static void lim_process_disconnect_sta(struct pe_session *session,
4767 				       struct scheduler_msg *msg)
4768 {
4769 	if (QDF_IS_STATUS_SUCCESS(
4770 	    wlan_vdev_is_restart_progress(session->vdev)))
4771 		wlan_vdev_mlme_sm_deliver_evt(session->vdev,
4772 					      WLAN_VDEV_SM_EV_RESTART_REQ_FAIL,
4773 					      sizeof(*msg), msg);
4774 	else
4775 		wlan_vdev_mlme_sm_deliver_evt(session->vdev,
4776 					      WLAN_VDEV_SM_EV_DOWN,
4777 					      sizeof(*msg), msg);
4778 }
4779 
lim_prepare_and_send_deauth(struct mac_context * mac_ctx,struct pe_session * pe_session,struct wlan_cm_vdev_discon_req * req)4780 static void lim_prepare_and_send_deauth(struct mac_context *mac_ctx,
4781 					struct pe_session *pe_session,
4782 					struct wlan_cm_vdev_discon_req *req)
4783 {
4784 	struct scheduler_msg msg = {0};
4785 	struct deauth_req deauth_req = {0};
4786 
4787 	deauth_req.messageType = eWNI_SME_DEAUTH_REQ;
4788 	deauth_req.length = sizeof(deauth_req);
4789 	deauth_req.vdev_id = req->req.vdev_id;
4790 	qdf_mem_copy(deauth_req.bssid.bytes, pe_session->bssId,
4791 		     QDF_MAC_ADDR_SIZE);
4792 	deauth_req.peer_macaddr = deauth_req.bssid;
4793 	deauth_req.reasonCode = req->req.reason_code;
4794 
4795 	msg.bodyptr = &deauth_req;
4796 	msg.type = eWNI_SME_DEAUTH_REQ;
4797 	lim_process_disconnect_sta(pe_session, &msg);
4798 }
4799 
lim_prepare_and_send_disassoc(struct mac_context * mac_ctx,struct pe_session * pe_session,struct wlan_cm_vdev_discon_req * req)4800 static void lim_prepare_and_send_disassoc(struct mac_context *mac_ctx,
4801 					  struct pe_session *pe_session,
4802 					  struct wlan_cm_vdev_discon_req *req)
4803 {
4804 	struct scheduler_msg msg = {0};
4805 	struct disassoc_req disassoc_req = {0};
4806 
4807 	disassoc_req.messageType = eWNI_SME_DISASSOC_REQ;
4808 	disassoc_req.length = sizeof(disassoc_req);
4809 	disassoc_req.sessionId = req->req.vdev_id;
4810 	qdf_mem_copy(disassoc_req.bssid.bytes, pe_session->bssId,
4811 		     QDF_MAC_ADDR_SIZE);
4812 	disassoc_req.peer_macaddr = disassoc_req.bssid;
4813 	disassoc_req.reasonCode = req->req.reason_code;
4814 	if (req->req.reason_code == REASON_FW_TRIGGERED_ROAM_FAILURE) {
4815 		disassoc_req.process_ho_fail = true;
4816 		disassoc_req.doNotSendOverTheAir = 1;
4817 	} else if (wlan_cm_is_vdev_roam_reassoc_state(pe_session->vdev)) {
4818 		disassoc_req.doNotSendOverTheAir = 1;
4819 		disassoc_req.reasonCode =
4820 					REASON_AUTHORIZED_ACCESS_LIMIT_REACHED;
4821 	} else if (req->req.reason_code == CM_MLO_LINK_SWITCH_DISCONNECT) {
4822 		disassoc_req.doNotSendOverTheAir = 1;
4823 	}
4824 
4825 	msg.bodyptr = &disassoc_req;
4826 	msg.type = eWNI_SME_DISASSOC_REQ;
4827 	lim_process_disconnect_sta(pe_session, &msg);
4828 }
4829 
lim_process_nb_disconnect_req(struct mac_context * mac_ctx,struct pe_session * pe_session,struct wlan_cm_vdev_discon_req * req)4830 static void lim_process_nb_disconnect_req(struct mac_context *mac_ctx,
4831 					  struct pe_session *pe_session,
4832 					  struct wlan_cm_vdev_discon_req *req)
4833 {
4834 	enum wlan_reason_code reason_code;
4835 	bool enable_deauth_to_disassoc_map = false;
4836 
4837 	reason_code = req->req.reason_code;
4838 
4839 	switch (reason_code) {
4840 	case REASON_IFACE_DOWN:
4841 	case REASON_DEVICE_RECOVERY:
4842 	case REASON_OPER_CHANNEL_BAND_CHANGE:
4843 	case REASON_USER_TRIGGERED_ROAM_FAILURE:
4844 	case REASON_CHANNEL_SWITCH_FAILED:
4845 	case REASON_GATEWAY_REACHABILITY_FAILURE:
4846 	case REASON_OPER_CHANNEL_DISABLED_INDOOR:
4847 		/* Set reason REASON_DEAUTH_NETWORK_LEAVING for prop deauth */
4848 		req->req.reason_code = REASON_DEAUTH_NETWORK_LEAVING;
4849 		fallthrough;
4850 	case REASON_PREV_AUTH_NOT_VALID:
4851 	case REASON_CLASS2_FRAME_FROM_NON_AUTH_STA:
4852 		lim_prepare_and_send_deauth(mac_ctx, pe_session, req);
4853 		break;
4854 	case REASON_DEAUTH_NETWORK_LEAVING:
4855 		wlan_mlme_get_enable_deauth_to_disassoc_map(
4856 					mac_ctx->psoc,
4857 					&enable_deauth_to_disassoc_map);
4858 		if (enable_deauth_to_disassoc_map) {
4859 			req->req.reason_code = REASON_DISASSOC_NETWORK_LEAVING;
4860 			return lim_prepare_and_send_disassoc(mac_ctx,
4861 							     pe_session, req);
4862 		}
4863 		lim_prepare_and_send_deauth(mac_ctx, pe_session, req);
4864 		break;
4865 	default:
4866 		/* Set reason REASON_UNSPEC_FAILURE for prop disassoc */
4867 		if (reason_code >= REASON_PROP_START &&
4868 		    reason_code != REASON_FW_TRIGGERED_ROAM_FAILURE)
4869 			req->req.reason_code = REASON_UNSPEC_FAILURE;
4870 		lim_prepare_and_send_disassoc(mac_ctx, pe_session, req);
4871 	}
4872 }
4873 
lim_process_sb_disconnect_req(struct mac_context * mac_ctx,struct pe_session * pe_session,struct wlan_cm_vdev_discon_req * req)4874 static void lim_process_sb_disconnect_req(struct mac_context *mac_ctx,
4875 					  struct pe_session *pe_session,
4876 					  struct wlan_cm_vdev_discon_req *req)
4877 {
4878 	struct scheduler_msg msg = {0};
4879 	struct disassoc_cnf disassoc_cnf = {0};
4880 
4881 	/* For SB disconnect smeState should be in Deauth state
4882 	 * One scenario where the smeState is not updated is when
4883 	 * AP sends deauth on link vdev and disconnect req is triggered
4884 	 */
4885 	if (pe_session->limSmeState == eLIM_SME_LINK_EST_STATE)
4886 		pe_session->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
4887 
4888 	if (pe_session->limSmeState == eLIM_SME_WT_DEAUTH_STATE)
4889 		disassoc_cnf.messageType = eWNI_SME_DEAUTH_CNF;
4890 	else
4891 		disassoc_cnf.messageType = eWNI_SME_DISASSOC_CNF;
4892 	disassoc_cnf.vdev_id = req->req.vdev_id;
4893 	qdf_mem_copy(disassoc_cnf.bssid.bytes, pe_session->bssId,
4894 		     QDF_MAC_ADDR_SIZE);
4895 	disassoc_cnf.length = sizeof(disassoc_cnf);
4896 	disassoc_cnf.peer_macaddr = disassoc_cnf.bssid;
4897 
4898 	msg.bodyptr = &disassoc_cnf;
4899 	msg.type = disassoc_cnf.messageType;
4900 	lim_process_disconnect_sta(pe_session, &msg);
4901 }
4902 
4903 static
lim_get_disconnect_session(struct mac_context * mac_ctx,struct wlan_cm_vdev_discon_req * req)4904 struct pe_session *lim_get_disconnect_session(struct mac_context *mac_ctx,
4905 					struct wlan_cm_vdev_discon_req *req)
4906 {
4907 	struct pe_session *session;
4908 	uint8_t pe_session_id;
4909 
4910 	/* Try to find pe session with bssid */
4911 	session = pe_find_session_by_bssid_and_vdev_id(mac_ctx,
4912 						       req->req.bssid.bytes,
4913 						       req->req.vdev_id,
4914 						       &pe_session_id);
4915 	/*
4916 	 * If bssid search fail try to find by vdev id, this can happen if
4917 	 * Roaming change the BSSID during disconnect was getting processed.
4918 	 */
4919 	if (!session) {
4920 		session = pe_find_session_by_vdev_id(mac_ctx, req->req.vdev_id);
4921 		if (session)
4922 			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",
4923 				req->req.vdev_id, req->cm_id, session->peSessionId,
4924 				QDF_MAC_ADDR_REF(session->bssId),
4925 				QDF_MAC_ADDR_REF(req->req.bssid.bytes),
4926 				session->limSmeState, session->limMlmState);
4927 	}
4928 
4929 	/*
4930 	 * In LFR2.0 roaming scenario, if HO disconnect is completed but
4931 	 * NB disconnect is received before reassoc can start OR reassoc failure
4932 	 * lead to disconnect, new AP's session will be idle in wait reassoc
4933 	 * state and vdev in INIT state, so cleanup the session and send
4934 	 * response of disconnect complete.
4935 	 */
4936 	if (session &&
4937 	    QDF_IS_STATUS_SUCCESS(wlan_vdev_mlme_is_init_state(session->vdev))) {
4938 		pe_err("vdev_id %d cm_id 0x%x: sme state %d mlm state %d: vdev is in INIT state. Delete session",
4939 		       req->req.vdev_id, req->cm_id, session->limSmeState,
4940 		       session->limMlmState);
4941 		pe_delete_session(mac_ctx, session);
4942 		session = NULL;
4943 	}
4944 
4945 	return session;
4946 }
4947 static QDF_STATUS
lim_cm_handle_disconnect_req(struct wlan_cm_vdev_discon_req * req)4948 lim_cm_handle_disconnect_req(struct wlan_cm_vdev_discon_req *req)
4949 {
4950 	struct mac_context *mac_ctx;
4951 	struct pe_session *pe_session;
4952 
4953 	if (!req)
4954 		return QDF_STATUS_E_INVAL;
4955 
4956 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
4957 	if (!mac_ctx)
4958 		return QDF_STATUS_E_INVAL;
4959 
4960 	pe_session = lim_get_disconnect_session(mac_ctx, req);
4961 	if (!pe_session) {
4962 		pe_err("vdev_id %d cm_id 0x%x: bssid " QDF_MAC_ADDR_FMT " : no session found",
4963 		       req->req.vdev_id, req->cm_id,
4964 		       QDF_MAC_ADDR_REF(req->req.bssid.bytes));
4965 		lim_cm_send_disconnect_rsp(mac_ctx, req->req.vdev_id);
4966 		return QDF_STATUS_E_INVAL;
4967 	}
4968 
4969 	if (req->req.source == CM_PEER_DISCONNECT ||
4970 	    req->req.source == CM_SB_DISCONNECT ||
4971 	    req->req.source == CM_MLO_LINK_SWITCH_DISCONNECT)
4972 		lim_process_sb_disconnect_req(mac_ctx, pe_session, req);
4973 	else
4974 		lim_process_nb_disconnect_req(mac_ctx, pe_session, req);
4975 
4976 	return QDF_STATUS_SUCCESS;
4977 }
4978 
cm_process_disconnect_req(struct scheduler_msg * msg)4979 QDF_STATUS cm_process_disconnect_req(struct scheduler_msg *msg)
4980 {
4981 	struct wlan_cm_vdev_discon_req *req;
4982 	QDF_STATUS status;
4983 
4984 	if (!msg || !msg->bodyptr) {
4985 		mlme_err("msg or msg->bodyptr is NULL");
4986 		return QDF_STATUS_E_INVAL;
4987 	}
4988 
4989 	req = msg->bodyptr;
4990 
4991 	status = lim_cm_handle_disconnect_req(req);
4992 
4993 	qdf_mem_free(req);
4994 	return status;
4995 }
4996 
4997 #ifdef WLAN_FEATURE_11BE_MLO
4998 /**
4999  * wma_get_mld_info_sta() - get peer_mld_addr and assoc peer flag for sta
5000  * @req: cm_peer_create_req
5001  * @peer_mld_addr: peer mld mac addr
5002  * @is_assoc_peer: is assoc peer
5003  *
5004  * Return: void
5005  */
wma_get_mld_info_sta(struct cm_peer_create_req * req,uint8_t ** peer_mld_addr,bool * is_assoc_peer)5006 static void wma_get_mld_info_sta(struct cm_peer_create_req *req,
5007 				 uint8_t **peer_mld_addr,
5008 				 bool *is_assoc_peer)
5009 {
5010 	if (!qdf_is_macaddr_zero(&req->mld_mac)) {
5011 		*peer_mld_addr = req->mld_mac.bytes;
5012 		*is_assoc_peer = req->is_assoc_peer;
5013 	} else {
5014 		*peer_mld_addr = NULL;
5015 		*is_assoc_peer = false;
5016 	}
5017 }
5018 #else
wma_get_mld_info_sta(struct cm_peer_create_req * req,uint8_t ** peer_mld_addr,bool * is_assoc_peer)5019 static void wma_get_mld_info_sta(struct cm_peer_create_req *req,
5020 				 uint8_t **peer_mld_addr,
5021 				 bool *is_assoc_peer)
5022 {
5023 	*peer_mld_addr = NULL;
5024 	*is_assoc_peer = false;
5025 }
5026 #endif
5027 
cm_process_peer_create(struct scheduler_msg * msg)5028 QDF_STATUS cm_process_peer_create(struct scheduler_msg *msg)
5029 {
5030 	struct cm_peer_create_req *req;
5031 	QDF_STATUS status;
5032 	uint8_t *peer_mld_addr = NULL;
5033 	bool is_assoc_peer = false;
5034 
5035 	if (!msg || !msg->bodyptr) {
5036 		mlme_err("msg or msg->bodyptr is NULL");
5037 		return QDF_STATUS_E_INVAL;
5038 	}
5039 
5040 	req = msg->bodyptr;
5041 
5042 	wma_get_mld_info_sta(req, &peer_mld_addr, &is_assoc_peer);
5043 	status = wma_add_bss_peer_sta(req->vdev_id, req->peer_mac.bytes, true,
5044 				      peer_mld_addr, is_assoc_peer);
5045 
5046 	qdf_mem_free(req);
5047 
5048 	return status;
5049 }
5050 
5051 #ifdef WLAN_FEATURE_HOST_ROAM
lim_handle_reassoc_req(struct cm_vdev_join_req * req)5052 static void lim_handle_reassoc_req(struct cm_vdev_join_req *req)
5053 {
5054 	struct mac_context *mac_ctx;
5055 	struct pe_session *session_entry;
5056 	uint8_t session_id;
5057 	uint8_t vdev_id;
5058 	uint32_t ie_len;
5059 	uint32_t bss_len;
5060 	struct join_req *reassoc_req = NULL;
5061 	uint16_t caps;
5062 	uint32_t val;
5063 	tLimMlmReassocReq *mlm_reassoc_req;
5064 	tSirResultCodes ret_code = eSIR_SME_SUCCESS;
5065 	int8_t local_pwr_constraint = 0, reg_max = 0;
5066 	uint32_t tele_bcn_en = 0;
5067 	QDF_STATUS status;
5068 	tDot11fBeaconIEs *ie_struct;
5069 	ePhyChanBondState cb_mode;
5070 	tSirMacCapabilityInfo *ap_cap_info;
5071 	struct bss_description *bss_desc;
5072 	uint8_t wmm_mode, value;
5073 	bool is_pwr_constraint;
5074 	int32_t ucast_cipher;
5075 	int32_t auth_mode;
5076 	int32_t akm;
5077 
5078 	if (!req)
5079 		return;
5080 
5081 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
5082 	if (!mac_ctx)
5083 		return;
5084 
5085 	vdev_id = req->vdev_id;
5086 	session_entry = pe_find_session_by_bssid(mac_ctx,
5087 						 req->entry->bssid.bytes,
5088 						 &session_id);
5089 	if (!session_entry) {
5090 		pe_err("Session does not exist for: "QDF_MAC_ADDR_FMT,
5091 			QDF_MAC_ADDR_REF(req->entry->bssid.bytes));
5092 		ret_code = eSIR_SME_INVALID_PARAMETERS;
5093 		session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
5094 		if (session_entry)
5095 			lim_handle_sme_join_result(mac_ctx,
5096 					eSIR_SME_INVALID_PARAMETERS,
5097 					STATUS_UNSPECIFIED_FAILURE,
5098 					session_entry);
5099 		goto end;
5100 	}
5101 
5102 	if  (session_entry->lim_join_req) {
5103 		qdf_mem_free(session_entry->lim_join_req);
5104 		session_entry->lim_join_req = NULL;
5105 	}
5106 
5107 	session_entry->cm_id = req->cm_id;
5108 	ie_len = util_scan_entry_ie_len(req->entry);
5109 	bss_len = (uint16_t)(offsetof(struct bss_description,
5110 			     ieFields[0]) + ie_len);
5111 
5112 	reassoc_req = qdf_mem_malloc(sizeof(*session_entry->lim_join_req) +
5113 				     bss_len);
5114 	if (!reassoc_req) {
5115 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5116 		goto end;
5117 	}
5118 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_REQ_EVENT,
5119 			      session_entry, QDF_STATUS_SUCCESS,
5120 			      QDF_STATUS_SUCCESS);
5121 
5122 	pe_debug("Beacon/probe frame received:");
5123 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
5124 			   util_scan_entry_frame_ptr(req->entry),
5125 			   util_scan_entry_frame_len(req->entry));
5126 
5127 	bss_desc = &reassoc_req->bssDescription;
5128 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
5129 						    req->entry);
5130 	if (QDF_IS_STATUS_ERROR(status)) {
5131 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5132 		goto end;
5133 	}
5134 	/* Store the reassoc handle in the session Table */
5135 	session_entry->lim_join_req = reassoc_req;
5136 	session_entry->pLimReAssocReq = reassoc_req;
5137 
5138 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5139 						     &ie_struct);
5140 	if (QDF_IS_STATUS_ERROR(status)) {
5141 		pe_err("IE parsing failed vdev id %d",
5142 		       session_entry->vdev_id);
5143 		session_entry->lim_join_req = NULL;
5144 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5145 		goto end;
5146 	}
5147 	pe_debug("Assoc IE len: %d", req->assoc_ie.len);
5148 	if (req->assoc_ie.len)
5149 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
5150 				   req->assoc_ie.ptr, req->assoc_ie.len);
5151 	if (lim_is_rsn_profile(session_entry))
5152 		lim_fill_rsn_ie(mac_ctx, session_entry, req);
5153 	else if (lim_is_wpa_profile(session_entry))
5154 		lim_fill_wpa_ie(mac_ctx, session_entry, req);
5155 	else if (lim_is_wapi_profile(session_entry))
5156 		lim_fill_wapi_ie(mac_ctx, session_entry, req);
5157 
5158 	lim_strip_rsnx_ie(mac_ctx, session_entry, req);
5159 
5160 	if (lim_is_rsn_profile(session_entry) &&
5161 	    !util_scan_entry_rsnxe(req->entry)) {
5162 		pe_debug("Bss bcn has no RSNXE, strip if has");
5163 		status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr,
5164 				      (uint16_t *)&req->assoc_ie.len,
5165 				      WLAN_ELEMID_RSNXE, ONE_BYTE,
5166 				      NULL, 0, NULL, 0);
5167 		if (QDF_IS_STATUS_ERROR(status))
5168 			pe_err("Strip RNSXE failed");
5169 	}
5170 
5171 	pe_debug("After stripping Assoc IE len: %d", req->assoc_ie.len);
5172 	if (req->assoc_ie.len)
5173 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
5174 				   req->assoc_ie.ptr, req->assoc_ie.len);
5175 	qdf_mem_copy(reassoc_req->addIEAssoc.addIEdata,
5176 		     req->assoc_ie.ptr, req->assoc_ie.len);
5177 	reassoc_req->addIEAssoc.length = req->assoc_ie.len;
5178 	/* update assoc ie to cm */
5179 	cm_update_session_assoc_ie(mac_ctx->psoc, vdev_id, &req->assoc_ie);
5180 	ucast_cipher = wlan_crypto_get_param(session_entry->vdev,
5181 					     WLAN_CRYPTO_PARAM_UCAST_CIPHER);
5182 	auth_mode = wlan_crypto_get_param(session_entry->vdev,
5183 					  WLAN_CRYPTO_PARAM_AUTH_MODE);
5184 	akm = wlan_crypto_get_param(session_entry->vdev,
5185 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
5186 	ap_cap_info = (tSirMacCapabilityInfo *)&req->entry->cap_info.value;
5187 
5188 	lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm,
5189 			ap_cap_info->privacy);
5190 
5191 	if (session_entry->vhtCapability) {
5192 		if (session_entry->opmode == QDF_STA_MODE) {
5193 			session_entry->vht_config.su_beam_formee =
5194 			    mac_ctx->mlme_cfg->vht_caps.vht_cap_info.su_bformee;
5195 		} else {
5196 			session_entry->vht_config.su_beam_formee = 0;
5197 		}
5198 		session_entry->enableVhtpAid =
5199 			mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_paid;
5200 		session_entry->enableVhtGid =
5201 			mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_gid;
5202 	}
5203 
5204 	if (session_entry->nss == 1)
5205 		session_entry->supported_nss_1x1 = true;
5206 
5207 	lim_check_oui_and_update_session(mac_ctx, session_entry, ie_struct);
5208 
5209 	session_entry->lim_reassoc_chan_freq = req->entry->channel.chan_freq;
5210 	cb_mode = wlan_get_cb_mode(mac_ctx,
5211 				  session_entry->lim_reassoc_chan_freq,
5212 				  ie_struct,
5213 				  session_entry);
5214 	session_entry->reAssocHtSupportedChannelWidthSet = cb_mode ? 1 : 0;
5215 	session_entry->reAssocHtRecommendedTxWidthSet =
5216 		session_entry->reAssocHtSupportedChannelWidthSet;
5217 	session_entry->reAssocHtSecondaryChannelOffset = cb_mode;
5218 
5219 	mac_ctx->mlme_cfg->power.local_power_constraint =
5220 		wlan_get_11h_power_constraint(mac_ctx,
5221 					      &ie_struct->PowerConstraints);
5222 	if (session_entry->dot11mode == MLME_DOT11_MODE_11B)
5223 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 0;
5224 	else
5225 		mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g =
5226 			mac_ctx->mlme_cfg->ht_caps.short_slot_time_enabled;
5227 	session_entry->enable_session_twt_support =
5228 					lim_enable_twt(mac_ctx, ie_struct);
5229 
5230 	qdf_mem_free(ie_struct);
5231 
5232 	session_entry->send_smps_action =
5233 		mac_ctx->roam.configParam.send_smps_action;
5234 	session_entry->lim_join_req = NULL;
5235 
5236 	/* Reassociate request is expected in link established state only. */
5237 	if (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE) {
5238 		if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) {
5239 			/*
5240 			 * May be from 11r FT pre-auth. So lets check it
5241 			 * before we bail out
5242 			 */
5243 			pe_debug("Session in reassoc state is %d",
5244 				 session_entry->peSessionId);
5245 
5246 			/* Make sure its our preauth bssid */
5247 			if (qdf_mem_cmp(req->entry->bssid.bytes,
5248 					session_entry->limReAssocbssId,
5249 					QDF_MAC_ADDR_SIZE)) {
5250 				pe_err("Requested BSSID: "QDF_MAC_ADDR_FMT " but bssId in reassoc state" QDF_MAC_ADDR_FMT,
5251 				       QDF_MAC_ADDR_REF(req->entry->bssid.bytes),
5252 				       QDF_MAC_ADDR_REF(session_entry->limReAssocbssId));
5253 				ret_code = eSIR_SME_INVALID_PARAMETERS;
5254 				goto end;
5255 			}
5256 
5257 			session_entry->vdev_id = vdev_id;
5258 			mlm_reassoc_req =
5259 				qdf_mem_malloc(sizeof(*mlm_reassoc_req));
5260 			if (!mlm_reassoc_req) {
5261 				ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5262 				goto end;
5263 			}
5264 
5265 			lim_dump_session_info(mac_ctx, session_entry);
5266 			lim_dump_he_info(mac_ctx, session_entry);
5267 			lim_dump_eht_info(session_entry);
5268 
5269 			/* Update PE sessionId */
5270 			mlm_reassoc_req->sessionId = session_entry->peSessionId;
5271 			status = lim_send_ft_reassoc_req(session_entry,
5272 							 mlm_reassoc_req);
5273 			if (QDF_IS_STATUS_ERROR(status)) {
5274 				qdf_mem_free(mlm_reassoc_req);
5275 				ret_code = eSIR_SME_REFUSED;
5276 				goto end;
5277 			}
5278 			return;
5279 		}
5280 		/*
5281 		 * Should not have received eWNI_SME_REASSOC_REQ
5282 		 */
5283 		pe_err("received unexpected SME_REASSOC_REQ in state %X",
5284 			session_entry->limSmeState);
5285 		lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState);
5286 
5287 		ret_code = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
5288 		goto end;
5289 	}
5290 
5291 	qdf_mem_copy(session_entry->limReAssocbssId, req->entry->bssid.bytes,
5292 		     sizeof(tSirMacAddr));
5293 
5294 	session_entry->limReassocBssCaps = req->entry->cap_info.value;
5295 	reg_max = wlan_reg_get_channel_reg_power_for_freq(
5296 		mac_ctx->pdev, session_entry->curr_op_freq);
5297 	local_pwr_constraint = reg_max;
5298 
5299 	lim_extract_ap_capability(mac_ctx, (uint8_t *)bss_desc->ieFields,
5300 				  lim_get_ielen_from_bss_description(bss_desc),
5301 				  &session_entry->limReassocBssQosCaps,
5302 				  &session_entry->gLimCurrentBssUapsd,
5303 				  &local_pwr_constraint, session_entry,
5304 				  &is_pwr_constraint);
5305 	if (is_pwr_constraint)
5306 		local_pwr_constraint = reg_max - local_pwr_constraint;
5307 
5308 	session_entry->maxTxPower = QDF_MIN(reg_max, (local_pwr_constraint));
5309 	session_entry->max_11h_pwr =
5310 		QDF_MIN(lim_get_cfg_max_tx_power(mac_ctx,
5311 						 bss_desc->chan_freq),
5312 			MAX_TX_PWR_CAP);
5313 	session_entry->min_11h_pwr = MIN_TX_PWR_CAP;
5314 	if (!session_entry->max_11h_pwr)
5315 		session_entry->max_11h_pwr = MAX_TX_PWR_CAP;
5316 
5317 	if (session_entry->max_11h_pwr > session_entry->maxTxPower)
5318 		session_entry->max_11h_pwr = session_entry->maxTxPower;
5319 
5320 	pe_info("Reg max = %d, local pwr constraint = %d, max tx = %d",
5321 		reg_max, local_pwr_constraint, session_entry->maxTxPower);
5322 	/* Copy the SSID from session entry to local variable */
5323 	session_entry->limReassocSSID.length = req->entry->ssid.length;
5324 	qdf_mem_copy(session_entry->limReassocSSID.ssId,
5325 		     req->entry->ssid.ssid,
5326 		     session_entry->limReassocSSID.length);
5327 
5328 	if (!session_entry->enable_session_twt_support) {
5329 		status = wlan_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode);
5330 		if (!QDF_IS_STATUS_SUCCESS(status)) {
5331 			pe_err("Get wmm_mode failed");
5332 			ret_code = eSIR_SME_INVALID_PARAMETERS;
5333 			goto end;
5334 		} else if (wmm_mode == 2) {
5335 			/*QoS not enabled in cfg file */
5336 			session_entry->gUapsdPerAcBitmask = 0;
5337 		} else {
5338 			/*QoS enabled, update uapsd mask from cfg file */
5339 			status = wlan_mlme_get_wmm_uapsd_mask(mac_ctx->psoc,
5340 							      &value);
5341 			if (QDF_IS_STATUS_ERROR(status)) {
5342 				pe_err("Get uapsd_mask failed");
5343 				ret_code = eSIR_SME_INVALID_PARAMETERS;
5344 				goto end;
5345 			} else
5346 				session_entry->gUapsdPerAcBitmask = value;
5347 		}
5348 	}
5349 
5350 	mlm_reassoc_req = qdf_mem_malloc(sizeof(tLimMlmReassocReq));
5351 	if (!mlm_reassoc_req) {
5352 		ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
5353 		goto end;
5354 	}
5355 
5356 	qdf_mem_copy(mlm_reassoc_req->peerMacAddr,
5357 		     session_entry->limReAssocbssId, sizeof(tSirMacAddr));
5358 
5359 	if (lim_get_capability_info(mac_ctx, &caps, session_entry) !=
5360 	    QDF_STATUS_SUCCESS)
5361 		pe_err("could not retrieve Capabilities value");
5362 
5363 	lim_update_caps_info_for_bss(mac_ctx, &caps,
5364 				     req->entry->cap_info.value);
5365 	pe_debug("Capabilities info Reassoc: 0x%X", caps);
5366 
5367 	mlm_reassoc_req->capabilityInfo = caps;
5368 
5369 	/* Update PE session_id */
5370 	mlm_reassoc_req->sessionId = session_id;
5371 
5372 	/*
5373 	 * If telescopic beaconing is enabled, set listen interval to
5374 	 * CFG_TELE_BCN_MAX_LI
5375 	 */
5376 
5377 	tele_bcn_en = mac_ctx->mlme_cfg->sap_cfg.tele_bcn_wakeup_en;
5378 
5379 	if (tele_bcn_en)
5380 		val = mac_ctx->mlme_cfg->sap_cfg.tele_bcn_max_li;
5381 	else
5382 		val = mac_ctx->mlme_cfg->sap_cfg.listen_interval;
5383 
5384 	mlm_reassoc_req->listenInterval = (uint16_t) val;
5385 	if (mac_ctx->mlme_cfg->gen.enabled_11h &&
5386 	    ap_cap_info->spectrumMgt && bss_desc->nwType == eSIR_11A_NW_TYPE)
5387 		session_entry->spectrumMgtEnabled = true;
5388 
5389 	/* Enable the spectrum management if this is a DFS channel */
5390 	if (session_entry->country_info_present &&
5391 	    lim_isconnected_on_dfs_freq(
5392 		mac_ctx, session_entry->curr_op_freq))
5393 		session_entry->spectrumMgtEnabled = true;
5394 
5395 	session_entry->limPrevSmeState = session_entry->limSmeState;
5396 	session_entry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
5397 
5398 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, session_entry->peSessionId,
5399 			 session_entry->limSmeState));
5400 
5401 	lim_dump_session_info(mac_ctx, session_entry);
5402 	lim_dump_he_info(mac_ctx, session_entry);
5403 	lim_dump_eht_info(session_entry);
5404 
5405 	status = lim_send_reassoc_req(session_entry, mlm_reassoc_req);
5406 	if (QDF_IS_STATUS_ERROR(status)) {
5407 		qdf_mem_free(mlm_reassoc_req);
5408 		ret_code = eSIR_SME_REFUSED;
5409 		goto end;
5410 	}
5411 
5412 	return;
5413 end:
5414 	if (reassoc_req) {
5415 		qdf_mem_free(reassoc_req);
5416 		if (session_entry)
5417 			session_entry->pLimReAssocReq = NULL;
5418 	}
5419 
5420 	/*
5421 	 * Send Reassoc failure response to host
5422 	 * (note session_entry may be NULL, but that's OK)
5423 	 */
5424 	lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP,
5425 				      ret_code, STATUS_UNSPECIFIED_FAILURE,
5426 				      session_entry, vdev_id);
5427 }
5428 
cm_process_reassoc_req(struct scheduler_msg * msg)5429 QDF_STATUS cm_process_reassoc_req(struct scheduler_msg *msg)
5430 {
5431 	struct cm_vdev_join_req *req;
5432 
5433 	if (!msg || !msg->bodyptr) {
5434 		mlme_err("msg or msg->bodyptr is NULL");
5435 		return QDF_STATUS_E_INVAL;
5436 	}
5437 
5438 	req = msg->bodyptr;
5439 
5440 	lim_handle_reassoc_req(req);
5441 
5442 	cm_free_join_req(req);
5443 
5444 	return QDF_STATUS_SUCCESS;
5445 }
5446 
5447 static QDF_STATUS
lim_fill_preauth_req_dot11_mode(struct mac_context * mac_ctx,tpSirFTPreAuthReq req,uint8_t vdev_id)5448 lim_fill_preauth_req_dot11_mode(struct mac_context *mac_ctx,
5449 				tpSirFTPreAuthReq req,
5450 				uint8_t vdev_id)
5451 {
5452 	QDF_STATUS status;
5453 	tDot11fBeaconIEs *ie_struct;
5454 	enum mlme_dot11_mode self_dot11_mode;
5455 	enum mlme_dot11_mode bss_dot11_mode;
5456 	enum mlme_dot11_mode intersected_mode;
5457 	struct bss_description *bss_desc = req->pbssDescription;
5458 
5459 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5460 						     &ie_struct);
5461 	if (QDF_IS_STATUS_ERROR(status)) {
5462 		mlme_err("IE parsing failed");
5463 		return QDF_STATUS_E_FAILURE;
5464 	}
5465 
5466 	self_dot11_mode = lim_get_self_dot11_mode(mac_ctx, QDF_STA_MODE,
5467 						  vdev_id);
5468 	/* if user set dot11 mode by cmd, need to do intersect first */
5469 	self_dot11_mode =
5470 		   lim_intersect_user_dot11_mode(mac_ctx, QDF_STA_MODE,
5471 						 vdev_id, self_dot11_mode);
5472 
5473 	bss_dot11_mode = lim_get_bss_dot11_mode(mac_ctx, bss_desc, ie_struct);
5474 
5475 	status = lim_get_intersected_dot11_mode_sta_ap(mac_ctx, self_dot11_mode,
5476 						       bss_dot11_mode,
5477 						       &intersected_mode,
5478 						       ie_struct, bss_desc);
5479 	if (QDF_IS_STATUS_ERROR(status)) {
5480 		qdf_mem_free(ie_struct);
5481 		return status;
5482 	}
5483 
5484 	req->dot11mode = intersected_mode;
5485 	pe_debug("vdev %d self dot11mode %d bss_dot11 mode %d intersected_mode %d",
5486 		 vdev_id, self_dot11_mode, bss_dot11_mode, intersected_mode);
5487 
5488 	qdf_mem_free(ie_struct);
5489 	return status;
5490 }
5491 
lim_cm_handle_preauth_req(struct wlan_preauth_req * req)5492 static QDF_STATUS lim_cm_handle_preauth_req(struct wlan_preauth_req *req)
5493 {
5494 	struct mac_context *mac_ctx;
5495 	struct wlan_objmgr_vdev *vdev;
5496 	struct scan_cache_entry *scan_entry;
5497 	struct bss_description *bss_desc = NULL;
5498 	uint32_t ie_len, bss_len;
5499 	uint8_t vdev_id;
5500 	struct mlme_legacy_priv *mlme_priv;
5501 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5502 	tpSirFTPreAuthReq preauth_req = NULL;
5503 	bool buf_consumed = true;
5504 
5505 	if (!req)
5506 		return QDF_STATUS_E_INVAL;
5507 
5508 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
5509 	if (!mac_ctx)
5510 		return QDF_STATUS_E_INVAL;
5511 
5512 	ie_len = util_scan_entry_ie_len(req->entry);
5513 	bss_len = (uint16_t)(offsetof(struct bss_description,
5514 			   ieFields[0]) + ie_len);
5515 
5516 	bss_desc = qdf_mem_malloc(sizeof(*bss_desc) + bss_len);
5517 	if (!bss_desc) {
5518 		status = QDF_STATUS_E_NOMEM;
5519 		goto end;
5520 	}
5521 
5522 	scan_entry = req->entry;
5523 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
5524 						    scan_entry);
5525 	if (QDF_IS_STATUS_ERROR(status))
5526 		goto end;
5527 
5528 	preauth_req = qdf_mem_malloc(sizeof(tSirFTPreAuthReq));
5529 	if (!preauth_req) {
5530 		status = QDF_STATUS_E_NOMEM;
5531 		goto end;
5532 	}
5533 
5534 	vdev_id = req->vdev_id;
5535 	preauth_req->pbssDescription = bss_desc;
5536 	status = lim_fill_preauth_req_dot11_mode(mac_ctx, preauth_req, vdev_id);
5537 	if (QDF_IS_STATUS_ERROR(status)) {
5538 		pe_err("dot11mode doesn't get proper filling");
5539 		goto end;
5540 	}
5541 
5542 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id,
5543 						    WLAN_MLME_CM_ID);
5544 	if (!vdev) {
5545 		status = QDF_STATUS_E_FAILURE;
5546 		goto end;
5547 	}
5548 
5549 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
5550 	if (!mlme_priv) {
5551 		status =  QDF_STATUS_E_FAILURE;
5552 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
5553 		goto end;
5554 	}
5555 	qdf_mem_copy(preauth_req->ft_ies,
5556 		     mlme_priv->connect_info.ft_info.auth_ft_ie,
5557 		     mlme_priv->connect_info.ft_info.auth_ie_len);
5558 	preauth_req->ft_ies_length =
5559 			mlme_priv->connect_info.ft_info.auth_ie_len;
5560 	preauth_req->pre_auth_channel_freq = scan_entry->channel.chan_freq;
5561 	wlan_mlme_get_bssid_vdev_id(
5562 			mac_ctx->pdev, vdev_id,
5563 			(struct qdf_mac_addr *)&preauth_req->currbssId);
5564 	qdf_mem_copy(&preauth_req->preAuthbssId,
5565 		     scan_entry->bssid.bytes, QDF_MAC_ADDR_SIZE);
5566 
5567 	wlan_vdev_obj_lock(vdev);
5568 	qdf_mem_copy(&preauth_req->self_mac_addr,
5569 		     wlan_vdev_mlme_get_macaddr(vdev), QDF_MAC_ADDR_SIZE);
5570 	wlan_vdev_obj_unlock(vdev);
5571 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
5572 
5573 	buf_consumed = lim_process_ft_pre_auth_req(mac_ctx, preauth_req);
5574 
5575 end:
5576 	if (buf_consumed) {
5577 		if (bss_desc)
5578 			qdf_mem_free(bss_desc);
5579 		if (preauth_req)
5580 			qdf_mem_free(preauth_req);
5581 	}
5582 
5583 	return status;
5584 }
5585 
cm_process_preauth_req(struct scheduler_msg * msg)5586 QDF_STATUS cm_process_preauth_req(struct scheduler_msg *msg)
5587 {
5588 	struct wlan_preauth_req *req;
5589 	QDF_STATUS status;
5590 
5591 	if (!msg || !msg->bodyptr) {
5592 		mlme_err("msg or msg->bodyptr is NULL");
5593 		return QDF_STATUS_E_INVAL;
5594 	}
5595 
5596 	req = msg->bodyptr;
5597 
5598 	status = lim_cm_handle_preauth_req(req);
5599 
5600 	cm_free_preauth_req(req);
5601 	return status;
5602 }
5603 #endif
5604 
5605 /**
5606  * lim_get_eirp_320_power_from_tpe_ie() - To get eirp power for 320 MHZ
5607  * @tpe: transmit power env Ie advertised by AP
5608  *
5609  * Return: eirp power
5610  */
5611 static uint8_t
lim_get_eirp_320_power_from_tpe_ie(tDot11fIEtransmit_power_env * tpe)5612 lim_get_eirp_320_power_from_tpe_ie(tDot11fIEtransmit_power_env *tpe)
5613 {
5614 	uint8_t eirp_power_320_Mhz = 0;
5615 
5616 	/*
5617 	 * Don't consider 320 MHz EIRP power until AP advertises EIRP
5618 	 * powers till 160 MHz.
5619 	 */
5620 	if (tpe->max_tx_pwr_count < MAX_TX_PWR_COUNT_FOR_160MHZ) {
5621 		pe_debug("tx power count advertised by ap %d less than %d",
5622 			 tpe->max_tx_pwr_count, MAX_TX_PWR_COUNT_FOR_160MHZ);
5623 		return INVALID_TPE_POWER;
5624 	}
5625 
5626 	if (tpe->num_tx_power < MAX_NUM_TX_POWER_FOR_320MHZ)
5627 		return INVALID_TPE_POWER;
5628 
5629 	if (tpe->max_tx_pwr_interpret == LOCAL_EIRP)
5630 		eirp_power_320_Mhz =
5631 			tpe->ext_max_tx_power.ext_max_tx_power_local_eirp.max_tx_power_for_320;
5632 	else
5633 		eirp_power_320_Mhz =
5634 			tpe->ext_max_tx_power.ext_max_tx_power_reg_eirp.max_tx_power_for_320;
5635 
5636 	return eirp_power_320_Mhz;
5637 }
5638 
5639 /**
5640  * lim_update_ext_tpe_power() - To update ext max transmit power element
5641  * @mac: mac context
5642  * @session: pe session
5643  * @tpe: transmit power env Ie
5644  * @curr_freq: current freq
5645  * @tpe_updated: tpe power changed or not
5646  * @existing_pwr_count: no of existing pwr updated
5647  * @is_psd: is psd or not
5648  *
5649  * Return: no. of power updated
5650  */
5651 static uint8_t
lim_update_ext_tpe_power(struct mac_context * mac,struct pe_session * session,tDot11fIEtransmit_power_env * tpe,qdf_freq_t curr_freq,bool * tpe_updated,uint8_t existing_pwr_count,bool is_psd)5652 lim_update_ext_tpe_power(struct mac_context *mac, struct pe_session *session,
5653 			 tDot11fIEtransmit_power_env *tpe, qdf_freq_t curr_freq,
5654 			 bool *tpe_updated, uint8_t existing_pwr_count,
5655 			 bool is_psd)
5656 {
5657 	struct vdev_mlme_obj *vdev_mlme;
5658 	struct ch_params ch_params = {0};
5659 	qdf_freq_t curr_op_freq;
5660 	uint8_t total_psd_power = 0;
5661 	uint8_t ext_power_updated = 0;
5662 	uint8_t i, j;
5663 	uint8_t eirp_pwr = 0;
5664 	uint8_t ext_psd_count = 0;
5665 
5666 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
5667 	if (!vdev_mlme)
5668 		return 0;
5669 
5670 	ch_params.ch_width = CH_WIDTH_320MHZ;
5671 	curr_op_freq = session->curr_op_freq;
5672 	if (is_psd) {
5673 		if (tpe->max_tx_pwr_interpret == LOCAL_EIRP_PSD)
5674 			ext_psd_count =
5675 			tpe->ext_max_tx_power.ext_max_tx_power_local_psd.ext_count;
5676 		else
5677 			ext_psd_count =
5678 			tpe->ext_max_tx_power.ext_max_tx_power_reg_psd.ext_count;
5679 
5680 		if (existing_pwr_count >= MAX_NUM_PWR_LEVEL) {
5681 			pe_debug("already updated %d psd powers",
5682 				 existing_pwr_count);
5683 			return 0;
5684 		}
5685 
5686 		if (!ext_psd_count)  {
5687 			pe_debug("Ext psd count is 0");
5688 			return 0;
5689 		}
5690 
5691 		total_psd_power = existing_pwr_count + ext_psd_count;
5692 		if (total_psd_power > MAX_NUM_PWR_LEVEL) {
5693 			pe_debug("total powers greater than max %d",
5694 				 MAX_NUM_PWR_LEVEL);
5695 			return existing_pwr_count;
5696 		}
5697 		i = existing_pwr_count;
5698 		for (j = 0; j < ext_psd_count && i < total_psd_power; j++)
5699 		{
5700 			if (tpe->max_tx_pwr_interpret == LOCAL_EIRP_PSD) {
5701 				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5702 				    tpe->ext_max_tx_power.ext_max_tx_power_local_psd.max_tx_psd_power[j] ||
5703 				    vdev_mlme->reg_tpc_obj.frequency[i] != curr_freq)
5704 					*tpe_updated = true;
5705 			} else {
5706 				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5707 				    tpe->ext_max_tx_power.ext_max_tx_power_local_psd.max_tx_psd_power[j] ||
5708 				    vdev_mlme->reg_tpc_obj.frequency[i] != curr_freq)
5709 					*tpe_updated = true;
5710 			}
5711 
5712 			vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq;
5713 			curr_freq += 20;
5714 			if (tpe->max_tx_pwr_interpret == LOCAL_EIRP_PSD)
5715 				vdev_mlme->reg_tpc_obj.tpe[i] =
5716 				tpe->ext_max_tx_power.ext_max_tx_power_local_psd.max_tx_psd_power[j];
5717 			else
5718 				vdev_mlme->reg_tpc_obj.tpe[i] =
5719 					tpe->ext_max_tx_power.ext_max_tx_power_reg_psd.max_tx_psd_power[j];
5720 			i++;
5721 		}
5722 		ext_power_updated = i;
5723 
5724 	} else {
5725 		eirp_pwr = lim_get_eirp_320_power_from_tpe_ie(tpe);
5726 		if (eirp_pwr == INVALID_TPE_POWER)
5727 			return 0;
5728 		i = lim_get_num_pwr_levels(false, CH_WIDTH_320MHZ) - 1;
5729 
5730 		wlan_reg_set_channel_params_for_pwrmode(
5731 				mac->pdev, curr_op_freq, 0,
5732 				&ch_params, REG_CURRENT_PWR_MODE);
5733 
5734 		if (vdev_mlme->reg_tpc_obj.tpe[i] != eirp_pwr ||
5735 		    vdev_mlme->reg_tpc_obj.frequency[i] !=
5736 							ch_params.mhz_freq_seg0)
5737 			*tpe_updated = true;
5738 
5739 		vdev_mlme->reg_tpc_obj.frequency[i] = ch_params.mhz_freq_seg0;
5740 		vdev_mlme->reg_tpc_obj.tpe[i] = eirp_pwr;
5741 		ext_power_updated = 1;
5742 	}
5743 	return ext_power_updated;
5744 }
5745 
lim_get_num_tpe_octets(uint8_t max_transmit_power_count)5746 static uint8_t lim_get_num_tpe_octets(uint8_t max_transmit_power_count)
5747 {
5748 	if (!max_transmit_power_count)
5749 		return max_transmit_power_count;
5750 
5751 	return 1 << (max_transmit_power_count - 1);
5752 }
5753 
lim_parse_tpe_ie(struct mac_context * mac,struct pe_session * session,tDot11fIEtransmit_power_env * tpe_ies,uint8_t num_tpe_ies,tDot11fIEhe_op * he_op,bool * has_tpe_updated)5754 void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session,
5755 		      tDot11fIEtransmit_power_env *tpe_ies, uint8_t num_tpe_ies,
5756 		      tDot11fIEhe_op *he_op, bool *has_tpe_updated)
5757 {
5758 	struct vdev_mlme_obj *vdev_mlme;
5759 	uint8_t i, local_tpe_count = 0, reg_tpe_count = 0, num_octets;
5760 	uint8_t psd_index = 0, non_psd_index = 0;
5761 	uint8_t bw_num;
5762 	uint16_t bw_val, ch_width;
5763 	qdf_freq_t curr_op_freq, curr_freq = 0;
5764 	enum reg_6g_client_type client_mobility_type;
5765 	struct ch_params ch_params = {0};
5766 	tDot11fIEtransmit_power_env single_tpe, local_tpe, reg_tpe;
5767 	/*
5768 	 * PSD is power spectral density, incoming TPE could contain
5769 	 * non PSD info, or PSD info, or both, so need to keep track of them
5770 	 */
5771 	bool non_psd_set = false, psd_set = false;
5772 	bool both_tpe_present = false;
5773 	bool local_eirp_set = false, local_psd_set = false;
5774 	bool reg_eirp_set = false, reg_psd_set = false;
5775 	uint8_t local_eirp_idx = 0, local_psd_idx = 0;
5776 	uint8_t reg_eirp_idx = 0, reg_psd_idx = 0;
5777 	uint8_t min_count = 0;
5778 	uint8_t ext_power_updated = 0, eirp_power = 0;
5779 	uint8_t expect_num;
5780 
5781 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
5782 	if (!vdev_mlme)
5783 		return;
5784 
5785 	if (session->sta_follows_sap_power) {
5786 		pe_debug_rl("STA operates in 6 GHz power of SAP, do not update STA power");
5787 		return;
5788 	}
5789 
5790 	vdev_mlme->reg_tpc_obj.num_pwr_levels = 0;
5791 	*has_tpe_updated = false;
5792 
5793 	wlan_reg_get_cur_6g_client_type(mac->pdev, &client_mobility_type);
5794 
5795 	for (i = 0; i < num_tpe_ies; i++) {
5796 		single_tpe = tpe_ies[i];
5797 		if (single_tpe.present &&
5798 		    (single_tpe.max_tx_pwr_category == client_mobility_type)) {
5799 			if (single_tpe.max_tx_pwr_interpret == LOCAL_EIRP ||
5800 			    single_tpe.max_tx_pwr_interpret == LOCAL_EIRP_PSD)
5801 				local_tpe_count++;
5802 			else if (single_tpe.max_tx_pwr_interpret ==
5803 				 REGULATORY_CLIENT_EIRP ||
5804 				 single_tpe.max_tx_pwr_interpret ==
5805 				 REGULATORY_CLIENT_EIRP_PSD)
5806 				reg_tpe_count++;
5807 		}
5808 	}
5809 
5810 	if (!reg_tpe_count && !local_tpe_count)
5811 		return;
5812 	else if (reg_tpe_count && local_tpe_count)
5813 		both_tpe_present = true;
5814 
5815 	for (i = 0; i < num_tpe_ies; i++) {
5816 		single_tpe = tpe_ies[i];
5817 		if (single_tpe.present &&
5818 		    (single_tpe.max_tx_pwr_category == client_mobility_type)) {
5819 			if (single_tpe.max_tx_pwr_interpret == LOCAL_EIRP) {
5820 				non_psd_index = i;
5821 				non_psd_set = true;
5822 				local_eirp_idx = non_psd_index;
5823 				local_eirp_set = non_psd_set;
5824 			} else if (single_tpe.max_tx_pwr_interpret ==
5825 				   LOCAL_EIRP_PSD) {
5826 				psd_index = i;
5827 				psd_set = true;
5828 				local_psd_idx = psd_index;
5829 				local_psd_set = psd_set;
5830 			} else if (single_tpe.max_tx_pwr_interpret ==
5831 				   REGULATORY_CLIENT_EIRP) {
5832 				non_psd_index = i;
5833 				non_psd_set = true;
5834 				reg_eirp_idx = non_psd_index;
5835 				reg_eirp_set = non_psd_set;
5836 			} else if (single_tpe.max_tx_pwr_interpret ==
5837 				   REGULATORY_CLIENT_EIRP_PSD) {
5838 				psd_index = i;
5839 				psd_set = true;
5840 				reg_psd_idx = psd_index;
5841 				reg_psd_set = psd_set;
5842 			}
5843 		}
5844 	}
5845 
5846 	curr_op_freq = session->curr_op_freq;
5847 	bw_val = wlan_reg_get_bw_value(session->ch_width);
5848 
5849 	if (non_psd_set && !psd_set) {
5850 		single_tpe = tpe_ies[non_psd_index];
5851 		if (single_tpe.max_tx_pwr_count >
5852 		    MAX_TX_PWR_COUNT_FOR_160MHZ) {
5853 			pe_debug("Invalid max tx pwr count: %d",
5854 				 single_tpe.max_tx_pwr_count);
5855 			single_tpe.max_tx_pwr_count =
5856 				MAX_TX_PWR_COUNT_FOR_160MHZ;
5857 		}
5858 		expect_num = lim_get_num_pwr_levels(false, session->ch_width);
5859 		single_tpe.max_tx_pwr_count =
5860 			QDF_MIN(single_tpe.max_tx_pwr_count, expect_num - 1);
5861 
5862 		vdev_mlme->reg_tpc_obj.is_psd_power = false;
5863 		vdev_mlme->reg_tpc_obj.eirp_power = 0;
5864 		bw_num = sizeof(get_next_higher_bw) /
5865 				sizeof(get_next_higher_bw[0]);
5866 		if (single_tpe.max_tx_pwr_count >= bw_num) {
5867 			pe_debug("tx pwr count: %d, larger than bw num: %d",
5868 				 single_tpe.max_tx_pwr_count, bw_num);
5869 			single_tpe.max_tx_pwr_count = bw_num - 1;
5870 		}
5871 		vdev_mlme->reg_tpc_obj.num_pwr_levels =
5872 					single_tpe.max_tx_pwr_count + 1;
5873 
5874 		ch_params.ch_width = CH_WIDTH_20MHZ;
5875 		/*
5876 		 * Update tpe power till 160 MHZ, 320 MHZ power will be
5877 		 * advertised via ext_max_tx_power param of TPE IE.
5878 		 */
5879 		for (i = 0; i < single_tpe.max_tx_pwr_count + 1 &&
5880 		     (ch_params.ch_width != CH_WIDTH_320MHZ); i++) {
5881 			wlan_reg_set_channel_params_for_pwrmode(
5882 							mac->pdev,
5883 							curr_op_freq, 0,
5884 							&ch_params,
5885 							REG_CURRENT_PWR_MODE);
5886 			if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5887 			    single_tpe.tx_power[i] ||
5888 			    vdev_mlme->reg_tpc_obj.frequency[i] !=
5889 			    ch_params.mhz_freq_seg0)
5890 				*has_tpe_updated = true;
5891 			vdev_mlme->reg_tpc_obj.frequency[i] =
5892 							ch_params.mhz_freq_seg0;
5893 			vdev_mlme->reg_tpc_obj.tpe[i] = single_tpe.tx_power[i];
5894 			if (ch_params.ch_width != CH_WIDTH_INVALID)
5895 				ch_params.ch_width =
5896 					get_next_higher_bw[ch_params.ch_width];
5897 		}
5898 
5899 		if (ch_params.ch_width == CH_WIDTH_320MHZ) {
5900 			ext_power_updated =
5901 				lim_update_ext_tpe_power(
5902 						mac, session, &single_tpe,
5903 						curr_freq, has_tpe_updated,
5904 						0, false);
5905 			vdev_mlme->reg_tpc_obj.num_pwr_levels +=
5906 							ext_power_updated;
5907 		}
5908 	}
5909 
5910 	if (psd_set) {
5911 		single_tpe = tpe_ies[psd_index];
5912 		if (single_tpe.max_tx_pwr_count >
5913 		    MAX_TX_PWR_COUNT_FOR_160MHZ_PSD) {
5914 			pe_debug("Invalid max tx pwr count psd: %d",
5915 				 single_tpe.max_tx_pwr_count);
5916 			single_tpe.max_tx_pwr_count =
5917 				MAX_TX_PWR_COUNT_FOR_160MHZ_PSD;
5918 		}
5919 		expect_num = lim_get_num_pwr_levels(true, session->ch_width);
5920 
5921 		vdev_mlme->reg_tpc_obj.is_psd_power = true;
5922 		num_octets =
5923 			lim_get_num_tpe_octets(single_tpe.max_tx_pwr_count);
5924 		num_octets = QDF_MIN(num_octets, expect_num);
5925 
5926 		vdev_mlme->reg_tpc_obj.num_pwr_levels = num_octets;
5927 
5928 		ch_params.ch_width = session->ch_width;
5929 		wlan_reg_set_channel_params_for_pwrmode(mac->pdev, curr_op_freq,
5930 							0, &ch_params,
5931 							REG_CURRENT_PWR_MODE);
5932 
5933 		if (ch_params.mhz_freq_seg1)
5934 			curr_freq = ch_params.mhz_freq_seg1 - bw_val / 2 + 10;
5935 		else
5936 			curr_freq = ch_params.mhz_freq_seg0 - bw_val / 2 + 10;
5937 
5938 		if (!num_octets) {
5939 			if (!he_op->oper_info_6g_present)
5940 				ch_width = session->ch_width;
5941 			else
5942 				ch_width = he_op->oper_info_6g.info.ch_width;
5943 			num_octets = lim_get_num_pwr_levels(true,
5944 							    session->ch_width);
5945 			vdev_mlme->reg_tpc_obj.num_pwr_levels = num_octets;
5946 			for (i = 0; i < num_octets; i++) {
5947 				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5948 				    single_tpe.tx_power[0] ||
5949 				    vdev_mlme->reg_tpc_obj.frequency[i] !=
5950 				    curr_freq)
5951 					*has_tpe_updated = true;
5952 				vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq;
5953 				curr_freq += 20;
5954 				vdev_mlme->reg_tpc_obj.tpe[i] =
5955 							single_tpe.tx_power[0];
5956 			}
5957 		} else {
5958 			for (i = 0; i < num_octets; i++) {
5959 				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
5960 				    single_tpe.tx_power[i] ||
5961 				    vdev_mlme->reg_tpc_obj.frequency[i] !=
5962 				    curr_freq)
5963 					*has_tpe_updated = true;
5964 				vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq;
5965 				curr_freq += 20;
5966 				vdev_mlme->reg_tpc_obj.tpe[i] =
5967 							single_tpe.tx_power[i];
5968 			}
5969 		}
5970 			ext_power_updated =
5971 			lim_update_ext_tpe_power(mac, session, &single_tpe,
5972 						 curr_freq, has_tpe_updated,
5973 						 num_octets, true);
5974 			vdev_mlme->reg_tpc_obj.num_pwr_levels =
5975 							ext_power_updated;
5976 	}
5977 
5978 	if (non_psd_set) {
5979 		single_tpe = tpe_ies[non_psd_index];
5980 		vdev_mlme->reg_tpc_obj.eirp_power =
5981 			single_tpe.tx_power[single_tpe.max_tx_pwr_count];
5982 		/*
5983 		 * If a valid eirp power is received in 320 MHZ via ext element
5984 		 * then update eirp power with received eirp.
5985 		 */
5986 		if (session->ch_width == CH_WIDTH_320MHZ) {
5987 			eirp_power =
5988 				lim_get_eirp_320_power_from_tpe_ie(&single_tpe);
5989 			if (eirp_power != INVALID_TPE_POWER)
5990 				vdev_mlme->reg_tpc_obj.eirp_power = eirp_power;
5991 		}
5992 		vdev_mlme->reg_tpc_obj.is_psd_power = false;
5993 	}
5994 
5995 	if (both_tpe_present) {
5996 		pe_debug("Local: eirp: %d psd: %d, Regulatory: eirp: %d psd %d",
5997 			 local_eirp_set, local_psd_set, reg_eirp_set,
5998 			 reg_psd_set);
5999 		if (local_eirp_set && reg_eirp_set) {
6000 			local_tpe = tpe_ies[local_eirp_idx];
6001 			reg_tpe = tpe_ies[reg_eirp_idx];
6002 		} else if (local_psd_set && reg_psd_set) {
6003 			local_tpe = tpe_ies[local_psd_idx];
6004 			reg_tpe = tpe_ies[reg_psd_idx];
6005 		} else {
6006 			return;
6007 		}
6008 
6009 		min_count = QDF_MIN(local_tpe.max_tx_pwr_count,
6010 				    reg_tpe.max_tx_pwr_count);
6011 		for (i = 0; i < min_count + 1; i++) {
6012 			if (vdev_mlme->reg_tpc_obj.tpe[i] !=
6013 			    QDF_MIN(local_tpe.tx_power[i], reg_tpe.tx_power[i]))
6014 				*has_tpe_updated = true;
6015 			vdev_mlme->reg_tpc_obj.tpe[i] =
6016 						QDF_MIN(local_tpe.tx_power[i],
6017 							reg_tpe.tx_power[i]);
6018 			pe_debug("TPE: Local: %d, Reg: %d, power updated: %d",
6019 				 local_tpe.tx_power[i], reg_tpe.tx_power[i],
6020 				 *has_tpe_updated);
6021 		}
6022 	}
6023 }
6024 
lim_process_tpe_ie_from_beacon(struct mac_context * mac,struct pe_session * session,struct bss_description * bss_desc,bool * has_tpe_updated)6025 void lim_process_tpe_ie_from_beacon(struct mac_context *mac,
6026 				    struct pe_session *session,
6027 				    struct bss_description *bss_desc,
6028 				    bool *has_tpe_updated)
6029 {
6030 	tDot11fBeaconIEs *bcn_ie;
6031 	uint32_t buf_len;
6032 	uint8_t *buf;
6033 	int status;
6034 
6035 	bcn_ie = qdf_mem_malloc(sizeof(*bcn_ie));
6036 	if (!bcn_ie)
6037 		return;
6038 
6039 	buf_len = lim_get_ielen_from_bss_description(bss_desc);
6040 	buf = (uint8_t *)bss_desc->ieFields;
6041 	status = dot11f_unpack_beacon_i_es(mac, buf, buf_len, bcn_ie, false);
6042 	if (DOT11F_FAILED(status)) {
6043 		pe_err("Failed to parse Beacon IEs (0x%08x, %d bytes):",
6044 		       status, buf_len);
6045 		qdf_mem_free(bcn_ie);
6046 		return;
6047 	} else if (DOT11F_WARNED(status)) {
6048 		pe_debug("warnings (0x%08x, %d bytes):", status, buf_len);
6049 	}
6050 
6051 	status = lim_strip_and_decode_eht_op(buf, buf_len, &bcn_ie->eht_op,
6052 					     bcn_ie->VHTOperation,
6053 					     bcn_ie->he_op,
6054 					     bcn_ie->HTInfo);
6055 	if (status != QDF_STATUS_SUCCESS) {
6056 		pe_err("Failed to extract eht op");
6057 		return;
6058 	}
6059 
6060 	status = lim_strip_and_decode_eht_cap(buf, buf_len, &bcn_ie->eht_cap,
6061 					      bcn_ie->he_cap,
6062 					      session->curr_op_freq);
6063 	if (status != QDF_STATUS_SUCCESS) {
6064 		pe_err("Failed to extract eht cap");
6065 		return;
6066 	}
6067 
6068 	lim_parse_tpe_ie(mac, session, bcn_ie->transmit_power_env,
6069 			 bcn_ie->num_transmit_power_env, &bcn_ie->he_op,
6070 			 has_tpe_updated);
6071 	qdf_mem_free(bcn_ie);
6072 }
6073 
lim_get_num_pwr_levels(bool is_psd,enum phy_ch_width ch_width)6074 uint32_t lim_get_num_pwr_levels(bool is_psd,
6075 				enum phy_ch_width ch_width)
6076 {
6077 	uint32_t num_pwr_levels = 0;
6078 
6079 	if (is_psd) {
6080 		switch (ch_width) {
6081 		case CH_WIDTH_20MHZ:
6082 			num_pwr_levels = 1;
6083 			break;
6084 		case CH_WIDTH_40MHZ:
6085 			num_pwr_levels = 2;
6086 			break;
6087 		case CH_WIDTH_80MHZ:
6088 			num_pwr_levels = 4;
6089 			break;
6090 		case CH_WIDTH_160MHZ:
6091 			num_pwr_levels = 8;
6092 			break;
6093 		case CH_WIDTH_320MHZ:
6094 			num_pwr_levels = 16;
6095 			break;
6096 		default:
6097 			pe_err_rl("Invalid channel width");
6098 			return 0;
6099 		}
6100 	} else {
6101 		switch (ch_width) {
6102 		case CH_WIDTH_20MHZ:
6103 			num_pwr_levels = 1;
6104 			break;
6105 		case CH_WIDTH_40MHZ:
6106 			num_pwr_levels = 2;
6107 			break;
6108 		case CH_WIDTH_80MHZ:
6109 			num_pwr_levels = 3;
6110 			break;
6111 		case CH_WIDTH_160MHZ:
6112 			num_pwr_levels = 4;
6113 			break;
6114 		case CH_WIDTH_320MHZ:
6115 			num_pwr_levels = 5;
6116 			break;
6117 		default:
6118 			pe_err_rl("Invalid channel width");
6119 			return 0;
6120 		}
6121 	}
6122 	return num_pwr_levels;
6123 }
6124 
lim_get_max_tx_power(struct mac_context * mac,struct vdev_mlme_obj * mlme_obj)6125 uint8_t lim_get_max_tx_power(struct mac_context *mac,
6126 			     struct vdev_mlme_obj *mlme_obj)
6127 {
6128 	uint8_t max_tx_power = 0;
6129 	uint8_t tx_power;
6130 
6131 	if (wlan_reg_get_fcc_constraint(mac->pdev,
6132 					mlme_obj->reg_tpc_obj.frequency[0]))
6133 		return mlme_obj->reg_tpc_obj.reg_max[0];
6134 
6135 	tx_power = QDF_MIN(mlme_obj->reg_tpc_obj.reg_max[0],
6136 			   mlme_obj->reg_tpc_obj.ap_constraint_power);
6137 
6138 	if (tx_power >= MIN_TX_PWR_CAP && tx_power <= MAX_TX_PWR_CAP)
6139 		max_tx_power = tx_power;
6140 	else if (tx_power < MIN_TX_PWR_CAP)
6141 		max_tx_power = MIN_TX_PWR_CAP;
6142 	else
6143 		max_tx_power = MAX_TX_PWR_CAP;
6144 
6145 	return max_tx_power;
6146 }
6147 
lim_calculate_tpc(struct mac_context * mac,struct pe_session * session)6148 void lim_calculate_tpc(struct mac_context *mac,
6149 		       struct pe_session *session)
6150 {
6151 	bool is_psd_power = false;
6152 	bool is_tpe_present = false, is_6ghz_freq = false;
6153 	uint8_t i = 0;
6154 	int8_t max_tx_power;
6155 	uint16_t reg_max = 0, reg_psd_pwr_max = 0;
6156 	uint16_t tx_power_within_bw = 0, psd_power_within_bw = 0;
6157 	uint16_t local_constraint, bw_val = 0;
6158 	uint32_t num_pwr_levels, ap_power_type_6g = 0;
6159 	qdf_freq_t oper_freq, start_freq = 0;
6160 	struct ch_params ch_params = {0};
6161 	struct vdev_mlme_obj *mlme_obj;
6162 	int8_t tpe_power;
6163 	bool skip_tpe = false;
6164 	bool rf_test_mode = false;
6165 	bool safe_mode_enable = false;
6166 
6167 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
6168 	if (!mlme_obj) {
6169 		pe_err("vdev component object is NULL");
6170 		return;
6171 	}
6172 
6173 	if (session->sta_follows_sap_power) {
6174 		pe_debug_rl("STA operates in 6 GHz power of SAP, do not update STA power");
6175 		return;
6176 	}
6177 
6178 	oper_freq = session->curr_op_freq;
6179 	bw_val = wlan_reg_get_bw_value(session->ch_width);
6180 
6181 	ch_params.ch_width = session->ch_width;
6182 	/* start frequency calculation */
6183 	wlan_reg_set_channel_params_for_pwrmode(mac->pdev, oper_freq, 0,
6184 						&ch_params,
6185 						REG_CURRENT_PWR_MODE);
6186 	if (ch_params.mhz_freq_seg1)
6187 		start_freq = ch_params.mhz_freq_seg1 - bw_val / 2 + 10;
6188 	else
6189 		start_freq = ch_params.mhz_freq_seg0 - bw_val / 2 + 10;
6190 
6191 	if (!wlan_reg_is_6ghz_chan_freq(oper_freq)) {
6192 		reg_max = wlan_reg_get_channel_reg_power_for_freq(mac->pdev,
6193 								  oper_freq);
6194 		skip_tpe = wlan_mlme_skip_tpe(mac->psoc);
6195 	} else {
6196 		is_6ghz_freq = true;
6197 		/* Power mode calculation for 6 GHz STA*/
6198 		if (LIM_IS_STA_ROLE(session)) {
6199 			ap_power_type_6g = session->best_6g_power_type;
6200 			wlan_mlme_get_safe_mode_enable(mac->psoc,
6201 						       &safe_mode_enable);
6202 			wlan_mlme_is_rf_test_mode_enabled(mac->psoc,
6203 							  &rf_test_mode);
6204 			/*
6205 			 * set LPI power if safe mode is enabled OR RF test
6206 			 * mode is enabled.
6207 			 */
6208 			if (rf_test_mode || safe_mode_enable)
6209 				ap_power_type_6g = REG_INDOOR_AP;
6210 		}
6211 	}
6212 
6213 	if (mlme_obj->reg_tpc_obj.num_pwr_levels) {
6214 		is_tpe_present = true;
6215 		num_pwr_levels = mlme_obj->reg_tpc_obj.num_pwr_levels;
6216 		is_psd_power = mlme_obj->reg_tpc_obj.is_psd_power;
6217 	} else {
6218 		/**
6219 		 * Set is_psd_power based on reg channel list if it is a 6 GHz
6220 		 * channel and TPE IE is absent.
6221 		 */
6222 		if (is_6ghz_freq)
6223 			is_psd_power = wlan_reg_is_6g_psd_power(mac->pdev);
6224 		num_pwr_levels = lim_get_num_pwr_levels(is_psd_power,
6225 							session->ch_width);
6226 	}
6227 
6228 	if (num_pwr_levels > MAX_NUM_PWR_LEVELS) {
6229 		pe_debug("reset num_pwr_levels %d to MAX_NUM_PWR_LEVELS %d",
6230 			 num_pwr_levels, MAX_NUM_PWR_LEVELS);
6231 		num_pwr_levels = MAX_NUM_PWR_LEVELS;
6232 	}
6233 
6234 	ch_params.ch_width = CH_WIDTH_20MHZ;
6235 
6236 	for (i = 0;
6237 		i < num_pwr_levels && (ch_params.ch_width != CH_WIDTH_INVALID);
6238 		i++) {
6239 		if (is_tpe_present) {
6240 			if (is_6ghz_freq) {
6241 				if (is_psd_power) {
6242 					wlan_reg_get_client_power_for_connecting_ap(
6243 					mac->pdev, ap_power_type_6g,
6244 					mlme_obj->reg_tpc_obj.frequency[i],
6245 					is_psd_power, &reg_max,
6246 					&reg_psd_pwr_max);
6247 				} else {
6248 					wlan_reg_get_client_power_for_connecting_ap(
6249 					mac->pdev, ap_power_type_6g, oper_freq,
6250 					is_psd_power, &reg_max,
6251 					&reg_psd_pwr_max);
6252 				}
6253 			}
6254 		} else {
6255 			/* center frequency calculation */
6256 			if (is_psd_power) {
6257 				mlme_obj->reg_tpc_obj.frequency[i] =
6258 						start_freq + (20 * i);
6259 			} else {
6260 				/* Use operating frequency to fetch EIRP pwr */
6261 				mlme_obj->reg_tpc_obj.frequency[i] = oper_freq;
6262 			}
6263 			if (is_6ghz_freq) {
6264 				if (LIM_IS_STA_ROLE(session)) {
6265 					wlan_reg_get_client_power_for_connecting_ap
6266 					(mac->pdev, ap_power_type_6g,
6267 					 mlme_obj->reg_tpc_obj.frequency[i],
6268 					 is_psd_power, &reg_max,
6269 					 &reg_psd_pwr_max);
6270 				} else {
6271 					if (wlan_reg_decide_6ghz_power_within_bw_for_freq(
6272 							mac->pdev, oper_freq,
6273 							session->ch_width,
6274 							&is_psd_power,
6275 							&tx_power_within_bw,
6276 							&psd_power_within_bw,
6277 							&ap_power_type_6g,
6278 							REG_BEST_PWR_MODE,
6279 							NO_SCHANS_PUNC) ==
6280 							QDF_STATUS_SUCCESS) {
6281 						pe_debug("get pwr attr from secondary list");
6282 						reg_max = tx_power_within_bw;
6283 						reg_psd_pwr_max =
6284 							psd_power_within_bw;
6285 					} else {
6286 						wlan_reg_get_cur_6g_ap_pwr_type(
6287 							mac->pdev,
6288 							&ap_power_type_6g);
6289 						wlan_reg_get_6g_chan_ap_power(
6290 							mac->pdev,
6291 							mlme_obj->reg_tpc_obj.
6292 							frequency[i],
6293 							&is_psd_power,
6294 							&reg_max,
6295 							&reg_psd_pwr_max);
6296 					}
6297 				}
6298 			}
6299 		}
6300 		/* Check for regulatory channel power. If it is zero due to
6301 		 * invalid frequency or other inputs, then assign the regulatory
6302 		 * power of operating frequency to reg_max.
6303 		 */
6304 		if (reg_max) {
6305 			mlme_obj->reg_tpc_obj.reg_max[i] = reg_max;
6306 		} else {
6307 			pe_debug("Reg power due to invalid freq: %d",
6308 				 mlme_obj->reg_tpc_obj.frequency[i]);
6309 			reg_max = mlme_obj->reg_tpc_obj.reg_max[0];
6310 			mlme_obj->reg_tpc_obj.reg_max[i] = reg_max;
6311 		}
6312 
6313 		mlme_obj->reg_tpc_obj.chan_power_info[i].chan_cfreq =
6314 					mlme_obj->reg_tpc_obj.frequency[i];
6315 
6316 		/* max tx power calculation */
6317 		max_tx_power = mlme_obj->reg_tpc_obj.reg_max[i];
6318 
6319 		local_constraint = mlme_obj->reg_tpc_obj.ap_constraint_power;
6320 		pe_debug("local constraint: %d power constraint absolute %d",
6321 			 local_constraint,
6322 			 mlme_obj->reg_tpc_obj.is_power_constraint_abs);
6323 
6324 		if (is_psd_power) {
6325 			max_tx_power = reg_psd_pwr_max;
6326 		} else if (mlme_obj->reg_tpc_obj.is_power_constraint_abs) {
6327 			if (!local_constraint) {
6328 				pe_debug("ignore abs ap constraint power 0!");
6329 				max_tx_power = reg_max;
6330 			} else {
6331 				max_tx_power = QDF_MIN(reg_max,
6332 						       local_constraint);
6333 			}
6334 		} else {
6335 			max_tx_power = reg_max - local_constraint;
6336 			if (!max_tx_power)
6337 				max_tx_power = reg_max;
6338 		}
6339 
6340 		/* If TPE is present */
6341 		if (is_tpe_present && !skip_tpe) {
6342 			if (!is_psd_power && mlme_obj->reg_tpc_obj.eirp_power)
6343 				tpe_power =  mlme_obj->reg_tpc_obj.eirp_power;
6344 			else
6345 				tpe_power = mlme_obj->reg_tpc_obj.tpe[i];
6346 			/**
6347 			 * AP advertises TPE IE tx power as 8-bit unsigned int.
6348 			 * STA needs to convert it into an 8-bit 2s complement
6349 			 * signed integer in the range –64 dBm to 63 dBm with a
6350 			 * 0.5 dB step
6351 			 */
6352 			tpe_power /= 2;
6353 			max_tx_power = QDF_MIN(max_tx_power, tpe_power);
6354 			pe_debug("TPE: %d", tpe_power);
6355 		}
6356 
6357 		mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power =
6358 						(uint8_t)max_tx_power;
6359 
6360 		pe_debug("freq: %d reg power: %d, max_tx_power(eirp/psd): %d",
6361 			 mlme_obj->reg_tpc_obj.frequency[i], reg_max,
6362 			 mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power);
6363 	}
6364 
6365 	mlme_obj->reg_tpc_obj.num_pwr_levels = num_pwr_levels;
6366 	mlme_obj->reg_tpc_obj.eirp_power = reg_max;
6367 	mlme_obj->reg_tpc_obj.power_type_6g = ap_power_type_6g;
6368 	mlme_obj->reg_tpc_obj.is_psd_power = is_psd_power;
6369 
6370 	if (LIM_IS_AP_ROLE(session) && is_psd_power)
6371 		wlan_mlme_set_sap_psd_for_20mhz(session->vdev,
6372 						(uint8_t)reg_psd_pwr_max);
6373 
6374 	pe_debug("num_pwr_levels: %d, is_psd_power: %d, total eirp_power: %d, ap_pwr_type: %d",
6375 		 num_pwr_levels, is_psd_power, reg_max, ap_power_type_6g);
6376 }
6377 
6378 /**
6379  * lim_mlo_sap_validate_and_update_ra() - Validate peer address for ML SAP
6380  * management frames.
6381  * @session: pe_session
6382  * @peer_addr: address of the peer
6383  *
6384  * Check if address pointed by @peer_addr is MLD of the client,
6385  * if so, replace the address with link address of the client
6386  * to send the management packet over the air.
6387  *
6388  * Return: void
6389  */
6390 #ifdef WLAN_FEATURE_11BE_MLO
lim_mlo_sap_validate_and_update_ra(struct pe_session * session,struct qdf_mac_addr * peer_addr)6391 static void lim_mlo_sap_validate_and_update_ra(struct pe_session *session,
6392 					       struct qdf_mac_addr *peer_addr)
6393 {
6394 	uint8_t i;
6395 	struct wlan_mlo_dev_context *ml_ctx;
6396 	struct wlan_mlo_peer_list *mlo_peer_list;
6397 	struct wlan_mlo_peer_context *ml_peer;
6398 	struct wlan_mlo_link_peer_entry *link_peer;
6399 
6400 	if (!wlan_vdev_mlme_is_mlo_ap(session->vdev))
6401 		return;
6402 
6403 	ml_ctx = session->vdev->mlo_dev_ctx;
6404 	mlo_peer_list = &ml_ctx->mlo_peer_list;
6405 
6406 	ml_peerlist_lock_acquire(mlo_peer_list);
6407 	ml_peer = mlo_get_mlpeer(ml_ctx, peer_addr);
6408 	if (!ml_peer) {
6409 		ml_peerlist_lock_release(mlo_peer_list);
6410 		return;
6411 	}
6412 
6413 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
6414 		link_peer = &ml_peer->peer_list[i];
6415 		if (link_peer->is_primary &&
6416 		    !qdf_is_macaddr_equal(peer_addr, &link_peer->link_addr)) {
6417 			qdf_copy_macaddr(peer_addr, &link_peer->link_addr);
6418 			break;
6419 		}
6420 	}
6421 	ml_peerlist_lock_release(mlo_peer_list);
6422 }
6423 #else
6424 static inline void
lim_mlo_sap_validate_and_update_ra(struct pe_session * session,struct qdf_mac_addr * peer_addr)6425 lim_mlo_sap_validate_and_update_ra(struct pe_session *session,
6426 				   struct qdf_mac_addr *peer_addr)
6427 {
6428 }
6429 #endif
6430 
6431 bool send_disassoc_frame = 1;
6432 /**
6433  * __lim_process_sme_disassoc_req()
6434  *
6435  ***FUNCTION:
6436  * This function is called to process SME_DISASSOC_REQ message
6437  * from HDD or upper layer application.
6438  *
6439  ***LOGIC:
6440  *
6441  ***ASSUMPTIONS:
6442  *
6443  ***NOTE:
6444  *
6445  * @param  mac      Pointer to Global MAC structure
6446  * @param  *msg_buf  A pointer to the SME message buffer
6447  * @return None
6448  */
6449 
__lim_process_sme_disassoc_req(struct mac_context * mac,uint32_t * msg_buf)6450 static void __lim_process_sme_disassoc_req(struct mac_context *mac,
6451 					   uint32_t *msg_buf)
6452 {
6453 	uint16_t disassocTrigger, reasonCode;
6454 	tLimMlmDisassocReq *pMlmDisassocReq;
6455 	tSirResultCodes retCode = eSIR_SME_SUCCESS;
6456 	struct disassoc_req smeDisassocReq;
6457 	struct pe_session *pe_session = NULL;
6458 	uint8_t sessionId;
6459 	uint8_t smesessionId;
6460 
6461 	if (!msg_buf) {
6462 		pe_err("Buffer is Pointing to NULL");
6463 		return;
6464 	}
6465 
6466 	qdf_mem_copy(&smeDisassocReq, msg_buf, sizeof(struct disassoc_req));
6467 	smesessionId = smeDisassocReq.sessionId;
6468 	if (!lim_is_sme_disassoc_req_valid(mac,
6469 					   &smeDisassocReq,
6470 					   pe_session)) {
6471 		pe_err("received invalid SME_DISASSOC_REQ message");
6472 		if (mac->lim.gLimRspReqd) {
6473 			mac->lim.gLimRspReqd = false;
6474 
6475 			retCode = eSIR_SME_INVALID_PARAMETERS;
6476 			disassocTrigger = eLIM_HOST_DISASSOC;
6477 			goto sendDisassoc;
6478 		}
6479 
6480 		return;
6481 	}
6482 
6483 	pe_session = pe_find_session_by_bssid_and_vdev_id(mac,
6484 				smeDisassocReq.bssid.bytes,
6485 				smeDisassocReq.sessionId,
6486 				&sessionId);
6487 	if (!pe_session) {
6488 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
6489 		       QDF_MAC_ADDR_REF(smeDisassocReq.bssid.bytes));
6490 		retCode = eSIR_SME_INVALID_PARAMETERS;
6491 		disassocTrigger = eLIM_HOST_DISASSOC;
6492 		goto sendDisassoc;
6493 	}
6494 	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,
6495 		 pe_session->vdev_id, pe_session->peSessionId,
6496 		 pe_session->opmode, smeDisassocReq.reasonCode,
6497 		 pe_session->limSmeState, pe_session->limMlmState,
6498 		 smeDisassocReq.process_ho_fail,
6499 		 smeDisassocReq.doNotSendOverTheAir,
6500 		 QDF_MAC_ADDR_REF(smeDisassocReq.peer_macaddr.bytes),
6501 		 QDF_MAC_ADDR_REF(smeDisassocReq.bssid.bytes));
6502 
6503 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
6504 	lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, pe_session,
6505 			      0, smeDisassocReq.reasonCode);
6506 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
6507 
6508 	pe_session->smeSessionId = smesessionId;
6509 	pe_session->process_ho_fail = smeDisassocReq.process_ho_fail;
6510 
6511 	switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
6512 	case eLIM_STA_ROLE:
6513 		switch (pe_session->limSmeState) {
6514 		case eLIM_SME_ASSOCIATED_STATE:
6515 		case eLIM_SME_LINK_EST_STATE:
6516 			pe_session->limPrevSmeState =
6517 				pe_session->limSmeState;
6518 			pe_session->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
6519 			/* Delete all TDLS peers connected before leaving BSS */
6520 			lim_delete_tdls_peers(mac, pe_session);
6521 			MTRACE(mac_trace(mac, TRACE_CODE_SME_STATE,
6522 				pe_session->peSessionId,
6523 				pe_session->limSmeState));
6524 			break;
6525 
6526 		case eLIM_SME_WT_DEAUTH_STATE:
6527 			/* PE shall still process the DISASSOC_REQ and proceed with
6528 			 * link tear down even if it had already sent a DEAUTH_IND to
6529 			 * to SME. mac->lim.gLimPrevSmeState shall remain the same as
6530 			 * its been set when PE entered WT_DEAUTH_STATE.
6531 			 */
6532 			pe_session->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
6533 			MTRACE(mac_trace
6534 				       (mac, TRACE_CODE_SME_STATE,
6535 				       pe_session->peSessionId,
6536 				       pe_session->limSmeState));
6537 			break;
6538 
6539 		case eLIM_SME_WT_DISASSOC_STATE:
6540 			/* PE Received a Disassoc frame. Normally it gets DISASSOC_CNF but it
6541 			 * received DISASSOC_REQ. Which means host is also trying to disconnect.
6542 			 * PE can continue processing DISASSOC_REQ and send the response instead
6543 			 * of failing the request. SME will anyway ignore DEAUTH_IND that was sent
6544 			 * for disassoc frame.
6545 			 *
6546 			 * It will send a disassoc, which is ok. However, we can use the global flag
6547 			 * sendDisassoc to not send disassoc frame.
6548 			 */
6549 			break;
6550 
6551 		case eLIM_SME_JOIN_FAILURE_STATE: {
6552 			/* Already in Disconnected State, return success */
6553 			if (mac->lim.gLimRspReqd) {
6554 				retCode = eSIR_SME_SUCCESS;
6555 				disassocTrigger = eLIM_HOST_DISASSOC;
6556 				goto sendDisassoc;
6557 			}
6558 		}
6559 		break;
6560 		default:
6561 			/**
6562 			 * STA is not currently associated.
6563 			 * Log error and send response to host
6564 			 */
6565 			pe_err("received unexpected SME_DISASSOC_REQ in state %X",
6566 				pe_session->limSmeState);
6567 			lim_print_sme_state(mac, LOGE,
6568 				pe_session->limSmeState);
6569 
6570 			if (mac->lim.gLimRspReqd) {
6571 				if (pe_session->limSmeState !=
6572 				    eLIM_SME_WT_ASSOC_STATE)
6573 					mac->lim.gLimRspReqd = false;
6574 
6575 				retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
6576 				disassocTrigger = eLIM_HOST_DISASSOC;
6577 				goto sendDisassoc;
6578 			}
6579 
6580 			return;
6581 		}
6582 
6583 		break;
6584 
6585 	case eLIM_AP_ROLE:
6586 		/* Check if MAC address is MLD of the client and
6587 		 * change it to primary link address to send OTA.
6588 		 */
6589 		lim_mlo_sap_validate_and_update_ra(
6590 				pe_session, &smeDisassocReq.peer_macaddr);
6591 		break;
6592 
6593 	default:
6594 		/* eLIM_UNKNOWN_ROLE */
6595 		pe_err("received unexpected SME_DISASSOC_REQ for role %d",
6596 			GET_LIM_SYSTEM_ROLE(pe_session));
6597 
6598 		retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
6599 		disassocTrigger = eLIM_HOST_DISASSOC;
6600 		goto sendDisassoc;
6601 	} /* end switch (mac->lim.gLimSystemRole) */
6602 
6603 	disassocTrigger = eLIM_HOST_DISASSOC;
6604 	reasonCode = smeDisassocReq.reasonCode;
6605 
6606 	if (smeDisassocReq.doNotSendOverTheAir)
6607 		send_disassoc_frame = 0;
6608 
6609 	pMlmDisassocReq = qdf_mem_malloc(sizeof(tLimMlmDisassocReq));
6610 	if (!pMlmDisassocReq)
6611 		return;
6612 
6613 	qdf_copy_macaddr(&pMlmDisassocReq->peer_macaddr,
6614 			 &smeDisassocReq.peer_macaddr);
6615 
6616 	pMlmDisassocReq->reasonCode = reasonCode;
6617 	pMlmDisassocReq->disassocTrigger = disassocTrigger;
6618 
6619 	/* Update PE session ID */
6620 	pMlmDisassocReq->sessionId = sessionId;
6621 
6622 	lim_post_mlm_message(mac,
6623 			     LIM_MLM_DISASSOC_REQ, (uint32_t *) pMlmDisassocReq);
6624 	return;
6625 
6626 sendDisassoc:
6627 	if (pe_session)
6628 		lim_send_sme_disassoc_ntf(mac,
6629 					  smeDisassocReq.peer_macaddr.bytes,
6630 					  retCode,
6631 					  disassocTrigger,
6632 					  1, smesessionId,
6633 					  pe_session);
6634 	else
6635 		lim_send_sme_disassoc_ntf(mac,
6636 					  smeDisassocReq.peer_macaddr.bytes,
6637 					  retCode, disassocTrigger, 1,
6638 					  smesessionId, NULL);
6639 
6640 } /*** end __lim_process_sme_disassoc_req() ***/
6641 
6642 /** -----------------------------------------------------------------
6643    \brief __lim_process_sme_disassoc_cnf() - Process SME_DISASSOC_CNF
6644 
6645    This function is called to process SME_DISASSOC_CNF message
6646    from HDD or upper layer application.
6647 
6648    \param mac - global mac structure
6649    \param sta - station dph hash node
6650    \return none
6651    \sa
6652    ----------------------------------------------------------------- */
__lim_process_sme_disassoc_cnf(struct mac_context * mac,uint32_t * msg_buf)6653 void __lim_process_sme_disassoc_cnf(struct mac_context *mac, uint32_t *msg_buf)
6654 {
6655 	struct disassoc_cnf smeDisassocCnf;
6656 	uint16_t aid;
6657 	tpDphHashNode sta;
6658 	struct pe_session *pe_session;
6659 	uint8_t sessionId;
6660 	uint32_t *msg = NULL;
6661 	QDF_STATUS status;
6662 
6663 	qdf_mem_copy(&smeDisassocCnf, msg_buf, sizeof(smeDisassocCnf));
6664 
6665 	pe_session = pe_find_session_by_bssid_and_vdev_id(mac,
6666 				smeDisassocCnf.bssid.bytes,
6667 				smeDisassocCnf.vdev_id,
6668 				&sessionId);
6669 	if (!pe_session) {
6670 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
6671 		       QDF_MAC_ADDR_REF(smeDisassocCnf.bssid.bytes));
6672 		status = lim_prepare_disconnect_done_ind(mac, &msg,
6673 						smeDisassocCnf.vdev_id,
6674 						eSIR_SME_INVALID_SESSION,
6675 						NULL);
6676 		if (QDF_IS_STATUS_SUCCESS(status))
6677 			lim_send_sme_disassoc_deauth_ntf(mac,
6678 							 QDF_STATUS_SUCCESS,
6679 							 (uint32_t *)msg);
6680 		return;
6681 	}
6682 
6683 	if (!lim_is_sme_disassoc_cnf_valid(mac, &smeDisassocCnf, pe_session)) {
6684 		pe_err("received invalid SME_DISASSOC_CNF message");
6685 		status = lim_prepare_disconnect_done_ind(
6686 					mac, &msg,
6687 					pe_session->smeSessionId,
6688 					eSIR_SME_INVALID_PARAMETERS,
6689 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6690 		if (QDF_IS_STATUS_SUCCESS(status))
6691 			lim_send_sme_disassoc_deauth_ntf(mac,
6692 							 QDF_STATUS_SUCCESS,
6693 							 (uint32_t *)msg);
6694 		return;
6695 	}
6696 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
6697 	if (smeDisassocCnf.messageType == eWNI_SME_DISASSOC_CNF)
6698 		lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_CNF_EVENT,
6699 				      pe_session,
6700 				      (uint16_t)smeDisassocCnf.status_code, 0);
6701 	else if (smeDisassocCnf.messageType == eWNI_SME_DEAUTH_CNF)
6702 		lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_CNF_EVENT,
6703 				      pe_session,
6704 				      (uint16_t)smeDisassocCnf.status_code, 0);
6705 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
6706 	pe_debug("vdev %d (%d) opmode %d SmeState: %d limMlmState %d from: " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT,
6707 		 pe_session->vdev_id, pe_session->peSessionId,
6708 		 pe_session->opmode, pe_session->limSmeState,
6709 		 pe_session->limMlmState,
6710 		 QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes),
6711 		 QDF_MAC_ADDR_REF(smeDisassocCnf.bssid.bytes));
6712 
6713 	switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
6714 	case eLIM_STA_ROLE:
6715 		if ((pe_session->limSmeState != eLIM_SME_IDLE_STATE) &&
6716 		    (pe_session->limSmeState != eLIM_SME_WT_DISASSOC_STATE)
6717 		    && (pe_session->limSmeState !=
6718 			eLIM_SME_WT_DEAUTH_STATE)) {
6719 			pe_err("received unexp SME_DISASSOC_CNF in state %X",
6720 				pe_session->limSmeState);
6721 			lim_print_sme_state(mac, LOGE,
6722 					    pe_session->limSmeState);
6723 			status = lim_prepare_disconnect_done_ind(
6724 					mac, &msg,
6725 					pe_session->smeSessionId,
6726 					eSIR_SME_INVALID_STATE,
6727 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6728 			if (QDF_IS_STATUS_SUCCESS(status))
6729 				lim_send_sme_disassoc_deauth_ntf(mac,
6730 							QDF_STATUS_SUCCESS,
6731 							(uint32_t *)msg);
6732 			return;
6733 		}
6734 		break;
6735 
6736 	case eLIM_AP_ROLE:
6737 		break;
6738 	default:                /* eLIM_UNKNOWN_ROLE */
6739 		pe_err("received unexpected SME_DISASSOC_CNF role %d",
6740 			GET_LIM_SYSTEM_ROLE(pe_session));
6741 		status = lim_prepare_disconnect_done_ind(
6742 					mac, &msg,
6743 					pe_session->smeSessionId,
6744 					eSIR_SME_INVALID_STATE,
6745 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6746 		if (QDF_IS_STATUS_SUCCESS(status))
6747 			lim_send_sme_disassoc_deauth_ntf(mac,
6748 							 QDF_STATUS_SUCCESS,
6749 							 (uint32_t *)msg);
6750 		return;
6751 	}
6752 
6753 	if ((pe_session->limSmeState == eLIM_SME_WT_DISASSOC_STATE) ||
6754 	    (pe_session->limSmeState == eLIM_SME_WT_DEAUTH_STATE) ||
6755 	    LIM_IS_AP_ROLE(pe_session)) {
6756 		sta = dph_lookup_hash_entry(mac,
6757 				smeDisassocCnf.peer_macaddr.bytes, &aid,
6758 				&pe_session->dph.dphHashTable);
6759 		if (!sta) {
6760 			pe_err("DISASSOC_CNF for a STA with no context, addr= "
6761 				QDF_MAC_ADDR_FMT,
6762 				QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes));
6763 			status = lim_prepare_disconnect_done_ind(
6764 					mac, &msg,
6765 					pe_session->smeSessionId,
6766 					eSIR_SME_INVALID_PARAMETERS,
6767 					&smeDisassocCnf.peer_macaddr.bytes[0]);
6768 			if (QDF_IS_STATUS_SUCCESS(status))
6769 				lim_send_sme_disassoc_deauth_ntf(mac,
6770 							QDF_STATUS_SUCCESS,
6771 							(uint32_t *)msg);
6772 			return;
6773 		}
6774 
6775 		if ((sta->mlmStaContext.mlmState ==
6776 				eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
6777 			(sta->mlmStaContext.mlmState ==
6778 				eLIM_MLM_WT_DEL_BSS_RSP_STATE)) {
6779 			pe_err("No need of cleanup for addr:" QDF_MAC_ADDR_FMT "as MLM state is %d",
6780 				QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes),
6781 				sta->mlmStaContext.mlmState);
6782 			status = lim_prepare_disconnect_done_ind(mac, &msg,
6783 						pe_session->smeSessionId,
6784 						eSIR_SME_SUCCESS,
6785 						NULL);
6786 			if (QDF_IS_STATUS_SUCCESS(status))
6787 				lim_send_sme_disassoc_deauth_ntf(mac,
6788 							QDF_STATUS_SUCCESS,
6789 							(uint32_t *)msg);
6790 			return;
6791 		}
6792 
6793 		lim_mlo_notify_peer_disconn(pe_session, sta);
6794 
6795 		/* Delete FT session if there exists one */
6796 		lim_ft_cleanup_pre_auth_info(mac, pe_session);
6797 		lim_cleanup_rx_path(mac, sta, pe_session, true);
6798 
6799 		lim_clean_up_disassoc_deauth_req(mac,
6800 				 (char *)&smeDisassocCnf.peer_macaddr, 0);
6801 	}
6802 
6803 	return;
6804 }
6805 
6806 /**
6807  * __lim_process_sme_deauth_req() - process sme deauth req
6808  * @mac_ctx: Pointer to Global MAC structure
6809  * @msg_buf: pointer to the SME message buffer
6810  *
6811  * This function is called to process SME_DEAUTH_REQ message
6812  * from HDD or upper layer application.
6813  *
6814  * Return: None
6815  */
6816 
__lim_process_sme_deauth_req(struct mac_context * mac_ctx,uint32_t * msg_buf)6817 static void __lim_process_sme_deauth_req(struct mac_context *mac_ctx,
6818 		uint32_t *msg_buf)
6819 {
6820 	uint16_t deauth_trigger, reason_code;
6821 	tLimMlmDeauthReq *mlm_deauth_req;
6822 	struct deauth_req sme_deauth_req;
6823 	tSirResultCodes ret_code = eSIR_SME_SUCCESS;
6824 	struct pe_session *session_entry;
6825 	uint8_t session_id;      /* PE sessionId */
6826 	uint8_t vdev_id;
6827 
6828 	qdf_mem_copy(&sme_deauth_req, msg_buf, sizeof(sme_deauth_req));
6829 	vdev_id = sme_deauth_req.vdev_id;
6830 
6831 	/*
6832 	 * We need to get a session first but we don't even know
6833 	 * if the message is correct.
6834 	 */
6835 	session_entry = pe_find_session_by_bssid_and_vdev_id(mac_ctx,
6836 					sme_deauth_req.bssid.bytes,
6837 					sme_deauth_req.vdev_id,
6838 					&session_id);
6839 	if (!session_entry) {
6840 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
6841 		       QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes));
6842 		ret_code = eSIR_SME_INVALID_PARAMETERS;
6843 		deauth_trigger = eLIM_HOST_DEAUTH;
6844 		goto send_deauth;
6845 	}
6846 
6847 	if (!lim_is_sme_deauth_req_valid(mac_ctx, &sme_deauth_req,
6848 				session_entry)) {
6849 		pe_err("received invalid SME_DEAUTH_REQ message");
6850 		mac_ctx->lim.gLimRspReqd = false;
6851 
6852 		ret_code = eSIR_SME_INVALID_PARAMETERS;
6853 		deauth_trigger = eLIM_HOST_DEAUTH;
6854 		goto send_deauth;
6855 	}
6856 	pe_debug("vdev %d (%d) opmode %d reasoncode %u limSmestate %d limMlmState %d to " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT,
6857 		 vdev_id, session_entry->peSessionId,
6858 		 session_entry->opmode, sme_deauth_req.reasonCode,
6859 		 session_entry->limSmeState, session_entry->limMlmState,
6860 		 QDF_MAC_ADDR_REF(sme_deauth_req.peer_macaddr.bytes),
6861 		 QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes));
6862 
6863 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
6864 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_DEAUTH_REQ_EVENT,
6865 			session_entry, 0, sme_deauth_req.reasonCode);
6866 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
6867 
6868 	session_entry->vdev_id = vdev_id;
6869 
6870 	switch (GET_LIM_SYSTEM_ROLE(session_entry)) {
6871 	case eLIM_STA_ROLE:
6872 		switch (session_entry->limSmeState) {
6873 		case eLIM_SME_ASSOCIATED_STATE:
6874 		case eLIM_SME_LINK_EST_STATE:
6875 			/* Delete all TDLS peers connected before leaving BSS */
6876 			lim_delete_tdls_peers(mac_ctx, session_entry);
6877 			fallthrough;
6878 		case eLIM_SME_WT_ASSOC_STATE:
6879 		case eLIM_SME_JOIN_FAILURE_STATE:
6880 		case eLIM_SME_IDLE_STATE:
6881 			session_entry->limPrevSmeState =
6882 				session_entry->limSmeState;
6883 			session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
6884 			MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
6885 				       session_entry->peSessionId,
6886 				       session_entry->limSmeState));
6887 			/* Send Deauthentication request to MLM below */
6888 			break;
6889 		case eLIM_SME_WT_DEAUTH_STATE:
6890 		case eLIM_SME_WT_DISASSOC_STATE:
6891 			/*
6892 			 * PE Received a Deauth/Disassoc frame. Normally it get
6893 			 * DEAUTH_CNF/DISASSOC_CNF but it received DEAUTH_REQ.
6894 			 * Which means host is also trying to disconnect.
6895 			 * PE can continue processing DEAUTH_REQ and send
6896 			 * the response instead of failing the request.
6897 			 * SME will anyway ignore DEAUTH_IND/DISASSOC_IND that
6898 			 * was sent for deauth/disassoc frame.
6899 			 */
6900 			session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
6901 			break;
6902 		default:
6903 			/*
6904 			 * STA is not in a state to deauthenticate with
6905 			 * peer. Log error and send response to host.
6906 			 */
6907 			pe_err("received unexp SME_DEAUTH_REQ in state %X",
6908 				session_entry->limSmeState);
6909 			lim_print_sme_state(mac_ctx, LOGE,
6910 					    session_entry->limSmeState);
6911 
6912 			if (mac_ctx->lim.gLimRspReqd) {
6913 				mac_ctx->lim.gLimRspReqd = false;
6914 
6915 				ret_code = eSIR_SME_STA_NOT_AUTHENTICATED;
6916 				deauth_trigger = eLIM_HOST_DEAUTH;
6917 
6918 				/*
6919 				 * here we received deauth request from AP so
6920 				 * sme state is eLIM_SME_WT_DEAUTH_STATE.if we
6921 				 * have ISSUED delSta then mlm state should be
6922 				 * eLIM_MLM_WT_DEL_STA_RSP_STATE and ifwe got
6923 				 * delBSS rsp then mlm state should be
6924 				 * eLIM_MLM_IDLE_STATE so the below condition
6925 				 * captures the state where delSta not done
6926 				 * and firmware still in connected state.
6927 				 */
6928 				if (session_entry->limSmeState ==
6929 					eLIM_SME_WT_DEAUTH_STATE &&
6930 					session_entry->limMlmState !=
6931 					eLIM_MLM_IDLE_STATE &&
6932 					session_entry->limMlmState !=
6933 					eLIM_MLM_WT_DEL_STA_RSP_STATE)
6934 					ret_code = eSIR_SME_DEAUTH_STATUS;
6935 				goto send_deauth;
6936 			}
6937 			return;
6938 		}
6939 		break;
6940 	case eLIM_AP_ROLE:
6941 		/* Check if MAC address is MLD of the client and
6942 		 * change it to primary link address to send OTA.
6943 		 */
6944 		lim_mlo_sap_validate_and_update_ra(
6945 				session_entry, &sme_deauth_req.peer_macaddr);
6946 		break;
6947 	default:
6948 		pe_err("received unexpected SME_DEAUTH_REQ for role %X",
6949 			GET_LIM_SYSTEM_ROLE(session_entry));
6950 		if (mac_ctx->lim.gLimRspReqd) {
6951 			mac_ctx->lim.gLimRspReqd = false;
6952 			ret_code = eSIR_SME_INVALID_PARAMETERS;
6953 			deauth_trigger = eLIM_HOST_DEAUTH;
6954 			goto send_deauth;
6955 		}
6956 		return;
6957 	} /* end switch (mac_ctx->lim.gLimSystemRole) */
6958 
6959 	if (sme_deauth_req.reasonCode == eLIM_LINK_MONITORING_DEAUTH &&
6960 	    session_entry->limSystemRole == eLIM_STA_ROLE) {
6961 		/* Deauthentication is triggered by Link Monitoring */
6962 		pe_debug("** Lost link with AP **");
6963 		deauth_trigger = eLIM_LINK_MONITORING_DEAUTH;
6964 		reason_code = REASON_UNSPEC_FAILURE;
6965 	} else {
6966 		deauth_trigger = eLIM_HOST_DEAUTH;
6967 		reason_code = sme_deauth_req.reasonCode;
6968 	}
6969 
6970 	/* Trigger Deauthentication frame to peer MAC entity */
6971 	mlm_deauth_req = qdf_mem_malloc(sizeof(tLimMlmDeauthReq));
6972 	if (!mlm_deauth_req) {
6973 		if (mac_ctx->lim.gLimRspReqd) {
6974 			mac_ctx->lim.gLimRspReqd = false;
6975 			ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
6976 			deauth_trigger = eLIM_HOST_DEAUTH;
6977 			goto send_deauth;
6978 		}
6979 		return;
6980 	}
6981 
6982 	qdf_copy_macaddr(&mlm_deauth_req->peer_macaddr,
6983 			 &sme_deauth_req.peer_macaddr);
6984 
6985 	mlm_deauth_req->reasonCode = reason_code;
6986 	mlm_deauth_req->deauthTrigger = deauth_trigger;
6987 
6988 	/* Update PE session Id */
6989 	mlm_deauth_req->sessionId = session_id;
6990 	lim_process_mlm_deauth_req(mac_ctx, (uint32_t *)mlm_deauth_req);
6991 
6992 	return;
6993 
6994 send_deauth:
6995 	lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peer_macaddr.bytes,
6996 				ret_code, deauth_trigger, 1, vdev_id);
6997 }
6998 
6999 /**
7000  * __lim_counter_measures()
7001  *
7002  * FUNCTION:
7003  * This function is called to "implement" MIC counter measure
7004  * and is *temporary* only
7005  *
7006  * LOGIC: on AP, disassoc all STA associated thru TKIP,
7007  * we don't do the proper STA disassoc sequence since the
7008  * BSS will be stopped anyway
7009  *
7010  ***ASSUMPTIONS:
7011  *
7012  ***NOTE:
7013  *
7014  * @param  mac      Pointer to Global MAC structure
7015  * @return None
7016  */
7017 
__lim_counter_measures(struct mac_context * mac,struct pe_session * pe_session)7018 static void __lim_counter_measures(struct mac_context *mac, struct pe_session *pe_session)
7019 {
7020 	tSirMacAddr mac_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
7021 
7022 	if (LIM_IS_AP_ROLE(pe_session))
7023 		lim_send_disassoc_mgmt_frame(mac, REASON_MIC_FAILURE,
7024 					     mac_addr, pe_session, false);
7025 };
7026 
lim_send_stop_bss_failure_resp(struct mac_context * mac_ctx,struct pe_session * session)7027 void lim_send_stop_bss_failure_resp(struct mac_context *mac_ctx,
7028 				    struct pe_session *session)
7029 {
7030 	session->limSmeState = session->limPrevSmeState;
7031 
7032 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, session->peSessionId,
7033 			  session->limSmeState));
7034 	lim_send_stop_bss_response(mac_ctx, session->vdev_id,
7035 				   eSIR_SME_STOP_BSS_FAILURE);
7036 }
7037 
lim_flush_all_peer_from_serialization_queue(struct mac_context * mac_ctx,struct pe_session * session)7038 static void lim_flush_all_peer_from_serialization_queue(
7039 				struct mac_context *mac_ctx,
7040 				struct pe_session *session)
7041 {
7042 	struct wlan_serialization_queued_cmd_info cmd = {0};
7043 	struct wlan_objmgr_vdev *vdev;
7044 
7045 	vdev = session->vdev;
7046 	if (!vdev) {
7047 		pe_err("vdev is null");
7048 		return;
7049 	}
7050 
7051 	pe_debug("vdev id is %d for disconnect/deauth cmd", session->vdev_id);
7052 
7053 	/* Flush any pending NB peer deauth command */
7054 	cmd.vdev = vdev;
7055 	cmd.cmd_type = WLAN_SER_CMD_FORCE_DEAUTH_STA;
7056 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
7057 	cmd.requestor = WLAN_UMAC_COMP_MLME;
7058 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
7059 
7060 	wlan_serialization_cancel_request(&cmd);
7061 
7062 	/* Flush any pending NB peer disassoc command */
7063 	qdf_mem_zero(&cmd, sizeof(cmd));
7064 	cmd.vdev = vdev;
7065 	cmd.cmd_type = WLAN_SER_CMD_FORCE_DISASSOC_STA;
7066 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
7067 	cmd.requestor = WLAN_UMAC_COMP_MLME;
7068 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
7069 
7070 	wlan_serialization_cancel_request(&cmd);
7071 
7072 	/* Flush any pending SB peer deauth/disconnect command */
7073 	qdf_mem_zero(&cmd, sizeof(cmd));
7074 	cmd.vdev = vdev;
7075 	cmd.cmd_type = WLAN_SER_CMD_WM_STATUS_CHANGE;
7076 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
7077 	cmd.requestor = WLAN_UMAC_COMP_MLME;
7078 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
7079 
7080 	wlan_serialization_cancel_request(&cmd);
7081 }
7082 
lim_delete_all_peers(struct pe_session * session)7083 void lim_delete_all_peers(struct pe_session *session)
7084 {
7085 	uint8_t i = 0;
7086 	struct mac_context *mac_ctx = session->mac_ctx;
7087 	tpDphHashNode sta_ds = NULL;
7088 	QDF_STATUS status;
7089 	tSirMacAddr bc_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
7090 
7091 	/* IBSS and NDI doesn't send Disassoc frame */
7092 	if (!LIM_IS_NDI_ROLE(session)) {
7093 		pe_debug("stop_bss_reason: %d", session->stop_bss_reason);
7094 		if (session->stop_bss_reason == eSIR_SME_MIC_COUNTER_MEASURES)
7095 			__lim_counter_measures(mac_ctx, session);
7096 		else
7097 			lim_send_disassoc_mgmt_frame(mac_ctx,
7098 				REASON_DEAUTH_NETWORK_LEAVING,
7099 				bc_addr, session, false);
7100 	}
7101 
7102 	for (i = 1; i < session->dph.dphHashTable.size; i++) {
7103 		sta_ds = dph_get_hash_entry(mac_ctx, i,
7104 					    &session->dph.dphHashTable);
7105 		if (!sta_ds)
7106 			continue;
7107 		lim_mlo_notify_peer_disconn(session, sta_ds);
7108 		status = lim_del_sta(mac_ctx, sta_ds, false, session);
7109 		if (QDF_STATUS_SUCCESS == status) {
7110 			lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr,
7111 						  sta_ds->assocId, session);
7112 			if (lim_is_mlo_conn(session, sta_ds))
7113 				lim_release_mlo_conn_idx(mac_ctx,
7114 							 sta_ds->assocId,
7115 							 session, false);
7116 			else
7117 				lim_release_peer_idx(mac_ctx, sta_ds->assocId,
7118 						     session);
7119 		} else {
7120 			pe_err("lim_del_sta failed with Status: %d", status);
7121 			QDF_ASSERT(0);
7122 		}
7123 	}
7124 
7125 	/**
7126 	 * Scenario: CSA happens and south bound disconnection got queued
7127 	 * in serialization parallelly.
7128 	 * As part of CSA, remove all peer from serialization, so that when
7129 	 * south bound disconnection becomes active, it should not lead to a
7130 	 * race where the peer is trying to connect and the driver is trying
7131 	 * to disconnect the same peer, leading to an active command timeout
7132 	 */
7133 	lim_flush_all_peer_from_serialization_queue(mac_ctx, session);
7134 
7135 	lim_disconnect_complete(session, false);
7136 	if (mac_ctx->del_peers_ind_cb)
7137 		mac_ctx->del_peers_ind_cb(mac_ctx->psoc, session->vdev_id);
7138 }
7139 
lim_sta_send_del_bss(struct pe_session * session)7140 QDF_STATUS lim_sta_send_del_bss(struct pe_session *session)
7141 {
7142 	struct mac_context *mac_ctx = session->mac_ctx;
7143 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
7144 	tpDphHashNode sta_ds = NULL;
7145 
7146 	sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
7147 				    &session->dph.dphHashTable);
7148 	if (!sta_ds) {
7149 		pe_err("DPH Entry for STA is missing, failed to send delbss");
7150 		goto end;
7151 	}
7152 
7153 	status = lim_del_bss(mac_ctx, sta_ds, 0, session);
7154 	if (QDF_IS_STATUS_ERROR(status))
7155 		pe_err("delBss failed for bss %d", session->vdev_id);
7156 
7157 end:
7158 	return status;
7159 }
7160 
lim_send_vdev_stop(struct pe_session * session)7161 QDF_STATUS lim_send_vdev_stop(struct pe_session *session)
7162 {
7163 	struct mac_context *mac_ctx = session->mac_ctx;
7164 	QDF_STATUS status;
7165 
7166 	status = lim_del_bss(mac_ctx, NULL, session->vdev_id, session);
7167 
7168 	if (QDF_IS_STATUS_ERROR(status)) {
7169 		pe_err("delBss failed for bss %d", session->vdev_id);
7170 		lim_send_stop_bss_failure_resp(mac_ctx, session);
7171 	}
7172 
7173 	return status;
7174 }
7175 
7176 /**
7177  * lim_delete_peers_and_send_vdev_stop() -delete peers and send vdev stop
7178  * @session: session pointer
7179  *
7180  * Return None
7181  */
lim_delete_peers_and_send_vdev_stop(struct pe_session * session)7182 static void lim_delete_peers_and_send_vdev_stop(struct pe_session *session)
7183 {
7184 	struct mac_context *mac_ctx = session->mac_ctx;
7185 	QDF_STATUS status;
7186 
7187 	if (QDF_IS_STATUS_SUCCESS(
7188 	    wlan_vdev_is_restart_progress(session->vdev)))
7189 		status =
7190 		 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
7191 					       WLAN_VDEV_SM_EV_RESTART_REQ_FAIL,
7192 					       sizeof(*session), session);
7193 	else
7194 		status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
7195 						       WLAN_VDEV_SM_EV_DOWN,
7196 						       sizeof(*session),
7197 						       session);
7198 	if (QDF_IS_STATUS_ERROR(status))
7199 		lim_send_stop_bss_failure_resp(mac_ctx, session);
7200 }
7201 
7202 static void
__lim_handle_sme_stop_bss_request(struct mac_context * mac,uint32_t * msg_buf)7203 __lim_handle_sme_stop_bss_request(struct mac_context *mac, uint32_t *msg_buf)
7204 {
7205 	struct stop_bss_req stop_bss_req;
7206 	tLimSmeStates prevState;
7207 	struct pe_session *pe_session;
7208 	struct qdf_mac_addr bssid;
7209 	uint8_t vdev_id;
7210 	uint8_t session_id;
7211 
7212 	qdf_mem_copy(&stop_bss_req, msg_buf, sizeof(stop_bss_req));
7213 	vdev_id = stop_bss_req.vdev_id;
7214 	wlan_mlme_get_mac_vdev_id(mac->pdev, vdev_id, &bssid);
7215 
7216 	pe_session = pe_find_session_by_bssid(mac, bssid.bytes,
7217 					       &session_id);
7218 	if (!pe_session) {
7219 		pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT,
7220 		       QDF_MAC_ADDR_REF(bssid.bytes));
7221 		lim_send_stop_bss_response(mac, vdev_id,
7222 					   eSIR_SME_INVALID_PARAMETERS);
7223 		return;
7224 	}
7225 
7226 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
7227 	lim_diag_event_report(mac, WLAN_PE_DIAG_STOP_BSS_REQ_EVENT, pe_session,
7228 			      0, 0);
7229 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
7230 
7231 	if (pe_session->limSmeState != eLIM_SME_NORMAL_STATE ||    /* Added For BT -AMP Support */
7232 	    LIM_IS_STA_ROLE(pe_session)) {
7233 		/**
7234 		 * Should not have received STOP_BSS_REQ in states
7235 		 * other than 'normal' state or on STA in Infrastructure
7236 		 * mode. Log error and return response to host.
7237 		 */
7238 		pe_err("received unexpected SME_STOP_BSS_REQ in state %X, for role %d",
7239 			pe_session->limSmeState,
7240 			GET_LIM_SYSTEM_ROLE(pe_session));
7241 		lim_print_sme_state(mac, LOGE, pe_session->limSmeState);
7242 		/* / Send Stop BSS response to host */
7243 		lim_send_stop_bss_response(mac, vdev_id,
7244 					   eSIR_SME_UNEXPECTED_REQ_RESULT_CODE);
7245 		return;
7246 	}
7247 
7248 	if (LIM_IS_AP_ROLE(pe_session))
7249 		lim_wpspbc_close(mac, pe_session);
7250 
7251 	prevState = pe_session->limSmeState;
7252 	pe_session->limPrevSmeState = prevState;
7253 
7254 	pe_session->limSmeState = eLIM_SME_IDLE_STATE;
7255 	MTRACE(mac_trace
7256 		       (mac, TRACE_CODE_SME_STATE, pe_session->peSessionId,
7257 		       pe_session->limSmeState));
7258 
7259 	pe_session->smeSessionId = vdev_id;
7260 	pe_session->stop_bss_reason = 0;
7261 
7262 	if (!LIM_IS_NDI_ROLE(pe_session)) {
7263 		/* Free the buffer allocated in START_BSS_REQ */
7264 		qdf_mem_free(pe_session->add_ie_params.probeRespData_buff);
7265 		pe_session->add_ie_params.probeRespDataLen = 0;
7266 		pe_session->add_ie_params.probeRespData_buff = NULL;
7267 
7268 		qdf_mem_free(pe_session->add_ie_params.assocRespData_buff);
7269 		pe_session->add_ie_params.assocRespDataLen = 0;
7270 		pe_session->add_ie_params.assocRespData_buff = NULL;
7271 
7272 		qdf_mem_free(pe_session->add_ie_params.probeRespBCNData_buff);
7273 		pe_session->add_ie_params.probeRespBCNDataLen = 0;
7274 		pe_session->add_ie_params.probeRespBCNData_buff = NULL;
7275 	}
7276 
7277 	lim_delete_peers_and_send_vdev_stop(pe_session);
7278 
7279 }
7280 
7281 /**
7282  * __lim_process_sme_stop_bss_req() - Process STOP_BSS from SME
7283  * @mac: Global MAC context
7284  * @pMsg: Message from SME
7285  *
7286  * Wrapper for the function __lim_handle_sme_stop_bss_request
7287  * This message will be deferred until softmac come out of
7288  * scan mode. Message should be handled even if we have
7289  * detected radar in the current operating channel.
7290  *
7291  * Return: true - If we consumed the buffer
7292  *         false - If have deferred the message.
7293  */
7294 
__lim_process_sme_stop_bss_req(struct mac_context * mac,struct scheduler_msg * pMsg)7295 static bool __lim_process_sme_stop_bss_req(struct mac_context *mac,
7296 					   struct scheduler_msg *pMsg)
7297 {
7298 	__lim_handle_sme_stop_bss_request(mac, (uint32_t *) pMsg->bodyptr);
7299 	return true;
7300 } /*** end __lim_process_sme_stop_bss_req() ***/
7301 
lim_process_sme_del_bss_rsp(struct mac_context * mac,struct pe_session * pe_session)7302 void lim_process_sme_del_bss_rsp(struct mac_context *mac,
7303 				 struct pe_session *pe_session)
7304 {
7305 	SET_LIM_PROCESS_DEFD_MESGS(mac, true);
7306 	dph_hash_table_init(mac, &pe_session->dph.dphHashTable);
7307 	lim_delete_pre_auth_list(mac);
7308 	lim_send_stop_bss_response(mac, pe_session->vdev_id,
7309 				   eSIR_SME_SUCCESS);
7310 	return;
7311 }
7312 
7313 /**
7314  * __lim_process_sme_assoc_cnf_new() - process sme assoc/reassoc cnf
7315  *
7316  * @mac_ctx: pointer to mac context
7317  * @msg_type: message type
7318  * @msg_buf: pointer to the SME message buffer
7319  *
7320  * This function handles SME_ASSOC_CNF/SME_REASSOC_CNF
7321  * in BTAMP AP.
7322  *
7323  * Return: None
7324  */
7325 
__lim_process_sme_assoc_cnf_new(struct mac_context * mac_ctx,uint32_t msg_type,uint32_t * msg_buf)7326 void __lim_process_sme_assoc_cnf_new(struct mac_context *mac_ctx, uint32_t msg_type,
7327 				uint32_t *msg_buf)
7328 {
7329 	struct assoc_cnf assoc_cnf;
7330 	tpDphHashNode sta_ds = NULL;
7331 	struct pe_session *session_entry = NULL;
7332 	uint8_t session_id;
7333 	tpSirAssocReq assoc_req;
7334 
7335 	if (!msg_buf) {
7336 		pe_err("msg_buf is NULL");
7337 		return;
7338 	}
7339 
7340 	qdf_mem_copy(&assoc_cnf, msg_buf, sizeof(assoc_cnf));
7341 	if (!__lim_is_sme_assoc_cnf_valid(&assoc_cnf)) {
7342 		pe_err("Received invalid SME_RE(ASSOC)_CNF message");
7343 		goto end;
7344 	}
7345 
7346 	session_entry = pe_find_session_by_bssid(mac_ctx, assoc_cnf.bssid.bytes,
7347 			&session_id);
7348 	if (!session_entry) {
7349 		pe_err("session does not exist for given bssId");
7350 		goto end;
7351 	}
7352 
7353 	if ((!LIM_IS_AP_ROLE(session_entry)) ||
7354 	    (session_entry->limSmeState != eLIM_SME_NORMAL_STATE)) {
7355 		pe_err("Rcvd unexpected msg %X in state %X, in role %X",
7356 			msg_type, session_entry->limSmeState,
7357 			GET_LIM_SYSTEM_ROLE(session_entry));
7358 		goto end;
7359 	}
7360 	sta_ds = dph_get_hash_entry(mac_ctx, assoc_cnf.aid,
7361 			&session_entry->dph.dphHashTable);
7362 	if (!sta_ds) {
7363 		pe_err("Rcvd invalid msg %X due to no STA ctx, aid %d, peer "QDF_MAC_ADDR_FMT,
7364 		       msg_type, assoc_cnf.aid,
7365 		       QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes));
7366 
7367 		/*
7368 		 * send a DISASSOC_IND message to WSM to make sure
7369 		 * the state in WSM and LIM is the same
7370 		 */
7371 		lim_send_sme_disassoc_ntf(mac_ctx, assoc_cnf.peer_macaddr.bytes,
7372 				eSIR_SME_STA_NOT_ASSOCIATED,
7373 				eLIM_PEER_ENTITY_DISASSOC, assoc_cnf.aid,
7374 				session_entry->smeSessionId,
7375 				session_entry);
7376 		goto end;
7377 	}
7378 	if (qdf_mem_cmp((uint8_t *)sta_ds->staAddr,
7379 				(uint8_t *) assoc_cnf.peer_macaddr.bytes,
7380 				QDF_MAC_ADDR_SIZE)) {
7381 		pe_debug("peerMacAddr mismatched for aid %d, peer "QDF_MAC_ADDR_FMT,
7382 			 assoc_cnf.aid,
7383 			 QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes));
7384 		goto end;
7385 	}
7386 
7387 	if ((sta_ds->mlmStaContext.mlmState != eLIM_MLM_WT_ASSOC_CNF_STATE) ||
7388 		((sta_ds->mlmStaContext.subType == LIM_ASSOC) &&
7389 		 (msg_type != eWNI_SME_ASSOC_CNF)) ||
7390 		((sta_ds->mlmStaContext.subType == LIM_REASSOC) &&
7391 		 (msg_type != eWNI_SME_ASSOC_CNF))) {
7392 		pe_debug("peer " QDF_MAC_ADDR_FMT " not in WT_ASSOC_CNF_STATE, for aid %d, sta mlmstate %d",
7393 			 QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes),
7394 			 assoc_cnf.aid, sta_ds->mlmStaContext.mlmState);
7395 		goto end;
7396 	}
7397 	/*
7398 	 * Deactivate/delete CNF_WAIT timer since ASSOC_CNF
7399 	 * has been received
7400 	 */
7401 	pe_debug("Received SME_ASSOC_CNF. Delete Timer");
7402 	lim_deactivate_and_change_per_sta_id_timer(mac_ctx,
7403 			eLIM_CNF_WAIT_TIMER, sta_ds->assocId);
7404 
7405 	if (assoc_cnf.status_code == eSIR_SME_SUCCESS) {
7406 		/*
7407 		 * In BTAMP-AP, PE already finished the WMA_ADD_STA sequence
7408 		 * when it had received Assoc Request frame. Now, PE just needs
7409 		 * to send association rsp frame to the requesting BTAMP-STA.
7410 		 */
7411 		sta_ds->mlmStaContext.mlmState =
7412 			eLIM_MLM_LINK_ESTABLISHED_STATE;
7413 		sta_ds->mlmStaContext.owe_ie = assoc_cnf.owe_ie;
7414 		sta_ds->mlmStaContext.owe_ie_len = assoc_cnf.owe_ie_len;
7415 		sta_ds->mlmStaContext.ft_ie = assoc_cnf.ft_ie;
7416 		sta_ds->mlmStaContext.ft_ie_len = assoc_cnf.ft_ie_len;
7417 		pe_debug("sending Assoc Rsp frame to STA assoc id=%d, tx cb %d",
7418 			 sta_ds->assocId, assoc_cnf.need_assoc_rsp_tx_cb);
7419 		lim_send_assoc_rsp_mgmt_frame(
7420 					mac_ctx, QDF_STATUS_SUCCESS,
7421 					sta_ds->assocId, sta_ds->staAddr,
7422 					sta_ds->mlmStaContext.subType, sta_ds,
7423 					session_entry,
7424 					assoc_cnf.need_assoc_rsp_tx_cb);
7425 		sta_ds->mlmStaContext.owe_ie = NULL;
7426 		sta_ds->mlmStaContext.owe_ie_len = 0;
7427 		sta_ds->mlmStaContext.ft_ie = NULL;
7428 		sta_ds->mlmStaContext.ft_ie_len = 0;
7429 		goto end;
7430 	} else {
7431 		uint8_t add_pre_auth_context = true;
7432 		/*
7433 		 * SME_ASSOC_CNF status is non-success, so STA is not allowed
7434 		 * to be associated since the HAL sta entry is created for
7435 		 * denied STA we need to remove this HAL entry.
7436 		 * So to do that set updateContext to 1
7437 		 */
7438 		enum wlan_status_code mac_status_code =
7439 					STATUS_UNSPECIFIED_FAILURE;
7440 
7441 		if (!sta_ds->mlmStaContext.updateContext)
7442 			sta_ds->mlmStaContext.updateContext = 1;
7443 		pe_debug("Recv Assoc Cnf, status Code : %d(assoc id=%d) Reason code: %d",
7444 			 assoc_cnf.status_code, sta_ds->assocId,
7445 			 assoc_cnf.mac_status_code);
7446 		if (assoc_cnf.mac_status_code)
7447 			mac_status_code = assoc_cnf.mac_status_code;
7448 		if (assoc_cnf.mac_status_code == STATUS_INVALID_PMKID ||
7449 		    assoc_cnf.mac_status_code ==
7450 			STATUS_NOT_SUPPORTED_AUTH_ALG)
7451 			add_pre_auth_context = false;
7452 
7453 		lim_reject_association(mac_ctx, sta_ds->staAddr,
7454 				       sta_ds->mlmStaContext.subType,
7455 				       add_pre_auth_context,
7456 				       sta_ds->mlmStaContext.authType,
7457 				       sta_ds->assocId, true,
7458 				       mac_status_code,
7459 				       session_entry);
7460 	}
7461 end:
7462 	if (((session_entry) && (sta_ds)) &&
7463 		(session_entry->parsedAssocReq[sta_ds->assocId]) &&
7464 		!assoc_cnf.need_assoc_rsp_tx_cb) {
7465 		assoc_req = (tpSirAssocReq)
7466 			session_entry->parsedAssocReq[sta_ds->assocId];
7467 		lim_free_assoc_req_frm_buf(assoc_req);
7468 		qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
7469 		session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
7470 	}
7471 	qdf_mem_free(assoc_cnf.owe_ie);
7472 	qdf_mem_free(assoc_cnf.ft_ie);
7473 }
7474 
7475 static void
__lim_process_sme_addts_req(struct mac_context * mac,uint32_t * msg_buf)7476 __lim_process_sme_addts_req(struct mac_context *mac, uint32_t *msg_buf)
7477 {
7478 	tpDphHashNode sta;
7479 	tSirMacAddr peerMac;
7480 	tpSirAddtsReq pSirAddts;
7481 	uint32_t timeout;
7482 	struct pe_session *pe_session;
7483 	uint8_t sessionId;      /* PE sessionId */
7484 	uint8_t smesessionId;
7485 
7486 	if (!msg_buf) {
7487 		pe_err("Buffer is Pointing to NULL");
7488 		return;
7489 	}
7490 
7491 	pSirAddts = (tpSirAddtsReq) msg_buf;
7492 	smesessionId = pSirAddts->sessionId;
7493 	pe_session = pe_find_session_by_bssid(mac, pSirAddts->bssid.bytes,
7494 						 &sessionId);
7495 	if (!pe_session) {
7496 		pe_err("Session Does not exist for given bssId");
7497 		lim_send_sme_addts_rsp(mac, pSirAddts->rspReqd,
7498 				       QDF_STATUS_E_FAILURE,
7499 				       NULL, pSirAddts->req.tspec,
7500 				       smesessionId);
7501 		return;
7502 	}
7503 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
7504 	lim_diag_event_report(mac, WLAN_PE_DIAG_ADDTS_REQ_EVENT, pe_session, 0,
7505 			      0);
7506 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
7507 
7508 	/* if sta
7509 	 *  - verify assoc state
7510 	 *  - send addts request to ap
7511 	 *  - wait for addts response from ap
7512 	 * if ap, just ignore with error log
7513 	 */
7514 	pe_debug("Received SME_ADDTS_REQ (TSid %d, UP %d)",
7515 		pSirAddts->req.tspec.tsinfo.traffic.tsid,
7516 		pSirAddts->req.tspec.tsinfo.traffic.userPrio);
7517 
7518 	if (!LIM_IS_STA_ROLE(pe_session)) {
7519 		pe_err("AddTs received on AP - ignoring");
7520 		goto send_failure_addts_rsp;
7521 	}
7522 
7523 	sta =
7524 		dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
7525 				   &pe_session->dph.dphHashTable);
7526 
7527 	if (!sta) {
7528 		pe_err("Cannot find AP context for addts req");
7529 		goto send_failure_addts_rsp;
7530 	}
7531 
7532 	if ((!sta->valid) || (sta->mlmStaContext.mlmState !=
7533 	    eLIM_MLM_LINK_ESTABLISHED_STATE)) {
7534 		pe_err("AddTs received in invalid MLM state");
7535 		goto send_failure_addts_rsp;
7536 	}
7537 
7538 	pSirAddts->req.wsmTspecPresent = 0;
7539 	pSirAddts->req.wmeTspecPresent = 0;
7540 	pSirAddts->req.lleTspecPresent = 0;
7541 
7542 	if ((sta->wsmEnabled) &&
7543 	    (pSirAddts->req.tspec.tsinfo.traffic.accessPolicy !=
7544 	     SIR_MAC_ACCESSPOLICY_EDCA))
7545 		pSirAddts->req.wsmTspecPresent = 1;
7546 	else if (sta->wmeEnabled)
7547 		pSirAddts->req.wmeTspecPresent = 1;
7548 	else if (sta->lleEnabled)
7549 		pSirAddts->req.lleTspecPresent = 1;
7550 	else {
7551 		pe_warn("ADDTS_REQ ignore - qos is disabled");
7552 		goto send_failure_addts_rsp;
7553 	}
7554 
7555 	if ((pe_session->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
7556 	    (pe_session->limSmeState != eLIM_SME_LINK_EST_STATE)) {
7557 		pe_err("AddTs received in invalid LIMsme state (%d)",
7558 			pe_session->limSmeState);
7559 		goto send_failure_addts_rsp;
7560 	}
7561 
7562 	if (mac->lim.gLimAddtsSent) {
7563 		pe_err("Addts (token %d, tsid %d, up %d) is still pending",
7564 			mac->lim.gLimAddtsReq.req.dialogToken,
7565 			mac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid,
7566 			mac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.
7567 			userPrio);
7568 		goto send_failure_addts_rsp;
7569 	}
7570 
7571 	sir_copy_mac_addr(peerMac, pe_session->bssId);
7572 
7573 	/* save the addts request */
7574 	mac->lim.gLimAddtsSent = true;
7575 	qdf_mem_copy((uint8_t *) &mac->lim.gLimAddtsReq,
7576 		     (uint8_t *) pSirAddts, sizeof(tSirAddtsReq));
7577 
7578 	/* ship out the message now */
7579 	lim_send_addts_req_action_frame(mac, peerMac, &pSirAddts->req,
7580 					pe_session);
7581 	pe_debug("Sent ADDTS request");
7582 	/* start a timer to wait for the response */
7583 	if (pSirAddts->timeout)
7584 		timeout = pSirAddts->timeout;
7585 	else
7586 		timeout = mac->mlme_cfg->timeouts.addts_rsp_timeout;
7587 
7588 	timeout = SYS_MS_TO_TICKS(timeout);
7589 	if (tx_timer_change(&mac->lim.lim_timers.gLimAddtsRspTimer, timeout, 0)
7590 	    != TX_SUCCESS) {
7591 		pe_err("AddtsRsp timer change failed!");
7592 		goto send_failure_addts_rsp;
7593 	}
7594 	mac->lim.gLimAddtsRspTimerCount++;
7595 	if (tx_timer_change_context(&mac->lim.lim_timers.gLimAddtsRspTimer,
7596 				    mac->lim.gLimAddtsRspTimerCount) !=
7597 	    TX_SUCCESS) {
7598 		pe_err("AddtsRsp timer change failed!");
7599 		goto send_failure_addts_rsp;
7600 	}
7601 	MTRACE(mac_trace
7602 		       (mac, TRACE_CODE_TIMER_ACTIVATE, pe_session->peSessionId,
7603 		       eLIM_ADDTS_RSP_TIMER));
7604 
7605 	/* add the sessionId to the timer object */
7606 	mac->lim.lim_timers.gLimAddtsRspTimer.sessionId = sessionId;
7607 	if (tx_timer_activate(&mac->lim.lim_timers.gLimAddtsRspTimer) !=
7608 	    TX_SUCCESS) {
7609 		pe_err("AddtsRsp timer activation failed!");
7610 		goto send_failure_addts_rsp;
7611 	}
7612 	return;
7613 
7614 send_failure_addts_rsp:
7615 	lim_send_sme_addts_rsp(mac, pSirAddts->rspReqd, QDF_STATUS_E_FAILURE,
7616 			       pe_session, pSirAddts->req.tspec,
7617 			       smesessionId);
7618 }
7619 
7620 #ifdef WLAN_FEATURE_MSCS
7621 static void
__lim_process_sme_mscs_req(struct mac_context * mac,uint32_t * msg_buf)7622 __lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf)
7623 {
7624 	struct qdf_mac_addr peer_mac;
7625 	struct mscs_req_info *mscs_req;
7626 	struct pe_session *pe_session;
7627 	uint8_t pe_session_id;
7628 
7629 	if (!msg_buf) {
7630 		pe_err("Buffer is Pointing to NULL");
7631 		return;
7632 	}
7633 
7634 	mscs_req = (struct mscs_req_info *) msg_buf;
7635 	pe_session = pe_find_session_by_bssid(mac, mscs_req->bssid.bytes,
7636 					      &pe_session_id);
7637 	if (!pe_session) {
7638 		pe_err("Session Does not exist for bssid: " QDF_MAC_ADDR_FMT,
7639 			QDF_MAC_ADDR_REF(mscs_req->bssid.bytes));
7640 		return;
7641 	}
7642 
7643 	if (!LIM_IS_STA_ROLE(pe_session)) {
7644 		pe_err("MSCS req received on AP - ignoring");
7645 		return;
7646 	}
7647 
7648 	if (QDF_IS_STATUS_ERROR(wlan_vdev_mlme_is_active(pe_session->vdev))) {
7649 		pe_err("mscs req in unexpected vdev SM state:%d",
7650 		       wlan_vdev_mlme_get_state(pe_session->vdev));
7651 		return;
7652 	}
7653 
7654 	if (mscs_req->is_mscs_req_sent) {
7655 		pe_err("MSCS req already sent");
7656 		return;
7657 	}
7658 
7659 	qdf_mem_copy(peer_mac.bytes, pe_session->bssId, QDF_MAC_ADDR_SIZE);
7660 
7661 	/* save the mscs request */
7662 	mscs_req->is_mscs_req_sent = true;
7663 
7664 	/* ship out the message now */
7665 	lim_send_mscs_req_action_frame(mac, peer_mac, mscs_req,
7666 				       pe_session);
7667 }
7668 #else
7669 static inline void
__lim_process_sme_mscs_req(struct mac_context * mac,uint32_t * msg_buf)7670 __lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf)
7671 {
7672 	return;
7673 }
7674 
7675 #endif
7676 
7677 static void
__lim_process_sme_delts_req(struct mac_context * mac,uint32_t * msg_buf)7678 __lim_process_sme_delts_req(struct mac_context *mac, uint32_t *msg_buf)
7679 {
7680 	tSirMacAddr peerMacAddr;
7681 	uint8_t ac;
7682 	struct mac_ts_info *pTsinfo;
7683 	tpSirDeltsReq pDeltsReq = (tpSirDeltsReq) msg_buf;
7684 	tpDphHashNode sta = NULL;
7685 	struct pe_session *pe_session;
7686 	uint8_t sessionId;
7687 	uint32_t status = QDF_STATUS_SUCCESS;
7688 	uint8_t smesessionId;
7689 
7690 	smesessionId = pDeltsReq->sessionId;
7691 
7692 	pe_session = pe_find_session_by_bssid(mac,
7693 				pDeltsReq->bssid.bytes,
7694 				&sessionId);
7695 	if (!pe_session) {
7696 		pe_err("Session Does not exist for given bssId");
7697 		status = QDF_STATUS_E_FAILURE;
7698 		goto end;
7699 	}
7700 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
7701 	lim_diag_event_report(mac, WLAN_PE_DIAG_DELTS_REQ_EVENT, pe_session, 0,
7702 			      0);
7703 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
7704 
7705 	if (QDF_STATUS_SUCCESS !=
7706 	    lim_validate_delts_req(mac, pDeltsReq, peerMacAddr, pe_session)) {
7707 		pe_err("lim_validate_delts_req failed");
7708 		status = QDF_STATUS_E_FAILURE;
7709 		lim_send_sme_delts_rsp(mac, pDeltsReq, QDF_STATUS_E_FAILURE,
7710 				       pe_session, smesessionId);
7711 		return;
7712 	}
7713 
7714 	pe_debug("Sent DELTS request to station with assocId = %d MacAddr = "
7715 		QDF_MAC_ADDR_FMT,
7716 		pDeltsReq->aid, QDF_MAC_ADDR_REF(peerMacAddr));
7717 
7718 	lim_send_delts_req_action_frame(mac, peerMacAddr,
7719 					pDeltsReq->req.wmeTspecPresent,
7720 					&pDeltsReq->req.tsinfo,
7721 					&pDeltsReq->req.tspec, pe_session);
7722 
7723 	pTsinfo =
7724 		pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.
7725 		tsinfo : &pDeltsReq->req.tsinfo;
7726 
7727 	/* We've successfully send DELTS frame to AP. Update the
7728 	 * dynamic UAPSD mask. The AC for this TSPEC to be deleted
7729 	 * is no longer trigger enabled or delivery enabled
7730 	 */
7731 	lim_set_tspec_uapsd_mask_per_session(mac, pe_session,
7732 					     pTsinfo, CLEAR_UAPSD_MASK);
7733 
7734 	/* We're deleting the TSPEC, so this particular AC is no longer
7735 	 * admitted.  PE needs to downgrade the EDCA
7736 	 * parameters(for the AC for which TS is being deleted) to the
7737 	 * next best AC for which ACM is not enabled, and send the
7738 	 * updated values to HAL.
7739 	 */
7740 	ac = upToAc(pTsinfo->traffic.userPrio);
7741 
7742 	if (pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) {
7743 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
7744 			~(1 << ac);
7745 	} else if (pTsinfo->traffic.direction ==
7746 		   SIR_MAC_DIRECTION_DNLINK) {
7747 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
7748 			~(1 << ac);
7749 	} else if (pTsinfo->traffic.direction ==
7750 		   SIR_MAC_DIRECTION_BIDIR) {
7751 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
7752 			~(1 << ac);
7753 		pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
7754 			~(1 << ac);
7755 	}
7756 
7757 	lim_set_active_edca_params(mac, pe_session->gLimEdcaParams,
7758 				   pe_session);
7759 
7760 	sta =
7761 		dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER,
7762 				   &pe_session->dph.dphHashTable);
7763 	if (sta) {
7764 		lim_send_edca_params(mac, pe_session->gLimEdcaParamsActive,
7765 				     pe_session->vdev_id, false);
7766 		status = QDF_STATUS_SUCCESS;
7767 	} else {
7768 		pe_err("Self entry missing in Hash Table");
7769 		status = QDF_STATUS_E_FAILURE;
7770 	}
7771 #ifdef FEATURE_WLAN_ESE
7772 	lim_send_sme_tsm_ie_ind(mac, pe_session, 0, 0, 0);
7773 #endif
7774 
7775 	/* send an sme response back */
7776 end:
7777 	lim_send_sme_delts_rsp(mac, pDeltsReq, QDF_STATUS_SUCCESS, pe_session,
7778 			       smesessionId);
7779 }
7780 
lim_process_sme_addts_rsp_timeout(struct mac_context * mac,uint32_t param)7781 void lim_process_sme_addts_rsp_timeout(struct mac_context *mac, uint32_t param)
7782 {
7783 	/* fetch the pe_session based on the sessionId */
7784 	struct pe_session *pe_session;
7785 
7786 	pe_session = pe_find_session_by_session_id(mac,
7787 				mac->lim.lim_timers.gLimAddtsRspTimer.
7788 				sessionId);
7789 	if (!pe_session) {
7790 		pe_err("Session Does not exist for given sessionID");
7791 		return;
7792 	}
7793 
7794 	if (!LIM_IS_STA_ROLE(pe_session)) {
7795 		pe_warn("AddtsRspTimeout in non-Sta role (%d)",
7796 			GET_LIM_SYSTEM_ROLE(pe_session));
7797 		mac->lim.gLimAddtsSent = false;
7798 		return;
7799 	}
7800 
7801 	if (!mac->lim.gLimAddtsSent) {
7802 		pe_warn("AddtsRspTimeout but no AddtsSent");
7803 		return;
7804 	}
7805 
7806 	if (param != mac->lim.gLimAddtsRspTimerCount) {
7807 		pe_err("Invalid AddtsRsp Timer count %d (exp %d)", param,
7808 			mac->lim.gLimAddtsRspTimerCount);
7809 		return;
7810 	}
7811 	/* this a real response timeout */
7812 	mac->lim.gLimAddtsSent = false;
7813 	mac->lim.gLimAddtsRspTimerCount++;
7814 
7815 	lim_send_sme_addts_rsp(mac, true, eSIR_SME_ADDTS_RSP_TIMEOUT,
7816 			       pe_session, mac->lim.gLimAddtsReq.req.tspec,
7817 			       pe_session->smeSessionId);
7818 }
7819 
7820 #ifdef FEATURE_WLAN_ESE
7821 /**
7822  * __lim_process_sme_get_tsm_stats_request() - get tsm stats request
7823  *
7824  * @mac: Pointer to Global MAC structure
7825  * @msg_buf: A pointer to the SME message buffer
7826  *
7827  * Return: None
7828  */
__lim_process_sme_get_tsm_stats_request(struct mac_context * mac,uint32_t * msg_buf)7829 static void __lim_process_sme_get_tsm_stats_request(struct mac_context *mac,
7830 						    uint32_t *msg_buf)
7831 {
7832 	struct scheduler_msg msgQ = {0};
7833 
7834 	msgQ.type = WMA_TSM_STATS_REQ;
7835 	msgQ.reserved = 0;
7836 	msgQ.bodyptr = msg_buf;
7837 	msgQ.bodyval = 0;
7838 	MTRACE(mac_trace_msg_tx(mac, NO_SESSION, msgQ.type));
7839 
7840 	if (QDF_STATUS_SUCCESS != (wma_post_ctrl_msg(mac, &msgQ))) {
7841 		qdf_mem_free(msg_buf);
7842 		msg_buf = NULL;
7843 		pe_err("Unable to forward request");
7844 		return;
7845 	}
7846 }
7847 #endif /* FEATURE_WLAN_ESE */
7848 
lim_process_sme_set_addba_accept(struct mac_context * mac_ctx,struct sme_addba_accept * msg)7849 static void lim_process_sme_set_addba_accept(struct mac_context *mac_ctx,
7850 		struct sme_addba_accept *msg)
7851 {
7852 	if (!msg) {
7853 		pe_err("Msg Buffer is NULL");
7854 		return;
7855 	}
7856 	if (!msg->addba_accept)
7857 		mac_ctx->reject_addba_req = 1;
7858 	else
7859 		mac_ctx->reject_addba_req = 0;
7860 }
7861 
lim_process_sme_update_edca_params(struct mac_context * mac_ctx,uint32_t vdev_id)7862 static void lim_process_sme_update_edca_params(struct mac_context *mac_ctx,
7863 					       uint32_t vdev_id)
7864 {
7865 	struct pe_session *pe_session;
7866 	tpDphHashNode sta_ds_ptr;
7867 
7868 	pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7869 	if (!pe_session) {
7870 		pe_err("Session does not exist: vdev_id %d", vdev_id);
7871 		return;
7872 	}
7873 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_BE].no_ack =
7874 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BE];
7875 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_BK].no_ack =
7876 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BK];
7877 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_VI].no_ack =
7878 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VI];
7879 	pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_VO].no_ack =
7880 		mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VO];
7881 	sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
7882 					&pe_session->dph.dphHashTable);
7883 	if (sta_ds_ptr)
7884 		lim_send_edca_params(mac_ctx,
7885 				     pe_session->gLimEdcaParamsActive,
7886 				     pe_session->vdev_id, false);
7887 	else
7888 		pe_err("Self entry missing in Hash Table");
7889 }
7890 
7891 /**
7892  * lim_process_sme_update_session_edca_txq_params()
7893  * Update the edca tx queue parameters for the vdev
7894  *
7895  * @mac_ctx: Pointer to Global MAC structure
7896  * @msg_buf: Pointer to SME message buffer
7897  *
7898  * Return: None
7899  */
7900 static void
lim_process_sme_update_session_edca_txq_params(struct mac_context * mac_ctx,uint32_t * msg_buf)7901 lim_process_sme_update_session_edca_txq_params(struct mac_context *mac_ctx,
7902 					       uint32_t *msg_buf)
7903 {
7904 	struct sir_update_session_txq_edca_param *msg;
7905 	struct pe_session *pe_session;
7906 	uint8_t ac;
7907 
7908 	if (!msg_buf) {
7909 		pe_err("Buffer is Pointing to NULL");
7910 		return;
7911 	}
7912 
7913 	msg = (struct sir_update_session_txq_edca_param *)msg_buf;
7914 
7915 	pe_session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
7916 	if (!pe_session) {
7917 		pe_warn("Session does not exist for given vdev_id %d",
7918 			msg->vdev_id);
7919 		return;
7920 	}
7921 
7922 	ac = msg->txq_edca_params.aci.aci;
7923 	pe_debug("received SME Session tx queue update for vdev %d queue %d",
7924 		 msg->vdev_id, ac);
7925 
7926 	if ((!LIM_IS_AP_ROLE(pe_session)) ||
7927 	    (pe_session->limSmeState != eLIM_SME_NORMAL_STATE)) {
7928 		pe_err("Rcvd edca update req in state %X, in role %X",
7929 		       pe_session->limSmeState,
7930 		       GET_LIM_SYSTEM_ROLE(pe_session));
7931 		return;
7932 	}
7933 
7934 	pe_session->gLimEdcaParams[ac].cw.min =
7935 			msg->txq_edca_params.cw.min;
7936 	pe_session->gLimEdcaParams[ac].cw.max =
7937 			msg->txq_edca_params.cw.max;
7938 	pe_session->gLimEdcaParams[ac].aci.aci =
7939 			msg->txq_edca_params.aci.aci;
7940 	pe_session->gLimEdcaParams[ac].aci.aifsn =
7941 			msg->txq_edca_params.aci.aifsn;
7942 	pe_session->gLimEdcaParams[ac].txoplimit =
7943 			msg->txq_edca_params.txoplimit;
7944 
7945 	lim_send_edca_params(mac_ctx,
7946 			     pe_session->gLimEdcaParams,
7947 			     pe_session->vdev_id, false);
7948 }
7949 
lim_process_sme_update_mu_edca_params(struct mac_context * mac_ctx,uint32_t vdev_id)7950 static void lim_process_sme_update_mu_edca_params(struct mac_context *mac_ctx,
7951 						  uint32_t vdev_id)
7952 {
7953 	struct pe_session *pe_session;
7954 	tpDphHashNode sta_ds_ptr;
7955 
7956 	pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
7957 	if (!pe_session) {
7958 		pe_err("Session does not exist: vdev_id %d", vdev_id);
7959 		return;
7960 	}
7961 	sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
7962 					&pe_session->dph.dphHashTable);
7963 	if (sta_ds_ptr)
7964 		lim_send_edca_params(mac_ctx, mac_ctx->usr_mu_edca_params,
7965 				     pe_session->vdev_id, true);
7966 	else
7967 		pe_err("Self entry missing in Hash Table");
7968 }
7969 
7970 static void
lim_process_sme_cfg_action_frm_in_tb_ppdu(struct mac_context * mac_ctx,struct sir_cfg_action_frm_tb_ppdu * msg)7971 lim_process_sme_cfg_action_frm_in_tb_ppdu(struct mac_context *mac_ctx,
7972 					  struct  sir_cfg_action_frm_tb_ppdu
7973 					  *msg)
7974 {
7975 	if (!msg) {
7976 		pe_err("Buffer is NULL");
7977 		return;
7978 	}
7979 
7980 	lim_send_action_frm_tb_ppdu_cfg(mac_ctx, msg->vdev_id, msg->cfg);
7981 }
7982 
7983 static void
lim_process_sme_send_vdev_pause(struct mac_context * mac_ctx,struct sme_vdev_pause * msg)7984 lim_process_sme_send_vdev_pause(struct mac_context *mac_ctx,
7985 				struct sme_vdev_pause *msg)
7986 {
7987 	struct pe_session *session;
7988 	uint16_t vdev_pause_dur_ms;
7989 
7990 	if (!msg) {
7991 		pe_err("Buffer is NULL");
7992 		return;
7993 	}
7994 
7995 	session = pe_find_session_by_vdev_id(mac_ctx, msg->session_id);
7996 	if (!session) {
7997 		pe_warn("Session does not exist for given BSSID");
7998 		return;
7999 	}
8000 
8001 	if (!(wlan_vdev_mlme_get_opmode(session->vdev) == QDF_STA_MODE) &&
8002 	    wlan_vdev_mlme_is_mlo_vdev(session->vdev)) {
8003 		pe_err("vdev is not ML STA");
8004 		return;
8005 	}
8006 
8007 	vdev_pause_dur_ms = session->beaconParams.beaconInterval *
8008 						msg->vdev_pause_duration;
8009 	wlan_mlo_send_vdev_pause(mac_ctx->psoc, session->vdev,
8010 				 msg->session_id, vdev_pause_dur_ms);
8011 }
8012 
lim_process_sme_update_config(struct mac_context * mac_ctx,struct update_config * msg)8013 static void lim_process_sme_update_config(struct mac_context *mac_ctx,
8014 					  struct update_config *msg)
8015 {
8016 	struct pe_session *pe_session;
8017 
8018 	pe_debug("received eWNI_SME_UPDATE_HT_CONFIG message");
8019 	if (!msg) {
8020 		pe_err("Buffer is Pointing to NULL");
8021 		return;
8022 	}
8023 
8024 	pe_session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
8025 	if (!pe_session) {
8026 		pe_warn("Session does not exist for given BSSID");
8027 		return;
8028 	}
8029 
8030 	switch (msg->capab) {
8031 	case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
8032 		pe_session->ht_config.adv_coding_cap = msg->value;
8033 		break;
8034 	case WNI_CFG_HT_CAP_INFO_TX_STBC:
8035 		pe_session->ht_config.tx_stbc = msg->value;
8036 		break;
8037 	case WNI_CFG_HT_CAP_INFO_RX_STBC:
8038 		pe_session->ht_config.rx_stbc = msg->value;
8039 		break;
8040 	case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
8041 		pe_session->ht_config.short_gi_20_mhz = msg->value;
8042 		break;
8043 	case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
8044 		pe_session->ht_config.short_gi_40_mhz = msg->value;
8045 		break;
8046 	}
8047 
8048 	if (LIM_IS_AP_ROLE(pe_session)) {
8049 		sch_set_fixed_beacon_fields(mac_ctx, pe_session);
8050 		lim_send_beacon_ind(mac_ctx, pe_session, REASON_CONFIG_UPDATE);
8051 	}
8052 }
8053 
8054 void
lim_send_vdev_restart(struct mac_context * mac,struct pe_session * pe_session,uint8_t sessionId)8055 lim_send_vdev_restart(struct mac_context *mac,
8056 		      struct pe_session *pe_session, uint8_t sessionId)
8057 {
8058 	struct vdev_mlme_obj *mlme_obj;
8059 
8060 	if (!pe_session) {
8061 		pe_err("Invalid parameters");
8062 		return;
8063 	}
8064 
8065 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
8066 	if (!mlme_obj) {
8067 		pe_err("vdev component object is NULL");
8068 		return;
8069 	}
8070 
8071 	mlme_obj->mgmt.ap.hidden_ssid = pe_session->ssidHidden ? true : false;
8072 
8073 	vdev_mgr_start_send(mlme_obj,  true);
8074 }
8075 
lim_handle_update_ssid_hidden(struct mac_context * mac_ctx,struct pe_session * session,uint8_t ssid_hidden)8076 static void lim_handle_update_ssid_hidden(struct mac_context *mac_ctx,
8077 				struct pe_session *session, uint8_t ssid_hidden)
8078 {
8079 	pe_debug("rcvd HIDE_SSID message old HIDE_SSID: %d new HIDE_SSID: %d",
8080 			session->ssidHidden, ssid_hidden);
8081 
8082 	if (ssid_hidden != session->ssidHidden) {
8083 		session->ssidHidden = ssid_hidden;
8084 	} else {
8085 		pe_debug("Dont process HIDE_SSID msg with existing setting");
8086 		return;
8087 	}
8088 
8089 	ap_mlme_set_hidden_ssid_restart_in_progress(session->vdev, true);
8090 	wlan_vdev_mlme_sm_deliver_evt(session->vdev,
8091 				      WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
8092 				      sizeof(*session), session);
8093 }
8094 
8095 /**
8096  * __lim_process_sme_session_update - process SME session update msg
8097  *
8098  * @mac_ctx: Pointer to global mac context
8099  * @msg_buf: Pointer to the received message buffer
8100  *
8101  * Return: None
8102  */
__lim_process_sme_session_update(struct mac_context * mac_ctx,uint32_t * msg_buf)8103 static void __lim_process_sme_session_update(struct mac_context *mac_ctx,
8104 						uint32_t *msg_buf)
8105 {
8106 	struct sir_update_session_param *msg;
8107 	struct pe_session *session;
8108 
8109 	if (!msg_buf) {
8110 		pe_err("Buffer is Pointing to NULL");
8111 		return;
8112 	}
8113 
8114 	msg = (struct sir_update_session_param *) msg_buf;
8115 
8116 	session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id);
8117 	if (!session) {
8118 		pe_warn("Session does not exist for given vdev_id %d",
8119 			msg->vdev_id);
8120 		return;
8121 	}
8122 
8123 	pe_debug("received SME Session update for %d val %d",
8124 			msg->param_type, msg->param_val);
8125 	switch (msg->param_type) {
8126 	case SIR_PARAM_SSID_HIDDEN:
8127 		lim_handle_update_ssid_hidden(mac_ctx, session, msg->param_val);
8128 		break;
8129 	default:
8130 		pe_err("Unknown session param");
8131 		break;
8132 	}
8133 }
8134 
8135 /*
8136    Update the beacon Interval dynamically if beaconInterval is different in MCC
8137  */
__lim_process_sme_change_bi(struct mac_context * mac,uint32_t * msg_buf)8138 static void __lim_process_sme_change_bi(struct mac_context *mac,
8139 					uint32_t *msg_buf)
8140 {
8141 	struct wlan_change_bi *pChangeBIParams;
8142 	struct pe_session *pe_session;
8143 	uint8_t sessionId = 0;
8144 	tUpdateBeaconParams beaconParams;
8145 
8146 	pe_debug("received Update Beacon Interval message");
8147 
8148 	if (!msg_buf) {
8149 		pe_err("Buffer is Pointing to NULL");
8150 		return;
8151 	}
8152 
8153 	qdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams));
8154 	pChangeBIParams = (struct wlan_change_bi *)msg_buf;
8155 
8156 	pe_session = pe_find_session_by_bssid(mac,
8157 				pChangeBIParams->bssid.bytes,
8158 				&sessionId);
8159 	if (!pe_session) {
8160 		pe_err("Session does not exist for given BSSID");
8161 		return;
8162 	}
8163 
8164 	/*Update pe_session Beacon Interval */
8165 	if (pe_session->beaconParams.beaconInterval !=
8166 	    pChangeBIParams->beacon_interval) {
8167 		pe_session->beaconParams.beaconInterval =
8168 			pChangeBIParams->beacon_interval;
8169 	}
8170 
8171 	/*Update sch beaconInterval */
8172 	if (mac->sch.beacon_interval !=
8173 	    pChangeBIParams->beacon_interval) {
8174 		mac->sch.beacon_interval =
8175 			pChangeBIParams->beacon_interval;
8176 
8177 		pe_debug("LIM send update BeaconInterval Indication: %d",
8178 			pChangeBIParams->beacon_interval);
8179 
8180 		if (false == mac->sap.SapDfsInfo.is_dfs_cac_timer_running) {
8181 			/* Update beacon */
8182 			sch_set_fixed_beacon_fields(mac, pe_session);
8183 
8184 			beaconParams.bss_idx = pe_session->vdev_id;
8185 			/* Set change in beacon Interval */
8186 			beaconParams.beaconInterval =
8187 				pChangeBIParams->beacon_interval;
8188 			beaconParams.paramChangeBitmap =
8189 				PARAM_BCN_INTERVAL_CHANGED;
8190 			lim_send_beacon_params(mac, &beaconParams, pe_session);
8191 		}
8192 	}
8193 
8194 	return;
8195 } /*** end __lim_process_sme_change_bi() ***/
8196 
8197 #ifdef QCA_HT_2040_COEX
__lim_process_sme_set_ht2040_mode(struct mac_context * mac,uint32_t * msg_buf)8198 static void __lim_process_sme_set_ht2040_mode(struct mac_context *mac,
8199 					      uint32_t *msg_buf)
8200 {
8201 	struct set_ht2040_mode *pSetHT2040Mode;
8202 	struct pe_session *pe_session;
8203 	uint8_t sessionId = 0;
8204 	struct scheduler_msg msg = {0};
8205 	tUpdateVHTOpMode *pHtOpMode = NULL;
8206 	uint16_t staId = 0;
8207 	tpDphHashNode sta = NULL;
8208 
8209 	pe_debug("received Set HT 20/40 mode message");
8210 	if (!msg_buf) {
8211 		pe_err("Buffer is Pointing to NULL");
8212 		return;
8213 	}
8214 
8215 	pSetHT2040Mode = (struct set_ht2040_mode *)msg_buf;
8216 
8217 	pe_session = pe_find_session_by_bssid(mac,
8218 				pSetHT2040Mode->bssid.bytes,
8219 				&sessionId);
8220 	if (!pe_session) {
8221 		pe_debug("Session does not exist for given BSSID: "QDF_MAC_ADDR_FMT,
8222 			 QDF_MAC_ADDR_REF(pSetHT2040Mode->bssid.bytes));
8223 		return;
8224 	}
8225 
8226 	pe_debug("Update session entry for cbMod=%d",
8227 		pSetHT2040Mode->cbMode);
8228 	/*Update pe_session HT related fields */
8229 	switch (pSetHT2040Mode->cbMode) {
8230 	case PHY_SINGLE_CHANNEL_CENTERED:
8231 		pe_session->htSecondaryChannelOffset =
8232 			PHY_SINGLE_CHANNEL_CENTERED;
8233 		pe_session->htRecommendedTxWidthSet = 0;
8234 		if (pSetHT2040Mode->obssEnabled)
8235 			pe_session->htSupportedChannelWidthSet
8236 					= eHT_CHANNEL_WIDTH_40MHZ;
8237 		else
8238 			pe_session->htSupportedChannelWidthSet
8239 					= eHT_CHANNEL_WIDTH_20MHZ;
8240 		break;
8241 	case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
8242 		pe_session->htSecondaryChannelOffset =
8243 			PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
8244 		pe_session->htRecommendedTxWidthSet = 1;
8245 		break;
8246 	case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
8247 		pe_session->htSecondaryChannelOffset =
8248 			PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
8249 		pe_session->htRecommendedTxWidthSet = 1;
8250 		break;
8251 	default:
8252 		pe_err("Invalid cbMode");
8253 		return;
8254 	}
8255 
8256 	/* Update beacon */
8257 	sch_set_fixed_beacon_fields(mac, pe_session);
8258 	lim_send_beacon_ind(mac, pe_session, REASON_SET_HT2040);
8259 
8260 	/* update OP Mode for each associated peer */
8261 	for (staId = 0; staId < pe_session->dph.dphHashTable.size; staId++) {
8262 		sta = dph_get_hash_entry(mac, staId,
8263 				&pe_session->dph.dphHashTable);
8264 		if (!sta)
8265 			continue;
8266 
8267 		if (sta->valid && sta->htSupportedChannelWidthSet) {
8268 			pHtOpMode = qdf_mem_malloc(sizeof(tUpdateVHTOpMode));
8269 			if (!pHtOpMode)
8270 				return;
8271 			pHtOpMode->opMode =
8272 				(pe_session->htSecondaryChannelOffset ==
8273 				 PHY_SINGLE_CHANNEL_CENTERED) ?
8274 				eHT_CHANNEL_WIDTH_20MHZ : eHT_CHANNEL_WIDTH_40MHZ;
8275 			qdf_mem_copy(pHtOpMode->peer_mac, &sta->staAddr,
8276 				     sizeof(tSirMacAddr));
8277 			pHtOpMode->smesessionId = pe_session->smeSessionId;
8278 
8279 			msg.type = WMA_UPDATE_OP_MODE;
8280 			msg.reserved = 0;
8281 			msg.bodyptr = pHtOpMode;
8282 			if (!QDF_IS_STATUS_SUCCESS
8283 				    (scheduler_post_message(QDF_MODULE_ID_PE,
8284 							    QDF_MODULE_ID_WMA,
8285 							    QDF_MODULE_ID_WMA,
8286 							    &msg))) {
8287 				pe_err("Not able to post WMA_UPDATE_OP_MODE message to WMA");
8288 				qdf_mem_free(pHtOpMode);
8289 				return;
8290 			}
8291 			pe_debug("Notified FW about OP mode: %d",
8292 				pHtOpMode->opMode);
8293 
8294 		} else
8295 			pe_debug("station does not support HT40");
8296 	}
8297 
8298 	return;
8299 }
8300 #endif
8301 
8302 /* -------------------------------------------------------------------- */
8303 /**
8304  * __lim_process_report_message
8305  *
8306  * FUNCTION:  Processes the next received Radio Resource Management message
8307  *
8308  * LOGIC:
8309  *
8310  * ASSUMPTIONS:
8311  *
8312  * NOTE:
8313  *
8314  * @param None
8315  * @return None
8316  */
8317 
__lim_process_report_message(struct mac_context * mac,struct scheduler_msg * pMsg)8318 static void __lim_process_report_message(struct mac_context *mac,
8319 					 struct scheduler_msg *pMsg)
8320 {
8321 	switch (pMsg->type) {
8322 	case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
8323 		rrm_process_neighbor_report_req(mac, pMsg->bodyptr);
8324 		break;
8325 	case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
8326 		rrm_process_beacon_report_xmit(mac, pMsg->bodyptr);
8327 		break;
8328 	case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND:
8329 		rrm_process_chan_load_report_xmit(mac, pMsg->bodyptr);
8330 		break;
8331 	default:
8332 		pe_err("Invalid msg type: %d", pMsg->type);
8333 	}
8334 }
8335 
8336 /* -------------------------------------------------------------------- */
8337 /**
8338  * lim_send_set_max_tx_power_req
8339  *
8340  * FUNCTION:  Send SIR_HAL_SET_MAX_TX_POWER_REQ message to change the max tx power.
8341  *
8342  * LOGIC:
8343  *
8344  * ASSUMPTIONS:
8345  *
8346  * NOTE:
8347  *
8348  * @param txPower txPower to be set.
8349  * @param pe_session session entry.
8350  * @return None
8351  */
8352 QDF_STATUS
lim_send_set_max_tx_power_req(struct mac_context * mac,int8_t txPower,struct pe_session * pe_session)8353 lim_send_set_max_tx_power_req(struct mac_context *mac, int8_t txPower,
8354 			      struct pe_session *pe_session)
8355 {
8356 	tpMaxTxPowerParams pMaxTxParams = NULL;
8357 	QDF_STATUS retCode = QDF_STATUS_SUCCESS;
8358 	struct scheduler_msg msgQ = {0};
8359 
8360 	if (!pe_session) {
8361 		pe_err("Invalid parameters");
8362 		return QDF_STATUS_E_FAILURE;
8363 	}
8364 
8365 	pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams));
8366 	if (!pMaxTxParams)
8367 		return QDF_STATUS_E_NOMEM;
8368 	pMaxTxParams->power = txPower;
8369 	qdf_mem_copy(pMaxTxParams->bssId.bytes, pe_session->bssId,
8370 		     QDF_MAC_ADDR_SIZE);
8371 	qdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes,
8372 			pe_session->self_mac_addr,
8373 			QDF_MAC_ADDR_SIZE);
8374 
8375 	msgQ.type = WMA_SET_MAX_TX_POWER_REQ;
8376 	msgQ.bodyptr = pMaxTxParams;
8377 	msgQ.bodyval = 0;
8378 	pe_debug("Post WMA_SET_MAX_TX_POWER_REQ to WMA");
8379 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type));
8380 	retCode = wma_post_ctrl_msg(mac, &msgQ);
8381 	if (QDF_STATUS_SUCCESS != retCode) {
8382 		pe_err("wma_post_ctrl_msg() failed");
8383 		qdf_mem_free(pMaxTxParams);
8384 	}
8385 	return retCode;
8386 }
8387 
8388 /**
8389  * __lim_process_sme_register_mgmt_frame_req() - process sme reg mgmt frame req
8390  *
8391  * @mac_ctx: Pointer to Global MAC structure
8392  * @msg_buf: pointer to the SME message buffer
8393  *
8394  * This function is called to process eWNI_SME_REGISTER_MGMT_FRAME_REQ message
8395  * from SME. It Register this information within PE.
8396  *
8397  * Return: None
8398  */
__lim_process_sme_register_mgmt_frame_req(struct mac_context * mac_ctx,uint32_t * msg_buf)8399 static void __lim_process_sme_register_mgmt_frame_req(struct mac_context *mac_ctx,
8400 		uint32_t *msg_buf)
8401 {
8402 	QDF_STATUS qdf_status;
8403 	struct register_mgmt_frame *sme_req =
8404 					(struct register_mgmt_frame *)msg_buf;
8405 	struct mgmt_frm_reg_info *lim_mgmt_regn = NULL;
8406 	struct mgmt_frm_reg_info *next = NULL;
8407 	bool match = false;
8408 
8409 	pe_nofl_debug("Register Frame: register %d, type %d, match length %d",
8410 		      sme_req->registerFrame, sme_req->frameType,
8411 		      sme_req->matchLen);
8412 	/* First check whether entry exists already */
8413 	qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
8414 	qdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
8415 			    (qdf_list_node_t **) &lim_mgmt_regn);
8416 	qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
8417 
8418 	while (lim_mgmt_regn) {
8419 		if (lim_mgmt_regn->frameType != sme_req->frameType)
8420 			goto skip_match;
8421 		if (sme_req->matchLen) {
8422 			if ((lim_mgmt_regn->matchLen == sme_req->matchLen) &&
8423 				(!qdf_mem_cmp(lim_mgmt_regn->matchData,
8424 					sme_req->matchData,
8425 					lim_mgmt_regn->matchLen))) {
8426 					/* found match! */
8427 					match = true;
8428 					break;
8429 			}
8430 		} else {
8431 			/* found match! */
8432 			match = true;
8433 			break;
8434 		}
8435 skip_match:
8436 		qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
8437 		qdf_status = qdf_list_peek_next(
8438 				&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
8439 				(qdf_list_node_t *)lim_mgmt_regn,
8440 				(qdf_list_node_t **)&next);
8441 		qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
8442 		lim_mgmt_regn = next;
8443 		next = NULL;
8444 	}
8445 	if (match) {
8446 		qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
8447 		if (QDF_STATUS_SUCCESS ==
8448 				qdf_list_remove_node(
8449 				&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
8450 				(qdf_list_node_t *)lim_mgmt_regn))
8451 			qdf_mem_free(lim_mgmt_regn);
8452 		qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
8453 	}
8454 
8455 	if (sme_req->registerFrame) {
8456 		lim_mgmt_regn =
8457 			qdf_mem_malloc(sizeof(struct mgmt_frm_reg_info) +
8458 					sme_req->matchLen);
8459 		if (lim_mgmt_regn) {
8460 			lim_mgmt_regn->frameType = sme_req->frameType;
8461 			lim_mgmt_regn->matchLen = sme_req->matchLen;
8462 			lim_mgmt_regn->sessionId = sme_req->sessionId;
8463 			if (sme_req->matchLen) {
8464 				qdf_mem_copy(lim_mgmt_regn->matchData,
8465 					     sme_req->matchData,
8466 					     sme_req->matchLen);
8467 			}
8468 			qdf_mutex_acquire(
8469 					&mac_ctx->lim.lim_frame_register_lock);
8470 			qdf_list_insert_front(&mac_ctx->lim.
8471 					      gLimMgmtFrameRegistratinQueue,
8472 					      &lim_mgmt_regn->node);
8473 			qdf_mutex_release(
8474 					&mac_ctx->lim.lim_frame_register_lock);
8475 		}
8476 	}
8477 	return;
8478 }
8479 
8480 /**
8481  * lim_register_mgmt_frame_ind_cb() - Save the Management frame
8482  * indication callback in PE.
8483  * @mac_ptr: Mac pointer
8484  * @msg_buf: Msg pointer containing the callback
8485  *
8486  * This function is used save the Management frame
8487  * indication callback in PE.
8488  *
8489  * Return: None
8490  */
lim_register_mgmt_frame_ind_cb(struct mac_context * mac_ctx,uint32_t * msg_buf)8491 static void lim_register_mgmt_frame_ind_cb(struct mac_context *mac_ctx,
8492 							uint32_t *msg_buf)
8493 {
8494 	struct sir_sme_mgmt_frame_cb_req *sme_req =
8495 		(struct sir_sme_mgmt_frame_cb_req *)msg_buf;
8496 
8497 	if (!msg_buf) {
8498 		pe_err("msg_buf is null");
8499 		return;
8500 	}
8501 	if (sme_req->callback)
8502 		mac_ctx->mgmt_frame_ind_cb =
8503 			(sir_mgmt_frame_ind_callback)sme_req->callback;
8504 	else
8505 		pe_err("sme_req->callback is null");
8506 }
8507 
8508 /**
8509  *__lim_process_send_disassoc_frame() - processes send disassoc frame request
8510  * @mac_ctx: pointer to mac context
8511  * @msg_buf: request message buffer
8512  *
8513  * Process a request from SME to send a disassoc frame
8514  *
8515  * Return: none
8516  */
__lim_process_send_disassoc_frame(struct mac_context * mac_ctx,void * msg_buf)8517 static void __lim_process_send_disassoc_frame(struct mac_context *mac_ctx,
8518 					      void *msg_buf)
8519 {
8520 	struct sme_send_disassoc_frm_req *req = msg_buf;
8521 	struct pe_session *session_entry;
8522 
8523 	if (!req) {
8524 		pe_err("NULL req");
8525 		return;
8526 	}
8527 
8528 	if ((IEEE80211_IS_MULTICAST(req->peer_mac) &&
8529 	     !QDF_IS_ADDR_BROADCAST(req->peer_mac))) {
8530 		pe_err("received invalid SME_DISASSOC_REQ message");
8531 		return;
8532 	}
8533 
8534 	session_entry = pe_find_session_by_vdev_id(mac_ctx, req->vdev_id);
8535 	if (!session_entry) {
8536 		pe_err("session does not exist for given bssId "
8537 		       QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(req->peer_mac));
8538 		return;
8539 	}
8540 
8541 	/* Check if MAC address is MLD of the client and
8542 	 * change it to primary link address to send OTA.
8543 	 */
8544 	lim_mlo_sap_validate_and_update_ra(
8545 			session_entry, (struct qdf_mac_addr *)req->peer_mac);
8546 
8547 	pe_debug("msg_type %d len %d vdev_id %d mac: " QDF_MAC_ADDR_FMT " reason %d wait_for_ack %d",
8548 		 req->msg_type, req->length,  req->vdev_id,
8549 		 QDF_MAC_ADDR_REF(req->peer_mac), req->reason, req->wait_for_ack);
8550 
8551 	lim_send_disassoc_mgmt_frame(mac_ctx, req->reason, req->peer_mac,
8552 				     session_entry, req->wait_for_ack);
8553 }
8554 
8555 /**
8556  * lim_set_pdev_ht_ie() - sends the set HT IE req to FW
8557  * @mac_ctx: Pointer to Global MAC structure
8558  * @pdev_id: pdev id to set the IE.
8559  * @nss: Nss values to prepare the HT IE.
8560  *
8561  * Prepares the HT IE with self capabilities for different
8562  * Nss values and sends the set HT IE req to FW.
8563  *
8564  * Return: None
8565  */
lim_set_pdev_ht_ie(struct mac_context * mac_ctx,uint8_t pdev_id,uint8_t nss)8566 static void lim_set_pdev_ht_ie(struct mac_context *mac_ctx, uint8_t pdev_id,
8567 		uint8_t nss)
8568 {
8569 	struct set_ie_param *ie_params;
8570 	struct scheduler_msg msg = {0};
8571 	QDF_STATUS rc = QDF_STATUS_SUCCESS;
8572 	const uint8_t *p_ie = NULL;
8573 	tHtCaps *p_ht_cap;
8574 	int i;
8575 
8576 	for (i = 1; i <= nss; i++) {
8577 		ie_params = qdf_mem_malloc(sizeof(*ie_params));
8578 		if (!ie_params)
8579 			return;
8580 		ie_params->nss = i;
8581 		ie_params->pdev_id = pdev_id;
8582 		ie_params->ie_type = DOT11_HT_IE;
8583 		/* 2 for IE len and EID */
8584 		ie_params->ie_len = 2 + sizeof(tHtCaps);
8585 		ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len);
8586 		if (!ie_params->ie_ptr) {
8587 			qdf_mem_free(ie_params);
8588 			return;
8589 		}
8590 		*ie_params->ie_ptr = WLAN_ELEMID_HTCAP_ANA;
8591 		*(ie_params->ie_ptr + 1) = ie_params->ie_len - 2;
8592 		lim_set_ht_caps(mac_ctx, ie_params->ie_ptr,
8593 				ie_params->ie_len);
8594 
8595 		if (NSS_1x1_MODE == i) {
8596 			p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_HTCAPS,
8597 					ie_params->ie_ptr, ie_params->ie_len);
8598 			if (!p_ie) {
8599 				qdf_mem_free(ie_params->ie_ptr);
8600 				qdf_mem_free(ie_params);
8601 				pe_err("failed to get IE ptr");
8602 				return;
8603 			}
8604 			p_ht_cap = (tHtCaps *)&p_ie[2];
8605 			p_ht_cap->supportedMCSSet[1] = 0;
8606 			p_ht_cap->txSTBC = 0;
8607 		}
8608 
8609 		msg.type = WMA_SET_PDEV_IE_REQ;
8610 		msg.bodyptr = ie_params;
8611 		msg.bodyval = 0;
8612 
8613 		rc = wma_post_ctrl_msg(mac_ctx, &msg);
8614 		if (rc != QDF_STATUS_SUCCESS) {
8615 			pe_err("wma_post_ctrl_msg() return failure");
8616 			qdf_mem_free(ie_params->ie_ptr);
8617 			qdf_mem_free(ie_params);
8618 			return;
8619 		}
8620 	}
8621 }
8622 
8623 /**
8624  * lim_set_pdev_vht_ie() - sends the set VHT IE to req FW
8625  * @mac_ctx: Pointer to Global MAC structure
8626  * @pdev_id: pdev id to set the IE.
8627  * @nss: Nss values to prepare the VHT IE.
8628  *
8629  * Prepares the VHT IE with self capabilities for different
8630  * Nss values and sends the set VHT IE req to FW.
8631  *
8632  * Return: None
8633  */
lim_set_pdev_vht_ie(struct mac_context * mac_ctx,uint8_t pdev_id,uint8_t nss)8634 static void lim_set_pdev_vht_ie(struct mac_context *mac_ctx, uint8_t pdev_id,
8635 		uint8_t nss)
8636 {
8637 	struct set_ie_param *ie_params;
8638 	struct scheduler_msg msg = {0};
8639 	QDF_STATUS rc = QDF_STATUS_SUCCESS;
8640 	const uint8_t *p_ie = NULL;
8641 	tSirMacVHTCapabilityInfo *vht_cap;
8642 	int i;
8643 	tSirVhtMcsInfo *vht_mcs;
8644 
8645 	for (i = 1; i <= nss; i++) {
8646 		ie_params = qdf_mem_malloc(sizeof(*ie_params));
8647 		if (!ie_params)
8648 			return;
8649 		ie_params->nss = i;
8650 		ie_params->pdev_id = pdev_id;
8651 		ie_params->ie_type = DOT11_VHT_IE;
8652 		/* 2 for IE len and EID */
8653 		ie_params->ie_len = 2 + sizeof(tSirMacVHTCapabilityInfo) +
8654 			sizeof(tSirVhtMcsInfo);
8655 		ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len);
8656 		if (!ie_params->ie_ptr) {
8657 			qdf_mem_free(ie_params);
8658 			return;
8659 		}
8660 		*ie_params->ie_ptr = WLAN_ELEMID_VHTCAP;
8661 		*(ie_params->ie_ptr + 1) = ie_params->ie_len - 2;
8662 		lim_set_vht_caps(mac_ctx, ie_params->ie_ptr, ie_params->ie_len);
8663 
8664 		if (NSS_1x1_MODE == i) {
8665 			p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_VHTCAPS,
8666 					ie_params->ie_ptr, ie_params->ie_len);
8667 			if (!p_ie) {
8668 				qdf_mem_free(ie_params->ie_ptr);
8669 				qdf_mem_free(ie_params);
8670 				pe_err("failed to get IE ptr");
8671 				return;
8672 			}
8673 			vht_cap = (tSirMacVHTCapabilityInfo *)&p_ie[2];
8674 			vht_cap->txSTBC = 0;
8675 			vht_mcs =
8676 				(tSirVhtMcsInfo *)&p_ie[2 +
8677 				sizeof(tSirMacVHTCapabilityInfo)];
8678 			vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS;
8679 			vht_mcs->rxHighest =
8680 				VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
8681 			vht_mcs->txMcsMap |= DISABLE_NSS2_MCS;
8682 			vht_mcs->txHighest =
8683 				VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
8684 		}
8685 		msg.type = WMA_SET_PDEV_IE_REQ;
8686 		msg.bodyptr = ie_params;
8687 		msg.bodyval = 0;
8688 
8689 		rc = wma_post_ctrl_msg(mac_ctx, &msg);
8690 		if (rc != QDF_STATUS_SUCCESS) {
8691 			pe_err("wma_post_ctrl_msg failure");
8692 			qdf_mem_free(ie_params->ie_ptr);
8693 			qdf_mem_free(ie_params);
8694 			return;
8695 		}
8696 	}
8697 }
8698 
8699 /**
8700  * lim_process_set_vdev_ies_per_band() - process the set vdev IE req
8701  * @mac_ctx: Pointer to Global MAC structure
8702  * @msg_buf: Pointer to the SME message buffer
8703  *
8704  * This function is called by limProcessMessageQueue(). This function sets the
8705  * VDEV IEs to the FW.
8706  *
8707  * Return: None
8708  */
lim_process_set_vdev_ies_per_band(struct mac_context * mac_ctx,uint32_t * msg_buf)8709 static void lim_process_set_vdev_ies_per_band(struct mac_context *mac_ctx,
8710 					      uint32_t *msg_buf)
8711 {
8712 	struct sir_set_vdev_ies_per_band *p_msg =
8713 				(struct sir_set_vdev_ies_per_band *)msg_buf;
8714 
8715 	if (!p_msg) {
8716 		pe_err("NULL p_msg");
8717 		return;
8718 	}
8719 
8720 	pe_debug("rcvd set vdev ie per band req vdev_id = %d",
8721 		p_msg->vdev_id);
8722 
8723 	if (lim_send_ies_per_band(mac_ctx, p_msg->vdev_id,
8724 				  p_msg->dot11_mode, p_msg->device_mode) !=
8725 	    QDF_STATUS_SUCCESS)
8726 		pe_err("Unable to send HT/VHT Cap to FW");
8727 }
8728 
8729 /**
8730  * lim_process_set_pdev_IEs() - process the set pdev IE req
8731  * @mac_ctx: Pointer to Global MAC structure
8732  * @msg_buf: Pointer to the SME message buffer
8733  *
8734  * This function is called by limProcessMessageQueue(). This
8735  * function sets the PDEV IEs to the FW.
8736  *
8737  * Return: None
8738  */
lim_process_set_pdev_IEs(struct mac_context * mac_ctx,uint32_t * msg_buf)8739 static void lim_process_set_pdev_IEs(struct mac_context *mac_ctx, uint32_t *msg_buf)
8740 {
8741 	struct sir_set_ht_vht_cfg *ht_vht_cfg;
8742 
8743 	ht_vht_cfg = (struct sir_set_ht_vht_cfg *)msg_buf;
8744 
8745 	if (!ht_vht_cfg) {
8746 		pe_err("NULL ht_vht_cfg");
8747 		return;
8748 	}
8749 
8750 	pe_debug("rcvd set pdev ht vht ie req with nss = %d",
8751 			ht_vht_cfg->nss);
8752 	lim_set_pdev_ht_ie(mac_ctx, ht_vht_cfg->pdev_id, ht_vht_cfg->nss);
8753 
8754 	if (IS_DOT11_MODE_VHT(ht_vht_cfg->dot11mode))
8755 		lim_set_pdev_vht_ie(mac_ctx, ht_vht_cfg->pdev_id,
8756 				ht_vht_cfg->nss);
8757 }
8758 
8759 /**
8760  * lim_process_sme_update_access_policy_vendor_ie: function updates vendor IE
8761  *
8762  * access policy
8763  * @mac_ctx: pointer to mac context
8764  * @msg: message buffer
8765  *
8766  * function processes vendor IE and access policy from SME and updates PE
8767  *
8768  * session entry
8769  *
8770  * return: none
8771 */
lim_process_sme_update_access_policy_vendor_ie(struct mac_context * mac_ctx,uint32_t * msg)8772 static void lim_process_sme_update_access_policy_vendor_ie(
8773 						struct mac_context *mac_ctx,
8774 						uint32_t *msg)
8775 {
8776 	struct sme_update_access_policy_vendor_ie *update_vendor_ie;
8777 	struct pe_session *pe_session_entry;
8778 	uint16_t num_bytes;
8779 
8780 	if (!msg) {
8781 		pe_err("Buffer is Pointing to NULL");
8782 		return;
8783 	}
8784 	update_vendor_ie = (struct sme_update_access_policy_vendor_ie *) msg;
8785 	pe_session_entry = pe_find_session_by_vdev_id(mac_ctx,
8786 					update_vendor_ie->vdev_id);
8787 
8788 	if (!pe_session_entry) {
8789 		pe_err("Session does not exist for given vdev_id %d",
8790 			update_vendor_ie->vdev_id);
8791 		return;
8792 	}
8793 	if (pe_session_entry->access_policy_vendor_ie)
8794 		qdf_mem_free(pe_session_entry->access_policy_vendor_ie);
8795 
8796 	num_bytes = update_vendor_ie->ie[1] + 2;
8797 	pe_session_entry->access_policy_vendor_ie = qdf_mem_malloc(num_bytes);
8798 	if (!pe_session_entry->access_policy_vendor_ie)
8799 		return;
8800 	qdf_mem_copy(pe_session_entry->access_policy_vendor_ie,
8801 		&update_vendor_ie->ie[0], num_bytes);
8802 
8803 	pe_session_entry->access_policy = update_vendor_ie->access_policy;
8804 }
8805 
lim_sta_mlme_vdev_disconnect_bss(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)8806 QDF_STATUS lim_sta_mlme_vdev_disconnect_bss(struct vdev_mlme_obj *vdev_mlme,
8807 					    uint16_t data_len, void *data)
8808 {
8809 	struct mac_context *mac_ctx;
8810 	struct scheduler_msg *msg = (struct scheduler_msg *)data;
8811 
8812 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
8813 	if (!mac_ctx) {
8814 		if (data)
8815 			qdf_mem_free(data);
8816 		return QDF_STATUS_E_INVAL;
8817 	}
8818 	pe_debug("Vdev %d: disconnect bss callback type:(%d)",
8819 		 wlan_vdev_get_id(vdev_mlme->vdev), msg->type);
8820 
8821 	switch (msg->type) {
8822 	case eWNI_SME_DEAUTH_REQ:
8823 		__lim_process_sme_deauth_req(mac_ctx,
8824 					     (uint32_t *)msg->bodyptr);
8825 		break;
8826 	case eWNI_SME_DISASSOC_CNF:
8827 	case eWNI_SME_DEAUTH_CNF:
8828 		__lim_process_sme_disassoc_cnf(mac_ctx,
8829 					       (uint32_t *)msg->bodyptr);
8830 		break;
8831 	case eWNI_SME_DISASSOC_REQ:
8832 		__lim_process_sme_disassoc_req(mac_ctx,
8833 					       (uint32_t *)msg->bodyptr);
8834 		break;
8835 	default:
8836 		pe_err("Vdev %d Wrong message type received %d",
8837 		       wlan_vdev_get_id(vdev_mlme->vdev), msg->type);
8838 	}
8839 	return QDF_STATUS_SUCCESS;
8840 }
8841 
lim_process_sme_disassoc_cnf(struct mac_context * mac_ctx,struct scheduler_msg * msg)8842 static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx,
8843 					 struct scheduler_msg *msg)
8844 {
8845 	struct disassoc_cnf sme_disassoc_cnf;
8846 	struct pe_session *session;
8847 	uint8_t session_id;
8848 	uint32_t *err_msg = NULL;
8849 	QDF_STATUS status;
8850 
8851 	qdf_mem_copy(&sme_disassoc_cnf, msg->bodyptr, sizeof(sme_disassoc_cnf));
8852 
8853 	session = pe_find_session_by_bssid(mac_ctx,
8854 					   sme_disassoc_cnf.bssid.bytes,
8855 					   &session_id);
8856 	if (!session) {
8857 		pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT,
8858 		       QDF_MAC_ADDR_REF(sme_disassoc_cnf.bssid.bytes));
8859 		status = lim_prepare_disconnect_done_ind
8860 						(mac_ctx, &err_msg,
8861 						sme_disassoc_cnf.vdev_id,
8862 						eSIR_SME_INVALID_SESSION,
8863 						NULL);
8864 
8865 		if (QDF_IS_STATUS_SUCCESS(status))
8866 			lim_send_sme_disassoc_deauth_ntf(mac_ctx,
8867 							 QDF_STATUS_SUCCESS,
8868 							 err_msg);
8869 		return;
8870 	}
8871 
8872 	__lim_process_sme_disassoc_cnf(mac_ctx, (uint32_t *)msg->bodyptr);
8873 }
8874 
lim_process_sme_disassoc_req(struct mac_context * mac_ctx,struct scheduler_msg * msg)8875 static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx,
8876 					 struct scheduler_msg *msg)
8877 {
8878 	struct disassoc_req disassoc_req;
8879 	struct pe_session *session;
8880 	uint8_t session_id;
8881 
8882 	qdf_mem_copy(&disassoc_req, msg->bodyptr, sizeof(struct disassoc_req));
8883 
8884 	session = pe_find_session_by_bssid(mac_ctx,
8885 					   disassoc_req.bssid.bytes,
8886 					   &session_id);
8887 	if (!session) {
8888 		pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT,
8889 		       QDF_MAC_ADDR_REF(disassoc_req.bssid.bytes));
8890 		lim_send_sme_disassoc_ntf(mac_ctx,
8891 					  disassoc_req.peer_macaddr.bytes,
8892 					  eSIR_SME_INVALID_PARAMETERS,
8893 					  eLIM_HOST_DISASSOC, 1,
8894 					  disassoc_req.sessionId, NULL);
8895 
8896 		return;
8897 	}
8898 
8899 	__lim_process_sme_disassoc_req(mac_ctx, (uint32_t *)msg->bodyptr);
8900 }
8901 
lim_process_sme_deauth_req(struct mac_context * mac_ctx,struct scheduler_msg * msg)8902 static void lim_process_sme_deauth_req(struct mac_context *mac_ctx,
8903 				       struct scheduler_msg *msg)
8904 {
8905 	struct deauth_req sme_deauth_req;
8906 	struct pe_session *session;
8907 	uint8_t session_id;
8908 
8909 	qdf_mem_copy(&sme_deauth_req, msg->bodyptr, sizeof(sme_deauth_req));
8910 
8911 	session = pe_find_session_by_bssid(mac_ctx,
8912 					   sme_deauth_req.bssid.bytes,
8913 					   &session_id);
8914 	if (!session) {
8915 		pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT,
8916 		       QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes));
8917 		lim_send_sme_deauth_ntf(mac_ctx,
8918 					sme_deauth_req.peer_macaddr.bytes,
8919 					eSIR_SME_INVALID_PARAMETERS,
8920 					eLIM_HOST_DEAUTH, 1,
8921 					sme_deauth_req.vdev_id);
8922 
8923 		return;
8924 	}
8925 
8926 	__lim_process_sme_deauth_req(mac_ctx, (uint32_t *)msg->bodyptr);
8927 }
8928 
lim_send_bcn_rsp(struct mac_context * mac_ctx,tpSendbeaconParams rsp)8929 void lim_send_bcn_rsp(struct mac_context *mac_ctx, tpSendbeaconParams rsp)
8930 {
8931 	if (!rsp) {
8932 		pe_err("rsp is NULL");
8933 		return;
8934 	}
8935 
8936 	/* Success case response is sent from beacon_tx completion/timeout */
8937 	if (rsp->reason == REASON_CH_WIDTH_UPDATE &&
8938 	    QDF_IS_STATUS_SUCCESS(rsp->status))
8939 		return;
8940 
8941 	pe_debug("Send beacon resp status %d for reason %d",
8942 		 rsp->status, rsp->reason);
8943 
8944 	lim_nss_or_ch_width_update_rsp(mac_ctx, rsp->vdev_id,
8945 				       rsp->status, rsp->reason);
8946 }
8947 
8948 static void
lim_update_bcn_with_new_ch_width(struct mac_context * mac_ctx,struct pe_session * session,enum phy_ch_width ch_width)8949 lim_update_bcn_with_new_ch_width(struct mac_context *mac_ctx,
8950 				 struct pe_session *session,
8951 				 enum phy_ch_width ch_width)
8952 {
8953 	QDF_STATUS status;
8954 
8955 	session->gLimOperatingMode.present = 1;
8956 	session->gLimOperatingMode.chanWidth = ch_width;
8957 
8958 	pe_debug("ch width %d",
8959 		 session->gLimOperatingMode.chanWidth);
8960 
8961 	session->bw_update_include_ch_sw_ie = true;
8962 	status = qdf_mc_timer_start(&session->ap_ecsa_timer,
8963 				    MAX_WAIT_FOR_CH_WIDTH_UPDATE_COMPLETE);
8964 	if (QDF_IS_STATUS_ERROR(status))
8965 		pe_err("cannot start ap_ecsa_timer");
8966 
8967 	/* Send nss update request from here */
8968 	status = sch_set_fixed_beacon_fields(mac_ctx, session);
8969 	if (QDF_IS_STATUS_ERROR(status)) {
8970 		pe_err("Unable to set op mode IE in beacon");
8971 		goto end;
8972 	}
8973 
8974 	status = lim_send_beacon_ind(mac_ctx, session,
8975 				     REASON_CH_WIDTH_UPDATE);
8976 	if (QDF_IS_STATUS_SUCCESS(status))
8977 		return;
8978 
8979 	pe_err("Unable to send beacon");
8980 end:
8981 	/*
8982 	 * send resp only in case of failure,
8983 	 * success case response will be from wma.
8984 	 */
8985 	lim_nss_or_ch_width_update_rsp(mac_ctx, session->vdev_id, status,
8986 				       REASON_CH_WIDTH_UPDATE);
8987 }
8988 
8989 static enum phy_ch_width
lim_calculate_peer_ch_width(struct pe_session * session,uint8_t * mac_addr,enum phy_ch_width new_ch_width)8990 lim_calculate_peer_ch_width(struct pe_session *session,
8991 			    uint8_t *mac_addr,
8992 			    enum phy_ch_width new_ch_width)
8993 {
8994 	enum phy_ch_width peer_org_bw, updated_bw;
8995 	struct peer_oper_mode_event data = {0};
8996 	QDF_STATUS status;
8997 
8998 	peer_org_bw = wlan_mlme_get_peer_ch_width(
8999 				wlan_vdev_get_psoc(session->vdev), mac_addr);
9000 
9001 	updated_bw = new_ch_width;
9002 
9003 	qdf_mem_copy(&data.peer_mac_address.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
9004 	status = wlan_mlme_get_peer_indicated_ch_width(
9005 				wlan_vdev_get_psoc(session->vdev), &data);
9006 	if (QDF_IS_STATUS_SUCCESS(status))
9007 		updated_bw = data.new_bw;
9008 
9009 	pe_debug("Peer: " QDF_MAC_ADDR_FMT " original bw: %d, updated bw: %d, new bw: %d",
9010 		 QDF_MAC_ADDR_REF(mac_addr), peer_org_bw, updated_bw,
9011 		 new_ch_width);
9012 
9013 	return qdf_min(peer_org_bw, qdf_min(updated_bw, new_ch_width));
9014 }
9015 
9016 static void
lim_update_new_ch_width_to_fw(struct mac_context * mac_ctx,struct pe_session * session,enum phy_ch_width ch_bandwidth)9017 lim_update_new_ch_width_to_fw(struct mac_context *mac_ctx,
9018 			      struct pe_session *session,
9019 			      enum phy_ch_width ch_bandwidth)
9020 {
9021 	uint8_t i;
9022 	tpDphHashNode psta;
9023 	tUpdateVHTOpMode params;
9024 
9025 	for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) {
9026 		psta = session->dph.dphHashTable.pDphNodeArray + i;
9027 		if (!psta || !psta->added)
9028 			continue;
9029 
9030 		params.opMode = lim_calculate_peer_ch_width(session,
9031 					psta->staAddr, ch_bandwidth);
9032 		params.smesessionId = session->smeSessionId;
9033 		qdf_mem_copy(params.peer_mac, psta->staAddr,
9034 			     sizeof(tSirMacAddr));
9035 
9036 		lim_send_mode_update(mac_ctx, &params, session);
9037 	}
9038 }
9039 
9040 /**
9041  * lim_process_sap_ch_width_update() - process sme nss update req
9042  *
9043  * @mac_ctx: Pointer to Global MAC structure
9044  * @msg_buf: pointer to the SME message buffer
9045  *
9046  * This function processes SME request messages from HDD or upper layer
9047  * application.
9048  *
9049  * Return: None
9050  */
9051 static void
lim_process_sap_ch_width_update(struct mac_context * mac_ctx,uint32_t * msg_buf)9052 lim_process_sap_ch_width_update(struct mac_context *mac_ctx,
9053 				uint32_t *msg_buf)
9054 {
9055 	struct sir_sap_ch_width_update *req;
9056 	struct pe_session *session = NULL;
9057 	uint8_t vdev_id;
9058 	struct sir_bcn_update_rsp *param;
9059 	struct scheduler_msg msg_return = {0};
9060 	uint8_t primary_channel;
9061 	struct ch_params ch_params = {0};
9062 
9063 	if (!msg_buf) {
9064 		pe_err("Buffer is Pointing to NULL");
9065 		return;
9066 	}
9067 
9068 	req = (struct sir_sap_ch_width_update *)msg_buf;
9069 	vdev_id = req->vdev_id;
9070 	session = pe_find_session_by_vdev_id(mac_ctx, req->vdev_id);
9071 	if (!session) {
9072 		pe_err("vdev %d session not found", req->vdev_id);
9073 		goto fail;
9074 	}
9075 
9076 	if (session->opmode != QDF_SAP_MODE) {
9077 		pe_err("Invalid opmode %d", session->opmode);
9078 		goto fail;
9079 	}
9080 
9081 	ch_params.ch_width = req->ch_width;
9082 	wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
9083 						session->curr_op_freq,
9084 						0,
9085 						&ch_params,
9086 						REG_CURRENT_PWR_MODE);
9087 
9088 	session->gLimChannelSwitch.switchCount = 1;
9089 	session->gLimChannelSwitch.sw_target_freq = session->curr_op_freq;
9090 	primary_channel = wlan_reg_freq_to_chan(mac_ctx->pdev,
9091 						session->curr_op_freq);
9092 	session->gLimChannelSwitch.primaryChannel = primary_channel;
9093 	session->gLimChannelSwitch.ch_width = req->ch_width;
9094 	session->gLimChannelSwitch.ch_center_freq_seg0 =
9095 						ch_params.center_freq_seg0;
9096 	session->gLimChannelSwitch.ch_center_freq_seg1 =
9097 						ch_params.center_freq_seg1;
9098 
9099 	wlan_mlme_set_ap_oper_ch_width(session->vdev, req->ch_width);
9100 
9101 	/* Send ECSA to the peers */
9102 	send_extended_chan_switch_action_frame(mac_ctx,
9103 				       session->curr_op_freq,
9104 				       req->ch_width, session);
9105 
9106 	/* Send beacon template to firmware */
9107 	lim_update_bcn_with_new_ch_width(mac_ctx, session, req->ch_width);
9108 	/* Send updated bw info of each peer to firmware */
9109 	lim_update_new_ch_width_to_fw(mac_ctx, session, req->ch_width);
9110 
9111 	/*
9112 	 * Release the SER command only after this, otherwise it may cause
9113 	 * out of sync issues if any other WMI commands go to fw
9114 	 */
9115 	return;
9116 
9117 fail:
9118 	pe_err("vdev %d: send bandwidth update fail", vdev_id);
9119 	param = qdf_mem_malloc(sizeof(*param));
9120 	if (param) {
9121 		param->status = QDF_STATUS_E_FAILURE;
9122 		param->vdev_id = INVALID_VDEV_ID;
9123 		param->reason = REASON_CH_WIDTH_UPDATE;
9124 	}
9125 	msg_return.type = eWNI_SME_SAP_CH_WIDTH_UPDATE_RSP;
9126 	msg_return.bodyptr = param;
9127 	msg_return.bodyval = 0;
9128 	sys_process_mmh_msg(mac_ctx, &msg_return);
9129 }
9130 
9131 /**
9132  * lim_process_sme_req_messages()
9133  *
9134  ***FUNCTION:
9135  * This function is called by limProcessMessageQueue(). This
9136  * function processes SME request messages from HDD or upper layer
9137  * application.
9138  *
9139  ***LOGIC:
9140  *
9141  ***ASSUMPTIONS:
9142  *
9143  ***NOTE:
9144  *
9145  * @param  mac      Pointer to Global MAC structure
9146  * @param  msgType   Indicates the SME message type
9147  * @param  *msg_buf  A pointer to the SME message buffer
9148  * @return Boolean - true - if msg_buf is consumed and can be freed.
9149  *                   false - if msg_buf is not to be freed.
9150  */
9151 
lim_process_sme_req_messages(struct mac_context * mac,struct scheduler_msg * pMsg)9152 bool lim_process_sme_req_messages(struct mac_context *mac,
9153 				  struct scheduler_msg *pMsg)
9154 {
9155 	/*
9156 	 * Set this flag to false within case block of any following message,
9157 	 * that doesn't want msg_buf to be freed.
9158 	 */
9159 	bool bufConsumed = true;
9160 	uint32_t *msg_buf = pMsg->bodyptr;
9161 
9162 	pe_nofl_debug("LIM handle SME Msg %s(%d)",
9163 		      lim_msg_str(pMsg->type), pMsg->type);
9164 
9165 	/* If no insert NOA required then execute the code below */
9166 
9167 	switch (pMsg->type) {
9168 	case eWNI_SME_SYS_READY_IND:
9169 		bufConsumed = __lim_process_sme_sys_ready_ind(mac, msg_buf);
9170 		break;
9171 
9172 	case eWNI_SME_START_BSS_REQ:
9173 		bufConsumed = __lim_process_sme_start_bss_req(mac, pMsg);
9174 		break;
9175 	case eWNI_SME_DISASSOC_REQ:
9176 		lim_process_sme_disassoc_req(mac, pMsg);
9177 		break;
9178 
9179 	case eWNI_SME_DISASSOC_CNF:
9180 	case eWNI_SME_DEAUTH_CNF:
9181 		lim_process_sme_disassoc_cnf(mac, pMsg);
9182 		break;
9183 
9184 	case eWNI_SME_DEAUTH_REQ:
9185 		lim_process_sme_deauth_req(mac, pMsg);
9186 		break;
9187 
9188 	case eWNI_SME_SEND_DISASSOC_FRAME:
9189 		__lim_process_send_disassoc_frame(mac, msg_buf);
9190 		break;
9191 
9192 	case eWNI_SME_STOP_BSS_REQ:
9193 		bufConsumed = __lim_process_sme_stop_bss_req(mac, pMsg);
9194 		break;
9195 
9196 	case eWNI_SME_ASSOC_CNF:
9197 		pe_debug("Received ASSOC_CNF message");
9198 		__lim_process_sme_assoc_cnf_new(mac, pMsg->type,
9199 						msg_buf);
9200 		break;
9201 
9202 	case eWNI_SME_ADDTS_REQ:
9203 		pe_debug("Received ADDTS_REQ message");
9204 		__lim_process_sme_addts_req(mac, msg_buf);
9205 		break;
9206 
9207 	case eWNI_SME_MSCS_REQ:
9208 		pe_debug("Received MSCS_REQ message");
9209 		__lim_process_sme_mscs_req(mac, msg_buf);
9210 		break;
9211 
9212 	case eWNI_SME_DELTS_REQ:
9213 		pe_debug("Received DELTS_REQ message");
9214 		__lim_process_sme_delts_req(mac, msg_buf);
9215 		break;
9216 
9217 	case SIR_LIM_ADDTS_RSP_TIMEOUT:
9218 		pe_debug("Received SIR_LIM_ADDTS_RSP_TIMEOUT message");
9219 		lim_process_sme_addts_rsp_timeout(mac, pMsg->bodyval);
9220 		break;
9221 
9222 #ifdef FEATURE_WLAN_ESE
9223 	case eWNI_SME_GET_TSM_STATS_REQ:
9224 		__lim_process_sme_get_tsm_stats_request(mac, msg_buf);
9225 		bufConsumed = false;
9226 		break;
9227 #endif /* FEATURE_WLAN_ESE */
9228 	case eWNI_SME_SESSION_UPDATE_PARAM:
9229 		__lim_process_sme_session_update(mac, msg_buf);
9230 		break;
9231 	case eWNI_SME_CHNG_MCC_BEACON_INTERVAL:
9232 		/* Update the beaconInterval */
9233 		__lim_process_sme_change_bi(mac, msg_buf);
9234 		break;
9235 
9236 #ifdef QCA_HT_2040_COEX
9237 	case eWNI_SME_SET_HT_2040_MODE:
9238 		__lim_process_sme_set_ht2040_mode(mac, msg_buf);
9239 		break;
9240 #endif
9241 
9242 	case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
9243 	case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
9244 	case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND:
9245 		__lim_process_report_message(mac, pMsg);
9246 		break;
9247 	case eWNI_SME_FT_AGGR_QOS_REQ:
9248 		lim_process_ft_aggr_qos_req(mac, msg_buf);
9249 		break;
9250 
9251 	case eWNI_SME_REGISTER_MGMT_FRAME_REQ:
9252 		__lim_process_sme_register_mgmt_frame_req(mac, msg_buf);
9253 		break;
9254 #ifdef FEATURE_WLAN_TDLS
9255 	case eWNI_SME_TDLS_SEND_MGMT_REQ:
9256 		lim_process_sme_tdls_mgmt_send_req(mac, msg_buf);
9257 		break;
9258 	case eWNI_SME_TDLS_ADD_STA_REQ:
9259 		lim_process_sme_tdls_add_sta_req(mac, msg_buf);
9260 		break;
9261 	case eWNI_SME_TDLS_DEL_STA_REQ:
9262 		lim_process_sme_tdls_del_sta_req(mac, msg_buf);
9263 		break;
9264 #endif
9265 	case eWNI_SME_CHANNEL_CHANGE_REQ:
9266 		lim_process_sme_channel_change_request(mac, msg_buf);
9267 		break;
9268 
9269 	case eWNI_SME_START_BEACON_REQ:
9270 		lim_process_sme_start_beacon_req(mac, msg_buf);
9271 		break;
9272 
9273 	case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ:
9274 		lim_process_sme_dfs_csa_ie_request(mac, msg_buf);
9275 		break;
9276 
9277 	case eWNI_SME_UPDATE_ADDITIONAL_IES:
9278 		lim_process_update_add_ies(mac, msg_buf);
9279 		break;
9280 
9281 	case eWNI_SME_MODIFY_ADDITIONAL_IES:
9282 		lim_process_modify_add_ies(mac, msg_buf);
9283 		break;
9284 	case eWNI_SME_SET_HW_MODE_REQ:
9285 		lim_process_set_hw_mode(mac, msg_buf);
9286 		break;
9287 	case eWNI_SME_NSS_UPDATE_REQ:
9288 		lim_process_nss_update_request(mac, msg_buf);
9289 		break;
9290 	case eWNI_SME_SET_DUAL_MAC_CFG_REQ:
9291 		lim_process_set_dual_mac_cfg_req(mac, msg_buf);
9292 		break;
9293 	case eWNI_SME_SET_IE_REQ:
9294 		lim_process_set_ie_req(mac, msg_buf);
9295 		break;
9296 	case eWNI_SME_REGISTER_MGMT_FRAME_CB:
9297 		lim_register_mgmt_frame_ind_cb(mac, msg_buf);
9298 		break;
9299 	case eWNI_SME_EXT_CHANGE_CHANNEL:
9300 		lim_process_ext_change_channel(mac, msg_buf);
9301 		break;
9302 	case eWNI_SME_SET_ANTENNA_MODE_REQ:
9303 		lim_process_set_antenna_mode_req(mac, msg_buf);
9304 		break;
9305 	case eWNI_SME_PDEV_SET_HT_VHT_IE:
9306 		lim_process_set_pdev_IEs(mac, msg_buf);
9307 		break;
9308 	case eWNI_SME_SET_VDEV_IES_PER_BAND:
9309 		lim_process_set_vdev_ies_per_band(mac, msg_buf);
9310 		break;
9311 	case eWNI_SME_UPDATE_ACCESS_POLICY_VENDOR_IE:
9312 		lim_process_sme_update_access_policy_vendor_ie(mac, msg_buf);
9313 		break;
9314 	case eWNI_SME_UPDATE_CONFIG:
9315 		lim_process_sme_update_config(mac,
9316 					(struct update_config *)msg_buf);
9317 		break;
9318 	case eWNI_SME_SET_ADDBA_ACCEPT:
9319 		lim_process_sme_set_addba_accept(mac,
9320 					(struct sme_addba_accept *)msg_buf);
9321 		break;
9322 	case eWNI_SME_UPDATE_EDCA_PROFILE:
9323 		lim_process_sme_update_edca_params(mac, pMsg->bodyval);
9324 		break;
9325 	case WNI_SME_UPDATE_MU_EDCA_PARAMS:
9326 		lim_process_sme_update_mu_edca_params(mac, pMsg->bodyval);
9327 		break;
9328 	case eWNI_SME_UPDATE_SESSION_EDCA_TXQ_PARAMS:
9329 		lim_process_sme_update_session_edca_txq_params(mac, msg_buf);
9330 		break;
9331 	case WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU:
9332 		lim_process_sme_cfg_action_frm_in_tb_ppdu(mac,
9333 				(struct  sir_cfg_action_frm_tb_ppdu *)msg_buf);
9334 		break;
9335 	case eWNI_SME_VDEV_PAUSE_IND:
9336 		lim_process_sme_send_vdev_pause(mac,
9337 					(struct sme_vdev_pause *)msg_buf);
9338 		break;
9339 	case eWNI_SME_SAP_CH_WIDTH_UPDATE_REQ:
9340 		lim_process_sap_ch_width_update(mac, msg_buf);
9341 		break;
9342 	default:
9343 		qdf_mem_free((void *)pMsg->bodyptr);
9344 		pMsg->bodyptr = NULL;
9345 		break;
9346 	} /* switch (msgType) */
9347 
9348 	return bufConsumed;
9349 } /*** end lim_process_sme_req_messages() ***/
9350 
9351 /**
9352  * lim_process_sme_start_beacon_req()
9353  *
9354  ***FUNCTION:
9355  * This function is called by limProcessMessageQueue(). This
9356  * function processes SME request messages from HDD or upper layer
9357  * application.
9358  *
9359  ***LOGIC:
9360  *
9361  ***ASSUMPTIONS:
9362  *
9363  ***NOTE:
9364  *
9365  * @param  mac      Pointer to Global MAC structure
9366  * @param  msgType   Indicates the SME message type
9367  * @param  *msg_buf  A pointer to the SME message buffer
9368  * @return Boolean - true - if msg_buf is consumed and can be freed.
9369  *                   false - if msg_buf is not to be freed.
9370  */
lim_process_sme_start_beacon_req(struct mac_context * mac,uint32_t * pMsg)9371 static void lim_process_sme_start_beacon_req(struct mac_context *mac, uint32_t *pMsg)
9372 {
9373 	tpSirStartBeaconIndication pBeaconStartInd;
9374 	struct pe_session *pe_session;
9375 	uint8_t sessionId;      /* PE sessionID */
9376 
9377 	if (!pMsg) {
9378 		pe_err("Buffer is Pointing to NULL");
9379 		return;
9380 	}
9381 
9382 	pBeaconStartInd = (tpSirStartBeaconIndication) pMsg;
9383 	pe_session = pe_find_session_by_bssid(mac,
9384 				pBeaconStartInd->bssid,
9385 				&sessionId);
9386 	if (!pe_session) {
9387 		pe_err("Session does not exist for given bssId: "QDF_MAC_ADDR_FMT,
9388 		       QDF_MAC_ADDR_REF(pBeaconStartInd->bssid));
9389 		return;
9390 	}
9391 
9392 	if (pBeaconStartInd->beaconStartStatus == true) {
9393 		/*
9394 		 * Currently this Indication comes from SAP
9395 		 * to start Beacon Tx on a DFS channel
9396 		 * since beaconing has to be done on DFS
9397 		 * channel only after CAC WAIT is completed.
9398 		 * On a DFS Channel LIM does not start beacon
9399 		 * Tx right after the WMA_ADD_BSS_RSP.
9400 		 */
9401 		lim_apply_configuration(mac, pe_session);
9402 		pe_debug("Start Beacon with ssid " QDF_SSID_FMT " Ch freq %d",
9403 			 QDF_SSID_REF(pe_session->ssId.length,
9404 				      pe_session->ssId.ssId),
9405 			 pe_session->curr_op_freq);
9406 		lim_send_beacon(mac, pe_session);
9407 		lim_enable_obss_detection_config(mac, pe_session);
9408 		lim_send_obss_color_collision_cfg(mac, pe_session,
9409 					OBSS_COLOR_COLLISION_DETECTION);
9410 	} else {
9411 		pe_err("Invalid Beacon Start Indication");
9412 		return;
9413 	}
9414 }
9415 
lim_mon_change_channel(struct mac_context * mac_ctx,struct pe_session * session_entry)9416 static void lim_mon_change_channel(
9417 	struct mac_context *mac_ctx,
9418 	struct pe_session *session_entry)
9419 {
9420 	if (wlan_vdev_mlme_get_state(session_entry->vdev) == WLAN_VDEV_S_INIT)
9421 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9422 					      WLAN_VDEV_SM_EV_START,
9423 					      sizeof(*session_entry),
9424 					      session_entry);
9425 	else if (wlan_vdev_mlme_get_state(session_entry->vdev) ==
9426 		 WLAN_VDEV_S_UP) {
9427 		mlme_set_chan_switch_in_progress(session_entry->vdev, true);
9428 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9429 					      WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
9430 					      sizeof(*session_entry),
9431 					      session_entry);
9432 	} else {
9433 		pe_err("Invalid vdev state to change channel");
9434 	}
9435 }
9436 
lim_change_channel(struct mac_context * mac_ctx,struct pe_session * session_entry)9437 static void lim_change_channel(
9438 	struct mac_context *mac_ctx,
9439 	struct pe_session *session_entry)
9440 {
9441 	if (session_entry->bssType == eSIR_MONITOR_MODE)
9442 		return lim_mon_change_channel(mac_ctx, session_entry);
9443 
9444 	mlme_set_chan_switch_in_progress(session_entry->vdev, true);
9445 
9446 	if (wlan_vdev_mlme_get_state(session_entry->vdev) ==
9447 	    WLAN_VDEV_S_DFS_CAC_WAIT)
9448 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9449 					      WLAN_VDEV_SM_EV_RADAR_DETECTED,
9450 					      sizeof(*session_entry),
9451 					      session_entry);
9452 	else
9453 		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9454 					      WLAN_VDEV_SM_EV_CSA_COMPLETE,
9455 					      sizeof(*session_entry),
9456 					      session_entry);
9457 }
9458 
9459 #ifdef WLAN_FEATURE_11BE
9460 static bool
lim_is_puncture_bitmap_changed(struct pe_session * session,struct channel_change_req * ch_change_req)9461 lim_is_puncture_bitmap_changed(struct pe_session *session,
9462 			       struct channel_change_req *ch_change_req)
9463 {
9464 	uint16_t ori_puncture_bitmap;
9465 
9466 	ori_puncture_bitmap =
9467 		*(uint16_t *)session->eht_op.disabled_sub_chan_bitmap;
9468 
9469 	return ori_puncture_bitmap != ch_change_req->target_punc_bitmap;
9470 }
9471 #else
9472 static inline bool
lim_is_puncture_bitmap_changed(struct pe_session * session,struct channel_change_req * ch_change_req)9473 lim_is_puncture_bitmap_changed(struct pe_session *session,
9474 			       struct channel_change_req *ch_change_req)
9475 {
9476 	return false;
9477 }
9478 #endif
9479 
9480 /**
9481  * lim_abort_channel_change() - Abort channel change
9482  *
9483  * @mac_ctx : Pointer to pe_session
9484  * @vdev_id: vdev ID
9485  *
9486  * This function is called to abort channel change request after CSA
9487  * countdown and allow SAP/GO to operate on current channel without
9488  * vdev restart.
9489  *
9490  * Return: None
9491  */
lim_abort_channel_change(struct mac_context * mac_ctx,uint8_t vdev_id)9492 static void lim_abort_channel_change(struct mac_context *mac_ctx,
9493 				     uint8_t vdev_id)
9494 {
9495 	struct qdf_mac_addr bssid;
9496 	struct pe_session *session_entry;
9497 	uint8_t session_id;
9498 	QDF_STATUS status;
9499 	struct scheduler_msg sch_msg = {0};
9500 	struct sSirChanChangeResponse *chan_change_rsp;
9501 
9502 	status = wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, vdev_id, &bssid);
9503 	if (!QDF_IS_STATUS_SUCCESS(status)) {
9504 		pe_err("Failed to get vdev ID");
9505 		return;
9506 	}
9507 
9508 	session_entry = pe_find_session_by_bssid(mac_ctx, bssid.bytes,
9509 						 &session_id);
9510 	if (!session_entry) {
9511 		pe_err("Session does not exist for bssid " QDF_MAC_ADDR_FMT,
9512 		       QDF_MAC_ADDR_REF(bssid.bytes));
9513 		return;
9514 	}
9515 
9516 	session_entry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_SAP_DFS;
9517 	mac_ctx->sap.SapDfsInfo.target_chan_freq =
9518 					session_entry->curr_op_freq;
9519 	mac_ctx->sap.SapDfsInfo.new_chanWidth = session_entry->ch_width;
9520 	mac_ctx->sap.SapDfsInfo.new_ch_params.ch_width =
9521 						session_entry->ch_width;
9522 
9523 	wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
9524 				      WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED,
9525 				      sizeof(*session_entry), session_entry);
9526 
9527 	chan_change_rsp = qdf_mem_malloc(sizeof(struct sSirChanChangeResponse));
9528 	if (!chan_change_rsp) {
9529 		pe_err("Failed to allocate chan_change_rsp");
9530 		return;
9531 	}
9532 
9533 	chan_change_rsp->new_op_freq = session_entry->curr_op_freq;
9534 	chan_change_rsp->channelChangeStatus = QDF_STATUS_SUCCESS;
9535 	chan_change_rsp->sessionId = session_id;
9536 	sch_msg.type = eWNI_SME_CHANNEL_CHANGE_RSP;
9537 	sch_msg.bodyptr = (void *)chan_change_rsp;
9538 	sch_msg.bodyval = 0;
9539 
9540 	lim_sys_process_mmh_msg_api(mac_ctx, &sch_msg);
9541 }
9542 
9543 #ifdef WLAN_FEATURE_11AX
9544 static inline void
lim_update_he_capable(struct pe_session * session,uint8_t dot11mode)9545 lim_update_he_capable(struct pe_session *session, uint8_t dot11mode)
9546 {
9547 	session->he_capable = IS_DOT11_MODE_HE(dot11mode);
9548 }
9549 #else
9550 static inline void
lim_update_he_capable(struct pe_session * session,uint8_t dot11mode)9551 lim_update_he_capable(struct pe_session *session, uint8_t dot11mode)
9552 {}
9553 #endif
9554 #ifdef WLAN_FEATURE_11BE
9555 static inline void
lim_update_eht_capable(struct pe_session * session,uint8_t dot11mode)9556 lim_update_eht_capable(struct pe_session *session, uint8_t dot11mode)
9557 {
9558 	session->eht_capable = IS_DOT11_MODE_EHT(dot11mode);
9559 }
9560 #else
9561 static inline void
lim_update_eht_capable(struct pe_session * session,uint8_t dot11mode)9562 lim_update_eht_capable(struct pe_session *session, uint8_t dot11mode)
9563 {}
9564 #endif
9565 
9566 
9567 /**
9568  * lim_process_sme_channel_change_request() - process sme ch change req
9569  *
9570  * @mac_ctx: Pointer to Global MAC structure
9571  * @msg_buf: pointer to the SME message buffer
9572  *
9573  * This function is called to process SME_CHANNEL_CHANGE_REQ message
9574  *
9575  * Return: None
9576  */
lim_process_sme_channel_change_request(struct mac_context * mac_ctx,uint32_t * msg_buf)9577 static void lim_process_sme_channel_change_request(struct mac_context *mac_ctx,
9578 		uint32_t *msg_buf)
9579 {
9580 	struct channel_change_req *ch_change_req;
9581 	struct qdf_mac_addr bssid;
9582 	struct pe_session *session_entry;
9583 	uint8_t session_id;      /* PE session_id */
9584 	int8_t max_tx_pwr;
9585 	uint32_t target_freq;
9586 	bool is_curr_ch_2g, is_new_ch_2g, update_he_cap, update_eht_cap;
9587 
9588 	if (!msg_buf) {
9589 		pe_err("msg_buf is NULL");
9590 		return;
9591 	}
9592 	ch_change_req = (struct channel_change_req *)msg_buf;
9593 	target_freq = ch_change_req->target_chan_freq;
9594 
9595 	max_tx_pwr = wlan_reg_get_channel_reg_power_for_freq(
9596 				mac_ctx->pdev, target_freq);
9597 	if (max_tx_pwr == WMA_MAX_TXPOWER_INVALID) {
9598 		pe_err("Invalid max tx power");
9599 		return;
9600 	}
9601 	wlan_mlme_get_mac_vdev_id(mac_ctx->pdev,
9602 				  ch_change_req->vdev_id, &bssid);
9603 	session_entry = pe_find_session_by_bssid(mac_ctx, bssid.bytes,
9604 						 &session_id);
9605 	if (!session_entry) {
9606 		pe_err("Session does not exist for bssid " QDF_MAC_ADDR_FMT,
9607 		       QDF_MAC_ADDR_REF(bssid.bytes));
9608 		return;
9609 	}
9610 
9611 	/*
9612 	 * The scenario here is, existing SAP/GO is operating on non-DFS chan
9613 	 * and STA connects to a DFS AP which creates MCC. This will then
9614 	 * trigger SCC enforcement logic. Now during CSA countdown (before
9615 	 * GO/SAP actually moves to STA's channel), if STA disconnects, then
9616 	 * moving GO / SAP to DFS channel will lead to FCC violation if radar
9617 	 * detection is disabled
9618 	 *
9619 	 * Hence to handle this scenario, better to stop current GO/SAP's
9620 	 * movement to this DFS channel and allow to operate on current channel
9621 	 * only, STA associated to GO/SAP's will find that SAP/GO didn't beacon
9622 	 * on new channel so Heartbeat failure will happen and they will scan
9623 	 * and connect again.
9624 	 */
9625 
9626 	if (LIM_IS_AP_ROLE(session_entry) &&
9627 	    !policy_mgr_is_sap_allowed_on_dfs_freq(mac_ctx->pdev, session_id,
9628 						   target_freq)) {
9629 		lim_abort_channel_change(mac_ctx, ch_change_req->vdev_id);
9630 		return;
9631 	} else if ((session_entry->curr_op_freq == target_freq &&
9632 		    session_entry->ch_width == ch_change_req->ch_width) &&
9633 		   (!IS_DOT11_MODE_EHT(session_entry->dot11mode) ||
9634 		    !lim_is_puncture_bitmap_changed(session_entry,
9635 						    ch_change_req))) {
9636 		pe_err("Target channel and mode is same as current channel and mode channel freq %d and mode %d",
9637 		       session_entry->curr_op_freq, session_entry->ch_width);
9638 		return;
9639 	}
9640 
9641 	if (LIM_IS_AP_ROLE(session_entry))
9642 		session_entry->channelChangeReasonCode =
9643 			LIM_SWITCH_CHANNEL_SAP_DFS;
9644 	else
9645 		session_entry->channelChangeReasonCode =
9646 			LIM_SWITCH_CHANNEL_MONITOR;
9647 
9648 	pe_nofl_debug("SAP CSA: %d ---> %d, ch_bw %d, nw_type %d, dot11mode %d, old dot11mode %d",
9649 		      session_entry->curr_op_freq, target_freq,
9650 		      ch_change_req->ch_width, ch_change_req->nw_type,
9651 		      ch_change_req->dot11mode, session_entry->dot11mode);
9652 
9653 	/* Update ht/vht/he/eht capability as per the new dot11mode */
9654 	if (ch_change_req->dot11mode != session_entry->dot11mode) {
9655 		session_entry->htCapability =
9656 			IS_DOT11_MODE_HT(ch_change_req->dot11mode);
9657 		session_entry->vhtCapability =
9658 			IS_DOT11_MODE_VHT(ch_change_req->dot11mode);
9659 		lim_update_he_capable(session_entry, ch_change_req->dot11mode);
9660 		lim_update_eht_capable(session_entry, ch_change_req->dot11mode);
9661 	}
9662 
9663 	if (IS_DOT11_MODE_HE(ch_change_req->dot11mode) &&
9664 		((QDF_MONITOR_MODE == session_entry->opmode) ||
9665 		lim_is_session_he_capable(session_entry))) {
9666 		lim_update_session_he_capable_chan_switch
9667 			(mac_ctx, session_entry, target_freq);
9668 		is_new_ch_2g = wlan_reg_is_24ghz_ch_freq(target_freq);
9669 		is_curr_ch_2g = wlan_reg_is_24ghz_ch_freq(
9670 					session_entry->curr_op_freq);
9671 		if ((is_new_ch_2g && !is_curr_ch_2g) ||
9672 		    (!is_new_ch_2g && is_curr_ch_2g))
9673 			update_he_cap = true;
9674 		else
9675 			update_he_cap = false;
9676 		if (!update_he_cap) {
9677 			if ((session_entry->ch_width !=
9678 			     ch_change_req->ch_width) &&
9679 			    (session_entry->ch_width > CH_WIDTH_80MHZ ||
9680 			     ch_change_req->ch_width > CH_WIDTH_80MHZ))
9681 				update_he_cap = true;
9682 		}
9683 		if (update_he_cap) {
9684 			session_entry->curr_op_freq = target_freq;
9685 			session_entry->ch_width = ch_change_req->ch_width;
9686 			lim_copy_bss_he_cap(session_entry);
9687 			lim_update_he_bw_cap_mcs(session_entry, NULL);
9688 		}
9689 	} else if (wlan_reg_is_6ghz_chan_freq(target_freq)) {
9690 		pe_debug("Invalid target_freq %d for dot11mode %d cur HE %d",
9691 			 target_freq, ch_change_req->dot11mode,
9692 			 lim_is_session_he_capable(session_entry));
9693 		return;
9694 	}
9695 
9696 	if (IS_DOT11_MODE_EHT(ch_change_req->dot11mode) &&
9697 	    ((QDF_MONITOR_MODE == session_entry->opmode) ||
9698 	     lim_is_session_eht_capable(session_entry))) {
9699 		lim_update_session_eht_capable_chan_switch(
9700 				mac_ctx, session_entry, target_freq);
9701 		is_new_ch_2g = wlan_reg_is_24ghz_ch_freq(target_freq);
9702 		is_curr_ch_2g = wlan_reg_is_24ghz_ch_freq(
9703 					session_entry->curr_op_freq);
9704 		if ((is_new_ch_2g && !is_curr_ch_2g) ||
9705 		    (!is_new_ch_2g && is_curr_ch_2g))
9706 			update_eht_cap = true;
9707 		else
9708 			update_eht_cap = false;
9709 		if (!update_eht_cap) {
9710 			if ((session_entry->ch_width !=
9711 			     ch_change_req->ch_width) &&
9712 			    (session_entry->ch_width > CH_WIDTH_80MHZ ||
9713 			     ch_change_req->ch_width > CH_WIDTH_80MHZ))
9714 				update_eht_cap = true;
9715 		}
9716 		if (update_eht_cap) {
9717 			session_entry->curr_op_freq = target_freq;
9718 			session_entry->ch_width = ch_change_req->ch_width;
9719 			lim_copy_bss_eht_cap(session_entry);
9720 			lim_update_eht_bw_cap_mcs(session_entry, NULL);
9721 		}
9722 	}
9723 
9724 	/* Store the New Channel Params in session_entry */
9725 	session_entry->ch_width = ch_change_req->ch_width;
9726 	session_entry->ch_center_freq_seg0 =
9727 			 ch_change_req->center_freq_seg0;
9728 	session_entry->ch_center_freq_seg1 =
9729 			ch_change_req->center_freq_seg1;
9730 	session_entry->htSecondaryChannelOffset = ch_change_req->sec_ch_offset;
9731 	session_entry->htSupportedChannelWidthSet =
9732 		(ch_change_req->ch_width ? 1 : 0);
9733 	session_entry->htRecommendedTxWidthSet =
9734 		session_entry->htSupportedChannelWidthSet;
9735 	session_entry->curr_op_freq = target_freq;
9736 	session_entry->limRFBand = lim_get_rf_band(
9737 		session_entry->curr_op_freq);
9738 	if (mlme_get_cac_required(session_entry->vdev))
9739 		session_entry->cac_duration_ms = ch_change_req->cac_duration_ms;
9740 	else
9741 		session_entry->cac_duration_ms = 0;
9742 	session_entry->dfs_regdomain = ch_change_req->dfs_regdomain;
9743 	session_entry->maxTxPower = max_tx_pwr;
9744 
9745 	/* Update the global beacon filter */
9746 	lim_update_bcn_probe_filter(mac_ctx, session_entry);
9747 
9748 	/* Initialize 11h Enable Flag */
9749 	if (CHAN_HOP_ALL_BANDS_ENABLE ||
9750 	    session_entry->limRFBand != REG_BAND_2G)
9751 		session_entry->lim11hEnable =
9752 			mac_ctx->mlme_cfg->gen.enabled_11h;
9753 	else
9754 		session_entry->lim11hEnable = 0;
9755 
9756 	session_entry->dot11mode = ch_change_req->dot11mode;
9757 	session_entry->nwType = ch_change_req->nw_type;
9758 	qdf_mem_copy(&session_entry->rateSet,
9759 		     &ch_change_req->opr_rates,
9760 		     sizeof(session_entry->rateSet));
9761 	qdf_mem_copy(&session_entry->extRateSet,
9762 		     &ch_change_req->ext_rates,
9763 		     sizeof(session_entry->extRateSet));
9764 	lim_change_channel(mac_ctx, session_entry);
9765 	lim_check_conc_power_for_csa(mac_ctx, session_entry);
9766 
9767 	lim_dump_session_info(mac_ctx, session_entry);
9768 	lim_dump_he_info(mac_ctx, session_entry);
9769 	lim_dump_eht_info(session_entry);
9770 }
9771 
9772 /******************************************************************************
9773 * lim_start_bss_update_add_ie_buffer()
9774 *
9775 ***FUNCTION:
9776 * This function checks the src buffer and its length and then malloc for
9777 * dst buffer update the same
9778 *
9779 ***LOGIC:
9780 *
9781 ***ASSUMPTIONS:
9782 *
9783 ***NOTE:
9784 *
9785 * @param  mac      Pointer to Global MAC structure
9786 * @param  **pDstData_buff  A pointer to pointer of  uint8_t dst buffer
9787 * @param  *pDstDataLen  A pointer to pointer of  uint16_t dst buffer length
9788 * @param  *pSrcData_buff  A pointer of  uint8_t  src buffer
9789 * @param  srcDataLen  src buffer length
9790 ******************************************************************************/
9791 
9792 static void
lim_start_bss_update_add_ie_buffer(struct mac_context * mac,uint8_t ** pDstData_buff,uint16_t * pDstDataLen,uint8_t * pSrcData_buff,uint16_t srcDataLen)9793 lim_start_bss_update_add_ie_buffer(struct mac_context *mac,
9794 				   uint8_t **pDstData_buff,
9795 				   uint16_t *pDstDataLen,
9796 				   uint8_t *pSrcData_buff, uint16_t srcDataLen)
9797 {
9798 
9799 	if (srcDataLen > 0 && pSrcData_buff) {
9800 		*pDstDataLen = srcDataLen;
9801 
9802 		*pDstData_buff = qdf_mem_malloc(*pDstDataLen);
9803 		if (!*pDstData_buff)
9804 			return;
9805 		qdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen);
9806 	} else {
9807 		*pDstData_buff = NULL;
9808 		*pDstDataLen = 0;
9809 	}
9810 }
9811 
9812 /******************************************************************************
9813 * lim_update_add_ie_buffer()
9814 *
9815 ***FUNCTION:
9816 * This function checks the src buffer and length if src buffer length more
9817 * than dst buffer length then free the dst buffer and malloc for the new src
9818 * length, and update the dst buffer and length. But if dst buffer is bigger
9819 * than src buffer length then it just update the dst buffer and length
9820 *
9821 ***LOGIC:
9822 *
9823 ***ASSUMPTIONS:
9824 *
9825 ***NOTE:
9826 *
9827 * @param  mac      Pointer to Global MAC structure
9828 * @param  **pDstData_buff  A pointer to pointer of  uint8_t dst buffer
9829 * @param  *pDstDataLen  A pointer to pointer of  uint16_t dst buffer length
9830 * @param  *pSrcData_buff  A pointer of  uint8_t  src buffer
9831 * @param  srcDataLen  src buffer length
9832 ******************************************************************************/
9833 
9834 static void
lim_update_add_ie_buffer(struct mac_context * mac,uint8_t ** pDstData_buff,uint16_t * pDstDataLen,uint8_t * pSrcData_buff,uint16_t srcDataLen)9835 lim_update_add_ie_buffer(struct mac_context *mac,
9836 			 uint8_t **pDstData_buff,
9837 			 uint16_t *pDstDataLen,
9838 			 uint8_t *pSrcData_buff, uint16_t srcDataLen)
9839 {
9840 
9841 	if (!pSrcData_buff) {
9842 		pe_err("src buffer is null");
9843 		return;
9844 	}
9845 
9846 	if (srcDataLen > *pDstDataLen) {
9847 		*pDstDataLen = srcDataLen;
9848 		/* free old buffer */
9849 		qdf_mem_free(*pDstData_buff);
9850 		/* allocate a new */
9851 		*pDstData_buff = qdf_mem_malloc(*pDstDataLen);
9852 		if (!*pDstData_buff) {
9853 			*pDstDataLen = 0;
9854 			return;
9855 		}
9856 	}
9857 
9858 	/* copy the content of buffer into dst buffer
9859 	 */
9860 	*pDstDataLen = srcDataLen;
9861 	qdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen);
9862 
9863 }
9864 
9865 /*
9866 * lim_process_modify_add_ies() - process modify additional IE req.
9867 *
9868 * @mac_ctx: Pointer to Global MAC structure
9869 * @msg_buf: pointer to the SME message buffer
9870 *
9871 * This function update the PE buffers for additional IEs.
9872 *
9873 * Return: None
9874 */
lim_process_modify_add_ies(struct mac_context * mac_ctx,uint32_t * msg_buf)9875 static void lim_process_modify_add_ies(struct mac_context *mac_ctx,
9876 		uint32_t *msg_buf)
9877 {
9878 	tpSirModifyIEsInd modify_add_ies;
9879 	struct pe_session *session_entry;
9880 	uint8_t session_id;
9881 	bool ret = false;
9882 	struct add_ie_params *add_ie_params;
9883 
9884 	if (!msg_buf) {
9885 		pe_err("msg_buf is NULL");
9886 		return;
9887 	}
9888 
9889 	modify_add_ies = (tpSirModifyIEsInd)msg_buf;
9890 	/* Incoming message has smeSession, use BSSID to find PE session */
9891 	session_entry = pe_find_session_by_bssid(mac_ctx,
9892 			modify_add_ies->modifyIE.bssid.bytes, &session_id);
9893 
9894 	if (!session_entry) {
9895 		pe_err("Session not found for given bssid"
9896 					QDF_MAC_ADDR_FMT,
9897 		QDF_MAC_ADDR_REF(modify_add_ies->modifyIE.bssid.bytes));
9898 		goto end;
9899 	}
9900 	if ((0 == modify_add_ies->modifyIE.ieBufferlength) ||
9901 		(0 == modify_add_ies->modifyIE.ieIDLen) ||
9902 		(!modify_add_ies->modifyIE.pIEBuffer)) {
9903 		pe_err("Invalid request pIEBuffer %pK ieBufferlength %d ieIDLen %d ieID %d. update Type %d",
9904 				modify_add_ies->modifyIE.pIEBuffer,
9905 				modify_add_ies->modifyIE.ieBufferlength,
9906 				modify_add_ies->modifyIE.ieID,
9907 				modify_add_ies->modifyIE.ieIDLen,
9908 				modify_add_ies->updateType);
9909 		goto end;
9910 	}
9911 	add_ie_params = &session_entry->add_ie_params;
9912 	switch (modify_add_ies->updateType) {
9913 	case eUPDATE_IE_PROBE_RESP:
9914 		/* Probe resp */
9915 		break;
9916 	case eUPDATE_IE_ASSOC_RESP:
9917 		/* assoc resp IE */
9918 		if (!add_ie_params->assocRespDataLen)
9919 			pe_err("assoc resp add ie not present");
9920 		/* search through the buffer and modify the IE */
9921 		break;
9922 	case eUPDATE_IE_PROBE_BCN:
9923 		/*probe beacon IE */
9924 		if (ret == true && modify_add_ies->modifyIE.notify) {
9925 			lim_handle_param_update(mac_ctx,
9926 					modify_add_ies->updateType);
9927 		}
9928 		break;
9929 	default:
9930 		pe_err("unhandled buffer type %d",
9931 				modify_add_ies->updateType);
9932 		break;
9933 	}
9934 end:
9935 	qdf_mem_free(modify_add_ies->modifyIE.pIEBuffer);
9936 	modify_add_ies->modifyIE.pIEBuffer = NULL;
9937 }
9938 
9939 /*
9940 * lim_process_update_add_ies() - process additional IE update req
9941 *
9942 * @mac_ctx: Pointer to Global MAC structure
9943 * @msg_buf: pointer to the SME message buffer
9944 *
9945 * This function update the PE buffers for additional IEs.
9946 *
9947 * Return: None
9948 */
lim_process_update_add_ies(struct mac_context * mac_ctx,uint32_t * msg_buf)9949 static void lim_process_update_add_ies(struct mac_context *mac_ctx,
9950 		uint32_t *msg_buf)
9951 {
9952 	tpSirUpdateIEsInd update_add_ies = (tpSirUpdateIEsInd)msg_buf;
9953 	uint8_t session_id;
9954 	struct pe_session *session_entry;
9955 	struct add_ie_params *addn_ie;
9956 	uint16_t new_length = 0;
9957 	uint8_t *new_ptr = NULL;
9958 	tSirUpdateIE *update_ie;
9959 
9960 	if (!msg_buf) {
9961 		pe_err("msg_buf is NULL");
9962 		return;
9963 	}
9964 	update_ie = &update_add_ies->updateIE;
9965 	/* incoming message has smeSession, use BSSID to find PE session */
9966 	session_entry = pe_find_session_by_bssid(mac_ctx,
9967 			update_ie->bssid.bytes, &session_id);
9968 
9969 	if (!session_entry) {
9970 		pe_debug("Session not found for given bssid"
9971 			 QDF_MAC_ADDR_FMT,
9972 			 QDF_MAC_ADDR_REF(update_ie->bssid.bytes));
9973 		goto end;
9974 	}
9975 	addn_ie = &session_entry->add_ie_params;
9976 	/* if len is 0, upper layer requested freeing of buffer */
9977 	if (0 == update_ie->ieBufferlength) {
9978 		switch (update_add_ies->updateType) {
9979 		case eUPDATE_IE_PROBE_RESP:
9980 			qdf_mem_free(addn_ie->probeRespData_buff);
9981 			addn_ie->probeRespData_buff = NULL;
9982 			addn_ie->probeRespDataLen = 0;
9983 			break;
9984 		case eUPDATE_IE_ASSOC_RESP:
9985 			qdf_mem_free(addn_ie->assocRespData_buff);
9986 			addn_ie->assocRespData_buff = NULL;
9987 			addn_ie->assocRespDataLen = 0;
9988 			break;
9989 		case eUPDATE_IE_PROBE_BCN:
9990 			qdf_mem_free(addn_ie->probeRespBCNData_buff);
9991 			addn_ie->probeRespBCNData_buff = NULL;
9992 			addn_ie->probeRespBCNDataLen = 0;
9993 
9994 			if (update_ie->notify)
9995 				lim_handle_param_update(mac_ctx,
9996 						update_add_ies->updateType);
9997 			break;
9998 		default:
9999 			break;
10000 		}
10001 		return;
10002 	}
10003 	switch (update_add_ies->updateType) {
10004 	case eUPDATE_IE_PROBE_RESP:
10005 		if (update_ie->append) {
10006 			/*
10007 			 * In case of append, allocate new memory
10008 			 * with combined length.
10009 			 * Multiple back to back append commands
10010 			 * can lead to a huge length.So, check
10011 			 * for the validity of the length.
10012 			 */
10013 			if (addn_ie->probeRespDataLen >
10014 				(USHRT_MAX - update_ie->ieBufferlength)) {
10015 				pe_err("IE Length overflow, curr:%d, new:%d",
10016 					addn_ie->probeRespDataLen,
10017 					update_ie->ieBufferlength);
10018 				goto end;
10019 			}
10020 			new_length = update_ie->ieBufferlength +
10021 				addn_ie->probeRespDataLen;
10022 			new_ptr = qdf_mem_malloc(new_length);
10023 			if (!new_ptr)
10024 				goto end;
10025 			/* append buffer to end of local buffers */
10026 			qdf_mem_copy(new_ptr, addn_ie->probeRespData_buff,
10027 					addn_ie->probeRespDataLen);
10028 			qdf_mem_copy(&new_ptr[addn_ie->probeRespDataLen],
10029 				     update_ie->pAdditionIEBuffer,
10030 				     update_ie->ieBufferlength);
10031 			/* free old memory */
10032 			qdf_mem_free(addn_ie->probeRespData_buff);
10033 			/* adjust length accordingly */
10034 			addn_ie->probeRespDataLen = new_length;
10035 			/* save reference of local buffer in PE session */
10036 			addn_ie->probeRespData_buff = new_ptr;
10037 			goto end;
10038 		}
10039 		lim_update_add_ie_buffer(mac_ctx, &addn_ie->probeRespData_buff,
10040 				&addn_ie->probeRespDataLen,
10041 				update_ie->pAdditionIEBuffer,
10042 				update_ie->ieBufferlength);
10043 		break;
10044 	case eUPDATE_IE_ASSOC_RESP:
10045 		/* assoc resp IE */
10046 		lim_update_add_ie_buffer(mac_ctx, &addn_ie->assocRespData_buff,
10047 				&addn_ie->assocRespDataLen,
10048 				update_ie->pAdditionIEBuffer,
10049 				update_ie->ieBufferlength);
10050 		break;
10051 	case eUPDATE_IE_PROBE_BCN:
10052 		/* probe resp Bcn IE */
10053 		lim_update_add_ie_buffer(mac_ctx,
10054 				&addn_ie->probeRespBCNData_buff,
10055 				&addn_ie->probeRespBCNDataLen,
10056 				update_ie->pAdditionIEBuffer,
10057 				update_ie->ieBufferlength);
10058 		if (update_ie->notify)
10059 			lim_handle_param_update(mac_ctx,
10060 					update_add_ies->updateType);
10061 		break;
10062 	default:
10063 		pe_err("unhandled buffer type %d", update_add_ies->updateType);
10064 		break;
10065 	}
10066 end:
10067 	qdf_mem_free(update_ie->pAdditionIEBuffer);
10068 	update_ie->pAdditionIEBuffer = NULL;
10069 }
10070 
send_extended_chan_switch_action_frame(struct mac_context * mac_ctx,uint16_t new_channel_freq,enum phy_ch_width ch_bandwidth,struct pe_session * session_entry)10071 void send_extended_chan_switch_action_frame(struct mac_context *mac_ctx,
10072 					    uint16_t new_channel_freq,
10073 					    enum phy_ch_width ch_bandwidth,
10074 					    struct pe_session *session_entry)
10075 {
10076 	uint8_t op_class = 0;
10077 	uint8_t switch_mode = 0, i;
10078 	tpDphHashNode psta;
10079 	uint8_t new_channel = 0;
10080 	enum phy_ch_width ch_width;
10081 	tLimChannelSwitchInfo *ch_switch = &session_entry->gLimChannelSwitch;
10082 
10083 	op_class =
10084 		lim_op_class_from_bandwidth(mac_ctx, new_channel_freq,
10085 					    ch_bandwidth,
10086 					    ch_switch->sec_ch_offset);
10087 	new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq);
10088 	if (LIM_IS_AP_ROLE(session_entry) &&
10089 		(mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false))
10090 		switch_mode = ch_switch->switchMode;
10091 
10092 	if (LIM_IS_AP_ROLE(session_entry)) {
10093 		for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) {
10094 			psta =
10095 			  session_entry->dph.dphHashTable.pDphNodeArray + i;
10096 			if (!psta || !psta->added)
10097 				continue;
10098 			ch_width = lim_calculate_peer_ch_width(session_entry,
10099 							       psta->staAddr,
10100 							       ch_bandwidth);
10101 			op_class = lim_op_class_from_bandwidth(mac_ctx,
10102 						new_channel_freq, ch_width,
10103 						ch_switch->sec_ch_offset);
10104 			lim_send_extended_chan_switch_action_frame(
10105 					mac_ctx, psta->staAddr,
10106 					switch_mode, op_class, new_channel,
10107 					ch_switch->switchCount, session_entry);
10108 		}
10109 	} else if (LIM_IS_STA_ROLE(session_entry)) {
10110 		lim_send_extended_chan_switch_action_frame(mac_ctx,
10111 					session_entry->bssId,
10112 					switch_mode, op_class, new_channel,
10113 					ch_switch->switchCount,
10114 					session_entry);
10115 	}
10116 
10117 }
10118 
lim_send_chan_switch_action_frame(struct mac_context * mac_ctx,uint16_t new_channel_freq,enum phy_ch_width ch_bandwidth,struct pe_session * session_entry)10119 void lim_send_chan_switch_action_frame(struct mac_context *mac_ctx,
10120 				       uint16_t new_channel_freq,
10121 				       enum phy_ch_width ch_bandwidth,
10122 				       struct pe_session *session_entry)
10123 {
10124 	uint8_t op_class = 0, new_channel;
10125 	uint8_t switch_mode = 0, i;
10126 	uint8_t switch_count;
10127 	tpDphHashNode psta;
10128 	tpDphHashNode dph_node_array_ptr;
10129 
10130 	dph_node_array_ptr = session_entry->dph.dphHashTable.pDphNodeArray;
10131 	op_class =
10132 		lim_op_class_from_bandwidth(mac_ctx, new_channel_freq,
10133 					    ch_bandwidth,
10134 					    session_entry->gLimChannelSwitch.sec_ch_offset);
10135 	new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq);
10136 
10137 	if (LIM_IS_AP_ROLE(session_entry) &&
10138 	    (false == mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch))
10139 		switch_mode = session_entry->gLimChannelSwitch.switchMode;
10140 
10141 	switch_count = session_entry->gLimChannelSwitch.switchCount;
10142 
10143 	if (LIM_IS_AP_ROLE(session_entry)) {
10144 		for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) {
10145 			psta = dph_node_array_ptr + i;
10146 			if (!(psta && psta->added))
10147 				continue;
10148 			if (session_entry->lim_non_ecsa_cap_num == 0)
10149 				lim_send_extended_chan_switch_action_frame
10150 					(mac_ctx, psta->staAddr, switch_mode,
10151 					 op_class, new_channel, switch_count,
10152 					 session_entry);
10153 			else
10154 				lim_send_channel_switch_mgmt_frame
10155 					(mac_ctx, psta->staAddr, switch_mode,
10156 					 new_channel, switch_count,
10157 					 session_entry);
10158 		}
10159 	} else if (LIM_IS_STA_ROLE(session_entry)) {
10160 		lim_send_extended_chan_switch_action_frame
10161 			(mac_ctx, session_entry->bssId, switch_mode, op_class,
10162 			 new_channel, switch_count, session_entry);
10163 	}
10164 }
10165 
10166 /**
10167  * lim_process_sme_dfs_csa_ie_request() - process sme dfs csa ie req
10168  *
10169  * @mac_ctx: Pointer to Global MAC structure
10170  * @msg_buf: pointer to the SME message buffer
10171  *
10172  * This function processes SME request messages from HDD or upper layer
10173  * application.
10174  *
10175  * Return: None
10176  */
lim_process_sme_dfs_csa_ie_request(struct mac_context * mac_ctx,uint32_t * msg_buf)10177 static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx,
10178 		uint32_t *msg_buf)
10179 {
10180 	tpSirDfsCsaIeRequest dfs_csa_ie_req;
10181 	struct pe_session *session_entry = NULL;
10182 	uint8_t session_id;
10183 	tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch;
10184 	QDF_STATUS status;
10185 	enum phy_ch_width ch_width;
10186 	uint32_t target_ch_freq;
10187 	bool is_vdev_ll_lt_sap = false;
10188 	uint8_t peer_count;
10189 	uint16_t max_wait_for_bcn_tx_complete;
10190 
10191 	if (!msg_buf) {
10192 		pe_err("Buffer is Pointing to NULL");
10193 		return;
10194 	}
10195 
10196 	dfs_csa_ie_req = (tSirDfsCsaIeRequest *)msg_buf;
10197 	session_entry = pe_find_session_by_bssid(mac_ctx,
10198 			dfs_csa_ie_req->bssid, &session_id);
10199 	if (!session_entry) {
10200 		pe_err("Session not found for given BSSID" QDF_MAC_ADDR_FMT,
10201 			QDF_MAC_ADDR_REF(dfs_csa_ie_req->bssid));
10202 		return;
10203 	}
10204 
10205 	if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
10206 		pe_err("Invalid SystemRole %d",
10207 			GET_LIM_SYSTEM_ROLE(session_entry));
10208 		return;
10209 	}
10210 
10211 	/* target channel */
10212 	session_entry->gLimChannelSwitch.primaryChannel =
10213 		wlan_reg_freq_to_chan(mac_ctx->pdev,
10214 				      dfs_csa_ie_req->target_chan_freq);
10215 	session_entry->gLimChannelSwitch.sw_target_freq =
10216 		dfs_csa_ie_req->target_chan_freq;
10217 	target_ch_freq = dfs_csa_ie_req->target_chan_freq;
10218 	/* Channel switch announcement needs to be included in beacon */
10219 	session_entry->dfsIncludeChanSwIe = true;
10220 
10221 	wlan_reg_set_create_punc_bitmap(&dfs_csa_ie_req->ch_params, false);
10222 	wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
10223 						dfs_csa_ie_req->target_chan_freq,
10224 						0,
10225 						&dfs_csa_ie_req->ch_params,
10226 						REG_CURRENT_PWR_MODE);
10227 
10228 	ch_width = dfs_csa_ie_req->ch_params.ch_width;
10229 	if (ch_width >= CH_WIDTH_160MHZ &&
10230 	    wma_get_vht_ch_width() < WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
10231 		ch_width = CH_WIDTH_80MHZ;
10232 	}
10233 	session_entry->gLimChannelSwitch.ch_width = ch_width;
10234 	session_entry->gLimChannelSwitch.sec_ch_offset =
10235 				 dfs_csa_ie_req->ch_params.sec_ch_offset;
10236 
10237 	is_vdev_ll_lt_sap = policy_mgr_is_vdev_ll_lt_sap(
10238 						mac_ctx->psoc,
10239 						session_entry->vdev_id);
10240 
10241 	if (is_vdev_ll_lt_sap) {
10242 		session_entry->gLimChannelSwitch.switchCount = 1;
10243 		session_entry->gLimChannelSwitch.switchMode = 0;
10244 	} else {
10245 		session_entry->gLimChannelSwitch.switchCount =
10246 			dfs_csa_ie_req->ch_switch_beacon_cnt;
10247 		if (!mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch)
10248 			session_entry->gLimChannelSwitch.switchMode =
10249 					dfs_csa_ie_req->ch_switch_mode;
10250 	}
10251 
10252 	/*
10253 	 * Validate if SAP is operating HT or VHT/HE mode and set the Channel
10254 	 * Switch Wrapper element with the Wide Band Switch subelement.
10255 	 */
10256 	if (!(session_entry->vhtCapability ||
10257 	      lim_is_session_he_capable(session_entry)))
10258 		goto skip_vht;
10259 
10260 	/* Now encode the Wider Ch BW element depending on the ch width */
10261 	wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch;
10262 	switch (ch_width) {
10263 	case CH_WIDTH_20MHZ:
10264 		/*
10265 		 * Wide channel BW sublement in channel wrapper element is not
10266 		 * required in case of 20 Mhz operation. Currently It is set
10267 		 * only set in case of 40/80 Mhz Operation.
10268 		 */
10269 		session_entry->dfsIncludeChanWrapperIe = false;
10270 		wider_bw_ch_switch->newChanWidth =
10271 			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
10272 		break;
10273 	case CH_WIDTH_40MHZ:
10274 		session_entry->dfsIncludeChanWrapperIe = false;
10275 		wider_bw_ch_switch->newChanWidth =
10276 			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
10277 		break;
10278 	case CH_WIDTH_80MHZ:
10279 		session_entry->dfsIncludeChanWrapperIe = true;
10280 		wider_bw_ch_switch->newChanWidth =
10281 			WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
10282 		break;
10283 	case CH_WIDTH_160MHZ:
10284 		session_entry->dfsIncludeChanWrapperIe = true;
10285 		wider_bw_ch_switch->newChanWidth =
10286 			WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
10287 		break;
10288 	case CH_WIDTH_80P80MHZ:
10289 		session_entry->dfsIncludeChanWrapperIe = true;
10290 		wider_bw_ch_switch->newChanWidth =
10291 			WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
10292 		/*
10293 		 * This is not applicable for 20/40/80 Mhz.
10294 		 * Only used when we support 80+80 Mhz operation.
10295 		 * In case of 80+80 Mhz, this parameter indicates
10296 		 * center channel frequency index of 80 Mhz channel of
10297 		 * frequency segment 1.
10298 		 */
10299 		wider_bw_ch_switch->newCenterChanFreq1 =
10300 			dfs_csa_ie_req->ch_params.center_freq_seg1;
10301 		break;
10302 	default:
10303 		session_entry->dfsIncludeChanWrapperIe = false;
10304 		/*
10305 		 * Need to handle 80+80 Mhz Scenario. When 80+80 is supported
10306 		 * set the gLimWiderBWChannelSwitch.newChanWidth to 3
10307 		 */
10308 		pe_err("Invalid Channel Width");
10309 		break;
10310 	}
10311 	/* Fetch the center channel based on the channel width */
10312 	wider_bw_ch_switch->newCenterChanFreq0 =
10313 		dfs_csa_ie_req->ch_params.center_freq_seg0;
10314 skip_vht:
10315 
10316 	/* Take a wakelock for CSA for 5 seconds and release in vdev start */
10317 
10318 	qdf_wake_lock_timeout_acquire(&session_entry->ap_ecsa_wakelock,
10319 				      MAX_WAKELOCK_FOR_CSA);
10320 	qdf_runtime_pm_prevent_suspend(&session_entry->ap_ecsa_runtime_lock);
10321 
10322 	session_entry->cac_duration_ms = dfs_csa_ie_req->new_chan_cac_ms;
10323 	wlan_util_vdev_mgr_set_cac_timeout_for_vdev(
10324 		session_entry->vdev, dfs_csa_ie_req->new_chan_cac_ms);
10325 
10326 	peer_count = wlan_vdev_get_peer_sta_count(session_entry->vdev);
10327 
10328 	if (is_vdev_ll_lt_sap && !peer_count) {
10329 		pe_debug("Peer count is 0 for LL_LT_SAP, continue CSA directly");
10330 		/* initiate vdev restart if no peer connected on XPAN */
10331 		lim_send_csa_tx_complete(session_entry->vdev_id);
10332 		/* Clear CSA IE count and update beacon */
10333 		lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry);
10334 		return;
10335 	}
10336 
10337 	/* Send CSA IE request from here */
10338 	lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry);
10339 
10340 	/*
10341 	 * Wait for max_wait_for_bcn_tx_complete ms for tx complete for beacon.
10342 	 * If tx complete for beacon is received before this timer expire,
10343 	 * stop this timer and then this will be restarted for every beacon
10344 	 * interval until switchCount become 0 and bcn template with new
10345 	 * switchCount will be sent to firmware.
10346 	 * OR
10347 	 * If no tx complete for beacon is received till this timer expire
10348 	 * this will be restarted for every beacon interval until switchCount
10349 	 * become 0 and bcn template with new switchCount will be sent to
10350 	 * firmware.
10351 	 */
10352 	if (is_vdev_ll_lt_sap)
10353 		max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE_FOR_LL_SAP;
10354 	else
10355 		max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE;
10356 
10357 	status = qdf_mc_timer_start(&session_entry->ap_ecsa_timer,
10358 				    max_wait_for_bcn_tx_complete);
10359 
10360 	if (QDF_IS_STATUS_ERROR(status))
10361 		pe_err("cannot start ap_ecsa_timer");
10362 
10363 	lim_cp_stats_cstats_log_csa_evt(
10364 			session_entry, CSTATS_DIR_TX,
10365 			session_entry->gLimChannelSwitch.sw_target_freq,
10366 			session_entry->gLimChannelSwitch.ch_width,
10367 			session_entry->gLimChannelSwitch.switchMode);
10368 
10369 	pe_debug("IE count:%d chan:%d freq %d width:%d wrapper:%d ch_offset:%d",
10370 		 session_entry->gLimChannelSwitch.switchCount,
10371 		 session_entry->gLimChannelSwitch.primaryChannel,
10372 		 session_entry->gLimChannelSwitch.sw_target_freq,
10373 		 session_entry->gLimChannelSwitch.ch_width,
10374 		 session_entry->dfsIncludeChanWrapperIe,
10375 		 session_entry->gLimChannelSwitch.sec_ch_offset);
10376 
10377 	/*
10378 	 * Send ECSA/CSA Action frame after updating the beacon.
10379 	 * For LL_LT_SAP, send ECSA action frame only
10380 	 */
10381 	if (CHAN_HOP_ALL_BANDS_ENABLE &&
10382 	    session_entry->lim_non_ecsa_cap_num &&
10383 	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(target_ch_freq) &&
10384 	    !is_vdev_ll_lt_sap)
10385 		lim_send_chan_switch_action_frame
10386 			(mac_ctx,
10387 			 session_entry->gLimChannelSwitch.primaryChannel,
10388 			 ch_width, session_entry);
10389 	else
10390 		send_extended_chan_switch_action_frame
10391 			(mac_ctx, target_ch_freq, ch_width,
10392 			 session_entry);
10393 }
10394 
10395 /**
10396  * lim_process_ext_change_channel()- function to send ECSA
10397  * action frame for STA/CLI .
10398  * @mac_ctx: pointer to global mac structure
10399  * @msg: params from sme for new channel.
10400  *
10401  * This function is called to send ECSA frame for STA/CLI.
10402  *
10403  * Return: void
10404  */
10405 
lim_process_ext_change_channel(struct mac_context * mac_ctx,uint32_t * msg)10406 static void lim_process_ext_change_channel(struct mac_context *mac_ctx,
10407 							uint32_t *msg)
10408 {
10409 	struct sir_sme_ext_cng_chan_req *ext_chng_channel =
10410 				(struct sir_sme_ext_cng_chan_req *) msg;
10411 	struct pe_session *session_entry = NULL;
10412 
10413 	if (!msg) {
10414 		pe_err("Buffer is Pointing to NULL");
10415 		return;
10416 	}
10417 	session_entry =
10418 		pe_find_session_by_vdev_id(mac_ctx, ext_chng_channel->vdev_id);
10419 	if (!session_entry) {
10420 		pe_err("Session not found for given vdev_id %d",
10421 			ext_chng_channel->vdev_id);
10422 		return;
10423 	}
10424 	if (LIM_IS_AP_ROLE(session_entry)) {
10425 		pe_err("not an STA/CLI session");
10426 		return;
10427 	}
10428 	session_entry->gLimChannelSwitch.sec_ch_offset = 0;
10429 	send_extended_chan_switch_action_frame(mac_ctx,
10430 					       ext_chng_channel->new_ch_freq, 0,
10431 					       session_entry);
10432 }
10433 
10434 /**
10435  * lim_process_nss_update_request() - process sme nss update req
10436  *
10437  * @mac_ctx: Pointer to Global MAC structure
10438  * @msg_buf: pointer to the SME message buffer
10439  *
10440  * This function processes SME request messages from HDD or upper layer
10441  * application.
10442  *
10443  * Return: None
10444  */
lim_process_nss_update_request(struct mac_context * mac_ctx,uint32_t * msg_buf)10445 static void lim_process_nss_update_request(struct mac_context *mac_ctx,
10446 		uint32_t *msg_buf)
10447 {
10448 	struct sir_nss_update_request *nss_update_req_ptr;
10449 	struct pe_session *session_entry = NULL;
10450 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
10451 	uint8_t vdev_id;
10452 
10453 	if (!msg_buf) {
10454 		pe_err("Buffer is Pointing to NULL");
10455 		return;
10456 	}
10457 
10458 	nss_update_req_ptr = (struct sir_nss_update_request *)msg_buf;
10459 	vdev_id = nss_update_req_ptr->vdev_id;
10460 	session_entry = pe_find_session_by_vdev_id(mac_ctx,
10461 						   nss_update_req_ptr->vdev_id);
10462 	if (!session_entry) {
10463 		pe_err("Session not found for given session_id %d",
10464 			nss_update_req_ptr->vdev_id);
10465 		goto end;
10466 	}
10467 
10468 	if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
10469 		pe_err("Invalid SystemRole %d",
10470 			GET_LIM_SYSTEM_ROLE(session_entry));
10471 		goto end;
10472 	}
10473 
10474 	/* populate nss field in the beacon */
10475 	session_entry->gLimOperatingMode.present = 1;
10476 	session_entry->gLimOperatingMode.rxNSS = nss_update_req_ptr->new_nss;
10477 	session_entry->gLimOperatingMode.chanWidth = session_entry->ch_width;
10478 
10479 	if ((nss_update_req_ptr->new_nss == NSS_1x1_MODE) &&
10480 			(session_entry->ch_width > CH_WIDTH_80MHZ))
10481 		session_entry->gLimOperatingMode.chanWidth = CH_WIDTH_80MHZ;
10482 	if (session_entry->gLimOperatingMode.chanWidth <= CH_WIDTH_160MHZ &&
10483 	    nss_update_req_ptr->ch_width <
10484 			session_entry->gLimOperatingMode.chanWidth)
10485 		session_entry->gLimOperatingMode.chanWidth =
10486 			nss_update_req_ptr->ch_width;
10487 
10488 	pe_debug("ch width %d Rx NSS %d",
10489 		 session_entry->gLimOperatingMode.chanWidth,
10490 		 session_entry->gLimOperatingMode.rxNSS);
10491 
10492 	/* Send nss update request from here */
10493 	status = sch_set_fixed_beacon_fields(mac_ctx, session_entry);
10494 	if (QDF_IS_STATUS_ERROR(status)) {
10495 		pe_err("Unable to set op mode IE in beacon");
10496 		goto end;
10497 	}
10498 
10499 	status = lim_send_beacon_ind(mac_ctx, session_entry, REASON_NSS_UPDATE);
10500 	if (QDF_IS_STATUS_SUCCESS(status))
10501 		return;
10502 
10503 	pe_err("Unable to send beacon");
10504 end:
10505 	/*
10506 	 * send resp only in case of failure,
10507 	 * success case response will be from wma.
10508 	 */
10509 	lim_nss_or_ch_width_update_rsp(mac_ctx, vdev_id, status,
10510 				       REASON_NSS_UPDATE);
10511 }
10512 
10513 /**
10514  * lim_process_set_ie_req() - process sme set IE request
10515  *
10516  * @mac_ctx: Pointer to Global MAC structure
10517  * @msg_buf: pointer to the SME message buffer
10518  *
10519  * This function processes SME request messages from HDD or upper layer
10520  * application.
10521  *
10522  * Return: None
10523  */
lim_process_set_ie_req(struct mac_context * mac_ctx,uint32_t * msg_buf)10524 static void lim_process_set_ie_req(struct mac_context *mac_ctx, uint32_t *msg_buf)
10525 {
10526 	struct send_extcap_ie *msg;
10527 	QDF_STATUS status;
10528 	tDot11fIEExtCap extra_ext_cap = {0};
10529 	uint16_t vdev_id;
10530 	struct wlan_objmgr_vdev *vdev = NULL;
10531 	struct mlme_legacy_priv *mlme_priv;
10532 	struct s_ext_cap *p_ext_cap;
10533 
10534 	if (!msg_buf) {
10535 		pe_err("Buffer is Pointing to NULL");
10536 		return;
10537 	}
10538 
10539 	msg = (struct send_extcap_ie *)msg_buf;
10540 	vdev_id = msg->session_id;
10541 
10542 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
10543 						    vdev_id,
10544 						    WLAN_LEGACY_SME_ID);
10545 	if (!vdev)
10546 		return;
10547 
10548 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
10549 	if (!mlme_priv) {
10550 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
10551 		return;
10552 	}
10553 
10554 	if (!mlme_priv->connect_info.ext_cap_ie[0])
10555 		goto send_ie;
10556 
10557 	lim_update_extcap_struct(mac_ctx,
10558 				 mlme_priv->connect_info.ext_cap_ie,
10559 				 &extra_ext_cap);
10560 	p_ext_cap = (struct s_ext_cap *)extra_ext_cap.bytes;
10561 	if (p_ext_cap->interworking_service)
10562 		p_ext_cap->qos_map = 1;
10563 	extra_ext_cap.num_bytes =
10564 		lim_compute_ext_cap_ie_length(&extra_ext_cap);
10565 send_ie:
10566 	status = lim_send_ext_cap_ie(mac_ctx, msg->session_id, &extra_ext_cap,
10567 				     true);
10568 	if (QDF_IS_STATUS_ERROR(status))
10569 		pe_err("Unable to send ExtCap to FW");
10570 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
10571 }
10572 
10573 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
10574 
10575 /**
10576  * obss_color_collision_process_color_disable() - Disable bss color
10577  * @mac_ctx: Pointer to Global MAC structure
10578  * @session: pointer to session
10579  *
10580  * This function will disable bss color.
10581  *
10582  * Return: None
10583  */
obss_color_collision_process_color_disable(struct mac_context * mac_ctx,struct pe_session * session)10584 static void obss_color_collision_process_color_disable(struct mac_context *mac_ctx,
10585 						       struct pe_session *session)
10586 {
10587 	tUpdateBeaconParams beacon_params;
10588 
10589 	if (!session) {
10590 		pe_err("Invalid session");
10591 		return;
10592 	}
10593 
10594 	if (session->valid && !LIM_IS_AP_ROLE(session)) {
10595 		pe_err("Invalid SystemRole %d",
10596 		       GET_LIM_SYSTEM_ROLE(session));
10597 		return;
10598 	}
10599 
10600 	if (session->bss_color_changing == 1) {
10601 		pe_warn("%d: color change in progress", session->smeSessionId);
10602 		/* Continue color collision detection */
10603 		lim_send_obss_color_collision_cfg(mac_ctx, session,
10604 				OBSS_COLOR_COLLISION_DETECTION);
10605 		return;
10606 	}
10607 
10608 	if (session->he_op.bss_col_disabled == 1) {
10609 		pe_warn("%d: bss color already disabled",
10610 			session->smeSessionId);
10611 		/* Continue free color detection */
10612 		lim_send_obss_color_collision_cfg(mac_ctx, session,
10613 				OBSS_COLOR_FREE_SLOT_AVAILABLE);
10614 		return;
10615 	}
10616 
10617 	qdf_mem_zero(&beacon_params, sizeof(beacon_params));
10618 	beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED;
10619 	session->he_op.bss_col_disabled = 1;
10620 	beacon_params.bss_color_disabled = 1;
10621 	beacon_params.bss_color = session->he_op.bss_color;
10622 
10623 	if (sch_set_fixed_beacon_fields(mac_ctx, session) !=
10624 	    QDF_STATUS_SUCCESS) {
10625 		pe_err("Unable to set op mode IE in beacon");
10626 		return;
10627 	}
10628 
10629 	lim_send_beacon_params(mac_ctx, &beacon_params, session);
10630 	lim_send_obss_color_collision_cfg(mac_ctx, session,
10631 					  OBSS_COLOR_FREE_SLOT_AVAILABLE);
10632 }
10633 
10634 /**
10635  * obss_color_collision_process_color_change() - Process bss color change
10636  * @mac_ctx: Pointer to Global MAC structure
10637  * @session: pointer to session
10638  * @obss_color_info: obss color collision/free slot indication info
10639  *
10640  * This function selects new color ib case of bss color collision.
10641  *
10642  * Return: None
10643  */
obss_color_collision_process_color_change(struct mac_context * mac_ctx,struct pe_session * session,struct wmi_obss_color_collision_info * obss_color_info)10644 static void obss_color_collision_process_color_change(struct mac_context *mac_ctx,
10645 		struct pe_session *session,
10646 		struct wmi_obss_color_collision_info *obss_color_info)
10647 {
10648 	int i, num_bss_color = 0;
10649 	uint32_t bss_color_bitmap;
10650 	uint8_t bss_color_index_array[MAX_BSS_COLOR_VALUE];
10651 	uint32_t rand_byte = 0;
10652 	struct sir_set_he_bss_color he_bss_color;
10653 	bool is_color_collision = false;
10654 
10655 
10656 	if (session->bss_color_changing == 1) {
10657 		pe_err("%d: color change in progress", session->smeSessionId);
10658 		return;
10659 	}
10660 
10661 	if (!session->he_op.bss_col_disabled) {
10662 		if (session->he_op.bss_color < 32)
10663 			is_color_collision = (obss_color_info->
10664 					     obss_color_bitmap_bit0to31 >>
10665 					     session->he_op.bss_color) & 0x01;
10666 		else
10667 			is_color_collision = (obss_color_info->
10668 					     obss_color_bitmap_bit32to63 >>
10669 					     (session->he_op.bss_color -
10670 					      32)) & 0x01;
10671 		if (!is_color_collision) {
10672 			pe_err("%d: color collision not found, curr_color: %d",
10673 			       session->smeSessionId,
10674 			       session->he_op.bss_color);
10675 			return;
10676 		}
10677 	}
10678 
10679 	bss_color_bitmap = obss_color_info->obss_color_bitmap_bit0to31;
10680 
10681 	/* Skip color zero */
10682 	bss_color_bitmap = bss_color_bitmap >> 1;
10683 	for (i = 0; (i < 31) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) {
10684 		if (!(bss_color_bitmap & 0x01)) {
10685 			bss_color_index_array[num_bss_color] = i + 1;
10686 			num_bss_color++;
10687 		}
10688 		bss_color_bitmap = bss_color_bitmap >> 1;
10689 	}
10690 
10691 	bss_color_bitmap = obss_color_info->obss_color_bitmap_bit32to63;
10692 	for (i = 0; (i < 32) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) {
10693 		if (!(bss_color_bitmap & 0x01)) {
10694 			bss_color_index_array[num_bss_color] = i + 32;
10695 			num_bss_color++;
10696 		}
10697 		bss_color_bitmap = bss_color_bitmap >> 1;
10698 	}
10699 
10700 	if (num_bss_color) {
10701 		qdf_get_random_bytes((void *) &rand_byte, 1);
10702 		i = (rand_byte + qdf_mc_timer_get_system_ticks()) %
10703 		    num_bss_color;
10704 		pe_debug("New bss color = %d", bss_color_index_array[i]);
10705 		he_bss_color.vdev_id = obss_color_info->vdev_id;
10706 		he_bss_color.bss_color = bss_color_index_array[i];
10707 
10708 		/* Take the wakelock for 2 sec, release it after color change */
10709 		wma_prevent_suspend_on_obss_color_collision(session->vdev);
10710 
10711 		lim_process_set_he_bss_color(mac_ctx,
10712 					     (uint32_t *)&he_bss_color);
10713 	} else {
10714 		pe_err("Unable to find bss color from bitmasp");
10715 		if (obss_color_info->evt_type ==
10716 		    OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY &&
10717 		    session->obss_color_collision_dec_evt ==
10718 		    OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY)
10719 			/* In dot11BSSColorCollisionAPPeriod and
10720 			 * timer expired, time to disable bss color.
10721 			 */
10722 			obss_color_collision_process_color_disable(mac_ctx,
10723 								   session);
10724 		else
10725 			/*
10726 			 * Enter dot11BSSColorCollisionAPPeriod period.
10727 			 */
10728 			lim_send_obss_color_collision_cfg(mac_ctx, session,
10729 					OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY);
10730 	}
10731 }
10732 
lim_process_set_he_bss_color(struct mac_context * mac_ctx,uint32_t * msg_buf)10733 void lim_process_set_he_bss_color(struct mac_context *mac_ctx, uint32_t *msg_buf)
10734 {
10735 	struct sir_set_he_bss_color *bss_color;
10736 	struct pe_session *session_entry = NULL;
10737 	tUpdateBeaconParams beacon_params;
10738 
10739 	if (!msg_buf) {
10740 		pe_err("Buffer is Pointing to NULL");
10741 		return;
10742 	}
10743 
10744 	bss_color = (struct sir_set_he_bss_color *)msg_buf;
10745 	session_entry = pe_find_session_by_vdev_id(mac_ctx, bss_color->vdev_id);
10746 	if (!session_entry) {
10747 		pe_err("Session not found for given vdev_id %d",
10748 			bss_color->vdev_id);
10749 		return;
10750 	}
10751 
10752 	if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
10753 		pe_err("Invalid SystemRole %d",
10754 			GET_LIM_SYSTEM_ROLE(session_entry));
10755 		return;
10756 	}
10757 
10758 	if (bss_color->bss_color == session_entry->he_op.bss_color) {
10759 		pe_err("No change in  BSS color, current BSS color %d",
10760 			bss_color->bss_color);
10761 		return;
10762 	}
10763 	qdf_mem_zero(&beacon_params, sizeof(beacon_params));
10764 	beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED;
10765 	session_entry->he_op.bss_col_disabled = 1;
10766 	session_entry->he_bss_color_change.countdown =
10767 		BSS_COLOR_SWITCH_COUNTDOWN;
10768 	session_entry->he_bss_color_change.new_color = bss_color->bss_color;
10769 	beacon_params.bss_color_disabled = 1;
10770 	beacon_params.bss_color = session_entry->he_op.bss_color;
10771 	session_entry->bss_color_changing = 1;
10772 
10773 	if (wlan_vdev_mlme_get_he_spr_enabled(session_entry->vdev))
10774 		/* Disable spatial reuse during BSS color change */
10775 		wlan_spatial_reuse_config_set(session_entry->vdev, 0, 0);
10776 
10777 	if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) !=
10778 			QDF_STATUS_SUCCESS) {
10779 		pe_err("Unable to set op mode IE in beacon");
10780 		return;
10781 	}
10782 
10783 	lim_send_beacon_params(mac_ctx, &beacon_params, session_entry);
10784 	lim_send_obss_color_collision_cfg(mac_ctx, session_entry,
10785 			OBSS_COLOR_COLLISION_DETECTION_DISABLE);
10786 }
10787 
lim_reconfig_obss_scan_param(struct mac_context * mac_ctx,uint32_t * msg_buf)10788 void lim_reconfig_obss_scan_param(struct mac_context *mac_ctx,
10789 				  uint32_t *msg_buf)
10790 {
10791 	struct sir_cfg_obss_scan *obss_scan_param;
10792 	struct pe_session *session = NULL;
10793 	struct wmi_obss_color_collision_cfg_param *cfg_param;
10794 	struct scheduler_msg msg = {0};
10795 
10796 	if (!msg_buf) {
10797 		pe_err("Buffer is Pointing to NULL");
10798 		return;
10799 	}
10800 
10801 	obss_scan_param = (struct sir_cfg_obss_scan *)msg_buf;
10802 	session = pe_find_session_by_vdev_id(mac_ctx, obss_scan_param->vdev_id);
10803 	if (!session) {
10804 		pe_err("Session not found for given vdev_id %d",
10805 		       obss_scan_param->vdev_id);
10806 		return;
10807 	}
10808 
10809 	if (!session->he_capable ||
10810 	    !session->is_session_obss_color_collision_det_enabled ||
10811 	    session->obss_color_collision_dec_evt ==
10812 				OBSS_COLOR_COLLISION_DETECTION_DISABLE) {
10813 		pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d event_type:%d",
10814 			 session->smeSessionId, session->he_capable,
10815 			 session->is_session_obss_color_collision_det_enabled,
10816 			 mac_ctx->mlme_cfg->obss_ht40.obss_color_collision_offload_enabled,
10817 			 session->obss_color_collision_dec_evt);
10818 		return;
10819 	}
10820 
10821 	cfg_param = qdf_mem_malloc(sizeof(*cfg_param));
10822 	if (!cfg_param)
10823 		return;
10824 
10825 	pe_debug("vdev_id %d: sending event:%d scan_reconfig:%d",
10826 		 session->smeSessionId, session->obss_color_collision_dec_evt,
10827 		 obss_scan_param->is_scan_reconfig);
10828 	cfg_param->vdev_id = session->smeSessionId;
10829 	cfg_param->evt_type = session->obss_color_collision_dec_evt;
10830 	cfg_param->current_bss_color = session->he_op.bss_color;
10831 
10832 	if (obss_scan_param->is_scan_reconfig)
10833 		cfg_param->detection_period_ms =
10834 				OBSS_COLOR_COLLISION_DETECTION_NDP_PERIOD_MS;
10835 	else
10836 		cfg_param->detection_period_ms =
10837 				OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS;
10838 	cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS;
10839 
10840 	if (session->obss_color_collision_dec_evt ==
10841 	    OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY)
10842 		cfg_param->free_slot_expiry_time_ms =
10843 			OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS;
10844 
10845 	msg.type = WMA_OBSS_COLOR_COLLISION_REQ;
10846 	msg.bodyptr = cfg_param;
10847 	msg.reserved = 0;
10848 
10849 	if (QDF_IS_STATUS_ERROR(scheduler_post_message(QDF_MODULE_ID_PE,
10850 						       QDF_MODULE_ID_WMA,
10851 						       QDF_MODULE_ID_WMA,
10852 						       &msg))) {
10853 		qdf_mem_free(cfg_param);
10854 	}
10855 }
10856 
lim_send_obss_color_collision_cfg(struct mac_context * mac_ctx,struct pe_session * session,enum wmi_obss_color_collision_evt_type event_type)10857 void lim_send_obss_color_collision_cfg(struct mac_context *mac_ctx,
10858 				       struct pe_session *session,
10859 				       enum wmi_obss_color_collision_evt_type
10860 				       event_type)
10861 {
10862 	struct wmi_obss_color_collision_cfg_param *cfg_param;
10863 	struct scheduler_msg msg = {0};
10864 
10865 	if (!session) {
10866 		pe_err("Invalid session");
10867 		return;
10868 	}
10869 
10870 	if (!session->he_capable ||
10871 	    !session->is_session_obss_color_collision_det_enabled) {
10872 		pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d",
10873 			 session->smeSessionId, session->he_capable,
10874 			 session->is_session_obss_color_collision_det_enabled,
10875 			 mac_ctx->mlme_cfg->obss_ht40.
10876 			 obss_color_collision_offload_enabled);
10877 		return;
10878 	}
10879 
10880 	cfg_param = qdf_mem_malloc(sizeof(*cfg_param));
10881 	if (!cfg_param)
10882 		return;
10883 
10884 	pe_debug("%d: sending event:%d", session->smeSessionId, event_type);
10885 	qdf_mem_zero(cfg_param, sizeof(*cfg_param));
10886 	cfg_param->vdev_id = session->smeSessionId;
10887 	cfg_param->evt_type = event_type;
10888 	cfg_param->current_bss_color = session->he_op.bss_color;
10889 	if (LIM_IS_AP_ROLE(session))
10890 		cfg_param->detection_period_ms =
10891 			OBSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS;
10892 	else
10893 		cfg_param->detection_period_ms =
10894 			OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS;
10895 
10896 	cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS;
10897 	if (event_type == OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY)
10898 		cfg_param->free_slot_expiry_time_ms =
10899 			OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS;
10900 
10901 	msg.type = WMA_OBSS_COLOR_COLLISION_REQ;
10902 	msg.bodyptr = cfg_param;
10903 	msg.reserved = 0;
10904 
10905 	if (QDF_IS_STATUS_ERROR(scheduler_post_message(QDF_MODULE_ID_PE,
10906 						       QDF_MODULE_ID_WMA,
10907 						       QDF_MODULE_ID_WMA,
10908 						       &msg))) {
10909 		qdf_mem_free(cfg_param);
10910 	} else {
10911 		session->obss_color_collision_dec_evt = event_type;
10912 	}
10913 }
10914 
lim_process_obss_color_collision_info(struct mac_context * mac_ctx,uint32_t * msg_buf)10915 void lim_process_obss_color_collision_info(struct mac_context *mac_ctx,
10916 					   uint32_t *msg_buf)
10917 {
10918 	struct wmi_obss_color_collision_info *obss_color_info;
10919 	struct pe_session *session;
10920 
10921 	if (!msg_buf) {
10922 		pe_err("Buffer is Pointing to NULL");
10923 		return;
10924 	}
10925 
10926 	obss_color_info = (struct wmi_obss_color_collision_info *)msg_buf;
10927 	session = pe_find_session_by_vdev_id(mac_ctx, obss_color_info->vdev_id);
10928 	if (!session) {
10929 		pe_err("Session not found for given session_id %d",
10930 			obss_color_info->vdev_id);
10931 		return;
10932 	}
10933 
10934 	pe_debug("vdev_id:%d, evt:%d:%d, 0to31:0x%x, 32to63:0x%x, cap:%d:%d:%d",
10935 		 obss_color_info->vdev_id,
10936 		 obss_color_info->evt_type,
10937 		 session->obss_color_collision_dec_evt,
10938 		 obss_color_info->obss_color_bitmap_bit0to31,
10939 		 obss_color_info->obss_color_bitmap_bit32to63,
10940 		 session->he_capable,
10941 		 session->is_session_obss_color_collision_det_enabled,
10942 		 mac_ctx->mlme_cfg->obss_ht40.
10943 		 obss_color_collision_offload_enabled);
10944 
10945 	if (!session->he_capable ||
10946 	    !session->is_session_obss_color_collision_det_enabled) {
10947 		return;
10948 	}
10949 
10950 	switch (obss_color_info->evt_type) {
10951 	case OBSS_COLOR_COLLISION_DETECTION_DISABLE:
10952 		pe_err("%d: FW disabled obss color det. he_cap:%d, sup:%d:%d",
10953 		       session->smeSessionId, session->he_capable,
10954 		       session->is_session_obss_color_collision_det_enabled,
10955 		       mac_ctx->mlme_cfg->obss_ht40.
10956 		       obss_color_collision_offload_enabled);
10957 		session->is_session_obss_color_collision_det_enabled = false;
10958 		return;
10959 	case OBSS_COLOR_FREE_SLOT_AVAILABLE:
10960 	case OBSS_COLOR_COLLISION_DETECTION:
10961 	case OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY:
10962 		if (session->valid && !LIM_IS_AP_ROLE(session)) {
10963 			pe_debug("Invalid System Role %d",
10964 				 GET_LIM_SYSTEM_ROLE(session));
10965 			return;
10966 		}
10967 
10968 		if (session->obss_color_collision_dec_evt !=
10969 		    obss_color_info->evt_type) {
10970 			pe_debug("%d: Wrong event: %d, skipping",
10971 				 obss_color_info->vdev_id,
10972 				 obss_color_info->evt_type);
10973 			return;
10974 		}
10975 		obss_color_collision_process_color_change(mac_ctx, session,
10976 							  obss_color_info);
10977 		break;
10978 	default:
10979 		pe_err("%d: Invalid event type %d",
10980 		       obss_color_info->vdev_id, obss_color_info->evt_type);
10981 		return;
10982 	}
10983 }
10984 #endif
10985 
lim_send_csa_restart_req(struct mac_context * mac_ctx,uint8_t vdev_id)10986 void lim_send_csa_restart_req(struct mac_context *mac_ctx, uint8_t vdev_id)
10987 {
10988 	struct pe_session *session;
10989 
10990 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
10991 	if (!session) {
10992 		pe_err("session not found for vdev id %d", vdev_id);
10993 		return;
10994 	}
10995 
10996 	wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10997 				      WLAN_VDEV_SM_EV_CSA_RESTART,
10998 				      sizeof(*session), session);
10999 }
11000 
lim_continue_sta_csa_req(struct mac_context * mac_ctx,uint8_t vdev_id)11001 void lim_continue_sta_csa_req(struct mac_context *mac_ctx, uint8_t vdev_id)
11002 {
11003 	pe_info("Continue CSA for STA vdev id %d", vdev_id);
11004 	lim_process_channel_switch(mac_ctx, vdev_id);
11005 }
11006