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, ®_max,
6246 ®_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, ®_max,
6251 ®_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, ®_max,
6269 ®_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 ®_max,
6295 ®_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, ¶ms, 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