1 /*
2 * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * This file lim_utils.cc contains the utility functions
22 * LIM uses.
23 * Author: Chandra Modumudi
24 * Date: 02/13/02
25 * History:-
26 * Date Modified by Modification Information
27 * --------------------------------------------------------------------
28 */
29
30 #include "sch_api.h"
31 #include "lim_utils.h"
32 #include "lim_types.h"
33 #include "lim_security_utils.h"
34 #include "lim_prop_exts_utils.h"
35 #include "lim_send_messages.h"
36 #include "lim_ser_des_utils.h"
37 #include "lim_admit_control.h"
38 #include "dot11f.h"
39 #include "dot11fdefs.h"
40 #include "wmm_apsd.h"
41 #include "lim_trace.h"
42 #include "wlan_vdev_mlme_api.h"
43 #include "../../core/src/vdev_mgr_ops.h"
44
45 #ifdef FEATURE_WLAN_DIAG_SUPPORT
46 #include "host_diag_core_event.h"
47 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
48 #include "lim_session_utils.h"
49 #include "lim_ft_defs.h"
50 #include "lim_session.h"
51 #include "cds_reg_service.h"
52 #include "nan_datapath.h"
53 #include "wma.h"
54 #include "wlan_reg_services_api.h"
55 #include "wlan_policy_mgr_api.h"
56 #include "wlan_mlme_public_struct.h"
57 #include "wlan_mlme_ucfg_api.h"
58 #include "wma_pasn_peer_api.h"
59 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
60 #include "wma_he.h"
61 #endif
62 #include "wlan_utility.h"
63
64 #include "wni_cfg.h"
65 #include "cfg_mlme_obss_ht40.h"
66 #include "cfg_ucfg_api.h"
67 #include "lim_ft.h"
68 #include "wlan_mlme_main.h"
69 #include "qdf_util.h"
70 #include "wlan_qct_sys.h"
71 #include <wlan_scan_ucfg_api.h>
72 #include <wlan_dlm_api.h>
73 #include <lim_assoc_utils.h>
74 #include "wlan_mlme_ucfg_api.h"
75 #include "nan_ucfg_api.h"
76 #include "wlan_twt_ucfg_ext_cfg.h"
77 #ifdef WLAN_FEATURE_11BE
78 #include "wma_eht.h"
79 #endif
80 #ifdef WLAN_FEATURE_11BE_MLO
81 #include <lim_mlo.h>
82 #endif
83 #include "wlan_cmn_ieee80211.h"
84 #include <wlan_cm_api.h>
85 #include <wlan_vdev_mgr_utils_api.h>
86 #include "parser_api.h"
87 #include "wlan_mlo_mgr_link_switch.h"
88 #include "wlan_epcs_api.h"
89 #include "wlan_nan_api_i.h"
90
91 /** -------------------------------------------------------------
92 \fn lim_delete_dialogue_token_list
93 \brief deletes the complete lim dialogue token linked list.
94 \param struct mac_context * mac
95 \return None
96 -------------------------------------------------------------*/
lim_delete_dialogue_token_list(struct mac_context * mac)97 void lim_delete_dialogue_token_list(struct mac_context *mac)
98 {
99 tpDialogueToken pCurrNode = mac->lim.pDialogueTokenHead;
100
101 while (mac->lim.pDialogueTokenHead) {
102 pCurrNode = mac->lim.pDialogueTokenHead;
103 mac->lim.pDialogueTokenHead =
104 mac->lim.pDialogueTokenHead->next;
105 qdf_mem_free(pCurrNode);
106 pCurrNode = NULL;
107 }
108 mac->lim.pDialogueTokenTail = NULL;
109 }
110
lim_mlm_state_str(tLimMlmStates state)111 char *lim_mlm_state_str(tLimMlmStates state)
112 {
113 switch (state) {
114 case eLIM_MLM_OFFLINE_STATE:
115 return "eLIM_MLM_OFFLINE_STATE";
116 case eLIM_MLM_IDLE_STATE:
117 return "eLIM_MLM_IDLE_STATE";
118 case eLIM_MLM_WT_JOIN_BEACON_STATE:
119 return "eLIM_MLM_WT_JOIN_BEACON_STATE";
120 case eLIM_MLM_JOINED_STATE:
121 return "eLIM_MLM_JOINED_STATE";
122 case eLIM_MLM_BSS_STARTED_STATE:
123 return "eLIM_MLM_BSS_STARTED_STATE";
124 case eLIM_MLM_WT_AUTH_FRAME2_STATE:
125 return "eLIM_MLM_WT_AUTH_FRAME2_STATE";
126 case eLIM_MLM_WT_AUTH_FRAME3_STATE:
127 return "eLIM_MLM_WT_AUTH_FRAME3_STATE";
128 case eLIM_MLM_WT_AUTH_FRAME4_STATE:
129 return "eLIM_MLM_WT_AUTH_FRAME4_STATE";
130 case eLIM_MLM_AUTH_RSP_TIMEOUT_STATE:
131 return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE";
132 case eLIM_MLM_AUTHENTICATED_STATE:
133 return "eLIM_MLM_AUTHENTICATED_STATE";
134 case eLIM_MLM_WT_ASSOC_RSP_STATE:
135 return "eLIM_MLM_WT_ASSOC_RSP_STATE";
136 case eLIM_MLM_WT_REASSOC_RSP_STATE:
137 return "eLIM_MLM_WT_REASSOC_RSP_STATE";
138 case eLIM_MLM_WT_FT_REASSOC_RSP_STATE:
139 return "eLIM_MLM_WT_FT_REASSOC_RSP_STATE";
140 case eLIM_MLM_WT_DEL_STA_RSP_STATE:
141 return "eLIM_MLM_WT_DEL_STA_RSP_STATE";
142 case eLIM_MLM_WT_DEL_BSS_RSP_STATE:
143 return "eLIM_MLM_WT_DEL_BSS_RSP_STATE";
144 case eLIM_MLM_WT_ADD_STA_RSP_STATE:
145 return "eLIM_MLM_WT_ADD_STA_RSP_STATE";
146 case eLIM_MLM_WT_ADD_BSS_RSP_STATE:
147 return "eLIM_MLM_WT_ADD_BSS_RSP_STATE";
148 case eLIM_MLM_REASSOCIATED_STATE:
149 return "eLIM_MLM_REASSOCIATED_STATE";
150 case eLIM_MLM_LINK_ESTABLISHED_STATE:
151 return "eLIM_MLM_LINK_ESTABLISHED_STATE";
152 case eLIM_MLM_WT_ASSOC_CNF_STATE:
153 return "eLIM_MLM_WT_ASSOC_CNF_STATE";
154 case eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE:
155 return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE";
156 case eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE:
157 return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE";
158 case eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE:
159 return "eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE";
160 case eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE:
161 return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE";
162 case eLIM_MLM_WT_SET_BSS_KEY_STATE:
163 return "eLIM_MLM_WT_SET_BSS_KEY_STATE";
164 case eLIM_MLM_WT_SET_STA_KEY_STATE:
165 return "eLIM_MLM_WT_SET_STA_KEY_STATE";
166 default:
167 return "INVALID MLM state";
168 }
169 }
170
171 void
lim_print_mlm_state(struct mac_context * mac,uint16_t logLevel,tLimMlmStates state)172 lim_print_mlm_state(struct mac_context *mac, uint16_t logLevel, tLimMlmStates state)
173 {
174 pe_debug("Mlm state: %s", lim_mlm_state_str(state));
175 }
176
lim_sme_state_str(tLimSmeStates state)177 char *lim_sme_state_str(tLimSmeStates state)
178 {
179 switch (state) {
180 case eLIM_SME_OFFLINE_STATE:
181 return "eLIM_SME_OFFLINE_STATE";
182 case eLIM_SME_IDLE_STATE:
183 return "eLIM_SME_OFFLINE_STATE";
184 case eLIM_SME_SUSPEND_STATE:
185 return "eLIM_SME_SUSPEND_STATE";
186 case eLIM_SME_WT_JOIN_STATE:
187 return "eLIM_SME_WT_JOIN_STATE";
188 case eLIM_SME_WT_AUTH_STATE:
189 return "eLIM_SME_WT_AUTH_STATE";
190 case eLIM_SME_WT_ASSOC_STATE:
191 return "eLIM_SME_WT_ASSOC_STATE";
192 case eLIM_SME_WT_REASSOC_STATE:
193 return "eLIM_SME_WT_REASSOC_STATE";
194 case eLIM_SME_JOIN_FAILURE_STATE:
195 return "eLIM_SME_JOIN_FAILURE_STATE";
196 case eLIM_SME_ASSOCIATED_STATE:
197 return "eLIM_SME_ASSOCIATED_STATE";
198 case eLIM_SME_REASSOCIATED_STATE:
199 return "eLIM_SME_REASSOCIATED_STATE";
200 case eLIM_SME_LINK_EST_STATE:
201 return "eLIM_SME_LINK_EST_STATE";
202 case eLIM_SME_WT_PRE_AUTH_STATE:
203 return "eLIM_SME_WT_PRE_AUTH_STATE";
204 case eLIM_SME_WT_DISASSOC_STATE:
205 return "eLIM_SME_WT_DISASSOC_STATE";
206 case eLIM_SME_WT_DEAUTH_STATE:
207 return "eLIM_SME_WT_DEAUTH_STATE";
208 case eLIM_SME_WT_START_BSS_STATE:
209 return "eLIM_SME_WT_START_BSS_STATE";
210 case eLIM_SME_WT_STOP_BSS_STATE:
211 return "eLIM_SME_WT_STOP_BSS_STATE";
212 case eLIM_SME_NORMAL_STATE:
213 return "eLIM_SME_NORMAL_STATE";
214 default:
215 return "INVALID SME STATE";
216 }
217 }
218
219 void
lim_print_sme_state(struct mac_context * mac,uint16_t logLevel,tLimSmeStates state)220 lim_print_sme_state(struct mac_context *mac, uint16_t logLevel, tLimSmeStates state)
221 {
222 pe_debug("SME state: %s", lim_sme_state_str(state));
223 }
224
lim_msg_str(uint32_t msgType)225 char *lim_msg_str(uint32_t msgType)
226 {
227 switch (msgType) {
228 case eWNI_SME_SYS_READY_IND:
229 return "eWNI_SME_SYS_READY_IND";
230 case eWNI_SME_JOIN_REQ:
231 return "eWNI_SME_JOIN_REQ";
232 case eWNI_SME_JOIN_RSP:
233 return "eWNI_SME_JOIN_RSP";
234 case eWNI_SME_SETCONTEXT_RSP:
235 return "eWNI_SME_SETCONTEXT_RSP";
236 case eWNI_SME_REASSOC_REQ:
237 return "eWNI_SME_REASSOC_REQ";
238 case eWNI_SME_REASSOC_RSP:
239 return "eWNI_SME_REASSOC_RSP";
240 case eWNI_SME_DISASSOC_REQ:
241 return "eWNI_SME_DISASSOC_REQ";
242 case eWNI_SME_DISASSOC_RSP:
243 return "eWNI_SME_DISASSOC_RSP";
244 case eWNI_SME_DISASSOC_IND:
245 return "eWNI_SME_DISASSOC_IND";
246 case eWNI_SME_DISASSOC_CNF:
247 return "eWNI_SME_DISASSOC_CNF";
248 case eWNI_SME_DEAUTH_REQ:
249 return "eWNI_SME_DEAUTH_REQ";
250 case eWNI_SME_DEAUTH_RSP:
251 return "eWNI_SME_DEAUTH_RSP";
252 case eWNI_SME_DEAUTH_IND:
253 return "eWNI_SME_DEAUTH_IND";
254 case eWNI_SME_START_BSS_REQ:
255 return "eWNI_SME_START_BSS_REQ";
256 case eWNI_SME_START_BSS_RSP:
257 return "eWNI_SME_START_BSS_RSP";
258 case eWNI_SME_ASSOC_IND:
259 return "eWNI_SME_ASSOC_IND";
260 case eWNI_SME_ASSOC_IND_UPPER_LAYER:
261 return "eWNI_SME_ASSOC_IND_UPPER_LAYER";
262 case eWNI_SME_ASSOC_CNF:
263 return "eWNI_SME_ASSOC_CNF";
264 case eWNI_SME_SWITCH_CHL_IND:
265 return "eWNI_SME_SWITCH_CHL_IND";
266 case eWNI_SME_STOP_BSS_REQ:
267 return "eWNI_SME_STOP_BSS_REQ";
268 case eWNI_SME_STOP_BSS_RSP:
269 return "eWNI_SME_STOP_BSS_RSP";
270 case eWNI_SME_DEAUTH_CNF:
271 return "eWNI_SME_DEAUTH_CNF";
272 case eWNI_SME_ADDTS_REQ:
273 return "eWNI_SME_ADDTS_REQ";
274 case eWNI_SME_MSCS_REQ:
275 return "eWNI_SME_MSCS_REQ";
276 case eWNI_SME_ADDTS_RSP:
277 return "eWNI_SME_ADDTS_RSP";
278 case eWNI_SME_DELTS_REQ:
279 return "eWNI_SME_DELTS_REQ";
280 case eWNI_SME_DELTS_RSP:
281 return "eWNI_SME_DELTS_RSP";
282 case eWNI_SME_DELTS_IND:
283 return "eWNI_SME_DELTS_IND";
284 case SIR_BB_XPORT_MGMT_MSG:
285 return "SIR_BB_XPORT_MGMT_MSG";
286 case SIR_LIM_JOIN_FAIL_TIMEOUT:
287 return "SIR_LIM_JOIN_FAIL_TIMEOUT";
288 case SIR_LIM_AUTH_FAIL_TIMEOUT:
289 return "SIR_LIM_AUTH_FAIL_TIMEOUT";
290 case SIR_LIM_AUTH_RSP_TIMEOUT:
291 return "SIR_LIM_AUTH_RSP_TIMEOUT";
292 case SIR_LIM_ASSOC_FAIL_TIMEOUT:
293 return "SIR_LIM_ASSOC_FAIL_TIMEOUT";
294 case SIR_LIM_REASSOC_FAIL_TIMEOUT:
295 return "SIR_LIM_REASSOC_FAIL_TIMEOUT";
296 case SIR_LIM_HEART_BEAT_TIMEOUT:
297 return "SIR_LIM_HEART_BEAT_TIMEOUT";
298 case SIR_LIM_ADDTS_RSP_TIMEOUT:
299 return "SIR_LIM_ADDTS_RSP_TIMEOUT";
300 case SIR_LIM_LINK_TEST_DURATION_TIMEOUT:
301 return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT";
302 case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT:
303 return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT";
304 case SIR_LIM_CNF_WAIT_TIMEOUT:
305 return "SIR_LIM_CNF_WAIT_TIMEOUT";
306 case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:
307 return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT";
308 #ifdef FEATURE_WLAN_ESE
309 case eWNI_SME_GET_TSM_STATS_REQ:
310 return "eWNI_SME_GET_TSM_STATS_REQ";
311 case eWNI_SME_GET_TSM_STATS_RSP:
312 return "eWNI_SME_GET_TSM_STATS_RSP";
313 #endif /* FEATURE_WLAN_ESE */
314 case eWNI_SME_SET_HW_MODE_REQ:
315 return "eWNI_SME_SET_HW_MODE_REQ";
316 case eWNI_SME_SET_HW_MODE_RESP:
317 return "eWNI_SME_SET_HW_MODE_RESP";
318 case eWNI_SME_HW_MODE_TRANS_IND:
319 return "eWNI_SME_HW_MODE_TRANS_IND";
320 case SIR_LIM_PROCESS_DEFERRED_QUEUE:
321 return "SIR_LIM_PROCESS_DEFERRED_QUEUE";
322 default:
323 return "Unknown";
324 }
325 }
326
lim_result_code_str(tSirResultCodes resultCode)327 char *lim_result_code_str(tSirResultCodes resultCode)
328 {
329 switch (resultCode) {
330 case eSIR_SME_SUCCESS:
331 return "eSIR_SME_SUCCESS";
332 case eSIR_LOGE_EXCEPTION:
333 return "eSIR_LOGE_EXCEPTION";
334 case eSIR_SME_INVALID_PARAMETERS:
335 return "eSIR_SME_INVALID_PARAMETERS";
336 case eSIR_SME_UNEXPECTED_REQ_RESULT_CODE:
337 return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE";
338 case eSIR_SME_RESOURCES_UNAVAILABLE:
339 return "eSIR_SME_RESOURCES_UNAVAILABLE";
340 case eSIR_SME_SCAN_FAILED:
341 return "eSIR_SME_SCAN_FAILED";
342 case eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED:
343 return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED";
344 case eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE:
345 return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE";
346 case eSIR_SME_REFUSED:
347 return "eSIR_SME_REFUSED";
348 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
349 return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE";
350 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
351 return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE";
352 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
353 return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE";
354 case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE:
355 return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE";
356 case eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED:
357 return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED";
358 case eSIR_SME_AUTH_REFUSED:
359 return "eSIR_SME_AUTH_REFUSED";
360 case eSIR_SME_INVALID_WEP_DEFAULT_KEY:
361 return "eSIR_SME_INVALID_WEP_DEFAULT_KEY";
362 case eSIR_SME_ASSOC_REFUSED:
363 return "eSIR_SME_ASSOC_REFUSED";
364 case eSIR_SME_REASSOC_REFUSED:
365 return "eSIR_SME_REASSOC_REFUSED";
366 case eSIR_SME_STA_NOT_AUTHENTICATED:
367 return "eSIR_SME_STA_NOT_AUTHENTICATED";
368 case eSIR_SME_STA_NOT_ASSOCIATED:
369 return "eSIR_SME_STA_NOT_ASSOCIATED";
370 case eSIR_SME_ALREADY_JOINED_A_BSS:
371 return "eSIR_SME_ALREADY_JOINED_A_BSS";
372 case eSIR_SME_MORE_SCAN_RESULTS_FOLLOW:
373 return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW";
374 case eSIR_SME_INVALID_ASSOC_RSP_RXED:
375 return "eSIR_SME_INVALID_ASSOC_RSP_RXED";
376 case eSIR_SME_MIC_COUNTER_MEASURES:
377 return "eSIR_SME_MIC_COUNTER_MEASURES";
378 case eSIR_SME_ADDTS_RSP_TIMEOUT:
379 return "eSIR_SME_ADDTS_RSP_TIMEOUT";
380 case eSIR_SME_CHANNEL_SWITCH_FAIL:
381 return "eSIR_SME_CHANNEL_SWITCH_FAIL";
382 case eSIR_SME_HAL_SCAN_INIT_FAILED:
383 return "eSIR_SME_HAL_SCAN_INIT_FAILED";
384 case eSIR_SME_HAL_SCAN_END_FAILED:
385 return "eSIR_SME_HAL_SCAN_END_FAILED";
386 case eSIR_SME_HAL_SCAN_FINISH_FAILED:
387 return "eSIR_SME_HAL_SCAN_FINISH_FAILED";
388 case eSIR_SME_HAL_SEND_MESSAGE_FAIL:
389 return "eSIR_SME_HAL_SEND_MESSAGE_FAIL";
390
391 default:
392 return "Unknown resultCode";
393 }
394 }
395
lim_print_msg_name(struct mac_context * mac,uint16_t logLevel,uint32_t msgType)396 void lim_print_msg_name(struct mac_context *mac, uint16_t logLevel, uint32_t msgType)
397 {
398 pe_debug("Msg: %s", lim_msg_str(msgType));
399 }
400
401 /**
402 * lim_init_mlm() - This function is called by limProcessSmeMessages() to
403 * initialize MLM state machine on STA
404 * @mac: Pointer to Global MAC structure
405 *
406 * @Return: Status of operation
407 */
lim_init_mlm(struct mac_context * mac)408 QDF_STATUS lim_init_mlm(struct mac_context *mac)
409 {
410 uint32_t retVal;
411
412 mac->lim.gLimTimersCreated = 0;
413
414 MTRACE(mac_trace(mac, TRACE_CODE_MLM_STATE, NO_SESSION,
415 mac->lim.gLimMlmState));
416
417 /* Initialize number of pre-auth contexts */
418 mac->lim.gLimNumPreAuthContexts = 0;
419
420 /* Initialize MAC based Authentication STA list */
421 lim_init_pre_auth_list(mac);
422
423 /* Create timers used by LIM */
424 retVal = lim_create_timers(mac);
425 if (retVal != TX_SUCCESS) {
426 pe_err("lim_create_timers Failed");
427 return QDF_STATUS_SUCCESS;
428 }
429
430 mac->lim.gLimTimersCreated = 1;
431 return QDF_STATUS_SUCCESS;
432 } /*** end lim_init_mlm() ***/
433
lim_deactivate_timers(struct mac_context * mac_ctx)434 void lim_deactivate_timers(struct mac_context *mac_ctx)
435 {
436 uint32_t n;
437 tLimTimers *lim_timer = &mac_ctx->lim.lim_timers;
438
439 lim_deactivate_timers_host_roam(mac_ctx);
440
441 /* Deactivate addts response timer. */
442 tx_timer_deactivate(&lim_timer->gLimAddtsRspTimer);
443
444 if (tx_timer_running(&lim_timer->gLimJoinFailureTimer)) {
445 pe_err("Join failure timer running call the timeout API");
446 /* Cleanup as if join timer expired */
447 lim_timer_handler(mac_ctx, SIR_LIM_JOIN_FAIL_TIMEOUT);
448 }
449 /* Deactivate Join failure timer. */
450 tx_timer_deactivate(&lim_timer->gLimJoinFailureTimer);
451
452 /* Deactivate Periodic Join Probe Request timer. */
453 tx_timer_deactivate(&lim_timer->gLimPeriodicJoinProbeReqTimer);
454
455 /* Deactivate Auth Retry timer. */
456 tx_timer_deactivate
457 (&lim_timer->g_lim_periodic_auth_retry_timer);
458
459 if (tx_timer_running(&lim_timer->gLimAssocFailureTimer)) {
460 pe_err("Assoc failure timer running call the timeout API");
461 /* Cleanup as if assoc timer expired */
462 lim_assoc_failure_timer_handler(mac_ctx, LIM_ASSOC);
463 }
464 /* Deactivate Association failure timer. */
465 tx_timer_deactivate(&lim_timer->gLimAssocFailureTimer);
466
467 if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer)) {
468 pe_err("Auth failure timer running call the timeout API");
469 /* Cleanup as if auth timer expired */
470 lim_timer_handler(mac_ctx, SIR_LIM_AUTH_FAIL_TIMEOUT);
471 }
472 /* Deactivate Authentication failure timer. */
473 tx_timer_deactivate(&lim_timer->gLimAuthFailureTimer);
474
475 /* Deactivate cnf wait timer */
476 for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) {
477 tx_timer_deactivate(&lim_timer->gpLimCnfWaitTimer[n]);
478 }
479
480 /* Deactivate any Authentication response timers */
481 lim_delete_pre_auth_list(mac_ctx);
482
483 tx_timer_deactivate(&lim_timer->gLimUpdateOlbcCacheTimer);
484 tx_timer_deactivate(&lim_timer->gLimPreAuthClnupTimer);
485
486 if (tx_timer_running(&lim_timer->gLimDisassocAckTimer)) {
487 pe_err("Disassoc timer running call the timeout API");
488 lim_timer_handler(mac_ctx, SIR_LIM_DISASSOC_ACK_TIMEOUT);
489 }
490 tx_timer_deactivate(&lim_timer->gLimDisassocAckTimer);
491
492 if (tx_timer_running(&lim_timer->gLimDeauthAckTimer)) {
493 pe_err("Deauth timer running call the timeout API");
494 lim_process_deauth_ack_timeout(mac_ctx, WLAN_INVALID_VDEV_ID);
495 }
496 tx_timer_deactivate(&lim_timer->gLimDeauthAckTimer);
497
498 if (tx_timer_running(&lim_timer->sae_auth_timer)) {
499 pe_err("SAE Auth failure timer running call the timeout API");
500 /* Cleanup as if SAE auth timer expired */
501 lim_timer_handler(mac_ctx, SIR_LIM_AUTH_SAE_TIMEOUT);
502 }
503 tx_timer_deactivate(&lim_timer->sae_auth_timer);
504
505 if (tx_timer_running(&lim_timer->rrm_sta_stats_resp_timer)) {
506 pe_err("sta stats resp timer running call the timeout API");
507 lim_timer_handler(mac_ctx, SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT);
508 }
509 tx_timer_deactivate(&lim_timer->rrm_sta_stats_resp_timer);
510 }
511
lim_deactivate_timers_for_vdev(struct mac_context * mac_ctx,uint8_t vdev_id)512 void lim_deactivate_timers_for_vdev(struct mac_context *mac_ctx,
513 uint8_t vdev_id)
514 {
515 tLimTimers *lim_timer = &mac_ctx->lim.lim_timers;
516 struct pe_session *pe_session;
517
518 pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
519 if (!pe_session) {
520 pe_err("pe session invalid for vdev %d", vdev_id);
521 return;
522 }
523 pe_debug("pe limMlmState %s vdev %d",
524 lim_mlm_state_str(pe_session->limMlmState),
525 vdev_id);
526 switch (pe_session->limMlmState) {
527 case eLIM_MLM_WT_JOIN_BEACON_STATE:
528 if (tx_timer_running(
529 &lim_timer->gLimJoinFailureTimer)) {
530 pe_debug("Trigger Join failure timeout for vdev %d",
531 vdev_id);
532 tx_timer_deactivate(
533 &lim_timer->gLimJoinFailureTimer);
534 lim_process_join_failure_timeout(mac_ctx);
535 }
536 break;
537 case eLIM_MLM_WT_AUTH_FRAME2_STATE:
538 case eLIM_MLM_WT_AUTH_FRAME4_STATE:
539 if (tx_timer_running(
540 &lim_timer->gLimAuthFailureTimer)) {
541 pe_debug("Trigger Auth failure timeout for vdev %d",
542 vdev_id);
543 tx_timer_deactivate(
544 &lim_timer->gLimAuthFailureTimer);
545 lim_process_auth_failure_timeout(mac_ctx);
546 }
547 break;
548 case eLIM_MLM_WT_ASSOC_RSP_STATE:
549 if (tx_timer_running(
550 &lim_timer->gLimAssocFailureTimer)) {
551 pe_debug("Trigger Assoc failure timeout for vdev %d",
552 vdev_id);
553 tx_timer_deactivate(
554 &lim_timer->gLimAssocFailureTimer);
555 lim_process_assoc_failure_timeout(mac_ctx,
556 LIM_ASSOC);
557 }
558 break;
559 case eLIM_MLM_WT_SAE_AUTH_STATE:
560 if (tx_timer_running(&lim_timer->sae_auth_timer)) {
561 pe_debug("Trigger SAE Auth failure timeout for vdev %d",
562 vdev_id);
563 tx_timer_deactivate(
564 &lim_timer->sae_auth_timer);
565 lim_process_sae_auth_timeout(mac_ctx);
566 }
567 break;
568 case eLIM_MLM_LINK_ESTABLISHED_STATE:
569 if (!pe_session->ftPEContext.ftPreAuthSession)
570 break;
571
572 pe_debug("pre-auth in progress");
573 if (tx_timer_running(&lim_timer->gLimFTPreAuthRspTimer)) {
574 pe_debug("Trigger pre auth timeout for vdev %d",
575 vdev_id);
576 tx_timer_deactivate(
577 &lim_timer->gLimFTPreAuthRspTimer);
578 }
579 lim_process_ft_preauth_rsp_timeout(mac_ctx);
580 break;
581 default:
582 return;
583 }
584 }
585
586 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
587 QDF_STATUS
lim_process_pasn_delete_all_peers(struct mac_context * mac,struct pasn_peer_delete_msg * msg)588 lim_process_pasn_delete_all_peers(struct mac_context *mac,
589 struct pasn_peer_delete_msg *msg)
590 {
591 struct wlan_objmgr_vdev *vdev;
592 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
593 QDF_STATUS status;
594
595 if (!wma)
596 return QDF_STATUS_E_INVAL;
597
598 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, msg->vdev_id,
599 WLAN_WIFI_POS_CORE_ID);
600 if (!vdev)
601 return QDF_STATUS_E_INVAL;
602
603 status = wma_delete_all_pasn_peers(wma, vdev);
604 if (QDF_IS_STATUS_ERROR(status))
605 pe_err("Failed to delete all PASN peers for vdev:%d",
606 msg->vdev_id);
607
608 wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
609
610 return status;
611 }
612 #endif
613
614 /**
615 * lim_cleanup_mlm() - This function is called to cleanup
616 * @mac_ctx: Pointer to Global MAC structure
617 *
618 * Function is called to cleanup any resources allocated by the MLM
619 * state machine.
620 *
621 * Return: none
622 */
lim_cleanup_mlm(struct mac_context * mac_ctx)623 void lim_cleanup_mlm(struct mac_context *mac_ctx)
624 {
625 uint32_t n;
626
627 tLimPreAuthNode **pAuthNode;
628 tLimTimers *lim_timer = NULL;
629
630 if (mac_ctx->lim.gLimTimersCreated == 1) {
631 lim_timer = &mac_ctx->lim.lim_timers;
632
633 lim_deactivate_timers(mac_ctx);
634
635 lim_delete_timers_host_roam(mac_ctx);
636
637 /* Delete addts response timer. */
638 tx_timer_delete(&lim_timer->gLimAddtsRspTimer);
639
640 /* Delete Join failure timer. */
641 tx_timer_delete(&lim_timer->gLimJoinFailureTimer);
642
643 /* Delete Periodic Join Probe Request timer. */
644 tx_timer_delete(&lim_timer->gLimPeriodicJoinProbeReqTimer);
645
646 /* Delete Auth Retry timer. */
647 tx_timer_delete(&lim_timer->g_lim_periodic_auth_retry_timer);
648
649 /* Delete Association failure timer. */
650 tx_timer_delete(&lim_timer->gLimAssocFailureTimer);
651
652 /* Delete Authentication failure timer. */
653 tx_timer_delete(&lim_timer->gLimAuthFailureTimer);
654
655 /* Delete cnf wait timer */
656 for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) {
657 tx_timer_delete(&lim_timer->gpLimCnfWaitTimer[n]);
658 }
659
660 pAuthNode = mac_ctx->lim.gLimPreAuthTimerTable.pTable;
661
662 /* Delete any Auth rsp timers, which might have been started */
663 for (n = 0; n < mac_ctx->lim.gLimPreAuthTimerTable.numEntry;
664 n++)
665 tx_timer_delete(&pAuthNode[n]->timer);
666
667 tx_timer_delete(&lim_timer->gLimUpdateOlbcCacheTimer);
668 tx_timer_delete(&lim_timer->gLimPreAuthClnupTimer);
669
670 tx_timer_delete(&lim_timer->gLimDisassocAckTimer);
671
672 tx_timer_delete(&lim_timer->gLimDeauthAckTimer);
673
674 tx_timer_delete(&lim_timer->sae_auth_timer);
675 tx_timer_delete(&lim_timer->rrm_sta_stats_resp_timer);
676
677 mac_ctx->lim.gLimTimersCreated = 0;
678 }
679 } /*** end lim_cleanup_mlm() ***/
680
681 /*
682 * lim_reset_deferred_msg_q()
683 *
684 ***FUNCTION:
685 * This function resets the deferred message queue parameters.
686 *
687 ***PARAMS:
688 * @param mac - Pointer to Global MAC structure
689 *
690 ***LOGIC:
691 *
692 ***ASSUMPTIONS:
693 * NA
694 *
695 ***NOTE:
696 * NA
697 *
698 ***RETURNS:
699 * None
700 */
701
lim_reset_deferred_msg_q(struct mac_context * mac)702 void lim_reset_deferred_msg_q(struct mac_context *mac)
703 {
704 struct scheduler_msg *read_msg = {0};
705
706 if (mac->lim.gLimDeferredMsgQ.size > 0) {
707 while ((read_msg = lim_read_deferred_msg_q(mac)) != NULL) {
708 pe_free_msg(mac, read_msg);
709 }
710 }
711
712 mac->lim.gLimDeferredMsgQ.size =
713 mac->lim.gLimDeferredMsgQ.write =
714 mac->lim.gLimDeferredMsgQ.read = 0;
715
716 }
717
718 #define LIM_DEFERRED_Q_CHECK_THRESHOLD (MAX_DEFERRED_QUEUE_LEN/2)
719 #define LIM_MAX_NUM_MGMT_FRAME_DEFERRED (MAX_DEFERRED_QUEUE_LEN/2)
720
721 /**
722 * lim_write_deferred_msg_q() - This function queues up a deferred message
723 *
724 * @mac_ctx: Pointer to Global MAC structure
725 * @lim_msg: a LIM message
726 *
727 * Function queues up a deferred message for later processing on the
728 * STA side.
729 *
730 * Return: none
731 */
732
lim_write_deferred_msg_q(struct mac_context * mac_ctx,struct scheduler_msg * lim_msg)733 uint8_t lim_write_deferred_msg_q(struct mac_context *mac_ctx,
734 struct scheduler_msg *lim_msg)
735 {
736 uint8_t type = 0, subtype = 0;
737
738 pe_debug("Queue a deferred message size: %d write: %d - type: 0x%x",
739 mac_ctx->lim.gLimDeferredMsgQ.size,
740 mac_ctx->lim.gLimDeferredMsgQ.write,
741 lim_msg->type);
742
743 /* check if the deferred message queue is full */
744 if (mac_ctx->lim.gLimDeferredMsgQ.size >= MAX_DEFERRED_QUEUE_LEN) {
745 if (!(mac_ctx->lim.deferredMsgCnt & 0xF)) {
746 pe_err("queue->MsgQ full Msg: %d Msgs Failed: %d",
747 lim_msg->type,
748 ++mac_ctx->lim.deferredMsgCnt);
749 cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
750 WLAN_LOG_INDICATOR_HOST_DRIVER,
751 WLAN_LOG_REASON_QUEUE_FULL,
752 false, false);
753 } else {
754 mac_ctx->lim.deferredMsgCnt++;
755 }
756 return TX_QUEUE_FULL;
757 }
758
759 /*
760 * In the application, there should not be more than 1 message get
761 * queued up. If happens, flags a warning. In the future, this can
762 * happen.
763 */
764 if (mac_ctx->lim.gLimDeferredMsgQ.size > 0)
765 pe_debug("%d Deferred Msg type: 0x%x global sme: %d global mlme: %d addts: %d",
766 mac_ctx->lim.gLimDeferredMsgQ.size,
767 lim_msg->type,
768 mac_ctx->lim.gLimSmeState,
769 mac_ctx->lim.gLimMlmState,
770 mac_ctx->lim.gLimAddtsSent);
771
772 if (SIR_BB_XPORT_MGMT_MSG == lim_msg->type) {
773 lim_util_get_type_subtype(lim_msg->bodyptr,
774 &type, &subtype);
775 pe_debug(" Deferred management type %d subtype %d ",
776 type, subtype);
777 }
778
779 /*
780 * To prevent the deferred Q is full of management frames, only give
781 * them certain space
782 */
783 if ((SIR_BB_XPORT_MGMT_MSG == lim_msg->type) &&
784 (LIM_DEFERRED_Q_CHECK_THRESHOLD <
785 mac_ctx->lim.gLimDeferredMsgQ.size)) {
786 uint16_t idx, count = 0;
787
788 for (idx = 0; idx < mac_ctx->lim.gLimDeferredMsgQ.size;
789 idx++) {
790 if (SIR_BB_XPORT_MGMT_MSG ==
791 mac_ctx->lim.gLimDeferredMsgQ.
792 deferredQueue[idx].type) {
793 count++;
794 }
795 }
796 if (LIM_MAX_NUM_MGMT_FRAME_DEFERRED < count) {
797 /*
798 * We reach the quota for management frames,
799 * drop this one
800 */
801 pe_warn_rl("Too many queue->MsgQ Msg: %d count: %d",
802 lim_msg->type, count);
803 /* Return error, caller knows what to do */
804 return TX_QUEUE_FULL;
805 }
806 }
807
808 ++mac_ctx->lim.gLimDeferredMsgQ.size;
809
810 /* reset the count here since we are able to defer the message */
811 if (mac_ctx->lim.deferredMsgCnt != 0)
812 mac_ctx->lim.deferredMsgCnt = 0;
813
814 /* if the write pointer hits the end of the queue, rewind it */
815 if (mac_ctx->lim.gLimDeferredMsgQ.write >= MAX_DEFERRED_QUEUE_LEN)
816 mac_ctx->lim.gLimDeferredMsgQ.write = 0;
817
818 /* save the message to the queue and advanced the write pointer */
819 qdf_mem_copy((uint8_t *) &mac_ctx->lim.gLimDeferredMsgQ.
820 deferredQueue[mac_ctx->lim.gLimDeferredMsgQ.write++],
821 (uint8_t *) lim_msg,
822 sizeof(struct scheduler_msg));
823 return TX_SUCCESS;
824
825 }
826
827 /*
828 * lim_read_deferred_msg_q()
829 *
830 ***FUNCTION:
831 * This function dequeues a deferred message for processing on the
832 * STA side.
833 *
834 ***PARAMS:
835 * @param mac - Pointer to Global MAC structure
836 *
837 ***LOGIC:
838 *
839 ***ASSUMPTIONS:
840 * NA
841 *
842 ***NOTE:
843 *
844 *
845 ***RETURNS:
846 * Returns the message at the head of the deferred message queue
847 */
848
lim_read_deferred_msg_q(struct mac_context * mac)849 struct scheduler_msg *lim_read_deferred_msg_q(struct mac_context *mac)
850 {
851 struct scheduler_msg *msg = {0};
852
853 /*
854 ** check any messages left. If no, return
855 **/
856 if (mac->lim.gLimDeferredMsgQ.size <= 0)
857 return NULL;
858
859 /*
860 ** decrement the queue size
861 **/
862 mac->lim.gLimDeferredMsgQ.size--;
863
864 /*
865 ** retrieve the message from the head of the queue
866 **/
867 msg =
868 &mac->lim.gLimDeferredMsgQ.deferredQueue[mac->lim.
869 gLimDeferredMsgQ.read];
870
871 /*
872 ** advance the read pointer
873 **/
874 mac->lim.gLimDeferredMsgQ.read++;
875
876 /*
877 ** if the read pointer hits the end of the queue, rewind it
878 **/
879 if (mac->lim.gLimDeferredMsgQ.read >= MAX_DEFERRED_QUEUE_LEN)
880 mac->lim.gLimDeferredMsgQ.read = 0;
881
882 pe_debug("DeQueue a deferred message size: %d read: %d - type: 0x%x",
883 mac->lim.gLimDeferredMsgQ.size,
884 mac->lim.gLimDeferredMsgQ.read, msg->type);
885
886 pe_debug("DQ msg -- global sme: %d global mlme: %d addts: %d",
887 mac->lim.gLimSmeState, mac->lim.gLimMlmState,
888 mac->lim.gLimAddtsSent);
889
890 return msg;
891 }
892
893 /*
894 * lim_handle_update_olbc_cache() - This function update olbc cache
895 *
896 * @mac_ctx: Pointer to Global MAC structure
897 *
898 * Function updates olbc cache
899 *
900 * Return: none
901 */
lim_handle_update_olbc_cache(struct mac_context * mac_ctx)902 void lim_handle_update_olbc_cache(struct mac_context *mac_ctx)
903 {
904 int i;
905 static int enable;
906 tUpdateBeaconParams beaconParams;
907
908 struct pe_session *pe_session = lim_is_ap_session_active(mac_ctx);
909
910 if (!pe_session) {
911 pe_debug(" Session not found");
912 return;
913 }
914
915 if (pe_session->is_session_obss_offload_enabled) {
916 pe_debug("protection offloaded");
917 return;
918 }
919 qdf_mem_zero((uint8_t *) &beaconParams, sizeof(tUpdateBeaconParams));
920 beaconParams.bss_idx = pe_session->vdev_id;
921
922 beaconParams.paramChangeBitmap = 0;
923 /*
924 * This is doing a 2 pass check. The first pass is to invalidate
925 * all the cache entries. The second pass is to decide whether to
926 * disable protection.
927 */
928 if (!enable) {
929 pe_debug("Resetting OLBC cache");
930 pe_session->gLimOlbcParams.numSta = 0;
931 pe_session->gLimOverlap11gParams.numSta = 0;
932 pe_session->gLimOverlapHt20Params.numSta = 0;
933 pe_session->gLimNonGfParams.numSta = 0;
934 pe_session->gLimLsigTxopParams.numSta = 0;
935
936 for (i = 0; i < LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++)
937 mac_ctx->lim.protStaOverlapCache[i].active = false;
938
939 enable = 1;
940 } else {
941 if ((!pe_session->gLimOlbcParams.numSta) &&
942 (pe_session->gLimOlbcParams.protectionEnabled) &&
943 (!pe_session->gLim11bParams.protectionEnabled)) {
944 pe_debug("Overlap cache clear and no 11B STA set");
945 lim_enable11g_protection(mac_ctx, false, true,
946 &beaconParams,
947 pe_session);
948 }
949
950 if ((!pe_session->gLimOverlap11gParams.numSta) &&
951 (pe_session->gLimOverlap11gParams.protectionEnabled)
952 && (!pe_session->gLim11gParams.protectionEnabled)) {
953 pe_debug("Overlap cache clear and no 11G STA set");
954 lim_enable_ht_protection_from11g(mac_ctx, false, true,
955 &beaconParams,
956 pe_session);
957 }
958
959 if ((!pe_session->gLimOverlapHt20Params.numSta) &&
960 (pe_session->gLimOverlapHt20Params.protectionEnabled)
961 && (!pe_session->gLimHt20Params.protectionEnabled)) {
962 pe_debug("Overlap cache clear and no HT20 STA set");
963 lim_enable11g_protection(mac_ctx, false, true,
964 &beaconParams,
965 pe_session);
966 }
967
968 enable = 0;
969 }
970
971 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
972 && beaconParams.paramChangeBitmap) {
973 sch_set_fixed_beacon_fields(mac_ctx, pe_session);
974 lim_send_beacon_params(mac_ctx, &beaconParams, pe_session);
975 }
976 /* Start OLBC timer */
977 if (tx_timer_activate(&mac_ctx->lim.lim_timers.gLimUpdateOlbcCacheTimer)
978 != TX_SUCCESS)
979 pe_err("tx_timer_activate failed");
980 }
981
982 /**
983 * lim_is_null_ssid() - This function checks if ssid supplied is Null SSID
984 * @ssid: pointer to tSirMacSSid
985 *
986 * Function checks if ssid supplied is Null SSID
987 *
988 * Return: none
989 */
990
lim_is_null_ssid(tSirMacSSid * ssid)991 uint8_t lim_is_null_ssid(tSirMacSSid *ssid)
992 {
993 uint8_t fnull_ssid = false;
994 uint32_t ssid_len;
995 uint8_t *ssid_str;
996
997 if (0 == ssid->length) {
998 fnull_ssid = true;
999 return fnull_ssid;
1000 }
1001 /* If the first characters is space, then check if all
1002 * characters in SSID are spaces to consider it as NULL SSID
1003 */
1004 if ((ASCII_SPACE_CHARACTER == ssid->ssId[0]) &&
1005 (ssid->length == 1)) {
1006 fnull_ssid = true;
1007 return fnull_ssid;
1008 } else {
1009 /* check if all the characters in SSID are NULL */
1010 ssid_len = ssid->length;
1011 ssid_str = ssid->ssId;
1012
1013 while (ssid_len) {
1014 if (*ssid_str)
1015 return fnull_ssid;
1016
1017 ssid_str++;
1018 ssid_len--;
1019 }
1020
1021 if (0 == ssid_len) {
1022 fnull_ssid = true;
1023 return fnull_ssid;
1024 }
1025 }
1026
1027 return fnull_ssid;
1028 }
1029
1030 /** -------------------------------------------------------------
1031 \fn lim_update_prot_sta_params
1032 \brief updates protection related counters.
1033 \param struct mac_context * mac
1034 \param tSirMacAddr peerMacAddr
1035 \param tLimProtStaCacheType protStaCacheType
1036 \param tHalBitVal gfSupported
1037 \param tHalBitVal lsigTxopSupported
1038 \return None
1039 -------------------------------------------------------------*/
1040 static void
lim_update_prot_sta_params(struct mac_context * mac,tSirMacAddr peerMacAddr,tLimProtStaCacheType protStaCacheType,tHalBitVal gfSupported,tHalBitVal lsigTxopSupported,struct pe_session * pe_session)1041 lim_update_prot_sta_params(struct mac_context *mac,
1042 tSirMacAddr peerMacAddr,
1043 tLimProtStaCacheType protStaCacheType,
1044 tHalBitVal gfSupported, tHalBitVal lsigTxopSupported,
1045 struct pe_session *pe_session)
1046 {
1047 uint32_t i;
1048
1049 pe_debug("Associated STA addr is: "QDF_MAC_ADDR_FMT,
1050 QDF_MAC_ADDR_REF(peerMacAddr));
1051
1052 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1053 if (pe_session->protStaCache[i].active) {
1054 pe_debug("Addr:" QDF_MAC_ADDR_FMT,
1055 QDF_MAC_ADDR_REF(pe_session->protStaCache[i].addr));
1056
1057 if (!qdf_mem_cmp
1058 (pe_session->protStaCache[i].addr,
1059 peerMacAddr, sizeof(tSirMacAddr))) {
1060 pe_debug("matching cache entry at: %d already active",
1061 i);
1062 return;
1063 }
1064 }
1065 }
1066
1067 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1068 if (!pe_session->protStaCache[i].active)
1069 break;
1070 }
1071
1072 if (i >= LIM_PROT_STA_CACHE_SIZE) {
1073 pe_err("No space in ProtStaCache");
1074 return;
1075 }
1076
1077 qdf_mem_copy(pe_session->protStaCache[i].addr,
1078 peerMacAddr, sizeof(tSirMacAddr));
1079
1080 pe_session->protStaCache[i].protStaCacheType = protStaCacheType;
1081 pe_session->protStaCache[i].active = true;
1082 if (eLIM_PROT_STA_CACHE_TYPE_llB == protStaCacheType) {
1083 pe_session->gLim11bParams.numSta++;
1084 pe_debug("11B,");
1085 } else if (eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType) {
1086 pe_session->gLim11gParams.numSta++;
1087 pe_debug("11G,");
1088 } else if (eLIM_PROT_STA_CACHE_TYPE_HT20 == protStaCacheType) {
1089 pe_session->gLimHt20Params.numSta++;
1090 pe_debug("HT20,");
1091 }
1092
1093 if (!gfSupported) {
1094 pe_session->gLimNonGfParams.numSta++;
1095 pe_debug("NonGf,");
1096 }
1097 if (!lsigTxopSupported) {
1098 pe_session->gLimLsigTxopParams.numSta++;
1099 pe_debug("!lsigTxopSupported");
1100 }
1101 } /* --------------------------------------------------------------------- */
1102
1103 /** -------------------------------------------------------------
1104 \fn lim_decide_ap_protection
1105 \brief Decides all the protection related staiton coexistence and also sets
1106 \ short preamble and short slot appropriately. This function will be called
1107 \ when AP is ready to send assocRsp tp the station joining right now.
1108 \param struct mac_context * mac
1109 \param tSirMacAddr peerMacAddr
1110 \return None
1111 -------------------------------------------------------------*/
1112 void
lim_decide_ap_protection(struct mac_context * mac,tSirMacAddr peerMacAddr,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)1113 lim_decide_ap_protection(struct mac_context *mac, tSirMacAddr peerMacAddr,
1114 tpUpdateBeaconParams pBeaconParams,
1115 struct pe_session *pe_session)
1116 {
1117 uint16_t tmpAid;
1118 tpDphHashNode sta;
1119 enum reg_wifi_band rfBand = REG_BAND_UNKNOWN;
1120 uint32_t phyMode;
1121 tLimProtStaCacheType protStaCacheType =
1122 eLIM_PROT_STA_CACHE_TYPE_INVALID;
1123 tHalBitVal gfSupported = eHAL_SET, lsigTxopSupported = eHAL_SET;
1124
1125 pBeaconParams->paramChangeBitmap = 0;
1126 /* check whether to enable protection or not */
1127 sta =
1128 dph_lookup_hash_entry(mac, peerMacAddr, &tmpAid,
1129 &pe_session->dph.dphHashTable);
1130 if (!sta)
1131 return;
1132 lim_get_rf_band_new(mac, &rfBand, pe_session);
1133 /* if we are in 5 GHZ band */
1134 if (REG_BAND_5G == rfBand) {
1135 /* We are 11N. we need to protect from 11A and Ht20. we don't need any other protection in 5 GHZ. */
1136 /* HT20 case is common between both the bands and handled down as common code. */
1137 if (true == pe_session->htCapability) {
1138 /* we are 11N and 11A station is joining. */
1139 /* protection from 11A required. */
1140 if (false == sta->mlmStaContext.htCapability) {
1141 lim_update_11a_protection(mac, true, false,
1142 pBeaconParams,
1143 pe_session);
1144 return;
1145 }
1146 }
1147 } else if (REG_BAND_2G == rfBand) {
1148 lim_get_phy_mode(mac, &phyMode, pe_session);
1149
1150 /* We are 11G. Check if we need protection from 11b Stations. */
1151 if ((phyMode == WNI_CFG_PHY_MODE_11G) &&
1152 (false == pe_session->htCapability)) {
1153
1154 if (sta->erpEnabled == eHAL_CLEAR) {
1155 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB;
1156 /* enable protection */
1157 pe_debug("Enabling protection from 11B");
1158 lim_enable11g_protection(mac, true, false,
1159 pBeaconParams,
1160 pe_session);
1161 }
1162 }
1163 /* HT station. */
1164 if (true == pe_session->htCapability) {
1165 /* check if we need protection from 11b station */
1166 if ((sta->erpEnabled == eHAL_CLEAR) &&
1167 (!sta->mlmStaContext.htCapability)) {
1168 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB;
1169 /* enable protection */
1170 pe_debug("Enabling protection from 11B");
1171 lim_enable11g_protection(mac, true, false,
1172 pBeaconParams,
1173 pe_session);
1174 }
1175 /* station being joined is non-11b and non-ht ==> 11g device */
1176 else if (!sta->mlmStaContext.htCapability) {
1177 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llG;
1178 /* enable protection */
1179 lim_enable_ht_protection_from11g(mac, true, false,
1180 pBeaconParams,
1181 pe_session);
1182 }
1183 /* ERP mode is enabled for the latest station joined */
1184 /* latest station joined is HT capable */
1185 /* This case is being handled in common code (commn between both the bands) below. */
1186 }
1187 }
1188 /* we are HT and HT station is joining. This code is common for both the bands. */
1189 if ((true == pe_session->htCapability) &&
1190 (true == sta->mlmStaContext.htCapability)) {
1191 if (!sta->htGreenfield) {
1192 lim_enable_ht_non_gf_protection(mac, true, false,
1193 pBeaconParams,
1194 pe_session);
1195 gfSupported = eHAL_CLEAR;
1196 }
1197 /* Station joining is HT 20Mhz */
1198 if ((eHT_CHANNEL_WIDTH_20MHZ ==
1199 sta->htSupportedChannelWidthSet) &&
1200 (eHT_CHANNEL_WIDTH_20MHZ !=
1201 pe_session->htSupportedChannelWidthSet)){
1202 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_HT20;
1203 lim_enable_ht20_protection(mac, true, false,
1204 pBeaconParams, pe_session);
1205 }
1206 /* Station joining does not support LSIG TXOP Protection */
1207 if (!sta->htLsigTXOPProtection) {
1208 lim_enable_ht_lsig_txop_protection(mac, false, false,
1209 pBeaconParams,
1210 pe_session);
1211 lsigTxopSupported = eHAL_CLEAR;
1212 }
1213 }
1214
1215 lim_update_prot_sta_params(mac, peerMacAddr, protStaCacheType,
1216 gfSupported, lsigTxopSupported, pe_session);
1217
1218 return;
1219 }
1220
1221 /** -------------------------------------------------------------
1222 \fn lim_enable_overlap11g_protection
1223 \brief wrapper function for setting overlap 11g protection.
1224 \param struct mac_context * mac
1225 \param tpUpdateBeaconParams pBeaconParams
1226 \param tpSirMacMgmtHdr pMh
1227 \return None
1228 -------------------------------------------------------------*/
1229 void
lim_enable_overlap11g_protection(struct mac_context * mac,tpUpdateBeaconParams pBeaconParams,tpSirMacMgmtHdr pMh,struct pe_session * pe_session)1230 lim_enable_overlap11g_protection(struct mac_context *mac,
1231 tpUpdateBeaconParams pBeaconParams,
1232 tpSirMacMgmtHdr pMh, struct pe_session *pe_session)
1233 {
1234 lim_update_overlap_sta_param(mac, pMh->bssId,
1235 &(pe_session->gLimOlbcParams));
1236
1237 if (pe_session->gLimOlbcParams.numSta &&
1238 !pe_session->gLimOlbcParams.protectionEnabled) {
1239 /* enable protection */
1240 pe_debug("OLBC happens!!!");
1241 lim_enable11g_protection(mac, true, true, pBeaconParams,
1242 pe_session);
1243 }
1244 }
1245
1246 /**
1247 * lim_update_short_preamble() - This function Updates short preamble
1248 * @mac_ctx: pointer to Global MAC structure
1249 * @peer_mac_addr: pointer to tSirMacAddr
1250 * @pbeaconparams: pointer to tpUpdateBeaconParams
1251 * @psession_entry: pointer to struct pe_session *
1252 *
1253 * Function Updates short preamble if needed when a new station joins
1254 *
1255 * Return: none
1256 */
1257 void
lim_update_short_preamble(struct mac_context * mac_ctx,tSirMacAddr peer_mac_addr,tpUpdateBeaconParams beaconparams,struct pe_session * psession_entry)1258 lim_update_short_preamble(struct mac_context *mac_ctx, tSirMacAddr peer_mac_addr,
1259 tpUpdateBeaconParams beaconparams,
1260 struct pe_session *psession_entry)
1261 {
1262 uint16_t aid;
1263 tpDphHashNode sta_ds;
1264 uint32_t phy_mode;
1265 uint16_t i;
1266
1267 /* check whether to enable protection or not */
1268 sta_ds =
1269 dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid,
1270 &psession_entry->dph.dphHashTable);
1271
1272 lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry);
1273
1274 if (!sta_ds || phy_mode != WNI_CFG_PHY_MODE_11G)
1275 return;
1276
1277 if (sta_ds->shortPreambleEnabled != eHAL_CLEAR)
1278 return;
1279
1280 pe_debug("Short Preamble is not enabled in Assoc Req from "QDF_MAC_ADDR_FMT,
1281 QDF_MAC_ADDR_REF(peer_mac_addr));
1282
1283 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1284 if (LIM_IS_AP_ROLE(psession_entry) &&
1285 (psession_entry->gLimNoShortParams.
1286 staNoShortCache[i].active) &&
1287 (!qdf_mem_cmp
1288 (psession_entry->gLimNoShortParams.
1289 staNoShortCache[i].addr,
1290 peer_mac_addr, sizeof(tSirMacAddr))))
1291 return;
1292 else if (!LIM_IS_AP_ROLE(psession_entry) &&
1293 (mac_ctx->lim.gLimNoShortParams.
1294 staNoShortCache[i].active) &&
1295 (!qdf_mem_cmp(mac_ctx->lim.gLimNoShortParams.
1296 staNoShortCache[i].addr,
1297 peer_mac_addr,
1298 sizeof(tSirMacAddr))))
1299 return;
1300 }
1301
1302 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1303 if (LIM_IS_AP_ROLE(psession_entry) &&
1304 !psession_entry->gLimNoShortParams.
1305 staNoShortCache[i].active)
1306 break;
1307 else if (!mac_ctx->lim.gLimNoShortParams.
1308 staNoShortCache[i].active)
1309 break;
1310 }
1311
1312 if (i >= LIM_PROT_STA_CACHE_SIZE) {
1313 tLimNoShortParams *lim_params =
1314 &psession_entry->gLimNoShortParams;
1315 if (LIM_IS_AP_ROLE(psession_entry)) {
1316 pe_err("No space in Short cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT,
1317 i, lim_params->numNonShortPreambleSta,
1318 QDF_MAC_ADDR_REF(peer_mac_addr));
1319 return;
1320 } else {
1321 pe_err("No space in Short cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT,
1322 i, lim_params->numNonShortPreambleSta,
1323 QDF_MAC_ADDR_REF(peer_mac_addr));
1324 return;
1325 }
1326
1327 }
1328
1329 if (LIM_IS_AP_ROLE(psession_entry)) {
1330 qdf_mem_copy(psession_entry->gLimNoShortParams.
1331 staNoShortCache[i].addr,
1332 peer_mac_addr, sizeof(tSirMacAddr));
1333 psession_entry->gLimNoShortParams.staNoShortCache[i].
1334 active = true;
1335 psession_entry->gLimNoShortParams.numNonShortPreambleSta++;
1336 } else {
1337 qdf_mem_copy(mac_ctx->lim.gLimNoShortParams.
1338 staNoShortCache[i].addr,
1339 peer_mac_addr, sizeof(tSirMacAddr));
1340 mac_ctx->lim.gLimNoShortParams.staNoShortCache[i].active = true;
1341 mac_ctx->lim.gLimNoShortParams.numNonShortPreambleSta++;
1342 }
1343
1344 /* enable long preamble */
1345 pe_debug("Disabling short preamble");
1346
1347 if (lim_enable_short_preamble(mac_ctx, false, beaconparams,
1348 psession_entry) != QDF_STATUS_SUCCESS)
1349 pe_err("Cannot enable long preamble");
1350 }
1351
1352 /**
1353 * lim_update_short_slot_time() - This function Updates short slot time
1354 * @mac_ctx: pointer to Global MAC structure
1355 * @peer_mac_addr: pointer to tSirMacAddr
1356 * @beacon_params: pointer to tpUpdateBeaconParams
1357 * @psession_entry: pointer to struct pe_session *
1358 *
1359 * Function Updates short slot time if needed when a new station joins
1360 *
1361 * Return: None
1362 */
1363 void
lim_update_short_slot_time(struct mac_context * mac_ctx,tSirMacAddr peer_mac_addr,tpUpdateBeaconParams beacon_params,struct pe_session * session_entry)1364 lim_update_short_slot_time(struct mac_context *mac_ctx, tSirMacAddr peer_mac_addr,
1365 tpUpdateBeaconParams beacon_params,
1366 struct pe_session *session_entry)
1367 {
1368 uint16_t aid;
1369 tpDphHashNode sta_ds;
1370 uint32_t phy_mode;
1371 uint32_t val;
1372 uint16_t i;
1373
1374 /* check whether to enable protection or not */
1375 sta_ds = dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid,
1376 &session_entry->dph.dphHashTable);
1377 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
1378
1379 if (!sta_ds || phy_mode != WNI_CFG_PHY_MODE_11G)
1380 return;
1381
1382 /*
1383 * Only in case of softap in 11g mode, slot time might change
1384 * depending on the STA being added. In 11a case, it should
1385 * be always 1 and in 11b case, it should be always 0.
1386 * Only when the new STA has short slot time disabled, we need to
1387 * change softap's overall slot time settings else the default for
1388 * softap is always short slot enabled. When the last long slot STA
1389 * leaves softAP, we take care of it in lim_decide_short_slot
1390 */
1391 if (sta_ds->shortSlotTimeEnabled != eHAL_CLEAR)
1392 return;
1393
1394 pe_debug("Short Slot Time is not enabled in Assoc Req from "QDF_MAC_ADDR_FMT,
1395 QDF_MAC_ADDR_REF(peer_mac_addr));
1396 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1397 if (LIM_IS_AP_ROLE(session_entry) &&
1398 session_entry->gLimNoShortSlotParams.
1399 staNoShortSlotCache[i].active) {
1400 if (!qdf_mem_cmp(session_entry->
1401 gLimNoShortSlotParams.staNoShortSlotCache[i].addr,
1402 peer_mac_addr, sizeof(tSirMacAddr)))
1403 return;
1404 } else if (!LIM_IS_AP_ROLE(session_entry)) {
1405 if (mac_ctx->lim.gLimNoShortSlotParams.
1406 staNoShortSlotCache[i].active) {
1407 if (!qdf_mem_cmp(mac_ctx->
1408 lim.gLimNoShortSlotParams.
1409 staNoShortSlotCache[i].addr,
1410 peer_mac_addr, sizeof(tSirMacAddr)))
1411 return;
1412 }
1413 }
1414 }
1415 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
1416 if (LIM_IS_AP_ROLE(session_entry) &&
1417 !session_entry->gLimNoShortSlotParams.
1418 staNoShortSlotCache[i].active)
1419 break;
1420 else
1421 if (!mac_ctx->lim.gLimNoShortSlotParams.
1422 staNoShortSlotCache[i].active)
1423 break;
1424 }
1425
1426 if (i >= LIM_PROT_STA_CACHE_SIZE) {
1427 if (LIM_IS_AP_ROLE(session_entry)) {
1428 pe_err("No space in ShortSlot cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT,
1429 i, session_entry->gLimNoShortSlotParams.numNonShortSlotSta,
1430 QDF_MAC_ADDR_REF(peer_mac_addr));
1431 return;
1432 } else {
1433 pe_err("No space in ShortSlot cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT,
1434 i, mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta,
1435 QDF_MAC_ADDR_REF(peer_mac_addr));
1436 return;
1437 }
1438 }
1439
1440 if (LIM_IS_AP_ROLE(session_entry)) {
1441 qdf_mem_copy(session_entry->gLimNoShortSlotParams.
1442 staNoShortSlotCache[i].addr,
1443 peer_mac_addr, sizeof(tSirMacAddr));
1444 session_entry->gLimNoShortSlotParams.
1445 staNoShortSlotCache[i].active = true;
1446 session_entry->gLimNoShortSlotParams.numNonShortSlotSta++;
1447 } else {
1448 qdf_mem_copy(mac_ctx->lim.gLimNoShortSlotParams.
1449 staNoShortSlotCache[i].addr,
1450 peer_mac_addr, sizeof(tSirMacAddr));
1451 mac_ctx->lim.gLimNoShortSlotParams.
1452 staNoShortSlotCache[i].active = true;
1453 mac_ctx->lim.gLimNoShortSlotParams.
1454 numNonShortSlotSta++;
1455 }
1456 val = mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g;
1457 /*
1458 * Here we check if we are AP role and short slot enabled
1459 * (both admin and oper modes) but we have atleast one STA
1460 * connected with only long slot enabled, we need to change
1461 * our beacon/pb rsp to broadcast short slot disabled
1462 */
1463 if ((LIM_IS_AP_ROLE(session_entry)) && (val &&
1464 session_entry->gLimNoShortSlotParams.numNonShortSlotSta
1465 && session_entry->shortSlotTimeSupported)) {
1466 /* enable long slot time */
1467 beacon_params->fShortSlotTime = false;
1468 beacon_params->paramChangeBitmap |=
1469 PARAM_SHORT_SLOT_TIME_CHANGED;
1470 pe_debug("Disable short slot time. Enable long slot time");
1471 session_entry->shortSlotTimeSupported = false;
1472 } else if (!LIM_IS_AP_ROLE(session_entry) &&
1473 (val && mac_ctx->lim.gLimNoShortSlotParams.
1474 numNonShortSlotSta &&
1475 session_entry->shortSlotTimeSupported)) {
1476 /* enable long slot time */
1477 beacon_params->fShortSlotTime = false;
1478 beacon_params->paramChangeBitmap |=
1479 PARAM_SHORT_SLOT_TIME_CHANGED;
1480 pe_debug("Disable short slot time. Enable long slot time");
1481 session_entry->shortSlotTimeSupported = false;
1482 }
1483 }
1484
1485 /** -------------------------------------------------------------
1486 \fn lim_decide_sta_protection_on_assoc
1487 \brief Decide protection related settings on Sta while association.
1488 \param struct mac_context * mac
1489 \param tpSchBeaconStruct pBeaconStruct
1490 \return None
1491 -------------------------------------------------------------*/
1492 void
lim_decide_sta_protection_on_assoc(struct mac_context * mac,tpSchBeaconStruct pBeaconStruct,struct pe_session * pe_session)1493 lim_decide_sta_protection_on_assoc(struct mac_context *mac,
1494 tpSchBeaconStruct pBeaconStruct,
1495 struct pe_session *pe_session)
1496 {
1497 enum reg_wifi_band rfBand = REG_BAND_UNKNOWN;
1498 uint32_t phyMode = WNI_CFG_PHY_MODE_NONE;
1499
1500 lim_get_rf_band_new(mac, &rfBand, pe_session);
1501 lim_get_phy_mode(mac, &phyMode, pe_session);
1502
1503 if (REG_BAND_5G == rfBand) {
1504 if ((eSIR_HT_OP_MODE_MIXED == pBeaconStruct->HTInfo.opMode) ||
1505 (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
1506 pBeaconStruct->HTInfo.opMode)) {
1507 if (mac->lim.cfgProtection.fromlla)
1508 pe_session->beaconParams.llaCoexist = true;
1509 } else if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
1510 pBeaconStruct->HTInfo.opMode) {
1511 if (mac->lim.cfgProtection.ht20)
1512 pe_session->beaconParams.ht20Coexist = true;
1513 }
1514
1515 } else if (REG_BAND_2G == rfBand) {
1516 /* spec 7.3.2.13 */
1517 /* UseProtection will be set when nonERP STA is associated. */
1518 /* NonERPPresent bit will be set when: */
1519 /* --nonERP Sta is associated OR */
1520 /* --nonERP Sta exists in overlapping BSS */
1521 /* when useProtection is not set then protection from nonERP stations is optional. */
1522
1523 /* CFG protection from 11b is enabled and */
1524 /* 11B device in the BSS */
1525 /* TODO, This is not sessionized */
1526 if (phyMode != WNI_CFG_PHY_MODE_11B) {
1527 if (mac->lim.cfgProtection.fromllb &&
1528 pBeaconStruct->erpPresent &&
1529 (pBeaconStruct->erpIEInfo.useProtection ||
1530 pBeaconStruct->erpIEInfo.nonErpPresent)) {
1531 pe_session->beaconParams.llbCoexist = true;
1532 }
1533 /* AP has no 11b station associated. */
1534 else {
1535 pe_session->beaconParams.llbCoexist = false;
1536 }
1537 }
1538 /* following code block is only for HT station. */
1539 if ((pe_session->htCapability) &&
1540 (pBeaconStruct->HTInfo.present)) {
1541 tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo;
1542
1543 /* Obss Non HT STA present mode */
1544 pe_session->beaconParams.gHTObssMode =
1545 (uint8_t) htInfo.obssNonHTStaPresent;
1546
1547 /* CFG protection from 11G is enabled and */
1548 /* our AP has at least one 11G station associated. */
1549 if (mac->lim.cfgProtection.fromllg &&
1550 ((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) ||
1551 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode))
1552 && (!pe_session->beaconParams.llbCoexist)) {
1553 if (mac->lim.cfgProtection.fromllg)
1554 pe_session->beaconParams.llgCoexist =
1555 true;
1556 }
1557 /* AP has only HT stations associated and at least one station is HT 20 */
1558 /* disable protection from any non-HT devices. */
1559 /* decision for disabling protection from 11b has already been taken above. */
1560 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == htInfo.opMode) {
1561 /* Disable protection from 11G station. */
1562 pe_session->beaconParams.llgCoexist = false;
1563 /* CFG protection from HT 20 is enabled. */
1564 if (mac->lim.cfgProtection.ht20)
1565 pe_session->beaconParams.
1566 ht20Coexist = true;
1567 }
1568 /* Disable protection from non-HT and HT20 devices. */
1569 /* decision for disabling protection from 11b has already been taken above. */
1570 if (eSIR_HT_OP_MODE_PURE == htInfo.opMode) {
1571 pe_session->beaconParams.llgCoexist = false;
1572 pe_session->beaconParams.ht20Coexist = false;
1573 }
1574
1575 }
1576 }
1577 /* protection related factors other than HT operating mode. Applies to 2.4 GHZ as well as 5 GHZ. */
1578 if ((pe_session->htCapability) && (pBeaconStruct->HTInfo.present)) {
1579 tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo;
1580
1581 pe_session->beaconParams.fRIFSMode =
1582 (uint8_t) htInfo.rifsMode;
1583 pe_session->beaconParams.llnNonGFCoexist =
1584 (uint8_t) htInfo.nonGFDevicesPresent;
1585 pe_session->beaconParams.fLsigTXOPProtectionFullSupport =
1586 (uint8_t) htInfo.lsigTXOPProtectionFullSupport;
1587 }
1588 }
1589
1590
1591 /**
1592 * lim_decide_sta_11bg_protection() - decides protection related settings on sta
1593 * @mac_ctx: pointer to global mac structure
1594 * @beacon_struct: pointer to tpschbeaconstruct
1595 * @beaconparams: pointer to tpupdatebeaconparams
1596 * @psession_entry: pointer to tppesession
1597 * @phy_mode: phy mode index
1598 *
1599 * decides 11bg protection related settings on sta while processing beacon
1600 *
1601 * Return: none
1602 */
1603 static void
lim_decide_sta_11bg_protection(struct mac_context * mac_ctx,tpSchBeaconStruct beacon_struct,tpUpdateBeaconParams beaconparams,struct pe_session * psession_entry,uint32_t phy_mode)1604 lim_decide_sta_11bg_protection(struct mac_context *mac_ctx,
1605 tpSchBeaconStruct beacon_struct,
1606 tpUpdateBeaconParams beaconparams,
1607 struct pe_session *psession_entry,
1608 uint32_t phy_mode)
1609 {
1610
1611 tDot11fIEHTInfo htInfo;
1612
1613 /*
1614 * spec 7.3.2.13
1615 * UseProtection will be set when nonERP STA is associated.
1616 * NonERPPresent bit will be set when:
1617 * --nonERP Sta is associated OR
1618 * --nonERP Sta exists in overlapping BSS
1619 * when useProtection is not set then protection from
1620 * nonERP stations is optional.
1621 */
1622 if (phy_mode != WNI_CFG_PHY_MODE_11B) {
1623 if (beacon_struct->erpPresent &&
1624 (beacon_struct->erpIEInfo.useProtection ||
1625 beacon_struct->erpIEInfo.nonErpPresent)) {
1626 lim_enable11g_protection(mac_ctx, true, false,
1627 beaconparams,
1628 psession_entry);
1629 }
1630 /* AP has no 11b station associated. */
1631 else {
1632 /* disable protection from 11b station */
1633 lim_enable11g_protection(mac_ctx, false, false,
1634 beaconparams,
1635 psession_entry);
1636 }
1637 }
1638
1639 if (!(psession_entry->htCapability) ||
1640 !(beacon_struct->HTInfo.present))
1641 return;
1642
1643 /* following code is only for HT station. */
1644
1645 htInfo = beacon_struct->HTInfo;
1646 /* AP has at least one 11G station associated. */
1647 if (((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) ||
1648 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode)) &&
1649 (!psession_entry->beaconParams.llbCoexist)) {
1650 lim_enable_ht_protection_from11g(mac_ctx, true, false,
1651 beaconparams, psession_entry);
1652
1653 }
1654 /*
1655 * no HT operating mode change ==> no change in
1656 * protection settings except for MIXED_MODE/Legacy
1657 * Mode.
1658 */
1659 /*
1660 * in Mixed mode/legacy Mode even if there is no
1661 * change in HT operating mode, there might be
1662 * change in 11bCoexist or 11gCoexist. Hence this
1663 * check is being done after mixed/legacy mode
1664 * check.
1665 */
1666 if (mac_ctx->lim.gHTOperMode !=
1667 (tSirMacHTOperatingMode)htInfo.opMode) {
1668 mac_ctx->lim.gHTOperMode =
1669 (tSirMacHTOperatingMode) htInfo.opMode;
1670 /*
1671 * AP has only HT stations associated and
1672 * at least one station is HT 20
1673 */
1674
1675 /* disable protection from any non-HT devices. */
1676
1677 /*
1678 * decision for disabling protection from
1679 * 11b has already been taken above.
1680 */
1681 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
1682 htInfo.opMode) {
1683 /* Disable protection from 11G station. */
1684 lim_enable_ht_protection_from11g(mac_ctx, false,
1685 false, beaconparams,
1686 psession_entry);
1687
1688 lim_enable_ht20_protection(mac_ctx, true, false,
1689 beaconparams,
1690 psession_entry);
1691 }
1692 /*
1693 * Disable protection from non-HT and
1694 * HT20 devices.
1695 */
1696 /*
1697 * decision for disabling protection from
1698 * 11b has already been taken above.
1699 */
1700 else if (eSIR_HT_OP_MODE_PURE == htInfo.opMode) {
1701 lim_enable_ht_protection_from11g(mac_ctx, false,
1702 false, beaconparams,
1703 psession_entry);
1704
1705 lim_enable_ht20_protection(mac_ctx, false,
1706 false, beaconparams,
1707 psession_entry);
1708
1709 }
1710 }
1711
1712 }
1713
1714 /**
1715 * lim_decide_sta_protection() - decides protection related settings on sta
1716 * @mac_ctx: pointer to global mac structure
1717 * @beacon_struct: pointer to tpschbeaconstruct
1718 * @beaconparams: pointer to tpupdatebeaconparams
1719 * @psession_entry: pointer to tppesession
1720 *
1721 * decides protection related settings on sta while processing beacon
1722 *
1723 * Return: none
1724 */
1725 void
lim_decide_sta_protection(struct mac_context * mac_ctx,tpSchBeaconStruct beacon_struct,tpUpdateBeaconParams beaconparams,struct pe_session * psession_entry)1726 lim_decide_sta_protection(struct mac_context *mac_ctx,
1727 tpSchBeaconStruct beacon_struct,
1728 tpUpdateBeaconParams beaconparams,
1729 struct pe_session *psession_entry)
1730 {
1731
1732 enum reg_wifi_band rfband = REG_BAND_UNKNOWN;
1733 uint32_t phy_mode = WNI_CFG_PHY_MODE_NONE;
1734
1735 lim_get_rf_band_new(mac_ctx, &rfband, psession_entry);
1736 lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry);
1737
1738 if ((REG_BAND_5G == rfband) &&
1739 /* we are HT capable. */
1740 (true == psession_entry->htCapability) &&
1741 (beacon_struct->HTInfo.present)) {
1742 /*
1743 * we are HT capable, AP's HT OPMode is
1744 * mixed / overlap legacy ==> need protection
1745 * from 11A.
1746 */
1747 if ((eSIR_HT_OP_MODE_MIXED ==
1748 beacon_struct->HTInfo.opMode) ||
1749 (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
1750 beacon_struct->HTInfo.opMode)) {
1751 lim_update_11a_protection(mac_ctx, true, false,
1752 beaconparams, psession_entry);
1753 }
1754 /*
1755 * we are HT capable, AP's HT OPMode is
1756 * HT20 ==> disable protection from 11A if
1757 * enabled.
1758 */
1759 /* protection from HT20 if needed. */
1760 else if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
1761 beacon_struct->HTInfo.opMode) {
1762 lim_update_11a_protection(mac_ctx, false, false,
1763 beaconparams, psession_entry);
1764 lim_enable_ht20_protection(mac_ctx, true, false,
1765 beaconparams, psession_entry);
1766 } else if (eSIR_HT_OP_MODE_PURE ==
1767 beacon_struct->HTInfo.opMode) {
1768 lim_update_11a_protection(mac_ctx, false, false,
1769 beaconparams, psession_entry);
1770 lim_enable_ht20_protection(mac_ctx, false,
1771 false, beaconparams,
1772 psession_entry);
1773 }
1774 } else if (REG_BAND_2G == rfband) {
1775 lim_decide_sta_11bg_protection(mac_ctx, beacon_struct,
1776 beaconparams, psession_entry, phy_mode);
1777 }
1778 /*
1779 * following code block is only for HT station.
1780 * (2.4 GHZ as well as 5 GHZ)
1781 */
1782 if ((psession_entry->htCapability) && (beacon_struct->HTInfo.present)) {
1783 tDot11fIEHTInfo htInfo = beacon_struct->HTInfo;
1784 /*
1785 * Check for changes in protection related factors other
1786 * than HT operating mode.
1787 */
1788 /*
1789 * Check for changes in RIFS mode, nonGFDevicesPresent,
1790 * lsigTXOPProtectionFullSupport.
1791 */
1792 if (psession_entry->beaconParams.fRIFSMode !=
1793 (uint8_t) htInfo.rifsMode) {
1794 beaconparams->fRIFSMode =
1795 psession_entry->beaconParams.fRIFSMode =
1796 (uint8_t) htInfo.rifsMode;
1797 beaconparams->paramChangeBitmap |=
1798 PARAM_RIFS_MODE_CHANGED;
1799 }
1800
1801 if (psession_entry->beaconParams.llnNonGFCoexist !=
1802 htInfo.nonGFDevicesPresent) {
1803 beaconparams->llnNonGFCoexist =
1804 psession_entry->beaconParams.llnNonGFCoexist =
1805 (uint8_t) htInfo.nonGFDevicesPresent;
1806 beaconparams->paramChangeBitmap |=
1807 PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
1808 }
1809
1810 if (psession_entry->beaconParams.
1811 fLsigTXOPProtectionFullSupport !=
1812 (uint8_t) htInfo.lsigTXOPProtectionFullSupport) {
1813 beaconparams->fLsigTXOPProtectionFullSupport =
1814 psession_entry->beaconParams.
1815 fLsigTXOPProtectionFullSupport =
1816 (uint8_t) htInfo.
1817 lsigTXOPProtectionFullSupport;
1818 beaconparams->paramChangeBitmap |=
1819 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
1820 }
1821 /*
1822 * For Station just update the global lim variable,
1823 * no need to send message to HAL since Station already
1824 * taking care of HT OPR Mode=01,
1825 * meaning AP is seeing legacy
1826 */
1827 /* stations in overlapping BSS. */
1828 if (psession_entry->beaconParams.gHTObssMode !=
1829 (uint8_t) htInfo.obssNonHTStaPresent)
1830 psession_entry->beaconParams.gHTObssMode =
1831 (uint8_t) htInfo.obssNonHTStaPresent;
1832
1833 }
1834 }
1835
1836 /**
1837 * __lim_process_channel_switch_timeout()
1838 *
1839 ***FUNCTION:
1840 * This function is invoked when Channel Switch Timer expires at
1841 * the STA. Now, STA must stop traffic, and then change/disable
1842 * primary or secondary channel.
1843 *
1844 *
1845 ***NOTE:
1846 * @param pe_session - Pointer to pe session
1847 *
1848 * @return qdf_status
1849 */
1850 static QDF_STATUS
__lim_process_channel_switch_timeout(struct pe_session * pe_session)1851 __lim_process_channel_switch_timeout(struct pe_session *pe_session)
1852 {
1853 struct mac_context *mac;
1854 uint32_t channel_freq;
1855 QDF_STATUS status = QDF_STATUS_SUCCESS;
1856
1857 if (!pe_session) {
1858 pe_err("Invalid pe session");
1859 return QDF_STATUS_E_INVAL;
1860 }
1861 mac = pe_session->mac_ctx;
1862 if (!mac) {
1863 pe_err("Invalid mac context");
1864 return QDF_STATUS_E_INVAL;
1865 }
1866
1867 if (!LIM_IS_STA_ROLE(pe_session)) {
1868 pe_warn("Channel switch can be done only in STA role, Current Role: %d",
1869 GET_LIM_SYSTEM_ROLE(pe_session));
1870 return QDF_STATUS_E_INVAL;
1871 }
1872
1873 if (pe_session->gLimSpecMgmt.dot11hChanSwState !=
1874 eLIM_11H_CHANSW_RUNNING) {
1875 pe_warn("Channel switch timer should not have been running in state: %d",
1876 pe_session->gLimSpecMgmt.dot11hChanSwState);
1877 return QDF_STATUS_E_INVAL;
1878 }
1879
1880 channel_freq = pe_session->gLimChannelSwitch.sw_target_freq;
1881 /* Restore Channel Switch parameters to default */
1882 pe_session->gLimChannelSwitch.switchTimeoutValue = 0;
1883
1884 /* Channel-switch timeout has occurred. reset the state */
1885 pe_session->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_END;
1886
1887 /* Check if the AP is switching to a channel that we support.
1888 * Else, just don't bother to switch. Indicate HDD to look for a
1889 * better AP to associate
1890 */
1891 if (!lim_is_channel_valid_for_channel_switch(mac, channel_freq)) {
1892 /* We need to restore pre-channelSwitch state on the STA */
1893 if (lim_restore_pre_channel_switch_state(mac, pe_session) !=
1894 QDF_STATUS_SUCCESS) {
1895 pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system");
1896 return QDF_STATUS_E_INVAL;
1897 }
1898
1899 /*
1900 * The channel switch request received from AP is carrying
1901 * invalid channel. It's ok to ignore this channel switch
1902 * request as it might be from spoof AP. If it's from genuine
1903 * AP, it may lead to heart beat failure and result in
1904 * disconnection. DUT can go ahead and reconnect to it/any
1905 * other AP once it disconnects.
1906 */
1907 pe_err("Invalid channel freq %u Ignore CSA request",
1908 channel_freq);
1909 return QDF_STATUS_E_INVAL;
1910 }
1911 switch (pe_session->gLimChannelSwitch.state) {
1912 case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY:
1913 status = lim_switch_primary_channel(mac,
1914 pe_session->gLimChannelSwitch.sw_target_freq,
1915 pe_session);
1916 pe_session->gLimChannelSwitch.state =
1917 eLIM_CHANNEL_SWITCH_IDLE;
1918 break;
1919 case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY:
1920 status = lim_switch_primary_secondary_channel(mac, pe_session);
1921 pe_session->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE;
1922 break;
1923
1924 case eLIM_CHANNEL_SWITCH_IDLE:
1925 default:
1926 pe_err("incorrect state");
1927 if (lim_restore_pre_channel_switch_state(mac, pe_session) !=
1928 QDF_STATUS_SUCCESS) {
1929 pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system");
1930 status = QDF_STATUS_E_FAILURE;
1931 }
1932 /* Please note, this is 'return' and not 'break' */
1933 return status;
1934 }
1935
1936 return status;
1937 }
1938
lim_disconnect_complete(struct pe_session * session,bool del_bss)1939 void lim_disconnect_complete(struct pe_session *session, bool del_bss)
1940 {
1941 QDF_STATUS status;
1942 struct mac_context *mac = session->mac_ctx;
1943
1944 if (wlan_vdev_mlme_get_substate(session->vdev) ==
1945 WLAN_VDEV_SS_STOP_STOP_PROGRESS) {
1946 status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
1947 WLAN_VDEV_SM_EV_STOP_REQ,
1948 sizeof(*session),
1949 session);
1950 return;
1951 }
1952 status =
1953 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
1954 WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE,
1955 sizeof(*session), session);
1956 if (QDF_IS_STATUS_ERROR(status))
1957 lim_send_stop_bss_failure_resp(mac, session);
1958 }
1959
lim_process_channel_switch(struct mac_context * mac_ctx,uint8_t vdev_id)1960 void lim_process_channel_switch(struct mac_context *mac_ctx, uint8_t vdev_id)
1961 {
1962 struct pe_session *session_entry;
1963 QDF_STATUS status;
1964
1965 session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
1966 if (!session_entry) {
1967 pe_err("Session does not exist for given vdev_id %d", vdev_id);
1968 return;
1969 }
1970
1971 session_entry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION;
1972 mlme_set_chan_switch_in_progress(session_entry->vdev, true);
1973 status = wlan_vdev_mlme_sm_deliver_evt(
1974 session_entry->vdev,
1975 WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
1976 sizeof(*session_entry),
1977 session_entry);
1978 if (QDF_IS_STATUS_ERROR(status))
1979 mlme_set_chan_switch_in_progress(session_entry->vdev, false);
1980 }
1981
1982 /** ------------------------------------------------------------------------ **/
1983 /**
1984 * keep track of the number of ANI peers associated in the BSS
1985 * For the first and last ANI peer, we have to update EDCA params as needed
1986 *
1987 * When the first ANI peer joins the BSS, we notify SCH
1988 * When the last ANI peer leaves the BSS, we notfiy SCH
1989 */
1990 void
lim_util_count_sta_add(struct mac_context * mac,tpDphHashNode pSta,struct pe_session * pe_session)1991 lim_util_count_sta_add(struct mac_context *mac,
1992 tpDphHashNode pSta, struct pe_session *pe_session)
1993 {
1994
1995 if ((!pSta) || (!pSta->valid) || (pSta->fAniCount))
1996 return;
1997
1998 pSta->fAniCount = 1;
1999
2000 if (mac->lim.gLimNumOfAniSTAs++ != 0)
2001 return;
2002
2003 if (mac->mlme_cfg->wmm_params.edca_profile !=
2004 WNI_CFG_EDCA_PROFILE_ANI)
2005 return;
2006
2007 /* get here only if this is the first ANI peer in the BSS */
2008 sch_edca_profile_update(mac, pe_session);
2009 }
2010
2011 void
lim_util_count_sta_del(struct mac_context * mac,tpDphHashNode pSta,struct pe_session * pe_session)2012 lim_util_count_sta_del(struct mac_context *mac,
2013 tpDphHashNode pSta, struct pe_session *pe_session)
2014 {
2015
2016 if ((!pSta) || (!pSta->fAniCount))
2017 return;
2018
2019 /* Only if sta is invalid and the validInDummyState bit is set to 1,
2020 * then go ahead and update the count and profiles. This ensures
2021 * that the "number of ani station" count is properly incremented/decremented.
2022 */
2023 if (pSta->valid == 1)
2024 return;
2025
2026 pSta->fAniCount = 0;
2027
2028 if (mac->lim.gLimNumOfAniSTAs <= 0) {
2029 pe_err("CountStaDel: ignoring Delete Req when AniPeer count: %d",
2030 mac->lim.gLimNumOfAniSTAs);
2031 return;
2032 }
2033
2034 mac->lim.gLimNumOfAniSTAs--;
2035
2036 if (mac->lim.gLimNumOfAniSTAs != 0)
2037 return;
2038
2039 if (mac->mlme_cfg->wmm_params.edca_profile !=
2040 WNI_CFG_EDCA_PROFILE_ANI)
2041 return;
2042
2043 /* get here only if this is the last ANI peer in the BSS */
2044 sch_edca_profile_update(mac, pe_session);
2045 }
2046
2047 /**
2048 * lim_switch_channel_vdev_started() - Send vdev started when switch channel
2049 *
2050 * @pe_session: PE session entry
2051 *
2052 * This function is called to deliver WLAN_VDEV_SM_EV_START_SUCCESS to VDEV SM
2053 *
2054 * Return: None
2055 */
lim_switch_channel_vdev_started(struct pe_session * pe_session)2056 static void lim_switch_channel_vdev_started(struct pe_session *pe_session)
2057 {
2058 QDF_STATUS status;
2059
2060 status = wlan_vdev_mlme_sm_deliver_evt(
2061 pe_session->vdev,
2062 WLAN_VDEV_SM_EV_START_SUCCESS,
2063 sizeof(*pe_session), pe_session);
2064 }
2065
2066 /**
2067 * lim_switch_channel_cback()
2068 *
2069 ***FUNCTION:
2070 * This is the callback function registered while requesting to switch channel
2071 * after AP indicates a channel switch for spectrum management (11h).
2072 *
2073 ***NOTE:
2074 * @param mac Pointer to Global MAC structure
2075 * @param status Status of channel switch request
2076 * @param data User data
2077 * @param pe_session Session information
2078 * @return NONE
2079 */
lim_switch_channel_cback(struct mac_context * mac,QDF_STATUS status,uint32_t * data,struct pe_session * pe_session)2080 void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status,
2081 uint32_t *data, struct pe_session *pe_session)
2082 {
2083 struct scheduler_msg mmhMsg = { 0 };
2084 struct switch_channel_ind *pSirSmeSwitchChInd;
2085 struct wlan_channel *des_chan;
2086 struct vdev_mlme_obj *mlme_obj;
2087
2088 if (QDF_IS_STATUS_ERROR(status)) {
2089 lim_tear_down_link_with_ap(mac, pe_session->peSessionId,
2090 REASON_CHANNEL_SWITCH_FAILED,
2091 eLIM_HOST_DISASSOC);
2092 return;
2093 }
2094
2095 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
2096 if (!mlme_obj) {
2097 pe_err("vdev component object is NULL");
2098 return;
2099 }
2100
2101 des_chan = mlme_obj->vdev->vdev_mlme.des_chan;
2102 if (!des_chan) {
2103 pe_err("des_chan is NULL");
2104 return;
2105 }
2106 pe_session->curr_op_freq = pe_session->curr_req_chan_freq;
2107 /* We need to restore pre-channelSwitch state on the STA */
2108 if (lim_restore_pre_channel_switch_state(mac, pe_session) !=
2109 QDF_STATUS_SUCCESS) {
2110 pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system");
2111 return;
2112 }
2113
2114 mmhMsg.type = eWNI_SME_SWITCH_CHL_IND;
2115 pSirSmeSwitchChInd = qdf_mem_malloc(sizeof(*pSirSmeSwitchChInd));
2116 if (!pSirSmeSwitchChInd)
2117 return;
2118
2119 pSirSmeSwitchChInd->messageType = eWNI_SME_SWITCH_CHL_IND;
2120 pSirSmeSwitchChInd->length = sizeof(*pSirSmeSwitchChInd);
2121 pSirSmeSwitchChInd->freq = des_chan->ch_freq;
2122 pSirSmeSwitchChInd->sessionId = pe_session->smeSessionId;
2123 pSirSmeSwitchChInd->chan_params.ch_width = des_chan->ch_width;
2124 if (des_chan->ch_width > CH_WIDTH_20MHZ) {
2125 pSirSmeSwitchChInd->chan_params.sec_ch_offset =
2126 pe_session->gLimChannelSwitch.sec_ch_offset;
2127 pSirSmeSwitchChInd->chan_params.center_freq_seg0 =
2128 des_chan->ch_freq_seg1;
2129 pSirSmeSwitchChInd->chan_params.mhz_freq_seg0 =
2130 des_chan->ch_cfreq1;
2131 pSirSmeSwitchChInd->chan_params.center_freq_seg1 =
2132 des_chan->ch_freq_seg2;
2133 pSirSmeSwitchChInd->chan_params.mhz_freq_seg1 =
2134 des_chan->ch_cfreq2;
2135 }
2136 pSirSmeSwitchChInd->ch_phymode = des_chan->ch_phymode;
2137
2138 pSirSmeSwitchChInd->status = status;
2139 qdf_mem_copy(pSirSmeSwitchChInd->bssid.bytes, pe_session->bssId,
2140 QDF_MAC_ADDR_SIZE);
2141 mmhMsg.bodyptr = pSirSmeSwitchChInd;
2142 mmhMsg.bodyval = 0;
2143
2144 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
2145 pe_session->peSessionId, mmhMsg.type));
2146
2147 sys_process_mmh_msg(mac, &mmhMsg);
2148
2149 lim_switch_channel_vdev_started(pe_session);
2150 }
2151
2152 #ifdef WLAN_FEATURE_11BE
2153 /**
2154 * lim_set_puncture_from_chan_switch_to_session() - set puncture from channel
2155 * switch to pe session
2156 * @pe_session: pointer to pe session
2157 *
2158 * Return: void
2159 */
2160 static void
lim_set_puncture_from_chan_switch_to_session(struct pe_session * pe_session)2161 lim_set_puncture_from_chan_switch_to_session(struct pe_session *pe_session)
2162 {
2163 pe_session->puncture_bitmap =
2164 pe_session->gLimChannelSwitch.puncture_bitmap;
2165 }
2166 #else
2167 static void
lim_set_puncture_from_chan_switch_to_session(struct pe_session * pe_session)2168 lim_set_puncture_from_chan_switch_to_session(struct pe_session *pe_session)
2169 {
2170 }
2171 #endif
2172
lim_switch_primary_channel(struct mac_context * mac,uint32_t new_channel_freq,struct pe_session * pe_session)2173 QDF_STATUS lim_switch_primary_channel(struct mac_context *mac,
2174 uint32_t new_channel_freq,
2175 struct pe_session *pe_session)
2176 {
2177 pe_debug("freq: %d --> freq: %d", pe_session->curr_op_freq,
2178 new_channel_freq);
2179
2180 pe_session->curr_req_chan_freq = new_channel_freq;
2181 pe_session->curr_op_freq = pe_session->curr_req_chan_freq;
2182 pe_session->ch_center_freq_seg0 = 0;
2183 pe_session->ch_center_freq_seg1 = 0;
2184 pe_session->ch_width = CH_WIDTH_20MHZ;
2185 lim_set_puncture_from_chan_switch_to_session(pe_session);
2186 pe_session->limRFBand = lim_get_rf_band(pe_session->curr_req_chan_freq);
2187
2188 pe_session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION;
2189
2190 mac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
2191 mac->lim.gpchangeChannelData = NULL;
2192
2193 return lim_send_switch_chnl_params(mac, pe_session);
2194 }
2195
lim_switch_primary_secondary_channel(struct mac_context * mac,struct pe_session * pe_session)2196 QDF_STATUS lim_switch_primary_secondary_channel(struct mac_context *mac,
2197 struct pe_session *pe_session)
2198 {
2199 uint32_t new_channel_freq;
2200 uint8_t ch_center_freq_seg0;
2201 uint8_t ch_center_freq_seg1;
2202 enum phy_ch_width ch_width;
2203
2204 new_channel_freq = pe_session->gLimChannelSwitch.sw_target_freq,
2205 ch_center_freq_seg0 = pe_session->gLimChannelSwitch.ch_center_freq_seg0,
2206 ch_center_freq_seg1 = pe_session->gLimChannelSwitch.ch_center_freq_seg1,
2207 ch_width = pe_session->gLimChannelSwitch.ch_width;
2208
2209 /* Assign the callback to resume TX once channel is changed. */
2210 pe_session->curr_req_chan_freq = new_channel_freq;
2211 pe_session->limRFBand = lim_get_rf_band(pe_session->curr_req_chan_freq);
2212 pe_session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION;
2213 mac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
2214 mac->lim.gpchangeChannelData = NULL;
2215
2216 /* Store the new primary and secondary channel in session entries if different */
2217 if (pe_session->curr_op_freq != new_channel_freq ||
2218 pe_session->ch_width != ch_width) {
2219 pe_warn("freq: %d[%d] --> freq: %d[%d]",
2220 pe_session->curr_op_freq, pe_session->ch_width,
2221 new_channel_freq, ch_width);
2222 pe_session->curr_op_freq = new_channel_freq;
2223 }
2224 if (pe_session->htSecondaryChannelOffset !=
2225 pe_session->gLimChannelSwitch.sec_ch_offset) {
2226 pe_warn("HT sec chnl: %d --> HT sec chnl: %d",
2227 pe_session->htSecondaryChannelOffset,
2228 pe_session->gLimChannelSwitch.sec_ch_offset);
2229 pe_session->htSecondaryChannelOffset =
2230 pe_session->gLimChannelSwitch.sec_ch_offset;
2231 if (pe_session->htSecondaryChannelOffset ==
2232 PHY_SINGLE_CHANNEL_CENTERED) {
2233 pe_session->htSupportedChannelWidthSet =
2234 WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
2235 } else {
2236 pe_session->htSupportedChannelWidthSet =
2237 WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
2238 }
2239 pe_session->htRecommendedTxWidthSet =
2240 pe_session->htSupportedChannelWidthSet;
2241 }
2242
2243 pe_session->ch_center_freq_seg0 = ch_center_freq_seg0;
2244 pe_session->ch_center_freq_seg1 = ch_center_freq_seg1;
2245 pe_session->ch_width = ch_width;
2246 lim_set_puncture_from_chan_switch_to_session(pe_session);
2247
2248 return lim_send_switch_chnl_params(mac, pe_session);
2249 }
2250
2251 /**
2252 * lim_get_ht_capability()
2253 *
2254 ***FUNCTION:
2255 * A utility function that returns the "current HT capability state" for the HT
2256 * capability of interest (as requested in the API)
2257 *
2258 ***LOGIC:
2259 * This routine will return with the "current" setting of a requested HT
2260 * capability. This state info could be retrieved from -
2261 * a) CFG (for static entries)
2262 * b) Run time info
2263 * - Dynamic state maintained by LIM
2264 * - Configured at radio init time by SME
2265 *
2266 *
2267 ***ASSUMPTIONS:
2268 * NA
2269 *
2270 ***NOTE:
2271 *
2272 * @param mac Pointer to Global MAC structure
2273 * @param htCap The HT capability being queried
2274 * @return uint8_t The current state of the requested HT capability is returned in a
2275 * uint8_t variable
2276 */
2277
lim_get_ht_capability(struct mac_context * mac,uint32_t htCap,struct pe_session * pe_session)2278 uint8_t lim_get_ht_capability(struct mac_context *mac,
2279 uint32_t htCap, struct pe_session *pe_session)
2280 {
2281 uint8_t retVal = 0;
2282 uint8_t *ptr;
2283 tSirMacTxBFCapabilityInfo macTxBFCapabilityInfo = { 0 };
2284 tSirMacASCapabilityInfo macASCapabilityInfo = { 0 };
2285 struct mlme_vht_capabilities_info *vht_cap_info;
2286
2287 vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info;
2288
2289 /* */
2290 /* Determine which CFG to read from. Not ALL of the HT */
2291 /* related CFG's need to be read each time this API is */
2292 /* accessed */
2293 /* */
2294 if (htCap >= eHT_ANTENNA_SELECTION && htCap < eHT_SI_GRANULARITY) {
2295 /* Get Antenna Selection HT Capabilities */
2296 ptr = (uint8_t *) &macASCapabilityInfo;
2297 *((uint8_t *)ptr) = (uint8_t)(vht_cap_info->as_cap & 0xff);
2298 } else if (htCap >= eHT_TX_BEAMFORMING &&
2299 htCap < eHT_ANTENNA_SELECTION) {
2300 /* Get Transmit Beam Forming HT Capabilities */
2301 ptr = (uint8_t *)&macTxBFCapabilityInfo;
2302 *((uint32_t *)ptr) = (uint32_t)(vht_cap_info->tx_bf_cap);
2303 }
2304
2305 switch (htCap) {
2306 case eHT_LSIG_TXOP_PROTECTION:
2307 retVal = mac->lim.gHTLsigTXOPProtection;
2308 break;
2309
2310 case eHT_STBC_CONTROL_FRAME:
2311 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ht_cap_info.
2312 stbc_control_frame;
2313 break;
2314
2315 case eHT_PSMP:
2316 retVal = mac->lim.gHTPSMPSupport;
2317 break;
2318
2319 case eHT_DSSS_CCK_MODE_40MHZ:
2320 retVal = mac->lim.gHTDsssCckRate40MHzSupport;
2321 break;
2322
2323 case eHT_MAX_AMSDU_LENGTH:
2324 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ht_cap_info.
2325 maximal_amsdu_size;
2326 break;
2327
2328 case eHT_MAX_AMSDU_NUM:
2329 retVal = (uint8_t) pe_session->max_amsdu_num;
2330 break;
2331
2332 case eHT_RX_STBC:
2333 retVal = (uint8_t) pe_session->ht_config.rx_stbc;
2334 break;
2335
2336 case eHT_TX_STBC:
2337 retVal = (uint8_t) pe_session->ht_config.tx_stbc;
2338 break;
2339
2340 case eHT_SHORT_GI_40MHZ:
2341 retVal = (uint8_t)(pe_session->ht_config.short_gi_40_mhz) ?
2342 mac->mlme_cfg->ht_caps.ht_cap_info.short_gi_40_mhz : 0;
2343 break;
2344
2345 case eHT_SHORT_GI_20MHZ:
2346 retVal = (uint8_t)(pe_session->ht_config.short_gi_20_mhz) ?
2347 mac->mlme_cfg->ht_caps.ht_cap_info.short_gi_20_mhz : 0;
2348 break;
2349
2350 case eHT_GREENFIELD:
2351 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ht_cap_info.
2352 green_field;
2353 break;
2354
2355 case eHT_MIMO_POWER_SAVE:
2356 retVal = (uint8_t) mac->lim.gHTMIMOPSState;
2357 break;
2358
2359 case eHT_SUPPORTED_CHANNEL_WIDTH_SET:
2360 retVal = (uint8_t) pe_session->htSupportedChannelWidthSet;
2361 break;
2362
2363 case eHT_ADVANCED_CODING:
2364 retVal = (uint8_t) pe_session->ht_config.adv_coding_cap;
2365 break;
2366
2367 case eHT_MAX_RX_AMPDU_FACTOR:
2368 retVal = mac->lim.gHTMaxRxAMpduFactor;
2369 break;
2370
2371 case eHT_MPDU_DENSITY:
2372 retVal = mac->lim.gHTAMpduDensity;
2373 break;
2374
2375 case eHT_PCO:
2376 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ext_cap_info.pco;
2377 break;
2378
2379 case eHT_TRANSITION_TIME:
2380 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ext_cap_info.
2381 transition_time;
2382 break;
2383
2384 case eHT_MCS_FEEDBACK:
2385 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ext_cap_info.
2386 mcs_feedback;
2387 break;
2388
2389 case eHT_TX_BEAMFORMING:
2390 retVal = (uint8_t) macTxBFCapabilityInfo.txBF;
2391 break;
2392
2393 case eHT_ANTENNA_SELECTION:
2394 retVal = (uint8_t) macASCapabilityInfo.antennaSelection;
2395 break;
2396
2397 case eHT_SI_GRANULARITY:
2398 retVal = mac->lim.gHTServiceIntervalGranularity;
2399 break;
2400
2401 case eHT_CONTROLLED_ACCESS:
2402 retVal = mac->lim.gHTControlledAccessOnly;
2403 break;
2404
2405 case eHT_RIFS_MODE:
2406 retVal = pe_session->beaconParams.fRIFSMode;
2407 break;
2408
2409 case eHT_RECOMMENDED_TX_WIDTH_SET:
2410 retVal = pe_session->htRecommendedTxWidthSet;
2411 break;
2412
2413 case eHT_EXTENSION_CHANNEL_OFFSET:
2414 retVal = pe_session->htSecondaryChannelOffset;
2415 break;
2416
2417 case eHT_OP_MODE:
2418 if (LIM_IS_AP_ROLE(pe_session))
2419 retVal = pe_session->htOperMode;
2420 else
2421 retVal = mac->lim.gHTOperMode;
2422 break;
2423
2424 case eHT_BASIC_STBC_MCS:
2425 retVal = mac->lim.gHTSTBCBasicMCS;
2426 break;
2427
2428 case eHT_DUAL_CTS_PROTECTION:
2429 retVal = mac->lim.gHTDualCTSProtection;
2430 break;
2431
2432 case eHT_LSIG_TXOP_PROTECTION_FULL_SUPPORT:
2433 retVal =
2434 pe_session->beaconParams.fLsigTXOPProtectionFullSupport;
2435 break;
2436
2437 case eHT_PCO_ACTIVE:
2438 retVal = mac->lim.gHTPCOActive;
2439 break;
2440
2441 case eHT_PCO_PHASE:
2442 retVal = mac->lim.gHTPCOPhase;
2443 break;
2444
2445 default:
2446 break;
2447 }
2448
2449 return retVal;
2450 }
2451
2452 /**
2453 * lim_enable_11a_protection() - updates protection params for enable 11a
2454 * protection request
2455 * @mac_ctx: pointer to Global MAC structure
2456 * @overlap: 1=> called from overlap context, 0 => called from assoc context.
2457 * @bcn_prms: beacon parameters
2458 * @pe_session: pe session entry
2459 *
2460 * This function updates protection params for enable 11a protection request
2461 *
2462 * @Return: void
2463 */
2464 static void
lim_enable_11a_protection(struct mac_context * mac_ctx,uint8_t overlap,tpUpdateBeaconParams bcn_prms,struct pe_session * pe_session)2465 lim_enable_11a_protection(struct mac_context *mac_ctx,
2466 uint8_t overlap,
2467 tpUpdateBeaconParams bcn_prms,
2468 struct pe_session *pe_session)
2469 {
2470 /*
2471 * If we are AP and HT capable, we need to set the HT OP mode
2472 * appropriately.
2473 */
2474 if (LIM_IS_AP_ROLE(pe_session) && (true == pe_session->htCapability)) {
2475 if (overlap) {
2476 pe_session->gLimOverlap11aParams.protectionEnabled =
2477 true;
2478 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
2479 mac_ctx->lim.gHTOperMode)
2480 && (eSIR_HT_OP_MODE_MIXED !=
2481 mac_ctx->lim.gHTOperMode)) {
2482 mac_ctx->lim.gHTOperMode =
2483 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
2484 pe_session->htOperMode =
2485 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
2486 lim_enable_ht_rifs_protection(mac_ctx, true,
2487 overlap, bcn_prms, pe_session);
2488 lim_enable_ht_obss_protection(mac_ctx, true,
2489 overlap, bcn_prms, pe_session);
2490 }
2491 } else {
2492 pe_session->gLim11aParams.protectionEnabled = true;
2493 if (eSIR_HT_OP_MODE_MIXED != pe_session->htOperMode) {
2494 mac_ctx->lim.gHTOperMode =
2495 eSIR_HT_OP_MODE_MIXED;
2496 pe_session->htOperMode = eSIR_HT_OP_MODE_MIXED;
2497 lim_enable_ht_rifs_protection(mac_ctx, true,
2498 overlap, bcn_prms, pe_session);
2499 lim_enable_ht_obss_protection(mac_ctx, true,
2500 overlap, bcn_prms, pe_session);
2501 }
2502 }
2503 }
2504 /* This part is common for station as well. */
2505 if (false == pe_session->beaconParams.llaCoexist) {
2506 pe_debug(" => protection from 11A Enabled");
2507 bcn_prms->llaCoexist = true;
2508 pe_session->beaconParams.llaCoexist = true;
2509 bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
2510 }
2511 }
2512
2513 /**
2514 * lim_disable_11a_protection() - updates protection params for disable 11a
2515 * protection request
2516 * @mac_ctx: pointer to Global MAC structure
2517 * @overlap: 1=> called from overlap context, 0 => called from assoc context.
2518 * @bcn_prms: beacon parameters
2519 * @pe_session: pe session entry
2520 *
2521 * This function updates protection params for disable 11a protection request
2522 *
2523 * @Return: void
2524 */
2525 static void
lim_disable_11a_protection(struct mac_context * mac_ctx,uint8_t overlap,tpUpdateBeaconParams bcn_prms,struct pe_session * pe_session)2526 lim_disable_11a_protection(struct mac_context *mac_ctx,
2527 uint8_t overlap,
2528 tpUpdateBeaconParams bcn_prms,
2529 struct pe_session *pe_session)
2530 {
2531 if (false == pe_session->beaconParams.llaCoexist)
2532 return;
2533
2534 /* for station role */
2535 if (!LIM_IS_AP_ROLE(pe_session)) {
2536 pe_debug("===> Protection from 11A Disabled");
2537 bcn_prms->llaCoexist = false;
2538 pe_session->beaconParams.llaCoexist = false;
2539 bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
2540 return;
2541 }
2542 /*
2543 * for AP role.
2544 * we need to take care of HT OP mode change if needed.
2545 * We need to take care of Overlap cases.
2546 */
2547 if (overlap) {
2548 /* Overlap Legacy protection disabled. */
2549 pe_session->gLimOverlap11aParams.protectionEnabled = false;
2550
2551 /*
2552 * We need to take care of HT OP mode iff we are HT AP.
2553 * OR no HT op-mode change is needed if any of the overlap
2554 * protection enabled.
2555 */
2556 if (!pe_session->htCapability ||
2557 (pe_session->gLimOverlap11aParams.protectionEnabled
2558 || pe_session->gLimOverlapHt20Params.protectionEnabled
2559 || pe_session->gLimOverlapNonGfParams.protectionEnabled))
2560 goto disable_11a_end;
2561
2562 /* Check if there is a need to change HT OP mode. */
2563 if (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
2564 mac_ctx->lim.gHTOperMode) {
2565 lim_enable_ht_rifs_protection(mac_ctx, false, overlap,
2566 bcn_prms, pe_session);
2567 lim_enable_ht_obss_protection(mac_ctx, false, overlap,
2568 bcn_prms, pe_session);
2569
2570 if (pe_session->gLimHt20Params.protectionEnabled)
2571 mac_ctx->lim.gHTOperMode =
2572 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
2573 else
2574 mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
2575 }
2576 } else {
2577 /* Disable protection from 11A stations. */
2578 pe_session->gLim11aParams.protectionEnabled = false;
2579 lim_enable_ht_obss_protection(mac_ctx, false, overlap,
2580 bcn_prms, pe_session);
2581
2582 /*
2583 * Check if any other non-HT protection enabled. Right now we
2584 * are in HT OP Mixed mode. Change HT op mode appropriately.
2585 */
2586
2587 /* Change HT OP mode to 01 if any overlap protection enabled */
2588 if (pe_session->gLimOverlap11aParams.protectionEnabled
2589 || pe_session->gLimOverlapHt20Params.protectionEnabled
2590 || pe_session->gLimOverlapNonGfParams.protectionEnabled) {
2591 mac_ctx->lim.gHTOperMode =
2592 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
2593 pe_session->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY;
2594 lim_enable_ht_rifs_protection(mac_ctx, true, overlap,
2595 bcn_prms, pe_session);
2596 } else if (pe_session->gLimHt20Params.protectionEnabled) {
2597 mac_ctx->lim.gHTOperMode =
2598 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
2599 pe_session->htOperMode =
2600 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
2601 lim_enable_ht_rifs_protection(mac_ctx, false, overlap,
2602 bcn_prms, pe_session);
2603 } else {
2604 mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
2605 pe_session->htOperMode = eSIR_HT_OP_MODE_PURE;
2606 lim_enable_ht_rifs_protection(mac_ctx, false, overlap,
2607 bcn_prms, pe_session);
2608 }
2609 }
2610
2611 disable_11a_end:
2612 if (!pe_session->gLimOverlap11aParams.protectionEnabled &&
2613 !pe_session->gLim11aParams.protectionEnabled) {
2614 pe_warn("===> Protection from 11A Disabled");
2615 bcn_prms->llaCoexist = false;
2616 pe_session->beaconParams.llaCoexist = false;
2617 bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
2618 }
2619 }
2620
2621 /**
2622 * lim_update_11a_protection() - based on config setting enables\disables 11a
2623 * protection.
2624 * @mac_ctx: pointer to Global MAC structure
2625 * @enable: 1=> enable protection, 0=> disable protection.
2626 * @overlap: 1=> called from overlap context, 0 => called from assoc context.
2627 * @bcn_prms: beacon parameters
2628 * @session: pe session entry
2629 *
2630 * This based on config setting enables\disables 11a protection.
2631 *
2632 * @Return: success of failure of operation
2633 */
2634 QDF_STATUS
lim_update_11a_protection(struct mac_context * mac_ctx,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams bcn_prms,struct pe_session * session)2635 lim_update_11a_protection(struct mac_context *mac_ctx, uint8_t enable,
2636 uint8_t overlap, tpUpdateBeaconParams bcn_prms,
2637 struct pe_session *session)
2638 {
2639 if (!session) {
2640 pe_err("session is NULL");
2641 return QDF_STATUS_E_FAILURE;
2642 }
2643 /* overlapping protection configuration check. */
2644 if (!overlap) {
2645 /* normal protection config check */
2646 if ((LIM_IS_AP_ROLE(session)) &&
2647 (!session->cfgProtection.fromlla)) {
2648 /* protection disabled. */
2649 pe_warn("protection from 11a is disabled");
2650 return QDF_STATUS_SUCCESS;
2651 }
2652 }
2653
2654 if (enable)
2655 lim_enable_11a_protection(mac_ctx, overlap, bcn_prms, session);
2656 else
2657 lim_disable_11a_protection(mac_ctx, overlap, bcn_prms, session);
2658
2659 return QDF_STATUS_SUCCESS;
2660 }
2661
2662 /**
2663 * lim_handle_enable11g_protection_enabled() - handle 11g protection enabled
2664 * @mac_ctx: pointer to Globale Mac structure
2665 * @beaconparams: pointer to tpUpdateBeaconParams
2666 * @overlap: 1=> called from overlap context, 0 => called from assoc context.
2667 * @session_entry: pointer to struct pe_session *
2668 *
2669 * Function handles 11g protection enaled case
2670 *
2671 * Return: none
2672 */
2673 static void
lim_handle_enable11g_protection_enabled(struct mac_context * mac_ctx,tpUpdateBeaconParams beaconparams,uint8_t overlap,struct pe_session * session_entry)2674 lim_handle_enable11g_protection_enabled(struct mac_context *mac_ctx,
2675 tpUpdateBeaconParams beaconparams,
2676 uint8_t overlap, struct pe_session *session_entry)
2677 {
2678 /*
2679 * If we are AP and HT capable, we need to set the HT OP mode
2680 * appropriately.
2681 */
2682 if (LIM_IS_AP_ROLE(session_entry) && overlap) {
2683 session_entry->gLimOlbcParams.protectionEnabled = true;
2684
2685 pe_debug("protection from olbc is enabled");
2686
2687 if (true == session_entry->htCapability) {
2688 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
2689 session_entry->htOperMode) &&
2690 (eSIR_HT_OP_MODE_MIXED !=
2691 session_entry->htOperMode)) {
2692 session_entry->htOperMode =
2693 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
2694 }
2695 /*
2696 * CR-263021: OBSS bit is not switching back to 0 after
2697 * disabling the overlapping legacy BSS
2698 */
2699 /*
2700 * This fixes issue of OBSS bit not set after 11b, 11g
2701 * station leaves
2702 */
2703 lim_enable_ht_rifs_protection(mac_ctx, true,
2704 overlap, beaconparams, session_entry);
2705 /*
2706 * Not processing OBSS bit from other APs, as we are
2707 * already taking care of Protection from overlapping
2708 * BSS based on erp IE or useProtection bit
2709 */
2710 lim_enable_ht_obss_protection(mac_ctx, true,
2711 overlap, beaconparams, session_entry);
2712 }
2713 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
2714 session_entry->gLim11bParams.protectionEnabled = true;
2715 pe_debug("protection from 11b is enabled");
2716 if (true == session_entry->htCapability) {
2717 if (eSIR_HT_OP_MODE_MIXED !=
2718 session_entry->htOperMode) {
2719 session_entry->htOperMode =
2720 eSIR_HT_OP_MODE_MIXED;
2721 lim_enable_ht_rifs_protection(mac_ctx,
2722 true, overlap, beaconparams,
2723 session_entry);
2724 lim_enable_ht_obss_protection(mac_ctx,
2725 true, overlap, beaconparams,
2726 session_entry);
2727 }
2728 }
2729 }
2730
2731 /* This part is common for staiton as well. */
2732 if (false == session_entry->beaconParams.llbCoexist) {
2733 pe_debug("=> 11G Protection Enabled");
2734 beaconparams->llbCoexist =
2735 session_entry->beaconParams.llbCoexist = true;
2736 beaconparams->paramChangeBitmap |=
2737 PARAM_llBCOEXIST_CHANGED;
2738 }
2739 }
2740
2741 /**
2742 * lim_handle_11g_protection_for_11bcoexist() - 11g protection for 11b co-ex
2743 * @mac_ctx: pointer to Globale Mac structure
2744 * @beaconparams: pointer to tpUpdateBeaconParams
2745 * @overlap: 1=> called from overlap context, 0 => called from assoc context.
2746 * @session_entry: pointer to struct pe_session *
2747 *
2748 * Function handles 11g protection for 11b co-exist
2749 *
2750 * Return: none
2751 */
2752 static void
lim_handle_11g_protection_for_11bcoexist(struct mac_context * mac_ctx,tpUpdateBeaconParams beaconparams,uint8_t overlap,struct pe_session * session_entry)2753 lim_handle_11g_protection_for_11bcoexist(struct mac_context *mac_ctx,
2754 tpUpdateBeaconParams beaconparams,
2755 uint8_t overlap, struct pe_session *session_entry)
2756 {
2757 /*
2758 * For AP role:
2759 * we need to take care of HT OP mode change if needed.
2760 * We need to take care of Overlap cases.
2761 */
2762 if (LIM_IS_AP_ROLE(session_entry) && overlap) {
2763 /* Overlap Legacy protection disabled. */
2764 session_entry->gLimOlbcParams.protectionEnabled = false;
2765
2766 /* We need to take care of HT OP mode if we are HT AP. */
2767 if (session_entry->htCapability) {
2768 /*
2769 * no HT op mode change if any of the overlap
2770 * protection enabled.
2771 */
2772 if (!(session_entry->gLimOverlap11gParams.
2773 protectionEnabled ||
2774 session_entry->gLimOverlapHt20Params.
2775 protectionEnabled ||
2776 session_entry->gLimOverlapNonGfParams.
2777 protectionEnabled) &&
2778 /*
2779 * Check if there is a need to change HT
2780 * OP mode.
2781 */
2782 (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
2783 session_entry->htOperMode)) {
2784 lim_enable_ht_rifs_protection(mac_ctx, false,
2785 overlap, beaconparams, session_entry);
2786 lim_enable_ht_obss_protection(mac_ctx, false,
2787 overlap, beaconparams, session_entry);
2788 if (session_entry->gLimHt20Params.
2789 protectionEnabled) {
2790 if (eHT_CHANNEL_WIDTH_20MHZ ==
2791 session_entry->htSupportedChannelWidthSet)
2792 session_entry->htOperMode =
2793 eSIR_HT_OP_MODE_PURE;
2794 else
2795 session_entry->htOperMode =
2796 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
2797 } else
2798 session_entry->htOperMode =
2799 eSIR_HT_OP_MODE_PURE;
2800 }
2801 }
2802 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
2803 /* Disable protection from 11B stations. */
2804 session_entry->gLim11bParams.protectionEnabled = false;
2805 pe_debug("===> 11B Protection Disabled");
2806 /* Check if any other non-HT protection enabled. */
2807 if (!session_entry->gLim11gParams.protectionEnabled) {
2808 /* Right now we are in HT OP Mixed mode. */
2809 /* Change HT op mode appropriately. */
2810 lim_enable_ht_obss_protection(mac_ctx, false, overlap,
2811 beaconparams, session_entry);
2812 /*
2813 * Change HT OP mode to 01 if any overlap protection
2814 * enabled
2815 */
2816 if (session_entry->gLimOlbcParams.protectionEnabled ||
2817 session_entry->gLimOverlap11gParams.
2818 protectionEnabled ||
2819 session_entry->gLimOverlapHt20Params.
2820 protectionEnabled ||
2821 session_entry->gLimOverlapNonGfParams.
2822 protectionEnabled) {
2823 session_entry->htOperMode =
2824 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
2825 pe_debug("===> 11G Protection Disabled");
2826 lim_enable_ht_rifs_protection(mac_ctx, true,
2827 overlap, beaconparams,
2828 session_entry);
2829 } else if (session_entry->gLimHt20Params.
2830 protectionEnabled) {
2831 /* Commenting because of CR 258588 WFA cert */
2832 /* session_entry->htOperMode =
2833 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */
2834 session_entry->htOperMode =
2835 eSIR_HT_OP_MODE_PURE;
2836 pe_debug("===> 11G Protection Disabled");
2837 lim_enable_ht_rifs_protection(mac_ctx, false,
2838 overlap, beaconparams,
2839 session_entry);
2840 } else {
2841 session_entry->htOperMode =
2842 eSIR_HT_OP_MODE_PURE;
2843 lim_enable_ht_rifs_protection(mac_ctx, false,
2844 overlap, beaconparams,
2845 session_entry);
2846 }
2847 }
2848 }
2849 if (LIM_IS_AP_ROLE(session_entry)) {
2850 if (!session_entry->gLimOlbcParams.protectionEnabled &&
2851 !session_entry->gLim11bParams.protectionEnabled) {
2852 pe_debug("===> 11G Protection Disabled");
2853 beaconparams->llbCoexist =
2854 session_entry->beaconParams.llbCoexist =
2855 false;
2856 beaconparams->paramChangeBitmap |=
2857 PARAM_llBCOEXIST_CHANGED;
2858 }
2859 }
2860 /* For station role */
2861 if (!LIM_IS_AP_ROLE(session_entry)) {
2862 pe_debug("===> 11G Protection Disabled");
2863 beaconparams->llbCoexist =
2864 session_entry->beaconParams.llbCoexist = false;
2865 beaconparams->paramChangeBitmap |=
2866 PARAM_llBCOEXIST_CHANGED;
2867 }
2868 }
2869
2870 /**
2871 * lim_enable11g_protection() - Function to enable 11g protection
2872 * @mac_ctx: pointer to Global Mac structure
2873 * @enable: 1=> enable protection, 0=> disable protection.
2874 * @overlap: 1=> called from overlap context, 0 => called from assoc context.
2875 * @beaconparams: pointer to tpUpdateBeaconParams
2876 * @session_entry: pointer to struct pe_session *
2877 *
2878 * based on config setting enables\disables 11g protection.
2879 *
2880 * Return: Success - QDF_STATUS_SUCCESS - Success, Error number - Failure
2881 */
2882 QDF_STATUS
lim_enable11g_protection(struct mac_context * mac_ctx,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams beaconparams,struct pe_session * session_entry)2883 lim_enable11g_protection(struct mac_context *mac_ctx, uint8_t enable,
2884 uint8_t overlap, tpUpdateBeaconParams beaconparams,
2885 struct pe_session *session_entry)
2886 {
2887
2888 /* overlapping protection configuration check. */
2889 if (!overlap) {
2890 /* normal protection config check */
2891 if ((LIM_IS_AP_ROLE(session_entry)) &&
2892 !session_entry->cfgProtection.fromllb) {
2893 /* protection disabled. */
2894 pe_debug("protection from 11b is disabled");
2895 return QDF_STATUS_SUCCESS;
2896 } else if (!LIM_IS_AP_ROLE(session_entry)) {
2897 if (!mac_ctx->lim.cfgProtection.fromllb) {
2898 /* protection disabled. */
2899 pe_debug("protection from 11b is disabled");
2900 return QDF_STATUS_SUCCESS;
2901 }
2902 }
2903 }
2904
2905 if (enable) {
2906 lim_handle_enable11g_protection_enabled(mac_ctx, beaconparams,
2907 overlap, session_entry);
2908 } else if (true == session_entry->beaconParams.llbCoexist) {
2909 lim_handle_11g_protection_for_11bcoexist(mac_ctx, beaconparams,
2910 overlap, session_entry);
2911 }
2912 return QDF_STATUS_SUCCESS;
2913 }
2914
2915 /** -------------------------------------------------------------
2916 \fn lim_enable_ht_protection_from11g
2917 \brief based on cofig enables\disables protection from 11g.
2918 \param uint8_t enable : 1=> enable protection, 0=> disable protection.
2919 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
2920 \param tpUpdateBeaconParams pBeaconParams
2921 \return None
2922 -------------------------------------------------------------*/
2923 QDF_STATUS
lim_enable_ht_protection_from11g(struct mac_context * mac,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)2924 lim_enable_ht_protection_from11g(struct mac_context *mac, uint8_t enable,
2925 uint8_t overlap,
2926 tpUpdateBeaconParams pBeaconParams,
2927 struct pe_session *pe_session)
2928 {
2929 if (!pe_session->htCapability)
2930 return QDF_STATUS_SUCCESS; /* protection from 11g is only for HT stations. */
2931
2932 /* overlapping protection configuration check. */
2933 if (overlap) {
2934 if ((LIM_IS_AP_ROLE(pe_session))
2935 && (!pe_session->cfgProtection.overlapFromllg)) {
2936 /* protection disabled. */
2937 pe_debug("overlap protection from 11g is disabled");
2938 return QDF_STATUS_SUCCESS;
2939 }
2940 } else {
2941 /* normal protection config check */
2942 if (LIM_IS_AP_ROLE(pe_session) &&
2943 !pe_session->cfgProtection.fromllg) {
2944 /* protection disabled. */
2945 pe_debug("protection from 11g is disabled");
2946 return QDF_STATUS_SUCCESS;
2947 } else if (!LIM_IS_AP_ROLE(pe_session)) {
2948 if (!mac->lim.cfgProtection.fromllg) {
2949 /* protection disabled. */
2950 pe_debug("protection from 11g is disabled");
2951 return QDF_STATUS_SUCCESS;
2952 }
2953 }
2954 }
2955 if (enable) {
2956 /* If we are AP and HT capable, we need to set the HT OP mode */
2957 /* appropriately. */
2958
2959 if (LIM_IS_AP_ROLE(pe_session)) {
2960 if (overlap) {
2961 pe_session->gLimOverlap11gParams.
2962 protectionEnabled = true;
2963 /* 11g exists in overlap BSS. */
2964 /* need not to change the operating mode to overlap_legacy */
2965 /* if higher or same protection operating mode is enabled right now. */
2966 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
2967 pe_session->htOperMode)
2968 && (eSIR_HT_OP_MODE_MIXED !=
2969 pe_session->htOperMode)) {
2970 pe_session->htOperMode =
2971 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
2972 }
2973 lim_enable_ht_rifs_protection(mac, true, overlap,
2974 pBeaconParams,
2975 pe_session);
2976 lim_enable_ht_obss_protection(mac, true, overlap,
2977 pBeaconParams,
2978 pe_session);
2979 } else {
2980 /* 11g is associated to an AP operating in 11n mode. */
2981 /* Change the HT operating mode to 'mixed mode'. */
2982 pe_session->gLim11gParams.protectionEnabled =
2983 true;
2984 if (eSIR_HT_OP_MODE_MIXED !=
2985 pe_session->htOperMode) {
2986 pe_session->htOperMode =
2987 eSIR_HT_OP_MODE_MIXED;
2988 lim_enable_ht_rifs_protection(mac, true,
2989 overlap,
2990 pBeaconParams,
2991 pe_session);
2992 lim_enable_ht_obss_protection(mac, true,
2993 overlap,
2994 pBeaconParams,
2995 pe_session);
2996 }
2997 }
2998 }
2999 /* This part is common for staiton as well. */
3000 if (false == pe_session->beaconParams.llgCoexist) {
3001 pBeaconParams->llgCoexist =
3002 pe_session->beaconParams.llgCoexist = true;
3003 pBeaconParams->paramChangeBitmap |=
3004 PARAM_llGCOEXIST_CHANGED;
3005 } else if (true ==
3006 pe_session->gLimOverlap11gParams.
3007 protectionEnabled) {
3008 /* As operating mode changed after G station assoc some way to update beacon */
3009 /* This addresses the issue of mode not changing to - 11 in beacon when OBSS overlap is enabled */
3010 /* mac->sch.beacon_changed = 1; */
3011 pBeaconParams->paramChangeBitmap |=
3012 PARAM_llGCOEXIST_CHANGED;
3013 }
3014 } else if (true == pe_session->beaconParams.llgCoexist) {
3015 /* for AP role. */
3016 /* we need to take care of HT OP mode change if needed. */
3017 /* We need to take care of Overlap cases. */
3018
3019 if (LIM_IS_AP_ROLE(pe_session)) {
3020 if (overlap) {
3021 /* Overlap Legacy protection disabled. */
3022 if (pe_session->gLim11gParams.numSta == 0)
3023 pe_session->gLimOverlap11gParams.
3024 protectionEnabled = false;
3025
3026 /* no HT op mode change if any of the overlap protection enabled. */
3027 if (!
3028 (pe_session->gLimOlbcParams.
3029 protectionEnabled
3030 || pe_session->gLimOverlapHt20Params.
3031 protectionEnabled
3032 || pe_session->gLimOverlapNonGfParams.
3033 protectionEnabled)) {
3034 /* Check if there is a need to change HT OP mode. */
3035 if (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
3036 pe_session->htOperMode) {
3037 lim_enable_ht_rifs_protection(mac,
3038 false,
3039 overlap,
3040 pBeaconParams,
3041 pe_session);
3042 lim_enable_ht_obss_protection(mac,
3043 false,
3044 overlap,
3045 pBeaconParams,
3046 pe_session);
3047
3048 if (pe_session->gLimHt20Params.protectionEnabled) {
3049 if (eHT_CHANNEL_WIDTH_20MHZ ==
3050 pe_session->htSupportedChannelWidthSet)
3051 pe_session->htOperMode =
3052 eSIR_HT_OP_MODE_PURE;
3053 else
3054 pe_session->htOperMode =
3055 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
3056 } else
3057 pe_session->htOperMode =
3058 eSIR_HT_OP_MODE_PURE;
3059 }
3060 }
3061 } else {
3062 /* Disable protection from 11G stations. */
3063 pe_session->gLim11gParams.protectionEnabled =
3064 false;
3065 /* Check if any other non-HT protection enabled. */
3066 if (!pe_session->gLim11bParams.
3067 protectionEnabled) {
3068
3069 /* Right now we are in HT OP Mixed mode. */
3070 /* Change HT op mode appropriately. */
3071 lim_enable_ht_obss_protection(mac, false,
3072 overlap,
3073 pBeaconParams,
3074 pe_session);
3075
3076 /* Change HT OP mode to 01 if any overlap protection enabled */
3077 if (pe_session->gLimOlbcParams.
3078 protectionEnabled
3079 || pe_session->
3080 gLimOverlap11gParams.
3081 protectionEnabled
3082 || pe_session->
3083 gLimOverlapHt20Params.
3084 protectionEnabled
3085 || pe_session->
3086 gLimOverlapNonGfParams.
3087 protectionEnabled) {
3088 pe_session->htOperMode =
3089 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
3090 lim_enable_ht_rifs_protection(mac,
3091 true,
3092 overlap,
3093 pBeaconParams,
3094 pe_session);
3095 } else if (pe_session->
3096 gLimHt20Params.
3097 protectionEnabled) {
3098 /* Commenting because of CR 258588 WFA cert */
3099 /* pe_session->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */
3100 pe_session->htOperMode =
3101 eSIR_HT_OP_MODE_PURE;
3102 lim_enable_ht_rifs_protection(mac,
3103 false,
3104 overlap,
3105 pBeaconParams,
3106 pe_session);
3107 } else {
3108 pe_session->htOperMode =
3109 eSIR_HT_OP_MODE_PURE;
3110 lim_enable_ht_rifs_protection(mac,
3111 false,
3112 overlap,
3113 pBeaconParams,
3114 pe_session);
3115 }
3116 }
3117 }
3118 if (!pe_session->gLimOverlap11gParams.
3119 protectionEnabled
3120 && !pe_session->gLim11gParams.
3121 protectionEnabled) {
3122 pe_debug("===> Protection from 11G Disabled");
3123 pBeaconParams->llgCoexist =
3124 pe_session->beaconParams.llgCoexist =
3125 false;
3126 pBeaconParams->paramChangeBitmap |=
3127 PARAM_llGCOEXIST_CHANGED;
3128 }
3129 }
3130 /* for station role */
3131 else {
3132 pe_debug("===> Protection from 11G Disabled");
3133 pBeaconParams->llgCoexist =
3134 pe_session->beaconParams.llgCoexist = false;
3135 pBeaconParams->paramChangeBitmap |=
3136 PARAM_llGCOEXIST_CHANGED;
3137 }
3138 }
3139 return QDF_STATUS_SUCCESS;
3140 }
3141
3142 /* FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. */
3143 /* This check will be done at the caller. */
3144
3145 /** -------------------------------------------------------------
3146 \fn limEnableHtObssProtection
3147 \brief based on cofig enables\disables obss protection.
3148 \param uint8_t enable : 1=> enable protection, 0=> disable protection.
3149 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
3150 \param tpUpdateBeaconParams pBeaconParams
3151 \return None
3152 -------------------------------------------------------------*/
3153 QDF_STATUS
lim_enable_ht_obss_protection(struct mac_context * mac,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)3154 lim_enable_ht_obss_protection(struct mac_context *mac, uint8_t enable,
3155 uint8_t overlap, tpUpdateBeaconParams pBeaconParams,
3156 struct pe_session *pe_session)
3157 {
3158
3159 if (!pe_session->htCapability)
3160 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */
3161
3162 /* overlapping protection configuration check. */
3163 if (overlap) {
3164 /* overlapping protection configuration check. */
3165 } else {
3166 /* normal protection config check */
3167 if ((LIM_IS_AP_ROLE(pe_session)) &&
3168 !pe_session->cfgProtection.obss) { /* ToDo Update this field */
3169 /* protection disabled. */
3170 pe_debug("protection from Obss is disabled");
3171 return QDF_STATUS_SUCCESS;
3172 } else if (!LIM_IS_AP_ROLE(pe_session)) {
3173 if (!mac->lim.cfgProtection.obss) { /* ToDo Update this field */
3174 /* protection disabled. */
3175 pe_debug("protection from Obss is disabled");
3176 return QDF_STATUS_SUCCESS;
3177 }
3178 }
3179 }
3180
3181 if (LIM_IS_AP_ROLE(pe_session)) {
3182 if ((enable)
3183 && (false == pe_session->beaconParams.gHTObssMode)) {
3184 pe_debug("=>obss protection enabled");
3185 pe_session->beaconParams.gHTObssMode = true;
3186 pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; /* UPDATE AN ENUM FOR OBSS MODE <todo> */
3187
3188 } else if (!enable
3189 && (true ==
3190 pe_session->beaconParams.gHTObssMode)) {
3191 pe_debug("===> obss Protection disabled");
3192 pe_session->beaconParams.gHTObssMode = false;
3193 pBeaconParams->paramChangeBitmap |=
3194 PARAM_OBSS_MODE_CHANGED;
3195
3196 }
3197 /* CR-263021: OBSS bit is not switching back to 0 after disabling the overlapping legacy BSS */
3198 if (!enable && !overlap) {
3199 pe_session->gLimOverlap11gParams.protectionEnabled =
3200 false;
3201 }
3202 } else {
3203 if ((enable)
3204 && (false == pe_session->beaconParams.gHTObssMode)) {
3205 pe_debug("=>obss protection enabled");
3206 pe_session->beaconParams.gHTObssMode = true;
3207 pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; /* UPDATE AN ENUM FOR OBSS MODE <todo> */
3208
3209 } else if (!enable
3210 && (true ==
3211 pe_session->beaconParams.gHTObssMode)) {
3212 pe_debug("===> obss Protection disabled");
3213 pe_session->beaconParams.gHTObssMode = false;
3214 pBeaconParams->paramChangeBitmap |=
3215 PARAM_OBSS_MODE_CHANGED;
3216
3217 }
3218 }
3219 return QDF_STATUS_SUCCESS;
3220 }
3221
3222 /**
3223 * lim_handle_ht20protection_enabled() - Handle ht20 protection enabled
3224 * @mac_ctx: pointer to Gloal Mac Structure
3225 * @overlap: variable for overlap detection
3226 * @beaconparams: pointer to tpUpdateBeaconParams
3227 * @session_entry: pointer to struct pe_session *
3228 *
3229 * Function handles ht20 protection enabled
3230 *
3231 * Return: none
3232 */
lim_handle_ht20protection_enabled(struct mac_context * mac_ctx,uint8_t overlap,tpUpdateBeaconParams beaconparams,struct pe_session * session_entry)3233 static void lim_handle_ht20protection_enabled(struct mac_context *mac_ctx,
3234 uint8_t overlap, tpUpdateBeaconParams beaconparams,
3235 struct pe_session *session_entry)
3236 {
3237 /*
3238 * If we are AP and HT capable, we need to set the HT OP mode
3239 * appropriately.
3240 */
3241 if (LIM_IS_AP_ROLE(session_entry) && overlap) {
3242 session_entry->gLimOverlapHt20Params.protectionEnabled = true;
3243 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
3244 session_entry->htOperMode) &&
3245 (eSIR_HT_OP_MODE_MIXED !=
3246 session_entry->htOperMode)) {
3247 session_entry->htOperMode =
3248 eSIR_HT_OP_MODE_OVERLAP_LEGACY;
3249 lim_enable_ht_rifs_protection(mac_ctx, true,
3250 overlap, beaconparams, session_entry);
3251 }
3252 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
3253 session_entry->gLimHt20Params.protectionEnabled = true;
3254 if (eSIR_HT_OP_MODE_PURE == session_entry->htOperMode) {
3255 if (session_entry->htSupportedChannelWidthSet !=
3256 eHT_CHANNEL_WIDTH_20MHZ)
3257 session_entry->htOperMode =
3258 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
3259 lim_enable_ht_rifs_protection(mac_ctx, false,
3260 overlap, beaconparams, session_entry);
3261 lim_enable_ht_obss_protection(mac_ctx, false,
3262 overlap, beaconparams, session_entry);
3263 }
3264 }
3265 /* This part is common for staiton as well. */
3266 if (false == session_entry->beaconParams.ht20Coexist) {
3267 pe_debug("=> Protection from HT20 Enabled");
3268 beaconparams->ht20MhzCoexist =
3269 session_entry->beaconParams.ht20Coexist = true;
3270 beaconparams->paramChangeBitmap |=
3271 PARAM_HT20MHZCOEXIST_CHANGED;
3272 }
3273 }
3274
3275 /**
3276 * lim_handle_ht20coexist_ht20protection() - ht20 protection for ht20 coexist
3277 * @mac_ctx: pointer to Gloal Mac Structure
3278 * @beaconparams: pointer to tpUpdateBeaconParams
3279 * @session_entry: pointer to struct pe_session *
3280 * @overlap: variable for overlap detection
3281 *
3282 * Function handles ht20 protection for ht20 coexist
3283 *
3284 * Return: none
3285 */
lim_handle_ht20coexist_ht20protection(struct mac_context * mac_ctx,tpUpdateBeaconParams beaconparams,struct pe_session * session_entry,uint8_t overlap)3286 static void lim_handle_ht20coexist_ht20protection(struct mac_context *mac_ctx,
3287 tpUpdateBeaconParams beaconparams,
3288 struct pe_session *session_entry, uint8_t overlap)
3289 {
3290 /*
3291 * For AP role:
3292 * we need to take care of HT OP mode change if needed.
3293 * We need to take care of Overlap cases.
3294 */
3295 if (LIM_IS_AP_ROLE(session_entry) && overlap) {
3296 /* Overlap Legacy protection disabled. */
3297 session_entry->gLimOverlapHt20Params.protectionEnabled =
3298 false;
3299 /*
3300 * no HT op mode change if any of the overlap
3301 * protection enabled.
3302 */
3303 if (!(session_entry->gLimOlbcParams.protectionEnabled ||
3304 session_entry->gLimOverlap11gParams.protectionEnabled ||
3305 session_entry->gLimOverlapHt20Params.protectionEnabled
3306 || session_entry->gLimOverlapNonGfParams.
3307 protectionEnabled) &&
3308 /*
3309 * Check if there is a need to change HT
3310 * OP mode.
3311 */
3312 (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
3313 session_entry->htOperMode)) {
3314 if (session_entry->gLimHt20Params.
3315 protectionEnabled) {
3316 if (eHT_CHANNEL_WIDTH_20MHZ ==
3317 session_entry->
3318 htSupportedChannelWidthSet)
3319 session_entry->htOperMode =
3320 eSIR_HT_OP_MODE_PURE;
3321 else
3322 session_entry->htOperMode =
3323 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
3324
3325 lim_enable_ht_rifs_protection(mac_ctx,
3326 false, overlap, beaconparams,
3327 session_entry);
3328 lim_enable_ht_obss_protection(mac_ctx,
3329 false, overlap, beaconparams,
3330 session_entry);
3331 } else {
3332 session_entry->htOperMode =
3333 eSIR_HT_OP_MODE_PURE;
3334 }
3335 }
3336 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
3337 /* Disable protection from 11G stations. */
3338 session_entry->gLimHt20Params.protectionEnabled = false;
3339 /* Change HT op mode appropriately. */
3340 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
3341 session_entry->htOperMode) {
3342 session_entry->htOperMode =
3343 eSIR_HT_OP_MODE_PURE;
3344 lim_enable_ht_rifs_protection(mac_ctx, false,
3345 overlap, beaconparams, session_entry);
3346 lim_enable_ht_obss_protection(mac_ctx, false,
3347 overlap, beaconparams, session_entry);
3348 }
3349 }
3350 if (LIM_IS_AP_ROLE(session_entry)) {
3351 pe_debug("===> Protection from HT 20 Disabled");
3352 beaconparams->ht20MhzCoexist =
3353 session_entry->beaconParams.ht20Coexist = false;
3354 beaconparams->paramChangeBitmap |=
3355 PARAM_HT20MHZCOEXIST_CHANGED;
3356 }
3357 if (!LIM_IS_AP_ROLE(session_entry)) {
3358 /* For station role */
3359 pe_debug("===> Protection from HT20 Disabled");
3360 beaconparams->ht20MhzCoexist =
3361 session_entry->beaconParams.ht20Coexist = false;
3362 beaconparams->paramChangeBitmap |=
3363 PARAM_HT20MHZCOEXIST_CHANGED;
3364 }
3365 }
3366
3367 /**
3368 * lim_enable_ht20_protection() - Function to enable ht20 protection
3369 * @mac_ctx: pointer to Global Mac structure
3370 * @enable: 1=> enable protection, 0=> disable protection.
3371 * @overlap: 1=> called from overlap context, 0 => called from assoc context.
3372 * @beaconparams: pointer to tpUpdateBeaconParams
3373 * @session_entry: pointer to struct pe_session *
3374 *
3375 * based on cofig enables\disables protection from Ht20
3376 *
3377 * Return: 0 - success
3378 */
lim_enable_ht20_protection(struct mac_context * mac_ctx,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams beaconparams,struct pe_session * session_entry)3379 QDF_STATUS lim_enable_ht20_protection(struct mac_context *mac_ctx, uint8_t enable,
3380 uint8_t overlap, tpUpdateBeaconParams beaconparams,
3381 struct pe_session *session_entry)
3382 {
3383 /* This protection is only for HT stations. */
3384 if (!session_entry->htCapability)
3385 return QDF_STATUS_SUCCESS;
3386
3387 /* overlapping protection configuration check. */
3388 if (!overlap) {
3389 /* normal protection config check */
3390 if ((LIM_IS_AP_ROLE(session_entry)) &&
3391 !session_entry->cfgProtection.ht20) {
3392 /* protection disabled. */
3393 pe_debug("protection from HT20 is disabled");
3394 return QDF_STATUS_SUCCESS;
3395 } else if (!LIM_IS_AP_ROLE(session_entry)) {
3396 if (!mac_ctx->lim.cfgProtection.ht20) {
3397 /* protection disabled. */
3398 pe_debug("protection from HT20 is disabled");
3399 return QDF_STATUS_SUCCESS;
3400 }
3401 }
3402 }
3403
3404 if (enable)
3405 lim_handle_ht20protection_enabled(mac_ctx, overlap,
3406 beaconparams, session_entry);
3407 else if (true == session_entry->beaconParams.ht20Coexist)
3408 lim_handle_ht20coexist_ht20protection(mac_ctx, beaconparams,
3409 session_entry, overlap);
3410
3411 return QDF_STATUS_SUCCESS;
3412 }
3413
3414 /** -------------------------------------------------------------
3415 \fn lim_enable_ht_non_gf_protection
3416 \brief based on cofig enables\disables protection from NonGf.
3417 \param uint8_t enable : 1=> enable protection, 0=> disable protection.
3418 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
3419 \param tpUpdateBeaconParams pBeaconParams
3420 \return None
3421 -------------------------------------------------------------*/
3422 QDF_STATUS
lim_enable_ht_non_gf_protection(struct mac_context * mac,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)3423 lim_enable_ht_non_gf_protection(struct mac_context *mac, uint8_t enable,
3424 uint8_t overlap, tpUpdateBeaconParams pBeaconParams,
3425 struct pe_session *pe_session)
3426 {
3427 if (!pe_session->htCapability)
3428 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */
3429
3430 /* overlapping protection configuration check. */
3431 if (overlap) {
3432 } else {
3433 /* normal protection config check */
3434 if (LIM_IS_AP_ROLE(pe_session) &&
3435 !pe_session->cfgProtection.nonGf) {
3436 /* protection disabled. */
3437 pe_debug("protection from NonGf is disabled");
3438 return QDF_STATUS_SUCCESS;
3439 } else if (!LIM_IS_AP_ROLE(pe_session)) {
3440 /* normal protection config check */
3441 if (!mac->lim.cfgProtection.nonGf) {
3442 /* protection disabled. */
3443 pe_debug("protection from NonGf is disabled");
3444 return QDF_STATUS_SUCCESS;
3445 }
3446 }
3447 }
3448 if (LIM_IS_AP_ROLE(pe_session)) {
3449 if ((enable)
3450 && (false == pe_session->beaconParams.llnNonGFCoexist)) {
3451 pe_debug(" => Protection from non GF Enabled");
3452 pBeaconParams->llnNonGFCoexist =
3453 pe_session->beaconParams.llnNonGFCoexist = true;
3454 pBeaconParams->paramChangeBitmap |=
3455 PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
3456 } else if (!enable
3457 && (true ==
3458 pe_session->beaconParams.llnNonGFCoexist)) {
3459 pe_debug("===> Protection from Non GF Disabled");
3460 pBeaconParams->llnNonGFCoexist =
3461 pe_session->beaconParams.llnNonGFCoexist = false;
3462 pBeaconParams->paramChangeBitmap |=
3463 PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
3464 }
3465 } else {
3466 if ((enable)
3467 && (false == pe_session->beaconParams.llnNonGFCoexist)) {
3468 pe_debug(" => Protection from non GF Enabled");
3469 pBeaconParams->llnNonGFCoexist =
3470 pe_session->beaconParams.llnNonGFCoexist = true;
3471 pBeaconParams->paramChangeBitmap |=
3472 PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
3473 } else if (!enable
3474 && (true ==
3475 pe_session->beaconParams.llnNonGFCoexist)) {
3476 pe_debug("===> Protection from Non GF Disabled");
3477 pBeaconParams->llnNonGFCoexist =
3478 pe_session->beaconParams.llnNonGFCoexist = false;
3479 pBeaconParams->paramChangeBitmap |=
3480 PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
3481 }
3482 }
3483
3484 return QDF_STATUS_SUCCESS;
3485 }
3486
3487 /** -------------------------------------------------------------
3488 \fn lim_enable_ht_lsig_txop_protection
3489 \brief based on cofig enables\disables LsigTxop protection.
3490 \param uint8_t enable : 1=> enable protection, 0=> disable protection.
3491 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
3492 \param tpUpdateBeaconParams pBeaconParams
3493 \return None
3494 -------------------------------------------------------------*/
3495 QDF_STATUS
lim_enable_ht_lsig_txop_protection(struct mac_context * mac,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)3496 lim_enable_ht_lsig_txop_protection(struct mac_context *mac, uint8_t enable,
3497 uint8_t overlap,
3498 tpUpdateBeaconParams pBeaconParams,
3499 struct pe_session *pe_session)
3500 {
3501 if (!pe_session->htCapability)
3502 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */
3503
3504 /* overlapping protection configuration check. */
3505 if (overlap) {
3506 } else {
3507 /* normal protection config check */
3508 if (LIM_IS_AP_ROLE(pe_session) &&
3509 !pe_session->cfgProtection.lsigTxop) {
3510 /* protection disabled. */
3511 pe_debug("protection from LsigTxop not supported is disabled");
3512 return QDF_STATUS_SUCCESS;
3513 } else if (!LIM_IS_AP_ROLE(pe_session)) {
3514 /* normal protection config check */
3515 if (!mac->lim.cfgProtection.lsigTxop) {
3516 /* protection disabled. */
3517 pe_debug("protection from LsigTxop not supported is disabled");
3518 return QDF_STATUS_SUCCESS;
3519 }
3520 }
3521 }
3522
3523 if (LIM_IS_AP_ROLE(pe_session)) {
3524 if ((enable)
3525 && (false ==
3526 pe_session->beaconParams.
3527 fLsigTXOPProtectionFullSupport)) {
3528 pe_debug(" => Protection from LsigTxop Enabled");
3529 pBeaconParams->fLsigTXOPProtectionFullSupport =
3530 pe_session->beaconParams.
3531 fLsigTXOPProtectionFullSupport = true;
3532 pBeaconParams->paramChangeBitmap |=
3533 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
3534 } else if (!enable
3535 && (true ==
3536 pe_session->beaconParams.
3537 fLsigTXOPProtectionFullSupport)) {
3538 pe_debug("===> Protection from LsigTxop Disabled");
3539 pBeaconParams->fLsigTXOPProtectionFullSupport =
3540 pe_session->beaconParams.
3541 fLsigTXOPProtectionFullSupport = false;
3542 pBeaconParams->paramChangeBitmap |=
3543 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
3544 }
3545 } else {
3546 if ((enable)
3547 && (false ==
3548 pe_session->beaconParams.
3549 fLsigTXOPProtectionFullSupport)) {
3550 pe_debug(" => Protection from LsigTxop Enabled");
3551 pBeaconParams->fLsigTXOPProtectionFullSupport =
3552 pe_session->beaconParams.
3553 fLsigTXOPProtectionFullSupport = true;
3554 pBeaconParams->paramChangeBitmap |=
3555 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
3556 } else if (!enable
3557 && (true ==
3558 pe_session->beaconParams.
3559 fLsigTXOPProtectionFullSupport)) {
3560 pe_debug("===> Protection from LsigTxop Disabled");
3561 pBeaconParams->fLsigTXOPProtectionFullSupport =
3562 pe_session->beaconParams.
3563 fLsigTXOPProtectionFullSupport = false;
3564 pBeaconParams->paramChangeBitmap |=
3565 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
3566 }
3567 }
3568 return QDF_STATUS_SUCCESS;
3569 }
3570
3571 /* FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. */
3572 /* This check will be done at the caller. */
3573 /** -------------------------------------------------------------
3574 \fn lim_enable_ht_rifs_protection
3575 \brief based on cofig enables\disables Rifs protection.
3576 \param uint8_t enable : 1=> enable protection, 0=> disable protection.
3577 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
3578 \param tpUpdateBeaconParams pBeaconParams
3579 \return None
3580 -------------------------------------------------------------*/
3581 QDF_STATUS
lim_enable_ht_rifs_protection(struct mac_context * mac,uint8_t enable,uint8_t overlap,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)3582 lim_enable_ht_rifs_protection(struct mac_context *mac, uint8_t enable,
3583 uint8_t overlap, tpUpdateBeaconParams pBeaconParams,
3584 struct pe_session *pe_session)
3585 {
3586 if (!pe_session->htCapability)
3587 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */
3588
3589 /* overlapping protection configuration check. */
3590 if (overlap) {
3591 } else {
3592 /* normal protection config check */
3593 if (LIM_IS_AP_ROLE(pe_session) &&
3594 !pe_session->cfgProtection.rifs) {
3595 /* protection disabled. */
3596 pe_debug("protection from Rifs is disabled");
3597 return QDF_STATUS_SUCCESS;
3598 } else if (!LIM_IS_AP_ROLE(pe_session)) {
3599 /* normal protection config check */
3600 if (!mac->lim.cfgProtection.rifs) {
3601 /* protection disabled. */
3602 pe_debug("protection from Rifs is disabled");
3603 return QDF_STATUS_SUCCESS;
3604 }
3605 }
3606 }
3607
3608 if (LIM_IS_AP_ROLE(pe_session)) {
3609 /* Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS */
3610 if ((!enable)
3611 && (false == pe_session->beaconParams.fRIFSMode)) {
3612 pe_debug(" => Rifs protection Disabled");
3613 pBeaconParams->fRIFSMode =
3614 pe_session->beaconParams.fRIFSMode = true;
3615 pBeaconParams->paramChangeBitmap |=
3616 PARAM_RIFS_MODE_CHANGED;
3617 }
3618 /* Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS */
3619 else if (enable
3620 && (true == pe_session->beaconParams.fRIFSMode)) {
3621 pe_debug("===> Rifs Protection Enabled");
3622 pBeaconParams->fRIFSMode =
3623 pe_session->beaconParams.fRIFSMode = false;
3624 pBeaconParams->paramChangeBitmap |=
3625 PARAM_RIFS_MODE_CHANGED;
3626 }
3627 } else {
3628 /* Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS */
3629 if ((!enable)
3630 && (false == pe_session->beaconParams.fRIFSMode)) {
3631 pe_debug(" => Rifs protection Disabled");
3632 pBeaconParams->fRIFSMode =
3633 pe_session->beaconParams.fRIFSMode = true;
3634 pBeaconParams->paramChangeBitmap |=
3635 PARAM_RIFS_MODE_CHANGED;
3636 }
3637 /* Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS */
3638 else if (enable
3639 && (true == pe_session->beaconParams.fRIFSMode)) {
3640 pe_debug("===> Rifs Protection Enabled");
3641 pBeaconParams->fRIFSMode =
3642 pe_session->beaconParams.fRIFSMode = false;
3643 pBeaconParams->paramChangeBitmap |=
3644 PARAM_RIFS_MODE_CHANGED;
3645 }
3646 }
3647 return QDF_STATUS_SUCCESS;
3648 }
3649
3650 /* --------------------------------------------------------------------- */
3651 /**
3652 * lim_enable_short_preamble
3653 *
3654 * FUNCTION:
3655 * Enable/Disable short preamble
3656 *
3657 * LOGIC:
3658 *
3659 * ASSUMPTIONS:
3660 *
3661 * NOTE:
3662 *
3663 * @param enable Flag to enable/disable short preamble
3664 * @return None
3665 */
3666
3667 QDF_STATUS
lim_enable_short_preamble(struct mac_context * mac,uint8_t enable,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)3668 lim_enable_short_preamble(struct mac_context *mac, uint8_t enable,
3669 tpUpdateBeaconParams pBeaconParams,
3670 struct pe_session *pe_session)
3671 {
3672 if (!mac->mlme_cfg->ht_caps.short_preamble)
3673 return QDF_STATUS_SUCCESS;
3674
3675 /* 11G short preamble switching is disabled. */
3676 if (!mac->mlme_cfg->feature_flags.enable_short_preamble_11g)
3677 return QDF_STATUS_SUCCESS;
3678
3679 if (LIM_IS_AP_ROLE(pe_session)) {
3680 if (enable && (pe_session->beaconParams.fShortPreamble == 0)) {
3681 pe_debug("===> Short Preamble Enabled");
3682 pe_session->beaconParams.fShortPreamble = true;
3683 pBeaconParams->fShortPreamble =
3684 (uint8_t) pe_session->beaconParams.
3685 fShortPreamble;
3686 pBeaconParams->paramChangeBitmap |=
3687 PARAM_SHORT_PREAMBLE_CHANGED;
3688 } else if (!enable
3689 && (pe_session->beaconParams.fShortPreamble ==
3690 1)) {
3691 pe_debug("===> Short Preamble Disabled");
3692 pe_session->beaconParams.fShortPreamble = false;
3693 pBeaconParams->fShortPreamble =
3694 (uint8_t) pe_session->beaconParams.
3695 fShortPreamble;
3696 pBeaconParams->paramChangeBitmap |=
3697 PARAM_SHORT_PREAMBLE_CHANGED;
3698 }
3699 }
3700
3701 return QDF_STATUS_SUCCESS;
3702 }
3703
3704 /**
3705 * lim_tx_complete
3706 *
3707 * Function:
3708 * This is LIM's very own "TX MGMT frame complete" completion routine.
3709 *
3710 * Logic:
3711 * LIM wants to send a MGMT frame (broadcast or unicast)
3712 * LIM allocates memory using cds_packet_alloc( ..., **pData, **pPacket )
3713 * LIM transmits the MGMT frame using the API:
3714 * wma_tx_frame( ... pPacket, ..., (void *) lim_tx_complete, pData )
3715 * HDD, via wma_tx_frame/DXE, "transfers" the packet over to BMU
3716 * HDD, if it determines that a TX completion routine (in this case
3717 * lim_tx_complete) has been provided, will invoke this callback
3718 * LIM will try to free the TX MGMT packet that was earlier allocated, in order
3719 * to send this MGMT frame, using the PAL API cds_packet_free( ... pData, pPacket )
3720 *
3721 * Assumptions:
3722 * Presently, this is ONLY being used for MGMT frames/packets
3723 * TODO:
3724 * Would it do good for LIM to have some sort of "signature" validation to
3725 * ensure that the pData argument passed in was a buffer that was actually
3726 * allocated by LIM and/or is not corrupted?
3727 *
3728 * Note: FIXME and TODO
3729 * Looks like cds_packet_free() is interested in pPacket. But, when this completion
3730 * routine is called, only pData is made available to LIM!!
3731 *
3732 * @param void A pointer to pData. Shouldn't it be pPacket?!
3733 *
3734 * @return QDF_STATUS_SUCCESS - in case of success
3735 */
lim_tx_complete(void * context,qdf_nbuf_t buf,bool free)3736 QDF_STATUS lim_tx_complete(void *context, qdf_nbuf_t buf, bool free)
3737 {
3738 if (free)
3739 cds_packet_free((void *)buf);
3740
3741 return QDF_STATUS_SUCCESS;
3742 }
3743
3744 static QDF_STATUS
lim_ht_switch_chnl_params(struct pe_session * pe_session)3745 lim_ht_switch_chnl_params(struct pe_session *pe_session)
3746 {
3747 uint8_t center_freq = 0;
3748 enum phy_ch_width ch_width = CH_WIDTH_20MHZ;
3749 struct mac_context *mac;
3750 uint8_t primary_channel;
3751
3752 mac = pe_session->mac_ctx;
3753 if (!mac) {
3754 pe_err("Invalid mac_ctx");
3755 return QDF_STATUS_E_INVAL;
3756 }
3757
3758 primary_channel = wlan_reg_freq_to_chan(mac->pdev,
3759 pe_session->curr_op_freq);
3760 if (eHT_CHANNEL_WIDTH_40MHZ ==
3761 pe_session->htRecommendedTxWidthSet) {
3762 ch_width = CH_WIDTH_40MHZ;
3763 if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY ==
3764 pe_session->htSecondaryChannelOffset)
3765 center_freq = primary_channel + 2;
3766 else if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY ==
3767 pe_session->htSecondaryChannelOffset)
3768 center_freq = primary_channel - 2;
3769 else
3770 ch_width = CH_WIDTH_20MHZ;
3771 }
3772 pe_session->gLimChannelSwitch.primaryChannel = primary_channel;
3773 pe_session->curr_req_chan_freq = pe_session->curr_op_freq;
3774 pe_session->ch_center_freq_seg0 = center_freq;
3775 pe_session->gLimChannelSwitch.ch_center_freq_seg0 = center_freq;
3776 pe_session->gLimChannelSwitch.sw_target_freq =
3777 pe_session->curr_op_freq;
3778 pe_session->ch_width = ch_width;
3779 pe_session->gLimChannelSwitch.ch_width = ch_width;
3780 pe_session->gLimChannelSwitch.sec_ch_offset =
3781 pe_session->htSecondaryChannelOffset;
3782 pe_session->gLimChannelSwitch.ch_center_freq_seg1 = 0;
3783
3784 pe_debug("HT IE changed: Primary Channel: %d center chan: %d Channel Width: %d cur op freq %d",
3785 primary_channel, center_freq,
3786 pe_session->htRecommendedTxWidthSet,
3787 pe_session->gLimChannelSwitch.sw_target_freq);
3788 pe_session->channelChangeReasonCode =
3789 LIM_SWITCH_CHANNEL_HT_WIDTH;
3790 mac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
3791 mac->lim.gpchangeChannelData = NULL;
3792
3793 return lim_send_switch_chnl_params(mac, pe_session);
3794 }
3795
lim_ht_switch_chnl_req(struct pe_session * session)3796 static void lim_ht_switch_chnl_req(struct pe_session *session)
3797 {
3798 struct mac_context *mac;
3799 QDF_STATUS status;
3800
3801 mac = session->mac_ctx;
3802 if (!mac) {
3803 pe_err("Invalid mac context");
3804 return;
3805 }
3806
3807 session->channelChangeReasonCode =
3808 LIM_SWITCH_CHANNEL_HT_WIDTH;
3809 mlme_set_chan_switch_in_progress(session->vdev, true);
3810 status = wlan_vdev_mlme_sm_deliver_evt(
3811 session->vdev,
3812 WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
3813 sizeof(*session),
3814 session);
3815 if (QDF_IS_STATUS_ERROR(status)) {
3816 pe_err("Failed to post WLAN_VDEV_SM_EV_FW_VDEV_RESTART for vdevid %d",
3817 session->smeSessionId);
3818 mlme_set_chan_switch_in_progress(session->vdev, false);
3819 }
3820 }
3821
lim_get_cb_mode_for_freq(struct mac_context * mac,struct pe_session * session,qdf_freq_t chan_freq)3822 uint8_t lim_get_cb_mode_for_freq(struct mac_context *mac,
3823 struct pe_session *session,
3824 qdf_freq_t chan_freq)
3825 {
3826 uint8_t cb_mode = mac->roam.configParam.channelBondingMode5GHz;
3827
3828 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) {
3829 if (wlan_cm_get_force_20mhz_in_24ghz(session->vdev)) {
3830 cb_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
3831 pe_debug_rl("vdev %d force 20 Mhz in 2.4 GHz",
3832 session->vdev_id);
3833 } else {
3834 cb_mode = mac->roam.configParam.channelBondingMode24GHz;
3835 }
3836 }
3837
3838 return cb_mode;
3839 }
3840
3841 static
lim_get_sta_cb_mode_for_24ghz(struct mac_context * mac,uint8_t vdev_id)3842 uint8_t lim_get_sta_cb_mode_for_24ghz(struct mac_context *mac,
3843 uint8_t vdev_id)
3844 {
3845 struct wlan_objmgr_vdev *vdev;
3846 uint8_t cb_mode = mac->roam.configParam.channelBondingMode24GHz;
3847
3848 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc,
3849 vdev_id, WLAN_MLME_SB_ID);
3850 if (!vdev)
3851 return cb_mode;
3852
3853 if (!wlan_cm_get_force_20mhz_in_24ghz(vdev))
3854 goto end;
3855
3856 cb_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
3857
3858 end:
3859 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
3860 return cb_mode;
3861 }
3862
lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context * mac,tDot11fIEHTInfo * pHTInfo,struct pe_session * pe_session)3863 void lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context *mac,
3864 tDot11fIEHTInfo *pHTInfo,
3865 struct pe_session *pe_session)
3866 {
3867 qdf_freq_t chan_freq;
3868 uint8_t cb_mode;
3869
3870 cb_mode = lim_get_cb_mode_for_freq(mac, pe_session,
3871 pe_session->curr_op_freq);
3872
3873 /* If self capability is set to '20Mhz only', then do not change the CB mode. */
3874 if (cb_mode == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) {
3875 pe_debug_rl("self_cb_mode 0 for freq %d",
3876 pe_session->curr_op_freq);
3877 return;
3878 }
3879
3880 if (!wlan_cm_is_vdev_connected(pe_session->vdev)) {
3881 pe_debug_rl("vdev not connected, ignore HT IE BW update");
3882 return;
3883 }
3884
3885 if (pe_session->ch_switch_in_progress == true) {
3886 pe_debug("ch switch is in progress, ignore HT IE BW update");
3887 return;
3888 }
3889 chan_freq = wlan_reg_legacy_chan_to_freq(mac->pdev,
3890 pHTInfo->primaryChannel);
3891
3892 if (reg_is_chan_enum_invalid(
3893 wlan_reg_get_chan_enum_for_freq(chan_freq))) {
3894 pe_debug("Ignore Invalid channel in HT info");
3895 return;
3896 }
3897
3898 /* If channel mismatch the CSA will take care of this change */
3899 if (pHTInfo->primaryChannel != wlan_reg_freq_to_chan(
3900 mac->pdev, pe_session->curr_op_freq)) {
3901 pe_debug("Current channel doesn't match HT info ignore");
3902 return;
3903 }
3904
3905 if (pe_session->htSecondaryChannelOffset !=
3906 (uint8_t) pHTInfo->secondaryChannelOffset
3907 || pe_session->htRecommendedTxWidthSet !=
3908 (uint8_t) pHTInfo->recommendedTxWidthSet) {
3909 pe_session->htSecondaryChannelOffset =
3910 (ePhyChanBondState) pHTInfo->secondaryChannelOffset;
3911 pe_session->htRecommendedTxWidthSet =
3912 (uint8_t) pHTInfo->recommendedTxWidthSet;
3913 pe_session->htSupportedChannelWidthSet =
3914 pe_session->htRecommendedTxWidthSet;
3915
3916 /* Before restarting vdev, delete the tdls peers */
3917 lim_update_tdls_set_state_for_fw(pe_session, false);
3918 lim_delete_tdls_peers(mac, pe_session);
3919
3920 lim_ht_switch_chnl_req(pe_session);
3921 }
3922
3923 } /* End limUpdateStaRunTimeHTParams. */
3924
3925 /**
3926 * \brief This function updates the lim global structure, if any of the
3927 * HT Capabilities have changed.
3928 *
3929 *
3930 * \param mac Pointer to Global MAC structure
3931 *
3932 * \param pHTCapability Pointer to HT Capability Information Element
3933 * obtained from a Beacon or Probe Response
3934 *
3935 *
3936 *
3937 */
3938
lim_update_sta_run_time_ht_capability(struct mac_context * mac,tDot11fIEHTCaps * pHTCaps)3939 void lim_update_sta_run_time_ht_capability(struct mac_context *mac,
3940 tDot11fIEHTCaps *pHTCaps)
3941 {
3942
3943 if (mac->lim.gHTLsigTXOPProtection !=
3944 (uint8_t) pHTCaps->lsigTXOPProtection) {
3945 mac->lim.gHTLsigTXOPProtection =
3946 (uint8_t) pHTCaps->lsigTXOPProtection;
3947 /* Send change notification to HAL */
3948 }
3949
3950 if (mac->lim.gHTAMpduDensity != (uint8_t) pHTCaps->mpduDensity) {
3951 mac->lim.gHTAMpduDensity = (uint8_t) pHTCaps->mpduDensity;
3952 /* Send change notification to HAL */
3953 }
3954
3955 if (mac->lim.gHTMaxRxAMpduFactor !=
3956 (uint8_t) pHTCaps->maxRxAMPDUFactor) {
3957 mac->lim.gHTMaxRxAMpduFactor =
3958 (uint8_t) pHTCaps->maxRxAMPDUFactor;
3959 /* Send change notification to HAL */
3960 }
3961
3962 } /* End lim_update_sta_run_time_ht_capability. */
3963
3964 /**
3965 * \brief This function updates lim global structure, if any of the HT
3966 * Info Parameters have changed.
3967 *
3968 *
3969 * \param mac Pointer to the global MAC structure
3970 *
3971 * \param pHTInfo Pointer to the HT Info IE obtained from a Beacon or
3972 * Probe Response
3973 *
3974 *
3975 */
3976
lim_update_sta_run_time_ht_info(struct mac_context * mac,tDot11fIEHTInfo * pHTInfo,struct pe_session * pe_session)3977 void lim_update_sta_run_time_ht_info(struct mac_context *mac,
3978 tDot11fIEHTInfo *pHTInfo,
3979 struct pe_session *pe_session)
3980 {
3981 if (pe_session->htRecommendedTxWidthSet !=
3982 (uint8_t) pHTInfo->recommendedTxWidthSet) {
3983 pe_session->htRecommendedTxWidthSet =
3984 (uint8_t) pHTInfo->recommendedTxWidthSet;
3985 /* Send change notification to HAL */
3986 }
3987
3988 if (pe_session->beaconParams.fRIFSMode !=
3989 (uint8_t) pHTInfo->rifsMode) {
3990 pe_session->beaconParams.fRIFSMode =
3991 (uint8_t) pHTInfo->rifsMode;
3992 /* Send change notification to HAL */
3993 }
3994
3995 if (mac->lim.gHTServiceIntervalGranularity !=
3996 (uint8_t) pHTInfo->serviceIntervalGranularity) {
3997 mac->lim.gHTServiceIntervalGranularity =
3998 (uint8_t) pHTInfo->serviceIntervalGranularity;
3999 /* Send change notification to HAL */
4000 }
4001
4002 if (mac->lim.gHTOperMode != (tSirMacHTOperatingMode) pHTInfo->opMode) {
4003 mac->lim.gHTOperMode =
4004 (tSirMacHTOperatingMode) pHTInfo->opMode;
4005 /* Send change notification to HAL */
4006 }
4007
4008 if (pe_session->beaconParams.llnNonGFCoexist !=
4009 pHTInfo->nonGFDevicesPresent) {
4010 pe_session->beaconParams.llnNonGFCoexist =
4011 (uint8_t) pHTInfo->nonGFDevicesPresent;
4012 }
4013
4014 if (mac->lim.gHTSTBCBasicMCS != (uint8_t) pHTInfo->basicSTBCMCS) {
4015 mac->lim.gHTSTBCBasicMCS = (uint8_t) pHTInfo->basicSTBCMCS;
4016 /* Send change notification to HAL */
4017 }
4018
4019 if (mac->lim.gHTDualCTSProtection !=
4020 (uint8_t) pHTInfo->dualCTSProtection) {
4021 mac->lim.gHTDualCTSProtection =
4022 (uint8_t) pHTInfo->dualCTSProtection;
4023 /* Send change notification to HAL */
4024 }
4025
4026 if (mac->lim.gHTSecondaryBeacon != (uint8_t) pHTInfo->secondaryBeacon) {
4027 mac->lim.gHTSecondaryBeacon =
4028 (uint8_t) pHTInfo->secondaryBeacon;
4029 /* Send change notification to HAL */
4030 }
4031
4032 if (pe_session->beaconParams.fLsigTXOPProtectionFullSupport !=
4033 (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport) {
4034 pe_session->beaconParams.fLsigTXOPProtectionFullSupport =
4035 (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport;
4036 /* Send change notification to HAL */
4037 }
4038
4039 if (mac->lim.gHTPCOActive != (uint8_t) pHTInfo->pcoActive) {
4040 mac->lim.gHTPCOActive = (uint8_t) pHTInfo->pcoActive;
4041 /* Send change notification to HAL */
4042 }
4043
4044 if (mac->lim.gHTPCOPhase != (uint8_t) pHTInfo->pcoPhase) {
4045 mac->lim.gHTPCOPhase = (uint8_t) pHTInfo->pcoPhase;
4046 /* Send change notification to HAL */
4047 }
4048
4049 } /* End lim_update_sta_run_time_ht_info. */
4050
4051 /**
4052 * lim_validate_delts_req() - This function validates DelTs req
4053 * @mac_ctx: pointer to Global Mac structure
4054 * @delts_req: pointer to delete traffic stream structure
4055 * @peer_mac_addr: variable for peer mac address
4056 * @session: pe session entry
4057 *
4058 * Function validates DelTs req originated by SME or by HAL and also
4059 * sends halMsg_DelTs to HAL
4060 *
4061 * Return: QDF_STATUS_SUCCESS - Success, QDF_STATUS_E_FAILURE - Failure
4062 */
4063
4064 QDF_STATUS
lim_validate_delts_req(struct mac_context * mac_ctx,tpSirDeltsReq delts_req,tSirMacAddr peer_mac_addr,struct pe_session * session)4065 lim_validate_delts_req(struct mac_context *mac_ctx, tpSirDeltsReq delts_req,
4066 tSirMacAddr peer_mac_addr,
4067 struct pe_session *session)
4068 {
4069 tpDphHashNode sta;
4070 uint8_t ts_status;
4071 struct mac_ts_info *tsinfo;
4072 uint32_t i;
4073 uint8_t tspec_idx;
4074
4075 /*
4076 * if sta
4077 * - verify assoc state
4078 * - del tspec locally
4079 * if ap
4080 * - verify sta is in assoc state
4081 * - del sta tspec locally
4082 */
4083 if (!delts_req) {
4084 pe_err("Delete TS request pointer is NULL");
4085 return QDF_STATUS_E_FAILURE;
4086 }
4087
4088 if (LIM_IS_STA_ROLE(session)) {
4089 uint32_t val;
4090
4091 /* station always talks to the AP */
4092 sta = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
4093 &session->dph.dphHashTable);
4094
4095 val = sizeof(tSirMacAddr);
4096 sir_copy_mac_addr(peer_mac_addr, session->bssId);
4097
4098 } else {
4099 uint16_t associd;
4100 uint8_t *macaddr = (uint8_t *) peer_mac_addr;
4101
4102 associd = delts_req->aid;
4103 if (associd != 0)
4104 sta = dph_get_hash_entry(mac_ctx, associd,
4105 &session->dph.dphHashTable);
4106 else
4107 sta = dph_lookup_hash_entry(mac_ctx,
4108 delts_req->macaddr.bytes,
4109 &associd,
4110 &session->dph.
4111 dphHashTable);
4112
4113 if (sta)
4114 /* TBD: check sta assoc state as well */
4115 for (i = 0; i < sizeof(tSirMacAddr); i++)
4116 macaddr[i] = sta->staAddr[i];
4117 }
4118
4119 if (!sta) {
4120 pe_err("Cannot find station context for delts req");
4121 return QDF_STATUS_E_FAILURE;
4122 }
4123
4124 if ((!sta->valid) ||
4125 (sta->mlmStaContext.mlmState !=
4126 eLIM_MLM_LINK_ESTABLISHED_STATE)) {
4127 pe_err("Invalid Sta (or state) for DelTsReq");
4128 return QDF_STATUS_E_FAILURE;
4129 }
4130
4131 delts_req->req.wsmTspecPresent = 0;
4132 delts_req->req.wmeTspecPresent = 0;
4133 delts_req->req.lleTspecPresent = 0;
4134
4135 if ((sta->wsmEnabled) &&
4136 (delts_req->req.tspec.tsinfo.traffic.accessPolicy !=
4137 SIR_MAC_ACCESSPOLICY_EDCA))
4138 delts_req->req.wsmTspecPresent = 1;
4139 else if (sta->wmeEnabled)
4140 delts_req->req.wmeTspecPresent = 1;
4141 else if (sta->lleEnabled)
4142 delts_req->req.lleTspecPresent = 1;
4143 else {
4144 pe_warn("DELTS_REQ ignore - qos is disabled");
4145 return QDF_STATUS_E_FAILURE;
4146 }
4147
4148 tsinfo = delts_req->req.wmeTspecPresent ? &delts_req->req.tspec.tsinfo
4149 : &delts_req->req.tsinfo;
4150 pe_debug("received DELTS_REQ message wmeTspecPresent: %d lleTspecPresent: %d wsmTspecPresent: %d tsid: %d up: %d direction: %d",
4151 delts_req->req.wmeTspecPresent,
4152 delts_req->req.lleTspecPresent,
4153 delts_req->req.wsmTspecPresent, tsinfo->traffic.tsid,
4154 tsinfo->traffic.userPrio, tsinfo->traffic.direction);
4155
4156 /* if no Access Control, ignore the request */
4157 if (lim_admit_control_delete_ts(mac_ctx, sta->assocId, tsinfo,
4158 &ts_status, &tspec_idx) != QDF_STATUS_SUCCESS) {
4159 pe_err("DELTS request for sta assocId: %d tsid: %d up: %d",
4160 sta->assocId, tsinfo->traffic.tsid,
4161 tsinfo->traffic.userPrio);
4162 return QDF_STATUS_E_FAILURE;
4163 } else if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA)
4164 || (tsinfo->traffic.accessPolicy ==
4165 SIR_MAC_ACCESSPOLICY_BOTH)) {
4166 /* edca only now. */
4167 } else if (tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) {
4168 /* send message to HAL to delete TS */
4169 if (QDF_STATUS_SUCCESS !=
4170 lim_send_hal_msg_del_ts(mac_ctx,
4171 tspec_idx, delts_req->req,
4172 session->peSessionId,
4173 session->bssId)) {
4174 pe_warn("DelTs with UP: %d failed in lim_send_hal_msg_del_ts - ignoring request",
4175 tsinfo->traffic.userPrio);
4176 return QDF_STATUS_E_FAILURE;
4177 }
4178 }
4179 return QDF_STATUS_SUCCESS;
4180 }
4181
4182 /**
4183 * @function : lim_post_sm_state_update()
4184 *
4185 * @brief : This function Updates the HAL and Softmac about the change in the STA's SMPS state.
4186 *
4187 * LOGIC:
4188 *
4189 * ASSUMPTIONS:
4190 * NA
4191 *
4192 * NOTE:
4193 * NA
4194 *
4195 * @param mac - Pointer to Global MAC structure
4196 * @param limMsg - Lim Message structure object with the MimoPSparam in body
4197 * @return None
4198 */
4199 QDF_STATUS
lim_post_sm_state_update(struct mac_context * mac,tSirMacHTMIMOPowerSaveState state,uint8_t * pPeerStaMac,uint8_t sessionId)4200 lim_post_sm_state_update(struct mac_context *mac,
4201 tSirMacHTMIMOPowerSaveState state,
4202 uint8_t *pPeerStaMac, uint8_t sessionId)
4203 {
4204 QDF_STATUS retCode = QDF_STATUS_SUCCESS;
4205 struct scheduler_msg msgQ = {0};
4206 tpSetMIMOPS pMIMO_PSParams;
4207
4208 msgQ.reserved = 0;
4209 msgQ.type = WMA_SET_MIMOPS_REQ;
4210
4211 /* Allocate for WMA_SET_MIMOPS_REQ */
4212 pMIMO_PSParams = qdf_mem_malloc(sizeof(tSetMIMOPS));
4213 if (!pMIMO_PSParams)
4214 return QDF_STATUS_E_NOMEM;
4215
4216 pMIMO_PSParams->htMIMOPSState = state;
4217 pMIMO_PSParams->fsendRsp = true;
4218 pMIMO_PSParams->sessionId = sessionId;
4219 qdf_mem_copy(pMIMO_PSParams->peerMac, pPeerStaMac, sizeof(tSirMacAddr));
4220
4221 msgQ.bodyptr = pMIMO_PSParams;
4222 msgQ.bodyval = 0;
4223
4224 pe_debug("Sending WMA_SET_MIMOPS_REQ");
4225
4226 MTRACE(mac_trace_msg_tx(mac, NO_SESSION, msgQ.type));
4227 retCode = wma_post_ctrl_msg(mac, &msgQ);
4228 if (QDF_STATUS_SUCCESS != retCode) {
4229 pe_err("Posting WMA_SET_MIMOPS_REQ to HAL failed! Reason: %d",
4230 retCode);
4231 qdf_mem_free(pMIMO_PSParams);
4232 return retCode;
4233 }
4234
4235 return retCode;
4236 }
4237
lim_pkt_free(struct mac_context * mac,eFrameType frmType,uint8_t * pRxPacketInfo,void * pBody)4238 void lim_pkt_free(struct mac_context *mac,
4239 eFrameType frmType, uint8_t *pRxPacketInfo, void *pBody)
4240 {
4241 (void)mac;
4242 (void)frmType;
4243 (void)pRxPacketInfo;
4244 (void)pBody;
4245 }
4246
4247 /**
4248 * lim_get_b_dfrom_rx_packet()
4249 *
4250 ***FUNCTION:
4251 * This function is called to get pointer to Polaris
4252 * Buffer Descriptor containing MAC header & other control
4253 * info from the body of the message posted to LIM.
4254 *
4255 ***LOGIC:
4256 * NA
4257 *
4258 ***ASSUMPTIONS:
4259 * NA
4260 *
4261 ***NOTE:
4262 * NA
4263 *
4264 * @param body - Received message body
4265 * @param pRxPacketInfo - Pointer to received BD
4266 * @return None
4267 */
4268
4269 void
lim_get_b_dfrom_rx_packet(struct mac_context * mac,void * body,uint32_t ** pRxPacketInfo)4270 lim_get_b_dfrom_rx_packet(struct mac_context *mac, void *body, uint32_t **pRxPacketInfo)
4271 {
4272 *pRxPacketInfo = (uint32_t *) body;
4273 } /*** end lim_get_b_dfrom_rx_packet() ***/
4274
lim_is_channel_valid_for_channel_switch(struct mac_context * mac,uint32_t channel_freq)4275 bool lim_is_channel_valid_for_channel_switch(struct mac_context *mac,
4276 uint32_t channel_freq)
4277 {
4278 bool ok = false;
4279
4280 if (policy_mgr_is_chan_ok_for_dnbs(mac->psoc, channel_freq,
4281 &ok)) {
4282 pe_err("policy_mgr_is_chan_ok_for_dnbs() returned error");
4283 return false;
4284 }
4285
4286 if (!ok) {
4287 pe_debug("channel not ok for DNBS");
4288 return false;
4289 }
4290
4291 if (wlan_reg_is_freq_enabled(mac->pdev, channel_freq,
4292 REG_CURRENT_PWR_MODE))
4293 return true;
4294
4295 /* channel does not belong to list of valid channels */
4296 return false;
4297 }
4298
4299 /**
4300 * @function : lim_restore_pre_channel_switch_state()
4301 *
4302 * @brief : This API is called by the user to undo any
4303 * specific changes done on the device during
4304 * channel switch.
4305 * LOGIC:
4306 *
4307 * ASSUMPTIONS:
4308 * NA
4309 *
4310 * NOTE:
4311 * NA
4312 *
4313 * @param mac - Pointer to Global MAC structure
4314 * @return None
4315 */
4316
4317 QDF_STATUS
lim_restore_pre_channel_switch_state(struct mac_context * mac,struct pe_session * pe_session)4318 lim_restore_pre_channel_switch_state(struct mac_context *mac, struct pe_session *pe_session)
4319 {
4320
4321 QDF_STATUS retCode = QDF_STATUS_SUCCESS;
4322
4323 if (!LIM_IS_STA_ROLE(pe_session))
4324 return retCode;
4325
4326 /* Channel switch should be ready for the next time */
4327 pe_session->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_INIT;
4328
4329 return retCode;
4330 }
4331
4332 /**
4333 * @function: lim_prepare_for11h_channel_switch()
4334 *
4335 * @brief : This API is called by the user to prepare for
4336 * 11h channel switch. As of now, the API does
4337 * very minimal work. User can add more into the
4338 * same API if needed.
4339 * LOGIC:
4340 *
4341 * ASSUMPTIONS:
4342 * NA
4343 *
4344 * NOTE:
4345 * NA
4346 *
4347 * @param mac - Pointer to Global MAC structure
4348 * @param pe_session
4349 * @return None
4350 */
4351 void
lim_prepare_for11h_channel_switch(struct mac_context * mac,struct pe_session * pe_session)4352 lim_prepare_for11h_channel_switch(struct mac_context *mac, struct pe_session *pe_session)
4353 {
4354 if (!LIM_IS_STA_ROLE(pe_session))
4355 return;
4356
4357 /* Flag to indicate 11h channel switch in progress */
4358 pe_session->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_RUNNING;
4359
4360 /** We are safe to switch channel at this point */
4361 lim_stop_tx_and_switch_channel(mac, pe_session->peSessionId);
4362 }
4363
lim_get_nw_type(struct mac_context * mac,uint32_t chan_freq,uint32_t type,tpSchBeaconStruct pBeacon)4364 tSirNwType lim_get_nw_type(struct mac_context *mac, uint32_t chan_freq, uint32_t type,
4365 tpSchBeaconStruct pBeacon)
4366 {
4367 tSirNwType nwType = eSIR_11B_NW_TYPE;
4368
4369 /* Logic to be cleaned up for 11AC & 11AX */
4370 if (type == SIR_MAC_DATA_FRAME) {
4371 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) {
4372 nwType = eSIR_11G_NW_TYPE;
4373 } else {
4374 nwType = eSIR_11A_NW_TYPE;
4375 }
4376 } else {
4377 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) {
4378 int i;
4379 /* 11b or 11g packet */
4380 /* 11g iff extended Rate IE is present or */
4381 /* if there is an A rate in suppRate IE */
4382 for (i = 0; i < pBeacon->supportedRates.numRates; i++) {
4383 if (sirIsArate
4384 (pBeacon->supportedRates.rate[i] & 0x7f)) {
4385 nwType = eSIR_11G_NW_TYPE;
4386 break;
4387 }
4388 }
4389 if (pBeacon->extendedRatesPresent) {
4390 nwType = eSIR_11G_NW_TYPE;
4391 } else if (pBeacon->HTInfo.present ||
4392 IS_BSS_VHT_CAPABLE(pBeacon->VHTCaps)) {
4393 nwType = eSIR_11G_NW_TYPE;
4394 }
4395 } else {
4396 /* 11a packet */
4397 nwType = eSIR_11A_NW_TYPE;
4398 }
4399 }
4400 return nwType;
4401 }
4402
lim_get_channel_from_beacon(struct mac_context * mac,tpSchBeaconStruct pBeacon)4403 uint32_t lim_get_channel_from_beacon(struct mac_context *mac, tpSchBeaconStruct pBeacon)
4404 {
4405 uint8_t chan_freq = 0;
4406
4407 if (pBeacon->he_op.oper_info_6g_present)
4408 chan_freq = wlan_reg_chan_band_to_freq(mac->pdev,
4409 pBeacon->he_op.oper_info_6g.info.primary_ch,
4410 BIT(REG_BAND_6G));
4411 else if (pBeacon->dsParamsPresent)
4412 chan_freq = pBeacon->chan_freq;
4413 else if (pBeacon->HTInfo.present)
4414 chan_freq = wlan_reg_legacy_chan_to_freq(mac->pdev,
4415 pBeacon->HTInfo.primaryChannel);
4416 else
4417 chan_freq = pBeacon->chan_freq;
4418
4419 return chan_freq;
4420 }
4421
lim_set_tspec_uapsd_mask_per_session(struct mac_context * mac,struct pe_session * pe_session,struct mac_ts_info * pTsInfo,uint32_t action)4422 void lim_set_tspec_uapsd_mask_per_session(struct mac_context *mac,
4423 struct pe_session *pe_session,
4424 struct mac_ts_info *pTsInfo,
4425 uint32_t action)
4426 {
4427 uint8_t userPrio = (uint8_t) pTsInfo->traffic.userPrio;
4428 uint16_t direction = pTsInfo->traffic.direction;
4429 uint8_t ac = upToAc(userPrio);
4430
4431 pe_debug("Set UAPSD mask for AC: %d dir: %d action: %d"
4432 , ac, direction, action);
4433
4434 /* Converting AC to appropriate Uapsd Bit Mask
4435 * AC_BE(0) --> UAPSD_BITOFFSET_ACVO(3)
4436 * AC_BK(1) --> UAPSD_BITOFFSET_ACVO(2)
4437 * AC_VI(2) --> UAPSD_BITOFFSET_ACVO(1)
4438 * AC_VO(3) --> UAPSD_BITOFFSET_ACVO(0)
4439 */
4440 ac = ((~ac) & 0x3);
4441
4442 if (action == CLEAR_UAPSD_MASK) {
4443 if (direction == SIR_MAC_DIRECTION_UPLINK)
4444 pe_session->gUapsdPerAcTriggerEnableMask &=
4445 ~(1 << ac);
4446 else if (direction == SIR_MAC_DIRECTION_DNLINK)
4447 pe_session->gUapsdPerAcDeliveryEnableMask &=
4448 ~(1 << ac);
4449 else if (direction == SIR_MAC_DIRECTION_BIDIR) {
4450 pe_session->gUapsdPerAcTriggerEnableMask &=
4451 ~(1 << ac);
4452 pe_session->gUapsdPerAcDeliveryEnableMask &=
4453 ~(1 << ac);
4454 }
4455 } else if (action == SET_UAPSD_MASK) {
4456 if (direction == SIR_MAC_DIRECTION_UPLINK)
4457 pe_session->gUapsdPerAcTriggerEnableMask |=
4458 (1 << ac);
4459 else if (direction == SIR_MAC_DIRECTION_DNLINK)
4460 pe_session->gUapsdPerAcDeliveryEnableMask |=
4461 (1 << ac);
4462 else if (direction == SIR_MAC_DIRECTION_BIDIR) {
4463 pe_session->gUapsdPerAcTriggerEnableMask |=
4464 (1 << ac);
4465 pe_session->gUapsdPerAcDeliveryEnableMask |=
4466 (1 << ac);
4467 }
4468 }
4469
4470 pe_debug("New pe_session->gUapsdPerAcTriggerEnableMask 0x%x pe_session->gUapsdPerAcDeliveryEnableMask 0x%x",
4471 pe_session->gUapsdPerAcTriggerEnableMask,
4472 pe_session->gUapsdPerAcDeliveryEnableMask);
4473
4474 return;
4475 }
4476
4477 /**
4478 * lim_handle_heart_beat_timeout_for_session() - Handle heart beat time out
4479 * @mac_ctx: pointer to Global Mac Structure
4480 * @psession_entry: pointer to struct pe_session *
4481 *
4482 * Function handles heart beat time out for session
4483 *
4484 * Return: none
4485 */
lim_handle_heart_beat_timeout_for_session(struct mac_context * mac_ctx,struct pe_session * psession_entry)4486 void lim_handle_heart_beat_timeout_for_session(struct mac_context *mac_ctx,
4487 struct pe_session *psession_entry)
4488 {
4489 if (psession_entry->valid) {
4490 if ((psession_entry->bssType == eSIR_INFRASTRUCTURE_MODE) &&
4491 (LIM_IS_STA_ROLE(psession_entry)))
4492 lim_handle_heart_beat_failure(mac_ctx, psession_entry);
4493 }
4494 }
4495
lim_process_add_sta_rsp(struct mac_context * mac_ctx,struct scheduler_msg * msg)4496 void lim_process_add_sta_rsp(struct mac_context *mac_ctx,
4497 struct scheduler_msg *msg)
4498 {
4499 struct pe_session *session;
4500 tpAddStaParams add_sta_params;
4501
4502 add_sta_params = (tpAddStaParams) msg->bodyptr;
4503
4504 session = pe_find_session_by_session_id(mac_ctx,
4505 add_sta_params->sessionId);
4506 if (!session) {
4507 pe_err("Session Does not exist for given sessionID");
4508 qdf_mem_free(add_sta_params);
4509 return;
4510 }
4511 session->csaOffloadEnable = add_sta_params->csaOffloadEnable;
4512 if (LIM_IS_NDI_ROLE(session))
4513 lim_ndp_add_sta_rsp(mac_ctx, session, msg->bodyptr);
4514 #ifdef FEATURE_WLAN_TDLS
4515 else if (add_sta_params->staType == STA_ENTRY_TDLS_PEER)
4516 lim_process_tdls_add_sta_rsp(mac_ctx, msg->bodyptr, session);
4517 #endif
4518 else
4519 lim_process_mlm_add_sta_rsp(mac_ctx, msg, session);
4520
4521 }
4522
4523 /**
4524 * lim_update_beacon() - This function updates beacon
4525 * @mac_ctx: pointer to Global Mac Structure
4526 *
4527 * This Function is invoked to update the beacon
4528 *
4529 * Return: none
4530 */
lim_update_beacon(struct mac_context * mac_ctx)4531 void lim_update_beacon(struct mac_context *mac_ctx)
4532 {
4533 uint8_t i;
4534
4535 for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
4536 if (mac_ctx->lim.gpSession[i].valid != true)
4537 continue;
4538 if ((mac_ctx->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE)
4539 && (eLIM_SME_NORMAL_STATE ==
4540 mac_ctx->lim.gpSession[i].limSmeState)) {
4541
4542 sch_set_fixed_beacon_fields(mac_ctx,
4543 &mac_ctx->lim.gpSession[i]);
4544
4545 if (false == mac_ctx->sap.SapDfsInfo.
4546 is_dfs_cac_timer_running)
4547 lim_send_beacon_ind(mac_ctx,
4548 &mac_ctx->lim.gpSession[i],
4549 REASON_DEFAULT);
4550 }
4551 }
4552 }
4553
lim_is_ap_session_active(struct mac_context * mac)4554 struct pe_session *lim_is_ap_session_active(struct mac_context *mac)
4555 {
4556 uint8_t i;
4557
4558 for (i = 0; i < mac->lim.maxBssId; i++) {
4559 if (mac->lim.gpSession[i].valid &&
4560 (mac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE))
4561 return &mac->lim.gpSession[i];
4562 }
4563
4564 return NULL;
4565 }
4566
4567 /**---------------------------------------------------------
4568 \fn lim_handle_defer_msg_error
4569 \brief handles error scenario, when the msg can not be deferred.
4570 \param mac
4571 \param pLimMsg LIM msg, which could not be deferred.
4572 \return void
4573 -----------------------------------------------------------*/
4574
lim_handle_defer_msg_error(struct mac_context * mac,struct scheduler_msg * pLimMsg)4575 void lim_handle_defer_msg_error(struct mac_context *mac,
4576 struct scheduler_msg *pLimMsg)
4577 {
4578 if (SIR_BB_XPORT_MGMT_MSG == pLimMsg->type) {
4579 lim_decrement_pending_mgmt_count(mac);
4580 cds_pkt_return_packet((cds_pkt_t *) pLimMsg->bodyptr);
4581 pLimMsg->bodyptr = NULL;
4582 } else if (pLimMsg->bodyptr) {
4583 qdf_mem_free(pLimMsg->bodyptr);
4584 pLimMsg->bodyptr = NULL;
4585 }
4586
4587 }
4588
4589 #ifdef FEATURE_WLAN_DIAG_SUPPORT
4590 /**---------------------------------------------------------
4591 \fn lim_diag_event_report
4592 \brief This function reports Diag event
4593 \param mac
4594 \param eventType
4595 \param bssid
4596 \param status
4597 \param reasonCode
4598 \return void
4599 -----------------------------------------------------------*/
lim_diag_event_report(struct mac_context * mac,uint16_t eventType,struct pe_session * pe_session,uint16_t status,uint16_t reasonCode)4600 void lim_diag_event_report(struct mac_context *mac, uint16_t eventType,
4601 struct pe_session *pe_session, uint16_t status,
4602 uint16_t reasonCode)
4603 {
4604 tSirMacAddr nullBssid = { 0, 0, 0, 0, 0, 0 };
4605
4606 WLAN_HOST_DIAG_EVENT_DEF(peEvent, host_event_wlan_pe_payload_type);
4607
4608 qdf_mem_zero(&peEvent, sizeof(host_event_wlan_pe_payload_type));
4609
4610 if (!pe_session) {
4611 qdf_mem_copy(peEvent.bssid, nullBssid, sizeof(tSirMacAddr));
4612 peEvent.sme_state = (uint16_t) mac->lim.gLimSmeState;
4613 peEvent.mlm_state = (uint16_t) mac->lim.gLimMlmState;
4614
4615 } else {
4616 qdf_mem_copy(peEvent.bssid, pe_session->bssId,
4617 sizeof(tSirMacAddr));
4618 peEvent.sme_state = (uint16_t) pe_session->limSmeState;
4619 peEvent.mlm_state = (uint16_t) pe_session->limMlmState;
4620 }
4621 peEvent.event_type = eventType;
4622 peEvent.status = status;
4623 peEvent.reason_code = reasonCode;
4624
4625 WLAN_HOST_DIAG_EVENT_REPORT(&peEvent, EVENT_WLAN_PE);
4626 return;
4627 }
4628
lim_diag_fill_mgmt_event_report(struct mac_context * mac_ctx,tpSirMacMgmtHdr mac_hdr,struct pe_session * session,uint16_t result_code,uint16_t reason_code,struct host_event_wlan_mgmt_payload_type * mgmt_event)4629 static void lim_diag_fill_mgmt_event_report(struct mac_context *mac_ctx,
4630 tpSirMacMgmtHdr mac_hdr,
4631 struct pe_session *session, uint16_t result_code,
4632 uint16_t reason_code,
4633 struct host_event_wlan_mgmt_payload_type *mgmt_event)
4634 {
4635 uint8_t length;
4636
4637 qdf_mem_zero(mgmt_event, sizeof(*mgmt_event));
4638 mgmt_event->mgmt_type = mac_hdr->fc.type;
4639 mgmt_event->mgmt_subtype = mac_hdr->fc.subType;
4640 qdf_mem_copy(mgmt_event->self_mac_addr, session->self_mac_addr,
4641 QDF_MAC_ADDR_SIZE);
4642 qdf_mem_copy(mgmt_event->bssid, mac_hdr->bssId,
4643 QDF_MAC_ADDR_SIZE);
4644 length = session->ssId.length;
4645 if (length > WLAN_SSID_MAX_LEN)
4646 length = WLAN_SSID_MAX_LEN;
4647 qdf_mem_copy(mgmt_event->ssid, session->ssId.ssId, length);
4648 mgmt_event->ssid_len = length;
4649 mgmt_event->operating_channel = wlan_reg_freq_to_chan(
4650 mac_ctx->pdev, session->curr_op_freq);
4651 mgmt_event->result_code = result_code;
4652 mgmt_event->reason_code = reason_code;
4653 }
4654
lim_diag_mgmt_tx_event_report(struct mac_context * mac_ctx,void * mgmt_hdr,struct pe_session * session,uint16_t result_code,uint16_t reason_code)4655 void lim_diag_mgmt_tx_event_report(struct mac_context *mac_ctx, void *mgmt_hdr,
4656 struct pe_session *session, uint16_t result_code,
4657 uint16_t reason_code)
4658 {
4659 tpSirMacMgmtHdr mac_hdr = mgmt_hdr;
4660
4661 WLAN_HOST_DIAG_EVENT_DEF(mgmt_event,
4662 struct host_event_wlan_mgmt_payload_type);
4663 if (!session || !mac_hdr) {
4664 pe_err("not valid input");
4665 return;
4666 }
4667 lim_diag_fill_mgmt_event_report(mac_ctx, mac_hdr, session,
4668 result_code, reason_code, &mgmt_event);
4669
4670 pe_debug("TX frame: type:%d sub_type:%d seq_num:%d ssid:" QDF_SSID_FMT " selfmacaddr:" QDF_MAC_ADDR_FMT " bssid:" QDF_MAC_ADDR_FMT " channel:%d",
4671 mgmt_event.mgmt_type, mgmt_event.mgmt_subtype,
4672 ((mac_hdr->seqControl.seqNumHi << 4) |
4673 mac_hdr->seqControl.seqNumLo),
4674 QDF_SSID_REF(mgmt_event.ssid_len, mgmt_event.ssid),
4675 QDF_MAC_ADDR_REF(mgmt_event.self_mac_addr),
4676 QDF_MAC_ADDR_REF(mgmt_event.bssid),
4677 mgmt_event.operating_channel);
4678 WLAN_HOST_DIAG_EVENT_REPORT(&mgmt_event, EVENT_WLAN_HOST_MGMT_TX_V2);
4679 }
4680
lim_diag_mgmt_rx_event_report(struct mac_context * mac_ctx,void * mgmt_hdr,struct pe_session * session,uint16_t result_code,uint16_t reason_code)4681 void lim_diag_mgmt_rx_event_report(struct mac_context *mac_ctx, void *mgmt_hdr,
4682 struct pe_session *session, uint16_t result_code,
4683 uint16_t reason_code)
4684 {
4685 tpSirMacMgmtHdr mac_hdr = mgmt_hdr;
4686
4687 WLAN_HOST_DIAG_EVENT_DEF(mgmt_event,
4688 struct host_event_wlan_mgmt_payload_type);
4689 if (!session || !mac_hdr) {
4690 pe_debug("not valid input");
4691 return;
4692 }
4693 lim_diag_fill_mgmt_event_report(mac_ctx, mac_hdr, session,
4694 result_code, reason_code, &mgmt_event);
4695 pe_debug("RX frame: type:%d sub_type:%d seq_num:%d ssid:" QDF_SSID_FMT " selfmacaddr:" QDF_MAC_ADDR_FMT " bssid:" QDF_MAC_ADDR_FMT " channel:%d",
4696 mgmt_event.mgmt_type, mgmt_event.mgmt_subtype,
4697 ((mac_hdr->seqControl.seqNumHi << 4) |
4698 mac_hdr->seqControl.seqNumLo),
4699 QDF_SSID_REF(mgmt_event.ssid_len, mgmt_event.ssid),
4700 QDF_MAC_ADDR_REF(mgmt_event.self_mac_addr),
4701 QDF_MAC_ADDR_REF(mgmt_event.bssid),
4702 mgmt_event.operating_channel);
4703 WLAN_HOST_DIAG_EVENT_REPORT(&mgmt_event, EVENT_WLAN_HOST_MGMT_RX_V2);
4704 }
4705 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
4706
4707 /* Returns length of P2P stream and Pointer ie passed to this function is filled with noa stream */
4708
lim_build_p2p_ie(struct mac_context * mac,uint8_t * ie,uint8_t * data,uint8_t ie_len)4709 uint8_t lim_build_p2p_ie(struct mac_context *mac, uint8_t *ie, uint8_t *data,
4710 uint8_t ie_len)
4711 {
4712 int length = 0;
4713 uint8_t *ptr = ie;
4714
4715 ptr[length++] = WLAN_ELEMID_VENDOR;
4716 ptr[length++] = ie_len + SIR_MAC_P2P_OUI_SIZE;
4717 qdf_mem_copy(&ptr[length], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE);
4718 qdf_mem_copy(&ptr[length + SIR_MAC_P2P_OUI_SIZE], data, ie_len);
4719 return ie_len + SIR_P2P_IE_HEADER_LEN;
4720 }
4721
4722 /* Returns length of NoA stream and Pointer pNoaStream passed to this function is filled with noa stream */
lim_get_noa_attr_stream(struct mac_context * mac,uint8_t * pNoaStream,struct pe_session * pe_session)4723 uint8_t lim_get_noa_attr_stream(struct mac_context *mac, uint8_t *pNoaStream,
4724 struct pe_session *pe_session)
4725 {
4726 uint8_t len = 0;
4727
4728 uint8_t *pBody = pNoaStream;
4729
4730 if ((pe_session) && (pe_session->valid) &&
4731 (pe_session->opmode == QDF_P2P_GO_MODE)) {
4732 if ((!(pe_session->p2pGoPsUpdate.uNoa1Duration))
4733 && (!(pe_session->p2pGoPsUpdate.uNoa2Duration))
4734 && (!pe_session->p2pGoPsUpdate.oppPsFlag)
4735 )
4736 return 0; /* No NoA Descriptor then return 0 */
4737
4738 pBody[0] = SIR_P2P_NOA_ATTR;
4739
4740 pBody[3] = pe_session->p2pGoPsUpdate.index;
4741 pBody[4] =
4742 pe_session->p2pGoPsUpdate.ctWin | (pe_session->
4743 p2pGoPsUpdate.
4744 oppPsFlag << 7);
4745 len = 5;
4746 pBody += len;
4747
4748 if (pe_session->p2pGoPsUpdate.uNoa1Duration) {
4749 *pBody = pe_session->p2pGoPsUpdate.uNoa1IntervalCnt;
4750 pBody += 1;
4751 len += 1;
4752
4753 *((uint32_t *) (pBody)) =
4754 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate.
4755 uNoa1Duration);
4756 pBody += sizeof(uint32_t);
4757 len += 4;
4758
4759 *((uint32_t *) (pBody)) =
4760 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate.
4761 uNoa1Interval);
4762 pBody += sizeof(uint32_t);
4763 len += 4;
4764
4765 *((uint32_t *) (pBody)) =
4766 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate.
4767 uNoa1StartTime);
4768 pBody += sizeof(uint32_t);
4769 len += 4;
4770
4771 }
4772
4773 if (pe_session->p2pGoPsUpdate.uNoa2Duration) {
4774 *pBody = pe_session->p2pGoPsUpdate.uNoa2IntervalCnt;
4775 pBody += 1;
4776 len += 1;
4777
4778 *((uint32_t *) (pBody)) =
4779 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate.
4780 uNoa2Duration);
4781 pBody += sizeof(uint32_t);
4782 len += 4;
4783
4784 *((uint32_t *) (pBody)) =
4785 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate.
4786 uNoa2Interval);
4787 pBody += sizeof(uint32_t);
4788 len += 4;
4789
4790 *((uint32_t *) (pBody)) =
4791 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate.
4792 uNoa2StartTime);
4793 pBody += sizeof(uint32_t);
4794 len += 4;
4795
4796 }
4797
4798 pBody = pNoaStream + 1;
4799 *((uint16_t *) (pBody)) = sir_swap_u16if_needed(len - 3); /*one byte for Attr and 2 bytes for length */
4800
4801 return len;
4802
4803 }
4804 return 0;
4805
4806 }
4807
pe_set_resume_channel(struct mac_context * mac,uint16_t channel,ePhyChanBondState phyCbState)4808 void pe_set_resume_channel(struct mac_context *mac, uint16_t channel,
4809 ePhyChanBondState phyCbState)
4810 {
4811
4812 mac->lim.gResumeChannel = channel;
4813 mac->lim.gResumePhyCbState = phyCbState;
4814 }
4815
lim_isconnected_on_dfs_freq(struct mac_context * mac_ctx,qdf_freq_t oper_freq)4816 bool lim_isconnected_on_dfs_freq(struct mac_context *mac_ctx,
4817 qdf_freq_t oper_freq)
4818 {
4819 /* Indoor channels are also marked DFS, therefore
4820 * check if the channel has REGULATORY_CHAN_RADAR
4821 * channel flag to identify if the channel is DFS
4822 */
4823 if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev, oper_freq))
4824 return true;
4825 else
4826 return false;
4827 }
4828
lim_pmf_sa_query_timer_handler(void * pMacGlobal,uint32_t param)4829 void lim_pmf_sa_query_timer_handler(void *pMacGlobal, uint32_t param)
4830 {
4831 struct mac_context *mac = (struct mac_context *) pMacGlobal;
4832 tPmfSaQueryTimerId timerId;
4833 struct pe_session *pe_session;
4834 tpDphHashNode pSta;
4835 uint8_t maxretries;
4836
4837 pe_debug("SA Query timer fires");
4838 timerId.value = param;
4839
4840 /* Check that SA Query is in progress */
4841 pe_session = pe_find_session_by_session_id(mac,
4842 timerId.fields.sessionId);
4843 if (!pe_session) {
4844 pe_err("Session does not exist for given session ID: %d",
4845 timerId.fields.sessionId);
4846 return;
4847 }
4848 pSta = dph_get_hash_entry(mac, timerId.fields.peerIdx,
4849 &pe_session->dph.dphHashTable);
4850 if (!pSta) {
4851 pe_err("Entry does not exist for given peer index: %d",
4852 timerId.fields.peerIdx);
4853 return;
4854 }
4855 if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState)
4856 return;
4857
4858 /* Increment the retry count, check if reached maximum */
4859 maxretries = mac->mlme_cfg->gen.pmf_sa_query_max_retries;
4860 pSta->pmfSaQueryRetryCount++;
4861 if (pSta->pmfSaQueryRetryCount >= maxretries) {
4862 pe_err("SA Query timed out,Deleting STA: "QDF_MAC_ADDR_FMT,
4863 QDF_MAC_ADDR_REF(pSta->staAddr));
4864 lim_send_disassoc_mgmt_frame(mac,
4865 REASON_DISASSOC_DUE_TO_INACTIVITY,
4866 pSta->staAddr, pe_session, false);
4867 lim_trigger_sta_deletion(mac, pSta, pe_session);
4868 pSta->pmfSaQueryState = DPH_SA_QUERY_TIMED_OUT;
4869 return;
4870 }
4871 /* Retry SA Query */
4872 lim_send_sa_query_request_frame(mac,
4873 (uint8_t *) &(pSta->
4874 pmfSaQueryCurrentTransId),
4875 pSta->staAddr, pe_session);
4876 pSta->pmfSaQueryCurrentTransId++;
4877 pe_debug("Starting SA Query retry: %d", pSta->pmfSaQueryRetryCount);
4878 if (tx_timer_activate(&pSta->pmfSaQueryTimer) != TX_SUCCESS) {
4879 pe_err("PMF SA Query timer activation failed!");
4880 pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
4881 }
4882 }
4883
4884 /**
4885 * lim_get_update_bw_allow() whether bw can be sent to target directly
4886 * @session: pe session
4887 * @new_bw: bandwdith to set
4888 * @update_allow: return true if bw and puncture can be updated directly
4889 *
4890 * Return: QDF_STATUS
4891 */
4892 static QDF_STATUS
lim_get_update_bw_allow(struct pe_session * session,enum phy_ch_width new_bw,bool * update_allow)4893 lim_get_update_bw_allow(struct pe_session *session,
4894 enum phy_ch_width new_bw,
4895 bool *update_allow)
4896 {
4897 enum phy_ch_width ch_width;
4898 struct wlan_objmgr_psoc *psoc;
4899 enum wlan_phymode phy_mode;
4900 QDF_STATUS status = QDF_STATUS_E_INVAL;
4901
4902 if (!session || !update_allow) {
4903 pe_err("invalid input");
4904 return status;
4905 }
4906 *update_allow = false;
4907
4908 psoc = wlan_vdev_get_psoc(session->vdev);
4909 if (!psoc) {
4910 pe_err("psoc object invalid");
4911 return status;
4912 }
4913 status = mlme_get_peer_phymode(psoc, session->bssId, &phy_mode);
4914 if (QDF_IS_STATUS_ERROR(status)) {
4915 pe_err("failed to get phy_mode %d mac: " QDF_MAC_ADDR_FMT,
4916 status, QDF_MAC_ADDR_REF(session->bssId));
4917 return status;
4918 }
4919 ch_width = wlan_mlme_get_ch_width_from_phymode(phy_mode);
4920 if (new_bw <= ch_width)
4921 *update_allow = true;
4922
4923 return status;
4924 }
4925
lim_check_vht_op_mode_change(struct mac_context * mac,struct pe_session * pe_session,uint8_t chanWidth,uint8_t * peerMac)4926 bool lim_check_vht_op_mode_change(struct mac_context *mac,
4927 struct pe_session *pe_session,
4928 uint8_t chanWidth, uint8_t *peerMac)
4929 {
4930 QDF_STATUS status;
4931 bool update_allow;
4932 struct ch_params ch_params;
4933 struct csa_offload_params *csa_param;
4934 enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(pe_session->vdev);
4935
4936 if (mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE) {
4937 status = lim_get_update_bw_allow(pe_session, chanWidth,
4938 &update_allow);
4939 if (QDF_IS_STATUS_ERROR(status))
4940 return false;
4941 } else {
4942 update_allow = true;
4943 }
4944
4945 if (update_allow) {
4946 tUpdateVHTOpMode tempParam;
4947
4948 tempParam.opMode = chanWidth;
4949 tempParam.smesessionId = pe_session->smeSessionId;
4950 qdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr));
4951
4952 lim_send_mode_update(mac, &tempParam, pe_session);
4953 lim_update_tdls_2g_bw(pe_session);
4954
4955 return true;
4956 }
4957
4958 if (!wlan_cm_is_vdev_connected(pe_session->vdev))
4959 return false;
4960
4961 /* use vdev restart to update STA mode */
4962 qdf_mem_zero(&ch_params, sizeof(ch_params));
4963 ch_params.ch_width = chanWidth;
4964 wlan_reg_set_channel_params_for_pwrmode(mac->pdev,
4965 pe_session->curr_op_freq,
4966 0, &ch_params,
4967 REG_CURRENT_PWR_MODE);
4968 csa_param = qdf_mem_malloc(sizeof(*csa_param));
4969 if (!csa_param) {
4970 pe_err("csa_param allocation fails");
4971 return false;
4972 }
4973
4974 csa_param->channel = wlan_reg_freq_to_chan(mac->pdev,
4975 pe_session->curr_op_freq);
4976 csa_param->csa_chan_freq = pe_session->curr_op_freq;
4977 csa_param->new_ch_width = ch_params.ch_width;
4978 csa_param->new_ch_freq_seg1 = ch_params.center_freq_seg0;
4979 csa_param->new_ch_freq_seg2 = ch_params.center_freq_seg1;
4980 qdf_copy_macaddr(&csa_param->bssid,
4981 (struct qdf_mac_addr *)pe_session->bssId);
4982 lim_handle_sta_csa_param(mac, csa_param, false);
4983
4984 return true;
4985 }
4986
4987 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
lim_send_he_ie_update(struct mac_context * mac_ctx,struct pe_session * pe_session)4988 bool lim_send_he_ie_update(struct mac_context *mac_ctx, struct pe_session *pe_session)
4989 {
4990 QDF_STATUS status;
4991
4992 status = wma_update_he_ops_ie(cds_get_context(QDF_MODULE_ID_WMA),
4993 pe_session->smeSessionId,
4994 &pe_session->he_op);
4995 if (QDF_IS_STATUS_ERROR(status))
4996 return false;
4997
4998 return true;
4999 }
5000 #endif
5001
lim_set_nss_change(struct mac_context * mac,struct pe_session * pe_session,uint8_t rxNss,uint8_t * peerMac)5002 bool lim_set_nss_change(struct mac_context *mac, struct pe_session *pe_session,
5003 uint8_t rxNss, uint8_t *peerMac)
5004 {
5005 tUpdateRxNss tempParam;
5006
5007 if (!rxNss) {
5008 pe_err("Invalid rxNss value: %u", rxNss);
5009 return false;
5010 }
5011
5012 tempParam.rxNss = rxNss;
5013 tempParam.smesessionId = pe_session->smeSessionId;
5014 qdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr));
5015
5016 lim_send_rx_nss_update(mac, &tempParam, pe_session);
5017
5018 return true;
5019 }
5020
lim_check_membership_user_position(struct mac_context * mac,struct pe_session * pe_session,uint32_t membership,uint32_t userPosition)5021 bool lim_check_membership_user_position(struct mac_context *mac,
5022 struct pe_session *pe_session,
5023 uint32_t membership,
5024 uint32_t userPosition)
5025 {
5026 tUpdateMembership tempParamMembership;
5027 tUpdateUserPos tempParamUserPosition;
5028
5029 tempParamMembership.membership = membership;
5030 tempParamMembership.smesessionId = pe_session->smeSessionId;
5031 qdf_mem_copy(tempParamMembership.peer_mac, pe_session->bssId,
5032 sizeof(tSirMacAddr));
5033
5034 lim_set_membership(mac, &tempParamMembership, pe_session);
5035
5036 tempParamUserPosition.userPos = userPosition;
5037 tempParamUserPosition.smesessionId = pe_session->smeSessionId;
5038 qdf_mem_copy(tempParamUserPosition.peer_mac, pe_session->bssId,
5039 sizeof(tSirMacAddr));
5040
5041 lim_set_user_pos(mac, &tempParamUserPosition, pe_session);
5042
5043 return true;
5044 }
5045
lim_get_short_slot_from_phy_mode(struct mac_context * mac,struct pe_session * pe_session,uint32_t phyMode,uint8_t * pShortSlotEnabled)5046 void lim_get_short_slot_from_phy_mode(struct mac_context *mac, struct pe_session *pe_session,
5047 uint32_t phyMode, uint8_t *pShortSlotEnabled)
5048 {
5049 uint8_t val = 0;
5050
5051 /* only 2.4G band should have short slot enable, rest it should be default */
5052 if (phyMode == WNI_CFG_PHY_MODE_11G) {
5053 /* short slot is default in all other modes */
5054 if ((pe_session->opmode == QDF_SAP_MODE) ||
5055 (pe_session->opmode == QDF_IBSS_MODE) ||
5056 (pe_session->opmode == QDF_P2P_GO_MODE)) {
5057 val = true;
5058 }
5059 /* Program Polaris based on AP capability */
5060 if (pe_session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) {
5061 /* Joining BSS. */
5062 val =
5063 SIR_MAC_GET_SHORT_SLOT_TIME(pe_session->
5064 limCurrentBssCaps);
5065 } else if (pe_session->limMlmState ==
5066 eLIM_MLM_WT_REASSOC_RSP_STATE) {
5067 /* Reassociating with AP. */
5068 val =
5069 SIR_MAC_GET_SHORT_SLOT_TIME(pe_session->
5070 limReassocBssCaps);
5071 }
5072 } else {
5073 /*
5074 * 11B does not short slot and short slot is default
5075 * for 11A mode. Hence, not need to set this bit
5076 */
5077 val = false;
5078 }
5079
5080 pe_debug("phyMode: %u shortslotsupported: %u", phyMode, val);
5081 *pShortSlotEnabled = val;
5082 }
5083
5084 /**
5085 *
5086 * \brief This function is called by various LIM modules to correctly set
5087 * the Protected bit in the Frame Control Field of the 802.11 frame MAC header
5088 *
5089 *
5090 * \param mac Pointer to Global MAC structure
5091 *
5092 * \param pe_session Pointer to session corresponding to the connection
5093 *
5094 * \param peer Peer address of the STA to which the frame is to be sent
5095 *
5096 * \param pMacHdr Pointer to the frame MAC header
5097 *
5098 * \return nothing
5099 *
5100 *
5101 */
5102 void
lim_set_protected_bit(struct mac_context * mac,struct pe_session * pe_session,tSirMacAddr peer,tpSirMacMgmtHdr pMacHdr)5103 lim_set_protected_bit(struct mac_context *mac,
5104 struct pe_session *pe_session,
5105 tSirMacAddr peer, tpSirMacMgmtHdr pMacHdr)
5106 {
5107 uint16_t aid;
5108 tpDphHashNode sta;
5109
5110 sta = dph_lookup_hash_entry(mac, peer, &aid,
5111 &pe_session->dph.dphHashTable);
5112 if (sta) {
5113 /* rmfenabled will be set at the time of addbss.
5114 * but sometimes EAP auth fails and keys are not
5115 * installed then if we send any management frame
5116 * like deauth/disassoc with this bit set then
5117 * firmware crashes. so check for keys are
5118 * installed or not also before setting the bit
5119 */
5120 if (sta->rmfEnabled && sta->is_key_installed)
5121 pMacHdr->fc.wep = 1;
5122
5123 pe_debug("wep:%d rmf:%d is_key_set:%d", pMacHdr->fc.wep,
5124 sta->rmfEnabled, sta->is_key_installed);
5125 }
5126 } /*** end lim_set_protected_bit() ***/
5127
lim_set_ht_caps(struct mac_context * p_mac,uint8_t * p_ie_start,uint32_t num_bytes)5128 void lim_set_ht_caps(struct mac_context *p_mac, uint8_t *p_ie_start,
5129 uint32_t num_bytes)
5130 {
5131 const uint8_t *p_ie = NULL;
5132 tDot11fIEHTCaps dot11_ht_cap = {0,};
5133
5134 populate_dot11f_ht_caps(p_mac, NULL, &dot11_ht_cap);
5135 p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_HTCAPS,
5136 p_ie_start, num_bytes);
5137 pe_debug("p_ie: %pK dot11_ht_cap.supportedMCSSet[0]: 0x%x",
5138 p_ie, dot11_ht_cap.supportedMCSSet[0]);
5139 if (p_ie) {
5140 /* convert from unpacked to packed structure */
5141 tHtCaps *p_ht_cap = (tHtCaps *) &p_ie[2];
5142
5143 p_ht_cap->advCodingCap = dot11_ht_cap.advCodingCap;
5144 p_ht_cap->supportedChannelWidthSet =
5145 dot11_ht_cap.supportedChannelWidthSet;
5146 p_ht_cap->mimoPowerSave = dot11_ht_cap.mimoPowerSave;
5147 p_ht_cap->greenField = dot11_ht_cap.greenField;
5148 p_ht_cap->shortGI20MHz = dot11_ht_cap.shortGI20MHz;
5149 p_ht_cap->shortGI40MHz = dot11_ht_cap.shortGI40MHz;
5150 p_ht_cap->txSTBC = dot11_ht_cap.txSTBC;
5151 p_ht_cap->rxSTBC = dot11_ht_cap.rxSTBC;
5152 p_ht_cap->delayedBA = dot11_ht_cap.delayedBA;
5153 p_ht_cap->maximalAMSDUsize = dot11_ht_cap.maximalAMSDUsize;
5154 p_ht_cap->dsssCckMode40MHz = dot11_ht_cap.dsssCckMode40MHz;
5155 p_ht_cap->psmp = dot11_ht_cap.psmp;
5156 p_ht_cap->stbcControlFrame = dot11_ht_cap.stbcControlFrame;
5157 p_ht_cap->lsigTXOPProtection = dot11_ht_cap.lsigTXOPProtection;
5158 p_ht_cap->maxRxAMPDUFactor = dot11_ht_cap.maxRxAMPDUFactor;
5159 p_ht_cap->mpduDensity = dot11_ht_cap.mpduDensity;
5160 qdf_mem_copy((void *)p_ht_cap->supportedMCSSet,
5161 (void *)(dot11_ht_cap.supportedMCSSet),
5162 sizeof(p_ht_cap->supportedMCSSet));
5163 p_ht_cap->pco = dot11_ht_cap.pco;
5164 p_ht_cap->transitionTime = dot11_ht_cap.transitionTime;
5165 p_ht_cap->mcsFeedback = dot11_ht_cap.mcsFeedback;
5166 p_ht_cap->txBF = dot11_ht_cap.txBF;
5167 p_ht_cap->rxStaggeredSounding =
5168 dot11_ht_cap.rxStaggeredSounding;
5169 p_ht_cap->txStaggeredSounding =
5170 dot11_ht_cap.txStaggeredSounding;
5171 p_ht_cap->rxZLF = dot11_ht_cap.rxZLF;
5172 p_ht_cap->txZLF = dot11_ht_cap.txZLF;
5173 p_ht_cap->implicitTxBF = dot11_ht_cap.implicitTxBF;
5174 p_ht_cap->calibration = dot11_ht_cap.calibration;
5175 p_ht_cap->explicitCSITxBF = dot11_ht_cap.explicitCSITxBF;
5176 p_ht_cap->explicitUncompressedSteeringMatrix =
5177 dot11_ht_cap.explicitUncompressedSteeringMatrix;
5178 p_ht_cap->explicitBFCSIFeedback =
5179 dot11_ht_cap.explicitBFCSIFeedback;
5180 p_ht_cap->explicitUncompressedSteeringMatrixFeedback =
5181 dot11_ht_cap.explicitUncompressedSteeringMatrixFeedback;
5182 p_ht_cap->explicitCompressedSteeringMatrixFeedback =
5183 dot11_ht_cap.explicitCompressedSteeringMatrixFeedback;
5184 p_ht_cap->csiNumBFAntennae = dot11_ht_cap.csiNumBFAntennae;
5185 p_ht_cap->uncompressedSteeringMatrixBFAntennae =
5186 dot11_ht_cap.uncompressedSteeringMatrixBFAntennae;
5187 p_ht_cap->compressedSteeringMatrixBFAntennae =
5188 dot11_ht_cap.compressedSteeringMatrixBFAntennae;
5189 p_ht_cap->antennaSelection = dot11_ht_cap.antennaSelection;
5190 p_ht_cap->explicitCSIFeedbackTx =
5191 dot11_ht_cap.explicitCSIFeedbackTx;
5192 p_ht_cap->antennaIndicesFeedbackTx =
5193 dot11_ht_cap.antennaIndicesFeedbackTx;
5194 p_ht_cap->explicitCSIFeedback =
5195 dot11_ht_cap.explicitCSIFeedback;
5196 p_ht_cap->antennaIndicesFeedback =
5197 dot11_ht_cap.antennaIndicesFeedback;
5198 p_ht_cap->rxAS = dot11_ht_cap.rxAS;
5199 p_ht_cap->txSoundingPPDUs = dot11_ht_cap.txSoundingPPDUs;
5200 }
5201 }
5202
lim_set_vht_caps(struct mac_context * p_mac,uint8_t * p_ie_start,uint32_t num_bytes)5203 void lim_set_vht_caps(struct mac_context *p_mac,
5204 uint8_t *p_ie_start, uint32_t num_bytes)
5205 {
5206 const uint8_t *p_ie = NULL;
5207 tDot11fIEVHTCaps dot11_vht_cap;
5208
5209 populate_dot11f_vht_caps(p_mac, NULL, &dot11_vht_cap);
5210 p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_VHTCAPS, p_ie_start,
5211 num_bytes);
5212 if (p_ie) {
5213 tSirMacVHTCapabilityInfo *vht_cap =
5214 (tSirMacVHTCapabilityInfo *) &p_ie[2];
5215 tSirVhtMcsInfo *vht_mcs = (tSirVhtMcsInfo *) &p_ie[2 +
5216 sizeof(tSirMacVHTCapabilityInfo)];
5217
5218 union {
5219 uint16_t u_value;
5220 tSirMacVHTRxSupDataRateInfo vht_rx_supp_rate;
5221 tSirMacVHTTxSupDataRateInfo vht_tx_supp_rate;
5222 } u_vht_data_rate_info;
5223
5224 vht_cap->maxMPDULen = dot11_vht_cap.maxMPDULen;
5225 vht_cap->supportedChannelWidthSet =
5226 dot11_vht_cap.supportedChannelWidthSet;
5227 vht_cap->ldpcCodingCap = dot11_vht_cap.ldpcCodingCap;
5228 vht_cap->shortGI80MHz = dot11_vht_cap.shortGI80MHz;
5229 vht_cap->shortGI160and80plus80MHz =
5230 dot11_vht_cap.shortGI160and80plus80MHz;
5231 vht_cap->txSTBC = dot11_vht_cap.txSTBC;
5232 vht_cap->rxSTBC = dot11_vht_cap.rxSTBC;
5233 vht_cap->suBeamFormerCap = dot11_vht_cap.suBeamFormerCap;
5234 vht_cap->suBeamformeeCap = dot11_vht_cap.suBeamformeeCap;
5235 vht_cap->csnofBeamformerAntSup =
5236 dot11_vht_cap.csnofBeamformerAntSup;
5237 vht_cap->numSoundingDim = dot11_vht_cap.numSoundingDim;
5238 vht_cap->muBeamformerCap = dot11_vht_cap.muBeamformerCap;
5239 vht_cap->muBeamformeeCap = dot11_vht_cap.muBeamformeeCap;
5240 vht_cap->vhtTXOPPS = dot11_vht_cap.vhtTXOPPS;
5241 vht_cap->htcVHTCap = dot11_vht_cap.htcVHTCap;
5242 vht_cap->maxAMPDULenExp = dot11_vht_cap.maxAMPDULenExp;
5243 vht_cap->vhtLinkAdaptCap = dot11_vht_cap.vhtLinkAdaptCap;
5244 vht_cap->rxAntPattern = dot11_vht_cap.rxAntPattern;
5245 vht_cap->txAntPattern = dot11_vht_cap.txAntPattern;
5246 vht_cap->extended_nss_bw_supp =
5247 dot11_vht_cap.extended_nss_bw_supp;
5248
5249 /* Populate VHT MCS Information */
5250 vht_mcs->rxMcsMap = dot11_vht_cap.rxMCSMap;
5251 u_vht_data_rate_info.vht_rx_supp_rate.rxSupDataRate =
5252 dot11_vht_cap.rxHighSupDataRate;
5253 u_vht_data_rate_info.vht_rx_supp_rate.max_nsts_total =
5254 dot11_vht_cap.max_nsts_total;
5255 vht_mcs->rxHighest = u_vht_data_rate_info.u_value;
5256
5257 vht_mcs->txMcsMap = dot11_vht_cap.txMCSMap;
5258 u_vht_data_rate_info.vht_tx_supp_rate.txSupDataRate =
5259 dot11_vht_cap.txSupDataRate;
5260 u_vht_data_rate_info.vht_tx_supp_rate.vht_extended_nss_bw_cap =
5261 dot11_vht_cap.vht_extended_nss_bw_cap;
5262 vht_mcs->txHighest = u_vht_data_rate_info.u_value;
5263 }
5264 }
5265
5266 /*
5267 * Firmware will send RTS for every frame and also will disable SIFS bursting
5268 * if value 0x11 is sent for RTS profile.
5269 */
5270 #define A_EDCA_SCC_RTS_PROFILE_VALUE 0x11
5271 #define MAX_NUMBER_OF_SINGLE_PORT_CONC_CONNECTIONS 2
5272
lim_update_sta_edca_params(struct mac_context * mac,struct pe_session * sta_session)5273 static void lim_update_sta_edca_params(struct mac_context *mac,
5274 struct pe_session *sta_session)
5275 {
5276 uint8_t i;
5277
5278 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) {
5279 sta_session->gLimEdcaParamsActive[i] =
5280 sta_session->gLimEdcaParams[i];
5281 }
5282 lim_send_edca_params(mac,
5283 sta_session->gLimEdcaParamsActive,
5284 sta_session->vdev_id, false);
5285 }
5286
check_and_send_vendor_oui(struct mac_context * mac,struct pe_session * sta_session)5287 static void check_and_send_vendor_oui(struct mac_context *mac,
5288 struct pe_session *sta_session)
5289 {
5290 QDF_STATUS status;
5291 uint8_t *tmp_ptr = NULL;
5292 struct element_info frame;
5293
5294 status = wlan_scan_get_entry_by_mac_addr(
5295 mac->pdev,
5296 (struct qdf_mac_addr *)&sta_session->bssId,
5297 &frame);
5298 if (QDF_IS_STATUS_ERROR(status) && !frame.len) {
5299 pe_err("Failed to get scan entry for " QDF_MAC_ADDR_FMT,
5300 QDF_MAC_ADDR_REF(sta_session->bssId));
5301 return;
5302 }
5303
5304 tmp_ptr = frame.ptr;
5305 tmp_ptr += SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET;
5306 frame.len -= SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET;
5307
5308 if (!lim_enable_cts_to_self_for_exempted_iot_ap(
5309 mac, sta_session,
5310 tmp_ptr, frame.len))
5311 wma_cli_set_command(sta_session->vdev_id,
5312 wmi_vdev_param_enable_rtscts,
5313 cfg_get(mac->psoc,
5314 CFG_ENABLE_FW_RTS_PROFILE),
5315 VDEV_CMD);
5316 qdf_mem_free(frame.ptr);
5317 }
5318
5319 /**
5320 * lim_check_conc_and_send_edca() - Function to check and update EDCA params
5321 * and RTS profile based on STA/SAP
5322 * concurrency. If updated, it will also send
5323 * the updated parameters to FW. It will update
5324 * EDCA params and RTS profile such that:
5325 * 1) For STA and SAP concurrency, send STA's AP EDCA params to fw.
5326 * Also, for SAP or P2P Go, update the value in Broadcast EDCA params
5327 * as well so that it should be broadcasted to other stations connected
5328 * to that BSS. Also, update the RTS profile value to 0x11 for which
5329 * FW will send RTS for every frame and will also disable SIFS
5330 * bursting.
5331 *
5332 * 2) For standalone STA (can even happen after SAP/P2P Go
5333 * disconnects), if the parameters are updated, reset them to original
5334 * parameters and send them to FW. Also, update the RTS profile
5335 * value to which it was set before.
5336 *
5337 * 3) For standalone SAP (can even happen after STA disconnects),
5338 * if the parameters are updated, reset them to original
5339 * parameters and send them to FW and reset the Broadcast EDCA params
5340 * as well so that it should be broadcasted to other stations connected
5341 * to that BSS Also, update the RTS profile value to which it was set
5342 * before.
5343 *
5344 * This update is needed because throughput drop was seen because of
5345 * inconsistency in the EDCA params used in STA-SAP or STA-P2P_GO concurrency.
5346 *
5347 * Return: void
5348 */
5349
lim_check_conc_and_send_edca(struct mac_context * mac,struct pe_session * sta_session,struct pe_session * sap_session)5350 static void lim_check_conc_and_send_edca(struct mac_context *mac,
5351 struct pe_session *sta_session,
5352 struct pe_session *sap_session)
5353 {
5354 bool params_update_required = false;
5355 uint8_t i;
5356 tpDphHashNode sta_ds = NULL;
5357 uint16_t assoc_id;
5358
5359 if (sta_session && sap_session &&
5360 (sta_session->curr_op_freq ==
5361 sap_session->curr_op_freq)) {
5362 /* RTS profile update to FW */
5363 wma_cli_set_command(sap_session->vdev_id,
5364 wmi_vdev_param_enable_rtscts,
5365 A_EDCA_SCC_RTS_PROFILE_VALUE,
5366 VDEV_CMD);
5367 wma_cli_set_command(sta_session->vdev_id,
5368 wmi_vdev_param_enable_rtscts,
5369 A_EDCA_SCC_RTS_PROFILE_VALUE,
5370 VDEV_CMD);
5371
5372 sta_ds = dph_lookup_hash_entry(mac,
5373 sta_session->bssId,
5374 &assoc_id,
5375 &sta_session->dph.dphHashTable);
5376
5377 if (!sta_ds) {
5378 pe_debug("No STA DS entry found for " QDF_MAC_ADDR_FMT,
5379 QDF_MAC_ADDR_REF(sta_session->bssId));
5380 return;
5381 }
5382
5383 if (!sta_ds->qos.peer_edca_params.length) {
5384 pe_debug("No sta_ds edca_params present");
5385 return;
5386 }
5387
5388 /*
5389 * Here what we do is disable A-EDCA by sending the edca params of
5390 * connected AP which we got as part of assoc resp So as these EDCA
5391 * params are updated per mac , its fine to send for SAP which will
5392 * be used for STA as well on the same channel. No need to send for
5393 * both SAP and STA.
5394 */
5395
5396 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_BE] =
5397 sta_ds->qos.peer_edca_params.acbe;
5398 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_BK] =
5399 sta_ds->qos.peer_edca_params.acbk;
5400 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_VI] =
5401 sta_ds->qos.peer_edca_params.acvi;
5402 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_VO] =
5403 sta_ds->qos.peer_edca_params.acvo;
5404
5405 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_BE] =
5406 sta_ds->qos.peer_edca_params.acbe;
5407 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_BK] =
5408 sta_ds->qos.peer_edca_params.acbk;
5409 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_VI] =
5410 sta_ds->qos.peer_edca_params.acvi;
5411 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_VO] =
5412 sta_ds->qos.peer_edca_params.acvo;
5413
5414 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) {
5415 sta_session->gLimEdcaParamsActive[i] =
5416 sap_session->gLimEdcaParamsActive[i];
5417 }
5418 /* For AP, the bssID is stored in LIM Global context. */
5419 lim_send_edca_params(mac, sap_session->gLimEdcaParamsActive,
5420 sap_session->vdev_id, false);
5421
5422 sap_session->gLimEdcaParamSetCount++;
5423 csr_update_beacon(mac);
5424 } else if (!sap_session && sta_session) {
5425 /*
5426 * Enable A-EDCA for standalone STA. The original EDCA parameters are
5427 * stored in gLimEdcaParams (computed by sch_beacon_edca_process()),
5428 * if active parameters are not equal that means they have been updated
5429 * because of conncurrency and are need to be restored now
5430 */
5431 check_and_send_vendor_oui(mac, sta_session);
5432
5433 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) {
5434 if (qdf_mem_cmp(&sta_session->gLimEdcaParamsActive[i],
5435 &sta_session->gLimEdcaParams[i],
5436 sizeof(tSirMacEdcaParamRecord))) {
5437 pe_debug("local sta EDCA params are not equal to Active EDCA params, hence update required");
5438 params_update_required = true;
5439 break;
5440 }
5441 }
5442
5443 if (params_update_required) {
5444 lim_update_sta_edca_params(mac,
5445 sta_session);
5446 }
5447 } else {
5448 /*
5449 * For STA+SAP/GO DBS, STA+SAP/GO MCC or standalone SAP/GO
5450 */
5451
5452 wma_cli_set_command(sap_session->vdev_id,
5453 wmi_vdev_param_enable_rtscts,
5454 cfg_get(mac->psoc,
5455 CFG_ENABLE_FW_RTS_PROFILE),
5456 VDEV_CMD);
5457 if (sta_session) {
5458 check_and_send_vendor_oui(mac, sta_session);
5459 }
5460
5461 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) {
5462 if (qdf_mem_cmp(&sap_session->gLimEdcaParamsActive[i],
5463 &sap_session->gLimEdcaParams[i],
5464 sizeof(tSirMacEdcaParamRecord))) {
5465 pe_debug("local sap EDCA params are not equal to Active EDCA params, hence update required");
5466 params_update_required = true;
5467 break;
5468 }
5469 }
5470
5471 if (params_update_required) {
5472 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) {
5473 sap_session->gLimEdcaParamsActive[i] =
5474 sap_session->gLimEdcaParams[i];
5475 }
5476 lim_send_edca_params(mac,
5477 sap_session->gLimEdcaParamsActive,
5478 sap_session->vdev_id, false);
5479 sch_qos_update_broadcast(mac, sap_session);
5480
5481 /*
5482 * In case of mcc, where cb can come from scc to mcc switch where we
5483 * need to restore the default parameters
5484 */
5485 if (sta_session) {
5486 lim_update_sta_edca_params(mac,
5487 sta_session);
5488 }
5489 }
5490 }
5491 }
5492
lim_send_conc_params_update(void)5493 void lim_send_conc_params_update(void)
5494 {
5495 struct pe_session *sta_session = NULL;
5496 struct pe_session *sap_session = NULL;
5497 uint8_t i;
5498 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
5499
5500 if (!mac)
5501 return;
5502
5503 if (!mac->mlme_cfg->edca_params.enable_edca_params ||
5504 (policy_mgr_get_connection_count(mac->psoc) >
5505 MAX_NUMBER_OF_SINGLE_PORT_CONC_CONNECTIONS)) {
5506 pe_debug("A-EDCA not enabled or max number of connections: %d",
5507 policy_mgr_get_connection_count(mac->psoc));
5508 return;
5509 }
5510
5511 for (i = 0; i < mac->lim.maxBssId; i++) {
5512 /*
5513 * Finding whether STA or Go session exists
5514 */
5515 if (sta_session && sap_session)
5516 break;
5517
5518 if ((mac->lim.gpSession[i].valid) &&
5519 (mac->lim.gpSession[i].limSystemRole ==
5520 eLIM_STA_ROLE)) {
5521 sta_session = &mac->lim.gpSession[i];
5522 continue;
5523 }
5524 if ((mac->lim.gpSession[i].valid) &&
5525 ((mac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) ||
5526 (mac->lim.gpSession[i].limSystemRole ==
5527 eLIM_P2P_DEVICE_GO))) {
5528 sap_session = &mac->lim.gpSession[i];
5529 continue;
5530 }
5531 }
5532
5533 if (!(sta_session || sap_session)) {
5534 pe_debug("No sta or sap or P2P go session");
5535 return;
5536 }
5537
5538 pe_debug("Valid STA session: %d Valid SAP session: %d",
5539 (sta_session ? sta_session->valid : 0),
5540 (sap_session ? sap_session->valid : 0));
5541 lim_check_conc_and_send_edca(mac, sta_session, sap_session);
5542 }
5543
5544 /**
5545 * lim_validate_received_frame_a1_addr() - To validate received frame's A1 addr
5546 * @mac_ctx: pointer to mac context
5547 * @a1: received frame's a1 address which is nothing but our self address
5548 * @session: PE session pointer
5549 *
5550 * This routine will validate, A1 address of the received frame
5551 *
5552 * Return: true or false
5553 */
lim_validate_received_frame_a1_addr(struct mac_context * mac_ctx,tSirMacAddr a1,struct pe_session * session)5554 bool lim_validate_received_frame_a1_addr(struct mac_context *mac_ctx,
5555 tSirMacAddr a1, struct pe_session *session)
5556 {
5557 if (!mac_ctx || !session) {
5558 pe_err("mac or session context is null");
5559 /* let main routine handle it */
5560 return true;
5561 }
5562 if (IEEE80211_IS_MULTICAST(a1) || QDF_IS_ADDR_BROADCAST(a1)) {
5563 /* just for fail safe, don't handle MC/BC a1 in this routine */
5564 return true;
5565 }
5566 if (qdf_mem_cmp(a1, session->self_mac_addr, 6)) {
5567 pe_err("Invalid A1 address in received frame");
5568 return false;
5569 }
5570 return true;
5571 }
5572
5573 /**
5574 * lim_check_and_reset_protection_params() - reset protection related parameters
5575 *
5576 * @mac_ctx: pointer to global mac structure
5577 *
5578 * resets protection related global parameters if the pe active session count
5579 * is zero.
5580 *
5581 * Return: None
5582 */
lim_check_and_reset_protection_params(struct mac_context * mac_ctx)5583 void lim_check_and_reset_protection_params(struct mac_context *mac_ctx)
5584 {
5585 if (!pe_get_active_session_count(mac_ctx)) {
5586 mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
5587 }
5588 }
5589
5590 /**
5591 * lim_set_stads_rtt_cap() - update station node RTT capability
5592 * @sta_ds: Station hash node
5593 * @ext_cap: Pointer to extended capability
5594 * @mac_ctx: global MAC context
5595 *
5596 * This function update hash node's RTT capability based on received
5597 * Extended capability IE.
5598 *
5599 * Return: None
5600 */
lim_set_stads_rtt_cap(tpDphHashNode sta_ds,struct s_ext_cap * ext_cap,struct mac_context * mac_ctx)5601 void lim_set_stads_rtt_cap(tpDphHashNode sta_ds, struct s_ext_cap *ext_cap,
5602 struct mac_context *mac_ctx)
5603 {
5604 sta_ds->timingMeasCap = 0;
5605 sta_ds->timingMeasCap |= (ext_cap->timing_meas) ?
5606 RTT_TIMING_MEAS_CAPABILITY :
5607 RTT_INVALID;
5608 sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_initiator) ?
5609 RTT_FINE_TIME_MEAS_INITIATOR_CAPABILITY :
5610 RTT_INVALID;
5611 sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_responder) ?
5612 RTT_FINE_TIME_MEAS_RESPONDER_CAPABILITY :
5613 RTT_INVALID;
5614
5615 pe_debug("ExtCap present, timingMeas: %d Initiator: %d Responder: %d",
5616 ext_cap->timing_meas, ext_cap->fine_time_meas_initiator,
5617 ext_cap->fine_time_meas_responder);
5618 }
5619
5620 #ifdef WLAN_SUPPORT_TWT
lim_set_peer_twt_cap(struct pe_session * session,struct s_ext_cap * ext_cap)5621 void lim_set_peer_twt_cap(struct pe_session *session, struct s_ext_cap *ext_cap)
5622 {
5623 if (session->enable_session_twt_support) {
5624 session->peer_twt_requestor = ext_cap->twt_requestor_support;
5625 session->peer_twt_responder = ext_cap->twt_responder_support;
5626 }
5627
5628 pe_debug("Ext Cap peer TWT requestor: %d, responder: %d, enable_twt %d",
5629 ext_cap->twt_requestor_support,
5630 ext_cap->twt_responder_support,
5631 session->enable_session_twt_support);
5632 }
5633 #endif
5634
5635 /**
5636 * lim_send_ie() - sends IE to wma
5637 * @mac_ctx: global MAC context
5638 * @vdev_id: vdev_id
5639 * @eid: IE id
5640 * @band: band for which IE is intended
5641 * @buf: buffer containing IE
5642 * @len: length of buffer
5643 *
5644 * This function sends the IE data to WMA.
5645 *
5646 * Return: status of operation
5647 */
lim_send_ie(struct mac_context * mac_ctx,uint32_t vdev_id,uint8_t eid,enum cds_band_type band,uint8_t * buf,uint32_t len)5648 static QDF_STATUS lim_send_ie(struct mac_context *mac_ctx, uint32_t vdev_id,
5649 uint8_t eid, enum cds_band_type band,
5650 uint8_t *buf, uint32_t len)
5651 {
5652 struct vdev_ie_info *ie_msg;
5653 struct scheduler_msg msg = {0};
5654 QDF_STATUS status;
5655
5656 /* Allocate memory for the WMI request */
5657 ie_msg = qdf_mem_malloc(sizeof(*ie_msg) + len);
5658 if (!ie_msg)
5659 return QDF_STATUS_E_NOMEM;
5660
5661 ie_msg->vdev_id = vdev_id;
5662 ie_msg->ie_id = eid;
5663 ie_msg->length = len;
5664 ie_msg->band = band;
5665 /* IE data buffer starts at end of the struct */
5666 ie_msg->data = (uint8_t *)&ie_msg[1];
5667
5668 qdf_mem_copy(ie_msg->data, buf, len);
5669 msg.type = WMA_SET_IE_INFO;
5670 msg.bodyptr = ie_msg;
5671 msg.reserved = 0;
5672
5673 status = scheduler_post_message(QDF_MODULE_ID_PE,
5674 QDF_MODULE_ID_WMA,
5675 QDF_MODULE_ID_WMA, &msg);
5676 if (QDF_STATUS_SUCCESS != status) {
5677 pe_err("Not able to post WMA_SET_IE_INFO to WMA");
5678 qdf_mem_free(ie_msg);
5679 return status;
5680 }
5681
5682 return status;
5683 }
5684
5685 /**
5686 * lim_get_rx_ldpc() - gets ldpc setting for given channel(band)
5687 * @mac_ctx: global mac context
5688 * @ch: channel enum for which ldpc setting is required
5689 * Note: ch param is not absolute channel number rather it is
5690 * channel number enum.
5691 *
5692 * Return: true if enabled and false otherwise
5693 */
lim_get_rx_ldpc(struct mac_context * mac_ctx,enum channel_enum ch)5694 static inline bool lim_get_rx_ldpc(struct mac_context *mac_ctx,
5695 enum channel_enum ch)
5696 {
5697 if (mac_ctx->mlme_cfg->ht_caps.ht_cap_info.adv_coding_cap &&
5698 wma_is_rx_ldpc_supported_for_channel(wlan_reg_ch_to_freq(ch)))
5699 return true;
5700 else
5701 return false;
5702 }
5703
5704 /**
5705 * lim_populate_mcs_set_ht_per_vdev() - update the MCS set according to vdev nss
5706 * @mac_ctx: global mac context
5707 * @ht_cap: pointer to ht caps
5708 * @vdev_id: vdev for which IE is targeted
5709 * @band: band for which the MCS set has to be updated
5710 *
5711 * This function updates the MCS set according to vdev nss
5712 *
5713 * Return: None
5714 */
lim_populate_mcs_set_ht_per_vdev(struct mac_context * mac_ctx,struct sHtCaps * ht_cap,uint8_t vdev_id,uint8_t band)5715 static void lim_populate_mcs_set_ht_per_vdev(struct mac_context *mac_ctx,
5716 struct sHtCaps *ht_cap,
5717 uint8_t vdev_id,
5718 uint8_t band)
5719 {
5720 struct wlan_mlme_nss_chains *nss_chains_ini_cfg;
5721 struct wlan_objmgr_vdev *vdev =
5722 wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
5723 vdev_id,
5724 WLAN_MLME_SB_ID);
5725 if (!vdev) {
5726 pe_err("Got NULL vdev obj, returning");
5727 return;
5728 }
5729 if (!ht_cap->supportedMCSSet[1])
5730 goto end;
5731 nss_chains_ini_cfg = mlme_get_ini_vdev_config(vdev);
5732 if (!nss_chains_ini_cfg) {
5733 pe_err("nss chain dynamic config NULL");
5734 goto end;
5735 }
5736
5737 /* convert from unpacked to packed structure */
5738 if (nss_chains_ini_cfg->rx_nss[band] == 1)
5739 ht_cap->supportedMCSSet[1] = 0;
5740
5741 end:
5742 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
5743 }
5744
5745 /**
5746 * lim_populate_mcs_set_vht_per_vdev() - update MCS set according to vdev nss
5747 * @mac_ctx: global mac context
5748 * @vht_caps: pointer to vht_caps
5749 * @vdev_id: vdev for which IE is targeted
5750 * @band: band for which the MCS set has to be updated
5751 *
5752 * This function updates the MCS set according to vdev nss
5753 *
5754 * Return: None
5755 */
lim_populate_mcs_set_vht_per_vdev(struct mac_context * mac_ctx,uint8_t * vht_caps,uint8_t vdev_id,uint8_t band)5756 static void lim_populate_mcs_set_vht_per_vdev(struct mac_context *mac_ctx,
5757 uint8_t *vht_caps,
5758 uint8_t vdev_id,
5759 uint8_t band)
5760 {
5761 struct wlan_mlme_nss_chains *nss_chains_ini_cfg;
5762 tSirVhtMcsInfo *vht_mcs;
5763 struct wlan_objmgr_vdev *vdev =
5764 wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
5765 vdev_id,
5766 WLAN_MLME_SB_ID);
5767 if (!vdev) {
5768 pe_err("Got NULL vdev obj, returning");
5769 return;
5770 }
5771
5772 nss_chains_ini_cfg = mlme_get_ini_vdev_config(vdev);
5773 if (!nss_chains_ini_cfg) {
5774 pe_err("nss chain dynamic config NULL");
5775 goto end;
5776 }
5777
5778 vht_mcs = (tSirVhtMcsInfo *)&vht_caps[2 +
5779 sizeof(tSirMacVHTCapabilityInfo)];
5780 if (nss_chains_ini_cfg->tx_nss[band] == 1) {
5781 /* Populate VHT MCS Information */
5782 vht_mcs->txMcsMap |= DISABLE_NSS2_MCS;
5783 vht_mcs->txHighest =
5784 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
5785 }
5786
5787 if (nss_chains_ini_cfg->rx_nss[band] == 1) {
5788 /* Populate VHT MCS Information */
5789 vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS;
5790 vht_mcs->rxHighest =
5791 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
5792 }
5793
5794 end:
5795 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
5796 }
5797
5798 /**
5799 * is_dot11mode_support_ht_cap() - Check dot11mode supports HT capability
5800 * @dot11mode: dot11mode
5801 *
5802 * This function checks whether dot11mode support HT capability or not
5803 *
5804 * Return: True, if supports. False otherwise
5805 */
is_dot11mode_support_ht_cap(enum csr_cfgdot11mode dot11mode)5806 static bool is_dot11mode_support_ht_cap(enum csr_cfgdot11mode dot11mode)
5807 {
5808 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) ||
5809 (dot11mode == eCSR_CFG_DOT11_MODE_11N) ||
5810 (dot11mode == eCSR_CFG_DOT11_MODE_11AC) ||
5811 (dot11mode == eCSR_CFG_DOT11_MODE_11N_ONLY) ||
5812 (dot11mode == eCSR_CFG_DOT11_MODE_11AC_ONLY) ||
5813 (dot11mode == eCSR_CFG_DOT11_MODE_11AX) ||
5814 (dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY) ||
5815 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) ||
5816 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) {
5817 return true;
5818 }
5819
5820 return false;
5821 }
5822
5823 /**
5824 * is_dot11mode_support_vht_cap() - Check dot11mode supports VHT capability
5825 * @dot11mode: dot11mode
5826 *
5827 * This function checks whether dot11mode support VHT capability or not
5828 *
5829 * Return: True, if supports. False otherwise
5830 */
is_dot11mode_support_vht_cap(enum csr_cfgdot11mode dot11mode)5831 static bool is_dot11mode_support_vht_cap(enum csr_cfgdot11mode dot11mode)
5832 {
5833 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) ||
5834 (dot11mode == eCSR_CFG_DOT11_MODE_11AC) ||
5835 (dot11mode == eCSR_CFG_DOT11_MODE_11AC_ONLY) ||
5836 (dot11mode == eCSR_CFG_DOT11_MODE_11AX) ||
5837 (dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY) ||
5838 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) ||
5839 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) {
5840 return true;
5841 }
5842
5843 return false;
5844 }
5845
5846 /**
5847 * is_dot11mode_support_he_cap() - Check dot11mode supports HE capability
5848 * @dot11mode: dot11mode
5849 *
5850 * This function checks whether dot11mode support HE capability or not
5851 *
5852 * Return: True, if supports. False otherwise
5853 */
is_dot11mode_support_he_cap(enum csr_cfgdot11mode dot11mode)5854 static bool is_dot11mode_support_he_cap(enum csr_cfgdot11mode dot11mode)
5855 {
5856 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) ||
5857 (dot11mode == eCSR_CFG_DOT11_MODE_11AX) ||
5858 (dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY) ||
5859 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) ||
5860 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) {
5861 return true;
5862 }
5863
5864 return false;
5865 }
5866
5867 #ifdef WLAN_FEATURE_11BE
5868 /**
5869 * is_dot11mode_support_eht_cap() - Check dot11mode supports EHT capability
5870 * @dot11mode: dot11mode
5871 *
5872 * This function checks whether dot11mode support EHT capability or not
5873 *
5874 * Return: True, if supports. False otherwise
5875 */
is_dot11mode_support_eht_cap(enum csr_cfgdot11mode dot11mode)5876 static bool is_dot11mode_support_eht_cap(enum csr_cfgdot11mode dot11mode)
5877 {
5878 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) ||
5879 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) ||
5880 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) {
5881 return true;
5882 }
5883
5884 return false;
5885 }
5886
lim_is_session_chwidth_320mhz(struct pe_session * session)5887 bool lim_is_session_chwidth_320mhz(struct pe_session *session)
5888 {
5889 return session->ch_width == CH_WIDTH_320MHZ;
5890 }
5891 #else
is_dot11mode_support_eht_cap(enum csr_cfgdot11mode dot11mode)5892 static bool is_dot11mode_support_eht_cap(enum csr_cfgdot11mode dot11mode)
5893 {
5894 return false;
5895 }
5896 #endif
5897
5898 /**
5899 * lim_send_ht_caps_ie() - gets HT capability and send to firmware via wma
5900 * @mac_ctx: global mac context
5901 * @device_mode: VDEV op mode
5902 * @vdev_id: vdev for which IE is targeted
5903 *
5904 * This function gets HT capability and send to firmware via wma
5905 *
5906 * Return: QDF_STATUS
5907 */
lim_send_ht_caps_ie(struct mac_context * mac_ctx,enum QDF_OPMODE device_mode,uint8_t vdev_id)5908 static QDF_STATUS lim_send_ht_caps_ie(struct mac_context *mac_ctx,
5909 enum QDF_OPMODE device_mode,
5910 uint8_t vdev_id)
5911 {
5912 uint8_t ht_caps[DOT11F_IE_HTCAPS_MIN_LEN + 2] = {0};
5913 tHtCaps *p_ht_cap = (tHtCaps *)(&ht_caps[2]);
5914 QDF_STATUS status_5g, status_2g;
5915 bool nan_beamforming_supported;
5916
5917 ht_caps[0] = DOT11F_EID_HTCAPS;
5918 ht_caps[1] = DOT11F_IE_HTCAPS_MIN_LEN;
5919 lim_set_ht_caps(mac_ctx, ht_caps,
5920 DOT11F_IE_HTCAPS_MIN_LEN + 2);
5921 /* Get LDPC and over write for 2G */
5922 p_ht_cap->advCodingCap = lim_get_rx_ldpc(mac_ctx,
5923 CHAN_ENUM_2437);
5924 /* Get self cap for HT40 support in 2G */
5925 if (lim_get_sta_cb_mode_for_24ghz(mac_ctx, vdev_id)) {
5926 p_ht_cap->supportedChannelWidthSet = 1;
5927 p_ht_cap->shortGI40MHz = 1;
5928 } else {
5929 p_ht_cap->supportedChannelWidthSet = 0;
5930 p_ht_cap->shortGI40MHz = 0;
5931 }
5932
5933 lim_populate_mcs_set_ht_per_vdev(mac_ctx, p_ht_cap, vdev_id,
5934 NSS_CHAINS_BAND_2GHZ);
5935
5936 nan_beamforming_supported =
5937 ucfg_nan_is_beamforming_supported(mac_ctx->psoc);
5938 if (device_mode == QDF_NDI_MODE && !nan_beamforming_supported) {
5939 p_ht_cap->txBF = 0;
5940 p_ht_cap->implicitTxBF = 0;
5941 p_ht_cap->explicitCSITxBF = 0;
5942 }
5943
5944 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HTCAPS,
5945 CDS_BAND_2GHZ, &ht_caps[2],
5946 DOT11F_IE_HTCAPS_MIN_LEN);
5947 /*
5948 * Get LDPC and over write for 5G - using channel 64 because it
5949 * is available in all reg domains.
5950 */
5951 p_ht_cap->advCodingCap = lim_get_rx_ldpc(mac_ctx, CHAN_ENUM_5320);
5952 /* Get self cap for HT40 support in 5G */
5953 if (mac_ctx->roam.configParam.channelBondingMode5GHz) {
5954 p_ht_cap->supportedChannelWidthSet = 1;
5955 p_ht_cap->shortGI40MHz = 1;
5956 } else {
5957 p_ht_cap->supportedChannelWidthSet = 0;
5958 p_ht_cap->shortGI40MHz = 0;
5959 }
5960 lim_populate_mcs_set_ht_per_vdev(mac_ctx, p_ht_cap, vdev_id,
5961 NSS_CHAINS_BAND_5GHZ);
5962 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HTCAPS,
5963 CDS_BAND_5GHZ, &ht_caps[2],
5964 DOT11F_IE_HTCAPS_MIN_LEN);
5965
5966 if (QDF_IS_STATUS_SUCCESS(status_2g) &&
5967 QDF_IS_STATUS_SUCCESS(status_5g))
5968 return QDF_STATUS_SUCCESS;
5969
5970 return QDF_STATUS_E_FAILURE;
5971 }
5972
5973 /**
5974 * lim_send_vht_caps_ie() - gets VHT capability and send to firmware via wma
5975 * @mac_ctx: global mac context
5976 * @device_mode: VDEV op mode
5977 * @vdev_id: vdev for which IE is targeted
5978 *
5979 * This function gets VHT capability and send to firmware via wma
5980 *
5981 * Return: QDF_STATUS
5982 */
lim_send_vht_caps_ie(struct mac_context * mac_ctx,enum QDF_OPMODE device_mode,uint8_t vdev_id)5983 static QDF_STATUS lim_send_vht_caps_ie(struct mac_context *mac_ctx,
5984 enum QDF_OPMODE device_mode,
5985 uint8_t vdev_id)
5986 {
5987 uint8_t vht_caps[DOT11F_IE_VHTCAPS_MAX_LEN + 2] = {0};
5988 bool vht_for_2g_enabled = false, nan_beamforming_supported;
5989 tSirMacVHTCapabilityInfo *p_vht_cap =
5990 (tSirMacVHTCapabilityInfo *)(&vht_caps[2]);
5991 QDF_STATUS status_5g, status_2g;
5992
5993 vht_caps[0] = DOT11F_EID_VHTCAPS;
5994 vht_caps[1] = DOT11F_IE_VHTCAPS_MAX_LEN;
5995 lim_set_vht_caps(mac_ctx, vht_caps, DOT11F_IE_VHTCAPS_MIN_LEN + 2);
5996 /*
5997 * Get LDPC and over write for 5G - using channel 64 because it
5998 * is available in all reg domains.
5999 */
6000 p_vht_cap->ldpcCodingCap = lim_get_rx_ldpc(mac_ctx, CHAN_ENUM_5320);
6001 lim_populate_mcs_set_vht_per_vdev(mac_ctx, vht_caps, vdev_id,
6002 NSS_CHAINS_BAND_5GHZ);
6003
6004 nan_beamforming_supported =
6005 ucfg_nan_is_beamforming_supported(mac_ctx->psoc);
6006 if (device_mode == QDF_NDI_MODE && !nan_beamforming_supported) {
6007 p_vht_cap->muBeamformeeCap = 0;
6008 p_vht_cap->muBeamformerCap = 0;
6009 p_vht_cap->suBeamformeeCap = 0;
6010 p_vht_cap->suBeamFormerCap = 0;
6011 }
6012 /*
6013 * Self VHT channel width for 5G is already negotiated
6014 * with FW
6015 */
6016 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_VHTCAPS,
6017 CDS_BAND_5GHZ, &vht_caps[2],
6018 DOT11F_IE_VHTCAPS_MIN_LEN);
6019 /* Send VHT CAP for 2.4G band based on CFG_ENABLE_VHT_FOR_24GHZ ini */
6020 ucfg_mlme_get_vht_for_24ghz(mac_ctx->psoc, &vht_for_2g_enabled);
6021
6022 if (!vht_for_2g_enabled)
6023 return status_5g;
6024
6025
6026 /* Get LDPC and over write for 2G */
6027 p_vht_cap->ldpcCodingCap = lim_get_rx_ldpc(mac_ctx, CHAN_ENUM_2437);
6028 /* Self VHT 80/160/80+80 channel width for 2G is 0 */
6029 p_vht_cap->supportedChannelWidthSet = 0;
6030 p_vht_cap->shortGI80MHz = 0;
6031 p_vht_cap->shortGI160and80plus80MHz = 0;
6032 lim_populate_mcs_set_vht_per_vdev(mac_ctx, vht_caps, vdev_id,
6033 NSS_CHAINS_BAND_2GHZ);
6034 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_VHTCAPS,
6035 CDS_BAND_2GHZ, &vht_caps[2],
6036 DOT11F_IE_VHTCAPS_MIN_LEN);
6037
6038 if (QDF_IS_STATUS_SUCCESS(status_2g) &&
6039 QDF_IS_STATUS_SUCCESS(status_5g))
6040 return QDF_STATUS_SUCCESS;
6041
6042 return QDF_STATUS_E_FAILURE;
6043 }
6044
lim_send_ies_per_band(struct mac_context * mac_ctx,uint8_t vdev_id,enum csr_cfgdot11mode dot11_mode,enum QDF_OPMODE device_mode)6045 QDF_STATUS lim_send_ies_per_band(struct mac_context *mac_ctx, uint8_t vdev_id,
6046 enum csr_cfgdot11mode dot11_mode,
6047 enum QDF_OPMODE device_mode)
6048 {
6049 QDF_STATUS status_ht = QDF_STATUS_SUCCESS;
6050 QDF_STATUS status_vht = QDF_STATUS_SUCCESS;
6051 QDF_STATUS status_he = QDF_STATUS_SUCCESS;
6052 QDF_STATUS status_eht = QDF_STATUS_SUCCESS;
6053
6054 /*
6055 * Note: Do not use Dot11f VHT structure, since 1 byte present flag in
6056 * it is causing weird padding errors. Instead use Sir Mac VHT struct
6057 * to send IE to wma.
6058 */
6059 if (is_dot11mode_support_ht_cap(dot11_mode))
6060 status_ht = lim_send_ht_caps_ie(mac_ctx, device_mode, vdev_id);
6061
6062 if (is_dot11mode_support_vht_cap(dot11_mode))
6063 status_vht = lim_send_vht_caps_ie(mac_ctx, device_mode, vdev_id);
6064
6065 if (is_dot11mode_support_he_cap(dot11_mode)) {
6066 status_he = lim_send_he_caps_ie(mac_ctx, device_mode, vdev_id);
6067
6068 if (QDF_IS_STATUS_SUCCESS(status_he))
6069 status_he = lim_send_he_6g_band_caps_ie(mac_ctx,
6070 vdev_id);
6071 }
6072
6073 if (is_dot11mode_support_eht_cap(dot11_mode)) {
6074 if ((device_mode == QDF_NAN_DISC_MODE ||
6075 device_mode == QDF_NDI_MODE) &&
6076 !wlan_nan_is_eht_capable(mac_ctx->psoc))
6077 goto end;
6078
6079 status_eht = lim_send_eht_caps_ie(mac_ctx, device_mode,
6080 vdev_id);
6081 }
6082
6083 end:
6084 if (QDF_IS_STATUS_SUCCESS(status_ht) &&
6085 QDF_IS_STATUS_SUCCESS(status_vht) &&
6086 QDF_IS_STATUS_SUCCESS(status_he) &&
6087 QDF_IS_STATUS_SUCCESS(status_eht))
6088 return QDF_STATUS_SUCCESS;
6089
6090 return QDF_STATUS_E_FAILURE;
6091 }
6092
6093 #ifdef WLAN_FEATURE_11AX
6094 static
lim_update_ext_cap_he_params(struct mac_context * mac_ctx,tDot11fIEExtCap * ext_cap_data,uint8_t vdev_id)6095 void lim_update_ext_cap_he_params(struct mac_context *mac_ctx,
6096 tDot11fIEExtCap *ext_cap_data,
6097 uint8_t vdev_id)
6098 {
6099 struct wlan_objmgr_vdev *vdev;
6100 struct mlme_legacy_priv *mlme_priv;
6101 tDot11fIEhe_cap *he_cap;
6102 struct s_ext_cap *p_ext_cap;
6103
6104 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
6105 WLAN_LEGACY_MAC_ID);
6106 if (!vdev)
6107 return;
6108
6109 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
6110 if (!mlme_priv) {
6111 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
6112 return;
6113 }
6114
6115 he_cap = &mlme_priv->he_config;
6116
6117 p_ext_cap = (struct s_ext_cap *)ext_cap_data->bytes;
6118 p_ext_cap->twt_requestor_support = he_cap->twt_request;
6119 p_ext_cap->twt_responder_support = he_cap->twt_responder;
6120 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
6121
6122 ext_cap_data->num_bytes = lim_compute_ext_cap_ie_length(ext_cap_data);
6123 }
6124
6125 /**
6126 * lim_update_ap_he_op() - update ap he op
6127 * @session: session
6128 * @ch_params: pointer to ch_params
6129 *
6130 * Return: void
6131 */
lim_update_ap_he_op(struct pe_session * session,struct ch_params * ch_params)6132 static void lim_update_ap_he_op(struct pe_session *session,
6133 struct ch_params *ch_params)
6134 {
6135 pe_debug("freq0: %d, freq1: %d, width: %d",
6136 ch_params->center_freq_seg0, ch_params->center_freq_seg1,
6137 ch_params->ch_width);
6138 if (session->he_op.vht_oper_present) {
6139 session->he_op.vht_oper.info.center_freq_seg0 =
6140 ch_params->center_freq_seg0;
6141 session->he_op.vht_oper.info.center_freq_seg1 =
6142 ch_params->center_freq_seg1;
6143 session->he_op.vht_oper.info.chan_width =
6144 ch_params->ch_width;
6145 } else if (session->he_6ghz_band) {
6146 session->he_op.oper_info_6g_present = 1;
6147 session->he_op.oper_info_6g.info.center_freq_seg0 =
6148 ch_params->center_freq_seg0;
6149 session->he_op.oper_info_6g.info.center_freq_seg1 =
6150 ch_params->center_freq_seg1;
6151 session->he_op.oper_info_6g.info.ch_width =
6152 ch_params->ch_width;
6153 }
6154 }
6155 #else
6156 static inline void
lim_update_ext_cap_he_params(struct mac_context * mac_ctx,tDot11fIEExtCap * ext_cap_data,uint8_t vdev_id)6157 lim_update_ext_cap_he_params(struct mac_context *mac_ctx,
6158 tDot11fIEExtCap *ext_cap_data,
6159 uint8_t vdev_id)
6160 {}
6161
lim_update_ap_he_op(struct pe_session * session,struct ch_params * ch_params)6162 static void lim_update_ap_he_op(struct pe_session *session,
6163 struct ch_params *ch_params)
6164 {}
6165 #endif
6166
6167 /**
6168 * lim_send_ext_cap_ie() - send ext cap IE to FW
6169 * @mac_ctx: global MAC context
6170 * @session_entry: PE session
6171 * @extra_extcap: extracted ext cap
6172 * @merge: merge extra ext cap
6173 *
6174 * This function is invoked after VDEV is created to update firmware
6175 * about the extended capabilities that the corresponding VDEV is capable
6176 * of. Since STA/SAP can have different Extended capabilities set, this function
6177 * is called per vdev creation.
6178 *
6179 * Return: QDF_STATUS
6180 */
lim_send_ext_cap_ie(struct mac_context * mac_ctx,uint32_t vdev_id,tDot11fIEExtCap * extra_extcap,bool merge)6181 QDF_STATUS lim_send_ext_cap_ie(struct mac_context *mac_ctx,
6182 uint32_t vdev_id,
6183 tDot11fIEExtCap *extra_extcap, bool merge)
6184 {
6185 tDot11fIEExtCap ext_cap_data = {0};
6186 uint32_t dot11mode, num_bytes;
6187 bool vht_enabled = false;
6188 struct vdev_ie_info *vdev_ie;
6189 struct scheduler_msg msg = {0};
6190 QDF_STATUS status;
6191 struct pe_session *session_entry;
6192
6193 dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode;
6194 if (IS_DOT11_MODE_VHT(dot11mode))
6195 vht_enabled = true;
6196
6197 status = populate_dot11f_ext_cap(mac_ctx, vht_enabled, &ext_cap_data,
6198 NULL);
6199 if (QDF_STATUS_SUCCESS != status) {
6200 pe_err("Failed to populate ext cap IE");
6201 return QDF_STATUS_E_FAILURE;
6202 }
6203
6204 lim_update_ext_cap_he_params(mac_ctx, &ext_cap_data, vdev_id);
6205 num_bytes = ext_cap_data.num_bytes;
6206
6207 if (merge && extra_extcap && extra_extcap->num_bytes > 0) {
6208 if (extra_extcap->num_bytes > ext_cap_data.num_bytes)
6209 num_bytes = extra_extcap->num_bytes;
6210 lim_merge_extcap_struct(&ext_cap_data, extra_extcap, true);
6211 }
6212
6213 /* After merging extcap, check whether disable btm bit require or not */
6214 session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
6215 if (session_entry)
6216 populate_dot11f_btm_extended_caps(mac_ctx, session_entry,
6217 &ext_cap_data);
6218
6219 /* Allocate memory for the WMI request, and copy the parameter */
6220 vdev_ie = qdf_mem_malloc(sizeof(*vdev_ie) + num_bytes);
6221 if (!vdev_ie)
6222 return QDF_STATUS_E_NOMEM;
6223
6224 vdev_ie->vdev_id = vdev_id;
6225 vdev_ie->ie_id = DOT11F_EID_EXTCAP;
6226 vdev_ie->length = num_bytes;
6227 vdev_ie->band = 0;
6228
6229 vdev_ie->data = (uint8_t *)vdev_ie + sizeof(*vdev_ie);
6230 qdf_mem_copy(vdev_ie->data, ext_cap_data.bytes, num_bytes);
6231
6232 msg.type = WMA_SET_IE_INFO;
6233 msg.bodyptr = vdev_ie;
6234 msg.reserved = 0;
6235
6236 if (QDF_STATUS_SUCCESS !=
6237 scheduler_post_message(QDF_MODULE_ID_PE,
6238 QDF_MODULE_ID_WMA,
6239 QDF_MODULE_ID_WMA, &msg)) {
6240 pe_err("Not able to post WMA_SET_IE_INFO to WDA");
6241 qdf_mem_free(vdev_ie);
6242 return QDF_STATUS_E_FAILURE;
6243 }
6244
6245 return QDF_STATUS_SUCCESS;
6246 }
6247
lim_strip_ie(struct mac_context * mac_ctx,uint8_t * addn_ie,uint16_t * addn_ielen,uint8_t eid,enum size_of_len_field size_of_len_field,uint8_t * oui,uint8_t oui_length,uint8_t * extracted_ie,uint32_t eid_max_len)6248 QDF_STATUS lim_strip_ie(struct mac_context *mac_ctx,
6249 uint8_t *addn_ie, uint16_t *addn_ielen,
6250 uint8_t eid, enum size_of_len_field size_of_len_field,
6251 uint8_t *oui, uint8_t oui_length, uint8_t *extracted_ie,
6252 uint32_t eid_max_len)
6253 {
6254 return wlan_strip_ie(addn_ie, addn_ielen, eid, size_of_len_field,
6255 oui, oui_length, extracted_ie, eid_max_len);
6256 }
6257
lim_del_pmf_sa_query_timer(struct mac_context * mac_ctx,struct pe_session * pe_session)6258 void lim_del_pmf_sa_query_timer(struct mac_context *mac_ctx, struct pe_session *pe_session)
6259 {
6260 uint32_t associated_sta;
6261 tpDphHashNode sta_ds = NULL;
6262
6263 for (associated_sta = 1;
6264 associated_sta <=
6265 mac_ctx->lim.max_sta_of_pe_session;
6266 associated_sta++) {
6267 sta_ds = dph_get_hash_entry(mac_ctx, associated_sta,
6268 &pe_session->dph.dphHashTable);
6269 if (!sta_ds)
6270 continue;
6271 if (!sta_ds->rmfEnabled) {
6272 pe_debug("no PMF timer for assoc-id:%d sta mac"
6273 QDF_MAC_ADDR_FMT, sta_ds->assocId,
6274 QDF_MAC_ADDR_REF(sta_ds->staAddr));
6275 continue;
6276 }
6277
6278 pe_debug("Deleting pmfSaQueryTimer for assoc-id:%d sta mac"
6279 QDF_MAC_ADDR_FMT, sta_ds->assocId,
6280 QDF_MAC_ADDR_REF(sta_ds->staAddr));
6281 tx_timer_deactivate(&sta_ds->pmfSaQueryTimer);
6282 tx_timer_delete(&sta_ds->pmfSaQueryTimer);
6283 }
6284 }
6285
lim_strip_supp_op_class_update_struct(struct mac_context * mac_ctx,uint8_t * addn_ie,uint16_t * addn_ielen,tDot11fIESuppOperatingClasses * dst)6286 QDF_STATUS lim_strip_supp_op_class_update_struct(struct mac_context *mac_ctx,
6287 uint8_t *addn_ie, uint16_t *addn_ielen,
6288 tDot11fIESuppOperatingClasses *dst)
6289 {
6290 uint8_t extracted_buff[DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN + 2];
6291 QDF_STATUS status;
6292
6293 qdf_mem_zero((uint8_t *)&extracted_buff[0],
6294 DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN + 2);
6295 status = lim_strip_ie(mac_ctx, addn_ie, addn_ielen,
6296 DOT11F_EID_SUPPOPERATINGCLASSES, ONE_BYTE,
6297 NULL, 0, extracted_buff,
6298 DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN);
6299 if (QDF_STATUS_SUCCESS != status) {
6300 pe_warn("Failed to strip supp_op_mode IE status: %d",
6301 status);
6302 return status;
6303 }
6304
6305 if (DOT11F_EID_SUPPOPERATINGCLASSES != extracted_buff[0] ||
6306 extracted_buff[1] > DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN) {
6307 pe_warn("Invalid IEs eid: %d elem_len: %d",
6308 extracted_buff[0], extracted_buff[1]);
6309 return QDF_STATUS_E_FAILURE;
6310 }
6311
6312 /* update the extracted supp op class to struct*/
6313 if (DOT11F_PARSE_SUCCESS != dot11f_unpack_ie_supp_operating_classes(
6314 mac_ctx, &extracted_buff[2], extracted_buff[1], dst, false)) {
6315 pe_err("dot11f_unpack Parse Error");
6316 return QDF_STATUS_E_FAILURE;
6317 }
6318
6319 return QDF_STATUS_SUCCESS;
6320 }
6321
lim_op_class_from_bandwidth(struct mac_context * mac_ctx,uint16_t channel_freq,enum phy_ch_width ch_bandwidth,enum offset_t offset)6322 uint8_t lim_op_class_from_bandwidth(struct mac_context *mac_ctx,
6323 uint16_t channel_freq,
6324 enum phy_ch_width ch_bandwidth,
6325 enum offset_t offset)
6326 {
6327 uint8_t op_class = 0;
6328 uint16_t ch_behav_limit = BEHAV_NONE;
6329 uint8_t channel;
6330
6331 if (ch_bandwidth == CH_WIDTH_40MHZ &&
6332 wlan_reg_is_24ghz_ch_freq(channel_freq)) {
6333 if (offset == BW40_LOW_PRIMARY)
6334 ch_behav_limit = BEHAV_BW40_LOW_PRIMARY;
6335 else
6336 ch_behav_limit = BEHAV_BW40_HIGH_PRIMARY;
6337 } else if (ch_bandwidth == CH_WIDTH_80P80MHZ) {
6338 ch_behav_limit = BEHAV_BW80_PLUS;
6339 }
6340 wlan_reg_freq_width_to_chan_op_class(mac_ctx->pdev, channel_freq,
6341 ch_width_in_mhz(ch_bandwidth),
6342 true, BIT(ch_behav_limit),
6343 &op_class, &channel);
6344
6345 return op_class;
6346 }
6347
6348 /**
6349 * lim_update_extcap_struct() - poputlate the dot11f structure
6350 * @mac_ctx: global MAC context
6351 * @buf: extracted IE buffer
6352 * @dst: extended capability IE structure to be updated
6353 *
6354 * This function is used to update the extended capability structure
6355 * with @buf.
6356 *
6357 * Return: None
6358 */
lim_update_extcap_struct(struct mac_context * mac_ctx,uint8_t * buf,tDot11fIEExtCap * dst)6359 void lim_update_extcap_struct(struct mac_context *mac_ctx,
6360 uint8_t *buf, tDot11fIEExtCap *dst)
6361 {
6362 uint8_t out[DOT11F_IE_EXTCAP_MAX_LEN];
6363 uint32_t status;
6364
6365 if (!buf) {
6366 pe_err("Invalid Buffer Address");
6367 return;
6368 }
6369
6370 if (!dst) {
6371 pe_err("NULL dst pointer");
6372 return;
6373 }
6374
6375 if (DOT11F_EID_EXTCAP != buf[0] || buf[1] > DOT11F_IE_EXTCAP_MAX_LEN) {
6376 pe_debug_rl("Invalid IEs eid: %d elem_len: %d", buf[0], buf[1]);
6377 return;
6378 }
6379
6380 qdf_mem_zero((uint8_t *)&out[0], DOT11F_IE_EXTCAP_MAX_LEN);
6381 qdf_mem_copy(&out[0], &buf[2], buf[1]);
6382
6383 status = dot11f_unpack_ie_ext_cap(mac_ctx, &out[0],
6384 buf[1], dst, false);
6385 if (DOT11F_PARSE_SUCCESS != status)
6386 pe_err("dot11f_unpack Parse Error %d", status);
6387 }
6388
6389 /**
6390 * lim_strip_extcap_update_struct - strip extended capability IE and populate
6391 * the dot11f structure
6392 * @mac_ctx: global MAC context
6393 * @addn_ie: Additional IE buffer
6394 * @addn_ielen: Length of additional IE
6395 * @dst: extended capability IE structure to be updated
6396 *
6397 * This function is used to strip extended capability IE from IE buffer and
6398 * update the passed structure.
6399 *
6400 * Return: QDF_STATUS
6401 */
lim_strip_extcap_update_struct(struct mac_context * mac_ctx,uint8_t * addn_ie,uint16_t * addn_ielen,tDot11fIEExtCap * dst)6402 QDF_STATUS lim_strip_extcap_update_struct(struct mac_context *mac_ctx,
6403 uint8_t *addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst)
6404 {
6405 uint8_t extracted_buff[DOT11F_IE_EXTCAP_MAX_LEN + 2];
6406 QDF_STATUS status;
6407
6408 qdf_mem_zero((uint8_t *)&extracted_buff[0],
6409 DOT11F_IE_EXTCAP_MAX_LEN + 2);
6410 status = lim_strip_ie(mac_ctx, addn_ie, addn_ielen,
6411 DOT11F_EID_EXTCAP, ONE_BYTE,
6412 NULL, 0, extracted_buff,
6413 DOT11F_IE_EXTCAP_MAX_LEN);
6414 if (QDF_STATUS_SUCCESS != status) {
6415 pe_debug("Failed to strip extcap IE status: %d", status);
6416 return status;
6417 }
6418
6419 /* update the extracted ExtCap to struct*/
6420 lim_update_extcap_struct(mac_ctx, extracted_buff, dst);
6421 return status;
6422 }
6423
6424 /**
6425 * lim_merge_extcap_struct() - merge extended capabilities info
6426 * @dst: destination extended capabilities
6427 * @src: source extended capabilities
6428 * @add: true if add the capabilities, false if strip the capabilities.
6429 *
6430 * This function is used to take @src info and add/strip it to/from
6431 * @dst extended capabilities info.
6432 *
6433 * Return: None
6434 */
lim_merge_extcap_struct(tDot11fIEExtCap * dst,tDot11fIEExtCap * src,bool add)6435 void lim_merge_extcap_struct(tDot11fIEExtCap *dst,
6436 tDot11fIEExtCap *src,
6437 bool add)
6438 {
6439 uint8_t *tempdst = (uint8_t *)dst->bytes;
6440 uint8_t *tempsrc = (uint8_t *)src->bytes;
6441 uint8_t structlen = member_size(tDot11fIEExtCap, bytes);
6442
6443 /* Return if @src not present */
6444 if (!src->present)
6445 return;
6446
6447 pe_debug("source extended capabilities length:%d", src->num_bytes);
6448 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
6449 src->bytes, src->num_bytes);
6450
6451 /* Return if strip the capabilities from @dst which not present */
6452 if (!dst->present && !add)
6453 return;
6454
6455 /* Merge the capabilities info in other cases */
6456 while (tempdst && tempsrc && structlen--) {
6457 if (add)
6458 *tempdst |= *tempsrc;
6459 else
6460 *tempdst &= *tempsrc;
6461 tempdst++;
6462 tempsrc++;
6463 }
6464 dst->num_bytes = lim_compute_ext_cap_ie_length(dst);
6465 if (dst->num_bytes == 0) {
6466 dst->present = 0;
6467 } else {
6468 dst->present = 1;
6469 pe_debug("destination extended capabilities length: %d",
6470 dst->num_bytes);
6471 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
6472 dst->bytes, dst->num_bytes);
6473 }
6474 }
6475
6476 /**
6477 * lim_send_action_frm_tb_ppdu_cfg_flush_cb() - flush TB PPDU cfg msg
6478 * @msg: Message pointer
6479 *
6480 * Flushes the send action frame in HE TB PPDU configuration message.
6481 *
6482 * Return: QDF_STATUS
6483 */
6484 static QDF_STATUS
lim_send_action_frm_tb_ppdu_cfg_flush_cb(struct scheduler_msg * msg)6485 lim_send_action_frm_tb_ppdu_cfg_flush_cb(struct scheduler_msg *msg)
6486 {
6487 if (msg->bodyptr) {
6488 qdf_mem_free(msg->bodyptr);
6489 msg->bodyptr = NULL;
6490 }
6491 return QDF_STATUS_SUCCESS;
6492 }
6493
lim_send_action_frm_tb_ppdu_cfg(struct mac_context * mac_ctx,uint32_t vdev_id,uint8_t cfg)6494 QDF_STATUS lim_send_action_frm_tb_ppdu_cfg(struct mac_context *mac_ctx,
6495 uint32_t vdev_id, uint8_t cfg)
6496 {
6497 tDot11fvendor_action_frame *frm;
6498 uint8_t frm_len = sizeof(*frm);
6499 struct pe_session *session;
6500 struct cfg_action_frm_tb_ppdu *cfg_msg;
6501 struct scheduler_msg msg = {0};
6502 uint8_t *data_buf;
6503
6504 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
6505 if (!session) {
6506 pe_err("pe session does not exist for vdev_id %d",
6507 vdev_id);
6508 return QDF_STATUS_E_FAILURE;
6509 }
6510
6511 data_buf = qdf_mem_malloc(frm_len + sizeof(*cfg_msg));
6512 if (!data_buf)
6513 return QDF_STATUS_E_FAILURE;
6514
6515 cfg_msg = (struct cfg_action_frm_tb_ppdu *)data_buf;
6516
6517 frm = (tDot11fvendor_action_frame *)(data_buf + sizeof(*cfg_msg));
6518
6519 frm->Category.category = ACTION_CATEGORY_VENDOR_SPECIFIC;
6520
6521 frm->vendor_oui.oui_data[0] = 0x00;
6522 frm->vendor_oui.oui_data[1] = 0xA0;
6523 frm->vendor_oui.oui_data[2] = 0xC6;
6524
6525 frm->vendor_action_subtype.subtype = 0xFF;
6526
6527 cfg_msg->vdev_id = vdev_id;
6528 cfg_msg->cfg = cfg;
6529 cfg_msg->frm_len = frm_len;
6530 cfg_msg->data = (uint8_t *)frm;
6531
6532 msg.type = WMA_CFG_VENDOR_ACTION_TB_PPDU;
6533 msg.bodyptr = cfg_msg;
6534 msg.reserved = 0;
6535 msg.flush_callback = lim_send_action_frm_tb_ppdu_cfg_flush_cb;
6536
6537 if (QDF_STATUS_SUCCESS !=
6538 scheduler_post_message(QDF_MODULE_ID_PE,
6539 QDF_MODULE_ID_WMA,
6540 QDF_MODULE_ID_WMA, &msg)) {
6541 pe_err("Not able to post WMA_SET_IE_INFO to WDA");
6542 qdf_mem_free(data_buf);
6543 return QDF_STATUS_E_FAILURE;
6544 }
6545
6546 return QDF_STATUS_SUCCESS;
6547 }
6548
6549 /**
6550 * lim_get_80Mhz_center_channel - finds 80 Mhz center channel
6551 *
6552 * @primary_channel: Primary channel for given 80 MHz band
6553 *
6554 * There are fixed 80MHz band and for each fixed band there is only one center
6555 * valid channel. Also location of primary channel decides what 80 MHz band will
6556 * it use, hence it decides what center channel will be used. This function
6557 * does thus calculation and returns the center channel.
6558 *
6559 * Return: center channel
6560 */
6561 uint8_t
lim_get_80Mhz_center_channel(uint8_t primary_channel)6562 lim_get_80Mhz_center_channel(uint8_t primary_channel)
6563 {
6564 if (primary_channel >= 36 && primary_channel <= 48)
6565 return (36+48)/2;
6566 if (primary_channel >= 52 && primary_channel <= 64)
6567 return (52+64)/2;
6568 if (primary_channel >= 100 && primary_channel <= 112)
6569 return (100+112)/2;
6570 if (primary_channel >= 116 && primary_channel <= 128)
6571 return (116+128)/2;
6572 if (primary_channel >= 132 && primary_channel <= 144)
6573 return (132+144)/2;
6574 if (primary_channel >= 149 && primary_channel <= 161)
6575 return (149+161)/2;
6576
6577 return INVALID_CHANNEL_ID;
6578 }
6579
6580 /**
6581 * lim_bss_type_to_string(): converts bss type enum to string.
6582 * @bss_type: enum value of bss_type.
6583 *
6584 * Return: Printable string for bss_type
6585 */
lim_bss_type_to_string(const uint16_t bss_type)6586 const char *lim_bss_type_to_string(const uint16_t bss_type)
6587 {
6588 switch (bss_type) {
6589 CASE_RETURN_STRING(eSIR_INFRASTRUCTURE_MODE);
6590 CASE_RETURN_STRING(eSIR_INFRA_AP_MODE);
6591 CASE_RETURN_STRING(eSIR_AUTO_MODE);
6592 CASE_RETURN_STRING(eSIR_NDI_MODE);
6593 default:
6594 return "Unknown bss_type";
6595 }
6596 }
6597
6598 /**
6599 * lim_init_obss_params(): Initializes the OBSS Scan Parameters
6600 * @session: LIM session
6601 * @mac_ctx: Mac context
6602 *
6603 * Return: None
6604 */
lim_init_obss_params(struct mac_context * mac_ctx,struct pe_session * session)6605 void lim_init_obss_params(struct mac_context *mac_ctx, struct pe_session *session)
6606 {
6607 struct wlan_mlme_obss_ht40 *obss_ht40;
6608
6609 if (!(mac_ctx->mlme_cfg)) {
6610 pe_err("invalid mlme cfg");
6611 return;
6612 }
6613
6614 obss_ht40 = &mac_ctx->mlme_cfg->obss_ht40;
6615
6616 session->obss_ht40_scanparam.obss_active_dwelltime =
6617 obss_ht40->active_dwelltime;
6618
6619 session->obss_ht40_scanparam.obss_passive_dwelltime =
6620 obss_ht40->passive_dwelltime;
6621
6622 session->obss_ht40_scanparam.obss_width_trigger_interval =
6623 obss_ht40->width_trigger_interval;
6624
6625 session->obss_ht40_scanparam.obss_active_total_per_channel =
6626 obss_ht40->active_per_channel;
6627
6628 session->obss_ht40_scanparam.obss_passive_total_per_channel =
6629 obss_ht40->passive_per_channel;
6630
6631 session->obss_ht40_scanparam.bsswidth_ch_trans_delay =
6632 obss_ht40->width_trans_delay;
6633
6634 session->obss_ht40_scanparam.obss_activity_threshold =
6635 obss_ht40->scan_activity_threshold;
6636 }
6637
6638 /**
6639 * lim_update_obss_scanparams(): Updates OBSS SCAN IE parameters to session
6640 * @session: LIM session
6641 * @scan_params: Scan parameters
6642 *
6643 * Return: None
6644 */
lim_update_obss_scanparams(struct pe_session * session,tDot11fIEOBSSScanParameters * scan_params)6645 void lim_update_obss_scanparams(struct pe_session *session,
6646 tDot11fIEOBSSScanParameters *scan_params)
6647 {
6648 /*
6649 * If the received value is not in the range specified
6650 * by the Specification then it will be the default value
6651 * configured through cfg
6652 */
6653 if ((scan_params->obssScanActiveDwell >
6654 cfg_min(CFG_OBSS_HT40_SCAN_ACTIVE_DWELL_TIME)) &&
6655 (scan_params->obssScanActiveDwell <
6656 cfg_max(CFG_OBSS_HT40_SCAN_ACTIVE_DWELL_TIME)))
6657 session->obss_ht40_scanparam.obss_active_dwelltime =
6658 scan_params->obssScanActiveDwell;
6659
6660 if ((scan_params->obssScanPassiveDwell >
6661 cfg_min(CFG_OBSS_HT40_SCAN_PASSIVE_DWELL_TIME)) &&
6662 (scan_params->obssScanPassiveDwell <
6663 cfg_max(CFG_OBSS_HT40_SCAN_PASSIVE_DWELL_TIME)))
6664 session->obss_ht40_scanparam.obss_passive_dwelltime =
6665 scan_params->obssScanPassiveDwell;
6666
6667 if ((scan_params->bssWidthChannelTransitionDelayFactor >
6668 cfg_min(CFG_OBSS_HT40_WIDTH_CH_TRANSITION_DELAY)) &&
6669 (scan_params->bssWidthChannelTransitionDelayFactor <
6670 cfg_max(CFG_OBSS_HT40_WIDTH_CH_TRANSITION_DELAY)))
6671 session->obss_ht40_scanparam.bsswidth_ch_trans_delay =
6672 scan_params->bssWidthChannelTransitionDelayFactor;
6673
6674 if ((scan_params->obssScanActiveTotalPerChannel >
6675 cfg_min(CFG_OBSS_HT40_SCAN_ACTIVE_TOTAL_PER_CHANNEL)) &&
6676 (scan_params->obssScanActiveTotalPerChannel <
6677 cfg_max(CFG_OBSS_HT40_SCAN_ACTIVE_TOTAL_PER_CHANNEL)))
6678 session->obss_ht40_scanparam.obss_active_total_per_channel =
6679 scan_params->obssScanActiveTotalPerChannel;
6680
6681 if ((scan_params->obssScanPassiveTotalPerChannel >
6682 cfg_min(CFG_OBSS_HT40_SCAN_PASSIVE_TOTAL_PER_CHANNEL)) &&
6683 (scan_params->obssScanPassiveTotalPerChannel <
6684 cfg_max(CFG_OBSS_HT40_SCAN_PASSIVE_TOTAL_PER_CHANNEL)))
6685 session->obss_ht40_scanparam.obss_passive_total_per_channel =
6686 scan_params->obssScanPassiveTotalPerChannel;
6687
6688 if ((scan_params->bssChannelWidthTriggerScanInterval >
6689 cfg_min(CFG_OBSS_HT40_SCAN_WIDTH_TRIGGER_INTERVAL)) &&
6690 (scan_params->bssChannelWidthTriggerScanInterval <
6691 cfg_max(CFG_OBSS_HT40_SCAN_WIDTH_TRIGGER_INTERVAL)))
6692 session->obss_ht40_scanparam.obss_width_trigger_interval =
6693 scan_params->bssChannelWidthTriggerScanInterval;
6694
6695 if ((scan_params->obssScanActivityThreshold >
6696 cfg_min(CFG_OBSS_HT40_SCAN_ACTIVITY_THRESHOLD)) &&
6697 (scan_params->obssScanActivityThreshold <
6698 cfg_max(CFG_OBSS_HT40_SCAN_ACTIVITY_THRESHOLD)))
6699 session->obss_ht40_scanparam.obss_activity_threshold =
6700 scan_params->obssScanActivityThreshold;
6701 return;
6702 }
6703
6704 /**
6705 * lim_compute_ext_cap_ie_length - compute the length of ext cap ie
6706 * based on the bits set
6707 * @ext_cap: extended IEs structure
6708 *
6709 * Return: length of the ext cap ie, 0 means should not present
6710 */
lim_compute_ext_cap_ie_length(tDot11fIEExtCap * ext_cap)6711 uint8_t lim_compute_ext_cap_ie_length(tDot11fIEExtCap *ext_cap)
6712 {
6713 uint8_t i = DOT11F_IE_EXTCAP_MAX_LEN;
6714
6715 while (i) {
6716 if (ext_cap->bytes[i-1])
6717 break;
6718 i--;
6719 }
6720
6721 return i;
6722 }
6723
6724 /**
6725 * lim_update_caps_info_for_bss - Update capability info for this BSS
6726 *
6727 * @mac_ctx: mac context
6728 * @caps: Pointer to capability info to be updated
6729 * @bss_caps: Capability info of the BSS
6730 *
6731 * Update the capability info in Assoc/Reassoc request frames and reset
6732 * the spectrum management, short preamble, immediate block ack bits
6733 * if the BSS does not support it
6734 *
6735 * Return: None
6736 */
lim_update_caps_info_for_bss(struct mac_context * mac_ctx,uint16_t * caps,uint16_t bss_caps)6737 void lim_update_caps_info_for_bss(struct mac_context *mac_ctx,
6738 uint16_t *caps, uint16_t bss_caps)
6739 {
6740 if (!(bss_caps & LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) {
6741 *caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK);
6742 pe_debug("Clearing spectrum management:no AP support");
6743 }
6744
6745 if (!(bss_caps & LIM_SHORT_PREAMBLE_BIT_MASK)) {
6746 *caps &= (~LIM_SHORT_PREAMBLE_BIT_MASK);
6747 pe_debug("Clearing short preamble:no AP support");
6748 }
6749
6750 if (!(bss_caps & LIM_IMMEDIATE_BLOCK_ACK_MASK)) {
6751 *caps &= (~LIM_IMMEDIATE_BLOCK_ACK_MASK);
6752 pe_debug("Clearing Immed Blk Ack:no AP support");
6753 }
6754 }
6755 /**
6756 * lim_send_set_dtim_period(): Send SIR_HAL_SET_DTIM_PERIOD message
6757 * to set dtim period.
6758 *
6759 * @session: LIM session
6760 * @dtim_period: dtim value
6761 * @mac_ctx: Mac context
6762 * @return None
6763 */
lim_send_set_dtim_period(struct mac_context * mac_ctx,uint8_t dtim_period,struct pe_session * session)6764 void lim_send_set_dtim_period(struct mac_context *mac_ctx, uint8_t dtim_period,
6765 struct pe_session *session)
6766 {
6767 struct set_dtim_params *dtim_params = NULL;
6768 QDF_STATUS ret = QDF_STATUS_SUCCESS;
6769 struct scheduler_msg msg = {0};
6770
6771 if (!session) {
6772 pe_err("Inavalid parameters");
6773 return;
6774 }
6775 dtim_params = qdf_mem_malloc(sizeof(*dtim_params));
6776 if (!dtim_params)
6777 return;
6778 dtim_params->dtim_period = dtim_period;
6779 dtim_params->session_id = session->smeSessionId;
6780 msg.type = WMA_SET_DTIM_PERIOD;
6781 msg.bodyptr = dtim_params;
6782 msg.bodyval = 0;
6783 pe_debug("Post WMA_SET_DTIM_PERIOD to WMA");
6784 ret = wma_post_ctrl_msg(mac_ctx, &msg);
6785 if (QDF_STATUS_SUCCESS != ret) {
6786 pe_err("wma_post_ctrl_msg() failed");
6787 qdf_mem_free(dtim_params);
6788 }
6789 }
6790
6791 /**
6792 * lim_is_valid_frame(): validate RX frame using last processed frame details
6793 * to find if it is duplicate frame.
6794 *
6795 * @last_processed_frm: last processed frame pointer.
6796 * @pRxPacketInfo: RX packet.
6797 *
6798 * Frame treat as duplicate:
6799 * if retry bit is set and
6800 * if source address and seq number matches with the last processed frame
6801 *
6802 * Return: false if duplicate frame, else true.
6803 */
lim_is_valid_frame(last_processed_msg * last_processed_frm,uint8_t * pRxPacketInfo)6804 bool lim_is_valid_frame(last_processed_msg *last_processed_frm,
6805 uint8_t *pRxPacketInfo)
6806 {
6807 uint16_t seq_num;
6808 tpSirMacMgmtHdr pHdr;
6809
6810 if (!pRxPacketInfo) {
6811 pe_err("Invalid RX frame");
6812 return false;
6813 }
6814
6815 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
6816
6817 if (pHdr->fc.retry == 0)
6818 return true;
6819
6820 seq_num = (((pHdr->seqControl.seqNumHi <<
6821 HIGH_SEQ_NUM_OFFSET) |
6822 pHdr->seqControl.seqNumLo));
6823
6824 if (last_processed_frm->seq_num == seq_num &&
6825 qdf_mem_cmp(last_processed_frm->sa, pHdr->sa, ETH_ALEN) == 0) {
6826 pe_err("Duplicate frame from "QDF_MAC_ADDR_FMT " Seq Number %d",
6827 QDF_MAC_ADDR_REF(pHdr->sa), seq_num);
6828 return false;
6829 }
6830 return true;
6831 }
6832
6833 /**
6834 * lim_update_last_processed_frame(): update new processed frame info to cache.
6835 *
6836 * @last_processed_frm: last processed frame pointer.
6837 * @pRxPacketInfo: Successfully processed RX packet.
6838 *
6839 * Return: None.
6840 */
lim_update_last_processed_frame(last_processed_msg * last_processed_frm,uint8_t * pRxPacketInfo)6841 void lim_update_last_processed_frame(last_processed_msg *last_processed_frm,
6842 uint8_t *pRxPacketInfo)
6843 {
6844 uint16_t seq_num;
6845 tpSirMacMgmtHdr pHdr;
6846
6847 if (!pRxPacketInfo) {
6848 pe_err("Invalid RX frame");
6849 return;
6850 }
6851
6852 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
6853 seq_num = (((pHdr->seqControl.seqNumHi <<
6854 HIGH_SEQ_NUM_OFFSET) |
6855 pHdr->seqControl.seqNumLo));
6856
6857 qdf_mem_copy(last_processed_frm->sa, pHdr->sa, ETH_ALEN);
6858 last_processed_frm->seq_num = seq_num;
6859 }
6860
6861 #if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX)
lim_support_6ghz_band_op_class(struct mac_context * mac_ctx,tDot11fIESuppOperatingClasses * op_class_ie)6862 static bool lim_support_6ghz_band_op_class(struct mac_context *mac_ctx,
6863 tDot11fIESuppOperatingClasses *
6864 op_class_ie)
6865 {
6866 uint16_t i;
6867
6868 if (!op_class_ie->present)
6869 return false;
6870 for (i = 0; i < op_class_ie->num_classes; i++) {
6871 if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
6872 op_class_ie->classes[i]))
6873 break;
6874 }
6875 if (i < op_class_ie->num_classes)
6876 return true;
6877
6878 return false;
6879 }
6880
lim_ap_check_6g_compatible_peer(struct mac_context * mac_ctx,struct pe_session * session)6881 void lim_ap_check_6g_compatible_peer(struct mac_context *mac_ctx,
6882 struct pe_session *session)
6883 {
6884 uint16_t i;
6885 tpDphHashNode sta_ds;
6886 bool legacy_client_present = false;
6887
6888 if (!LIM_IS_AP_ROLE(session))
6889 return;
6890
6891 for (i = 1; i < session->dph.dphHashTable.size; i++) {
6892 sta_ds = dph_get_hash_entry(mac_ctx, i,
6893 &session->dph.dphHashTable);
6894 if (!sta_ds)
6895 continue;
6896 if (sta_ds->staType != STA_ENTRY_PEER)
6897 continue;
6898 if (!lim_support_6ghz_band_op_class(
6899 mac_ctx, &sta_ds->supp_operating_classes)) {
6900 legacy_client_present = true;
6901 pe_debug("peer "QDF_MAC_ADDR_FMT" 6ghz not supported",
6902 QDF_MAC_ADDR_REF(sta_ds->staAddr));
6903 break;
6904 }
6905 pe_debug("peer "QDF_MAC_ADDR_FMT" 6ghz supported",
6906 QDF_MAC_ADDR_REF(sta_ds->staAddr));
6907 }
6908 if (legacy_client_present)
6909 policy_mgr_set_ap_6ghz_capable(
6910 mac_ctx->psoc, session->vdev_id, false,
6911 CONN_6GHZ_FLAG_NO_LEGACY_CLIENT);
6912 else
6913 policy_mgr_set_ap_6ghz_capable(
6914 mac_ctx->psoc, session->vdev_id, true,
6915 CONN_6GHZ_FLAG_NO_LEGACY_CLIENT);
6916 }
6917 #endif
6918
6919 #ifdef WLAN_FEATURE_11AX
lim_update_he_6ghz_band_caps(struct mac_context * mac,tDot11fIEhe_6ghz_band_cap * he_6ghz_band_cap,tpAddStaParams params)6920 void lim_update_he_6ghz_band_caps(struct mac_context *mac,
6921 tDot11fIEhe_6ghz_band_cap *he_6ghz_band_cap,
6922 tpAddStaParams params)
6923 {
6924 qdf_mem_copy(¶ms->he_6ghz_band_caps, he_6ghz_band_cap,
6925 sizeof(tDot11fIEhe_6ghz_band_cap));
6926
6927 lim_log_he_6g_cap(mac, ¶ms->he_6ghz_band_caps);
6928 }
6929
lim_add_he_cap(struct mac_context * mac_ctx,struct pe_session * pe_session,tpAddStaParams add_sta_params,tpSirAssocReq assoc_req)6930 void lim_add_he_cap(struct mac_context *mac_ctx, struct pe_session *pe_session,
6931 tpAddStaParams add_sta_params, tpSirAssocReq assoc_req)
6932 {
6933 if (!add_sta_params->he_capable || !assoc_req)
6934 return;
6935
6936 qdf_mem_copy(&add_sta_params->he_config, &assoc_req->he_cap,
6937 sizeof(add_sta_params->he_config));
6938
6939 if (lim_is_he_6ghz_band(pe_session))
6940 lim_update_he_6ghz_band_caps(mac_ctx,
6941 &assoc_req->he_6ghz_band_cap,
6942 add_sta_params);
6943
6944 }
6945
lim_add_self_he_cap(tpAddStaParams add_sta_params,struct pe_session * session)6946 void lim_add_self_he_cap(tpAddStaParams add_sta_params, struct pe_session *session)
6947 {
6948 if (!session)
6949 return;
6950
6951 add_sta_params->he_capable = true;
6952
6953 qdf_mem_copy(&add_sta_params->he_config, &session->he_config,
6954 sizeof(add_sta_params->he_config));
6955 qdf_mem_copy(&add_sta_params->he_op, &session->he_op,
6956 sizeof(add_sta_params->he_op));
6957 }
6958
lim_check_is_bss_greater_than_4_nss_supp(struct pe_session * session,tDot11fIEhe_cap * he_cap)6959 static bool lim_check_is_bss_greater_than_4_nss_supp(struct pe_session *session,
6960 tDot11fIEhe_cap *he_cap)
6961 {
6962 uint8_t i;
6963 uint16_t mcs_map;
6964 #define NSS_4 4
6965 #define NSS_8 8
6966
6967 if (!session->he_capable || !he_cap->present)
6968 return false;
6969 mcs_map = he_cap->rx_he_mcs_map_lt_80;
6970 for (i = NSS_4; i < NSS_8; i++) {
6971 if (((mcs_map >> (i * 2)) & 0x3) != 0x3)
6972 return true;
6973 }
6974
6975 return false;
6976 }
6977
lim_check_he_80_mcs11_supp(struct pe_session * session,tDot11fIEhe_cap * he_cap)6978 bool lim_check_he_80_mcs11_supp(struct pe_session *session,
6979 tDot11fIEhe_cap *he_cap)
6980 {
6981 uint16_t rx_mcs_map;
6982 uint16_t tx_mcs_map;
6983
6984 rx_mcs_map = he_cap->rx_he_mcs_map_lt_80;
6985 tx_mcs_map = he_cap->tx_he_mcs_map_lt_80;
6986 if ((session->nss == NSS_1x1_MODE) &&
6987 ((HE_GET_MCS_4_NSS(rx_mcs_map, 1) == HE_MCS_0_11) ||
6988 (HE_GET_MCS_4_NSS(tx_mcs_map, 1) == HE_MCS_0_11)))
6989 return true;
6990
6991 if ((session->nss == NSS_2x2_MODE) &&
6992 ((HE_GET_MCS_4_NSS(rx_mcs_map, 2) == HE_MCS_0_11) ||
6993 (HE_GET_MCS_4_NSS(tx_mcs_map, 2) == HE_MCS_0_11)))
6994 return true;
6995
6996 return false;
6997 }
6998
6999 /**
7000 * lim_check_he_ldpc_cap() - set he ldpc coding to one if
7001 * channel width is > 20 or mcs 10/11 bit are supported or
7002 * nss is greater than 4.
7003 * @beacon_struct: beacon structure
7004 * @session: A pointer to session entry.
7005 *
7006 * Return: None
7007 */
7008
lim_check_and_force_he_ldpc_cap(struct pe_session * session,tDot11fIEhe_cap * he_cap)7009 void lim_check_and_force_he_ldpc_cap(struct pe_session *session,
7010 tDot11fIEhe_cap *he_cap)
7011 {
7012 if (!he_cap->ldpc_coding &&
7013 (session->ch_width > CH_WIDTH_20MHZ ||
7014 lim_check_he_80_mcs11_supp(session, he_cap) ||
7015 lim_check_is_bss_greater_than_4_nss_supp(session, he_cap)))
7016 he_cap->ldpc_coding = 1;
7017 }
7018
7019 /**
7020 * lim_intersect_he_caps() - Intersect peer capability and self capability
7021 * @rcvd_he: pointer to received peer capability
7022 * @peer_he: pointer to Intersected capability
7023 * @session: A pointer to session entry.
7024 *
7025 * Return: None
7026 */
lim_intersect_he_caps(tDot11fIEhe_cap * rcvd_he,tDot11fIEhe_cap * peer_he,struct pe_session * session)7027 static void lim_intersect_he_caps(tDot11fIEhe_cap *rcvd_he,
7028 tDot11fIEhe_cap *peer_he,
7029 struct pe_session *session)
7030 {
7031 uint8_t val;
7032 tDot11fIEhe_cap *session_he = &session->he_config;
7033
7034 qdf_mem_copy(peer_he, rcvd_he, sizeof(*peer_he));
7035
7036 peer_he->fragmentation = QDF_MIN(session_he->fragmentation,
7037 peer_he->fragmentation);
7038
7039 peer_he->ldpc_coding &= session_he->ldpc_coding;
7040 lim_check_and_force_he_ldpc_cap(session, peer_he);
7041
7042 if (session_he->tb_ppdu_tx_stbc_lt_80mhz && peer_he->rx_stbc_lt_80mhz)
7043 peer_he->rx_stbc_lt_80mhz = 1;
7044 else
7045 peer_he->rx_stbc_lt_80mhz = 0;
7046
7047 if (session_he->rx_stbc_lt_80mhz && peer_he->tb_ppdu_tx_stbc_lt_80mhz)
7048 peer_he->tb_ppdu_tx_stbc_lt_80mhz = 1;
7049 else
7050 peer_he->tb_ppdu_tx_stbc_lt_80mhz = 0;
7051
7052 if (session_he->tb_ppdu_tx_stbc_gt_80mhz && peer_he->rx_stbc_gt_80mhz)
7053 peer_he->rx_stbc_gt_80mhz = 1;
7054 else
7055 peer_he->rx_stbc_gt_80mhz = 0;
7056
7057 if (session_he->rx_stbc_gt_80mhz && peer_he->tb_ppdu_tx_stbc_gt_80mhz)
7058 peer_he->tb_ppdu_tx_stbc_gt_80mhz = 1;
7059 else
7060 peer_he->tb_ppdu_tx_stbc_gt_80mhz = 0;
7061
7062 /* Tx Doppler is first bit and Rx Doppler is second bit */
7063 if (session_he->doppler) {
7064 val = 0;
7065 if ((session_he->doppler & 0x1) && (peer_he->doppler & 0x10))
7066 val |= (1 << 1);
7067 if ((session_he->doppler & 0x10) && (peer_he->doppler & 0x1))
7068 val |= (1 << 0);
7069 peer_he->doppler = val;
7070 }
7071
7072 peer_he->su_beamformer = session_he->su_beamformee ?
7073 peer_he->su_beamformer : 0;
7074 peer_he->su_beamformee = (session_he->su_beamformer ||
7075 session_he->mu_beamformer) ?
7076 peer_he->su_beamformee : 0;
7077 peer_he->mu_beamformer = session_he->su_beamformee ?
7078 peer_he->mu_beamformer : 0;
7079
7080 peer_he->twt_request = session_he->twt_responder ?
7081 peer_he->twt_request : 0;
7082 peer_he->twt_responder = session_he->twt_request ?
7083 peer_he->twt_responder : 0;
7084 }
7085
lim_intersect_sta_he_caps(struct mac_context * mac_ctx,tpSirAssocReq assoc_req,struct pe_session * session,tpDphHashNode sta_ds)7086 void lim_intersect_sta_he_caps(struct mac_context *mac_ctx,
7087 tpSirAssocReq assoc_req,
7088 struct pe_session *session,
7089 tpDphHashNode sta_ds)
7090 {
7091 tDot11fIEhe_cap *rcvd_he = &assoc_req->he_cap;
7092 tDot11fIEhe_cap *peer_he = &sta_ds->he_config;
7093 struct wlan_mlme_cfg *mlme_cfg = mac_ctx->mlme_cfg;
7094
7095 if (!sta_ds->mlmStaContext.he_capable)
7096 return;
7097
7098 /* If HE is not supported, do not fill sta_ds and return */
7099 if (!IS_DOT11_MODE_HE(session->dot11mode))
7100 return;
7101
7102 lim_intersect_he_caps(rcvd_he, peer_he, session);
7103
7104 if ((mlme_cfg->he_caps.disable_sap_mcs_12_13 &
7105 BIT(DISABLE_MCS_12_13_2G_40M)) &&
7106 LIM_IS_AP_ROLE(session) &&
7107 wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) &&
7108 session->ch_width == CH_WIDTH_40MHZ) {
7109 sta_ds->he_mcs_12_13_map = 0;
7110 return;
7111 }
7112
7113 /* If MCS 12/13 is supported from assoc QCN IE */
7114 if (assoc_req->qcn_ie.present &&
7115 assoc_req->qcn_ie.he_mcs13_attr.present) {
7116 sta_ds->he_mcs_12_13_map =
7117 assoc_req->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_80 |
7118 assoc_req->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_160 << 8;
7119 } else {
7120 return;
7121 }
7122
7123 /* Take intersection of FW capability for HE MCS 12/13 */
7124 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq))
7125 sta_ds->he_mcs_12_13_map &=
7126 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_2g;
7127 else
7128 sta_ds->he_mcs_12_13_map &=
7129 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_5g;
7130 }
7131
7132 static bool
lim_is_vendor_htc_he_ap(struct bss_description * bss_desc)7133 lim_is_vendor_htc_he_ap(struct bss_description *bss_desc)
7134 {
7135 struct action_oui_search_attr vendor_ap_search_attr = {0};
7136 uint16_t ie_len;
7137
7138 ie_len = wlan_get_ielen_from_bss_description(bss_desc);
7139
7140 vendor_ap_search_attr.ie_data = (uint8_t *)&bss_desc->ieFields[0];
7141 vendor_ap_search_attr.ie_length = ie_len;
7142
7143 return wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_BAD_HTC_HE_VENDOR_OUI1,
7144 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN,
7145 vendor_ap_search_attr.ie_data,
7146 ie_len) &&
7147 wlan_get_vendor_ie_ptr_from_oui(
7148 SIR_MAC_BAD_HTC_HE_VENDOR_OUI2,
7149 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN,
7150 vendor_ap_search_attr.ie_data,
7151 ie_len);
7152 }
7153
lim_intersect_ap_he_caps(struct pe_session * session,struct bss_params * add_bss,tSchBeaconStruct * beacon,tpSirAssocRsp assoc_rsp,struct bss_description * bss_desc)7154 void lim_intersect_ap_he_caps(struct pe_session *session,
7155 struct bss_params *add_bss,
7156 tSchBeaconStruct *beacon,
7157 tpSirAssocRsp assoc_rsp,
7158 struct bss_description *bss_desc)
7159 {
7160 tDot11fIEhe_cap *rcvd_he;
7161 tDot11fIEhe_cap *peer_he = &add_bss->staContext.he_config;
7162 bool vendor_ap_present = false;
7163
7164 if (assoc_rsp && assoc_rsp->he_cap.present)
7165 rcvd_he = &assoc_rsp->he_cap;
7166 else
7167 rcvd_he = &beacon->he_cap;
7168
7169 lim_intersect_he_caps(rcvd_he, peer_he, session);
7170 peer_he->htc_he = rcvd_he->htc_he;
7171 vendor_ap_present = lim_is_vendor_htc_he_ap(bss_desc);
7172 if (vendor_ap_present) {
7173 if (session->he_config.htc_he && peer_he->htc_he)
7174 peer_he->htc_he = 1;
7175 else
7176 peer_he->htc_he = 0;
7177 pe_debug("intersected htc he is: %d", peer_he->htc_he);
7178 }
7179
7180 pe_debug("HTC HE: self: %d recvd: %d, peer: %d",
7181 session->he_config.htc_he, rcvd_he->htc_he, peer_he->htc_he);
7182 add_bss->staContext.he_capable = true;
7183 }
7184
lim_add_bss_he_cap(struct bss_params * add_bss,tpSirAssocRsp assoc_rsp)7185 void lim_add_bss_he_cap(struct bss_params *add_bss, tpSirAssocRsp assoc_rsp)
7186 {
7187 tDot11fIEhe_cap *he_cap;
7188 tDot11fIEhe_op *he_op;
7189
7190 he_cap = &assoc_rsp->he_cap;
7191 he_op = &assoc_rsp->he_op;
7192 add_bss->he_capable = he_cap->present;
7193 if (he_cap)
7194 qdf_mem_copy(&add_bss->staContext.he_config,
7195 he_cap, sizeof(*he_cap));
7196 if (he_op)
7197 qdf_mem_copy(&add_bss->staContext.he_op,
7198 he_op, sizeof(*he_op));
7199 }
7200
lim_add_bss_he_cfg(struct bss_params * add_bss,struct pe_session * session)7201 void lim_add_bss_he_cfg(struct bss_params *add_bss, struct pe_session *session)
7202 {
7203 add_bss->he_sta_obsspd = session->he_sta_obsspd;
7204 }
7205
lim_update_he_6gop_assoc_resp(struct bss_params * pAddBssParams,tDot11fIEhe_op * he_op,struct pe_session * pe_session)7206 void lim_update_he_6gop_assoc_resp(struct bss_params *pAddBssParams,
7207 tDot11fIEhe_op *he_op,
7208 struct pe_session *pe_session)
7209 {
7210 if (!pe_session->he_6ghz_band)
7211 return;
7212
7213 if (!he_op->oper_info_6g_present) {
7214 pe_debug("6G operation info not present in beacon");
7215 return;
7216 }
7217 if (!pe_session->ch_width)
7218 return;
7219
7220 pAddBssParams->ch_width = QDF_MIN(he_op->oper_info_6g.info.ch_width,
7221 pe_session->ch_width);
7222
7223 if (pAddBssParams->ch_width == CH_WIDTH_160MHZ)
7224 pAddBssParams->ch_width = pe_session->ch_width;
7225 pAddBssParams->staContext.ch_width = pAddBssParams->ch_width;
7226 }
7227
lim_update_stads_he_caps(struct mac_context * mac_ctx,tpDphHashNode sta_ds,tpSirAssocRsp assoc_rsp,struct pe_session * session_entry,tSchBeaconStruct * beacon)7228 void lim_update_stads_he_caps(struct mac_context *mac_ctx,
7229 tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
7230 struct pe_session *session_entry,
7231 tSchBeaconStruct *beacon)
7232 {
7233 /* If HE is not supported, do not fill sta_ds and return */
7234 if (!IS_DOT11_MODE_HE(session_entry->dot11mode))
7235 goto out;
7236
7237 if (!assoc_rsp->he_cap.present && beacon && beacon->he_cap.present) {
7238 /* Use beacon HE caps if assoc resp doesn't have he caps */
7239 pe_debug("he_caps missing in assoc rsp");
7240 qdf_mem_copy(&assoc_rsp->he_cap, &beacon->he_cap,
7241 sizeof(tDot11fIEhe_cap));
7242 }
7243
7244 /* assoc resp and beacon doesn't have he caps */
7245 if (!assoc_rsp->he_cap.present)
7246 goto out;
7247
7248 sta_ds->mlmStaContext.he_capable = assoc_rsp->he_cap.present;
7249
7250 /* setting ldpc_coding if any of assoc_rsp or beacon has ldpc_coding
7251 * enabled
7252 */
7253 if (beacon)
7254 assoc_rsp->he_cap.ldpc_coding |= beacon->he_cap.ldpc_coding;
7255 lim_check_and_force_he_ldpc_cap(session_entry, &assoc_rsp->he_cap);
7256 if (beacon)
7257 beacon->he_cap.ldpc_coding = assoc_rsp->he_cap.ldpc_coding;
7258
7259 qdf_mem_copy(&sta_ds->he_config, &assoc_rsp->he_cap,
7260 sizeof(tDot11fIEhe_cap));
7261
7262 /* If MCS 12/13 is supported by the assoc resp QCN IE */
7263 if (assoc_rsp->qcn_ie.present &&
7264 assoc_rsp->qcn_ie.he_mcs13_attr.present) {
7265 sta_ds->he_mcs_12_13_map =
7266 assoc_rsp->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_80 |
7267 assoc_rsp->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_160 << 8;
7268 }
7269
7270 /* Take intersection of the FW capability for HE MCS 12/13 */
7271 if (wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq))
7272 sta_ds->he_mcs_12_13_map &=
7273 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_2g;
7274 else
7275 sta_ds->he_mcs_12_13_map &=
7276 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_5g;
7277 out:
7278 pe_debug("he_mcs_12_13_map: sta_ds 0x%x, 2g_fw 0x%x, 5g_fw 0x%x",
7279 sta_ds->he_mcs_12_13_map,
7280 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_2g,
7281 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_5g);
7282 lim_update_he_mcs_12_13_map(mac_ctx->psoc,
7283 session_entry->smeSessionId,
7284 sta_ds->he_mcs_12_13_map);
7285
7286 }
7287
lim_update_stads_he_6ghz_op(struct pe_session * session,tpDphHashNode sta_ds)7288 void lim_update_stads_he_6ghz_op(struct pe_session *session,
7289 tpDphHashNode sta_ds)
7290 {
7291 tDot11fIEhe_cap *peer_he = &sta_ds->he_config;
7292 enum phy_ch_width ch_width;
7293
7294 if (!session->he_6ghz_band)
7295 return;
7296
7297 if (!peer_he->present) {
7298 pe_debug("HE cap not present in peer");
7299 return;
7300 }
7301
7302 if (peer_he->chan_width_3)
7303 ch_width = CH_WIDTH_80P80MHZ;
7304 else if (peer_he->chan_width_2)
7305 ch_width = CH_WIDTH_160MHZ;
7306 else if (peer_he->chan_width_1)
7307 ch_width = CH_WIDTH_80MHZ;
7308 else
7309 ch_width = CH_WIDTH_20MHZ;
7310 if (ch_width > session->ch_width)
7311 ch_width = session->ch_width;
7312 sta_ds->ch_width = ch_width;
7313 }
7314
lim_update_usr_he_cap(struct mac_context * mac_ctx,struct pe_session * session)7315 void lim_update_usr_he_cap(struct mac_context *mac_ctx, struct pe_session *session)
7316 {
7317 struct add_ie_params *add_ie = &session->add_ie_params;
7318 tDot11fIEhe_cap *he_cap = &session->he_config;
7319 struct he_cap_network_endian *he_cap_from_ie;
7320 uint8_t extracted_buff[DOT11F_IE_HE_CAP_MAX_LEN + 2];
7321 QDF_STATUS status;
7322 struct wlan_vht_config *vht_cfg = &session->vht_config;
7323 struct mlme_legacy_priv *mlme_priv;
7324
7325 qdf_mem_zero(extracted_buff, sizeof(extracted_buff));
7326 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
7327 &add_ie->probeRespBCNDataLen,
7328 DOT11F_EID_HE_CAP, ONE_BYTE,
7329 HE_CAP_OUI_TYPE, (uint8_t)HE_CAP_OUI_SIZE,
7330 extracted_buff, DOT11F_IE_HE_CAP_MAX_LEN);
7331 if (QDF_STATUS_SUCCESS != status) {
7332 pe_debug("Failed to strip HE cap IE status: %d", status);
7333 return;
7334 }
7335
7336 pe_debug("Before update: su_beamformer: %d, su_beamformee: %d, mu_beamformer: %d",
7337 he_cap->su_beamformer, he_cap->su_beamformee, he_cap->mu_beamformer);
7338
7339 he_cap_from_ie = (struct he_cap_network_endian *)
7340 &extracted_buff[HE_CAP_OUI_SIZE + 2];
7341
7342 he_cap->su_beamformer =
7343 he_cap->su_beamformer & he_cap_from_ie->su_beamformer;
7344 he_cap->su_beamformee =
7345 he_cap->su_beamformee & he_cap_from_ie->su_beamformee;
7346 he_cap->mu_beamformer =
7347 he_cap->mu_beamformer & he_cap_from_ie->mu_beamformer;
7348
7349 pe_debug("After update: su_beamformer: %d, su_beamformee: %d, mu_beamformer: %d",
7350 he_cap->su_beamformer, he_cap->su_beamformee, he_cap->mu_beamformer);
7351 if (!he_cap->su_beamformer) {
7352 he_cap->mu_beamformer = 0;
7353 he_cap->num_sounding_lt_80 = 0;
7354 he_cap->num_sounding_gt_80 = 0;
7355 vht_cfg->su_beam_former = 0;
7356 vht_cfg->mu_beam_former = 0;
7357 vht_cfg->num_soundingdim = 0;
7358 }
7359 if (!he_cap->su_beamformee) {
7360 he_cap->bfee_sts_lt_80 = 0;
7361 he_cap->bfee_sts_gt_80 = 0;
7362 vht_cfg->su_beam_formee = 0;
7363 vht_cfg->mu_beam_formee = 0;
7364 vht_cfg->csnof_beamformer_antSup = 0;
7365 }
7366
7367 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
7368 if (mlme_priv) {
7369 mlme_priv->he_config.mu_beamformer = he_cap->mu_beamformer;
7370 mlme_priv->he_config.su_beamformer = he_cap->su_beamformer;
7371 mlme_priv->he_config.su_beamformee = he_cap->su_beamformee;
7372 mlme_priv->he_config.bfee_sts_lt_80 = he_cap->bfee_sts_lt_80;
7373 mlme_priv->he_config.bfee_sts_gt_80 = he_cap->bfee_sts_gt_80;
7374 mlme_priv->he_config.num_sounding_lt_80 =
7375 he_cap->num_sounding_lt_80;
7376 mlme_priv->he_config.num_sounding_gt_80 =
7377 he_cap->num_sounding_gt_80;
7378 }
7379 wma_set_he_txbf_params(session->vdev_id, he_cap->su_beamformer,
7380 he_cap->su_beamformee, he_cap->mu_beamformer);
7381 }
7382
lim_decide_he_op(struct mac_context * mac_ctx,uint32_t * mlme_he_ops,struct pe_session * session)7383 void lim_decide_he_op(struct mac_context *mac_ctx, uint32_t *mlme_he_ops,
7384 struct pe_session *session)
7385 {
7386 uint32_t val;
7387 uint8_t color;
7388 struct he_ops_network_endian *he_ops_from_ie;
7389 tDot11fIEhe_op he_ops = {0};
7390 struct add_ie_params *add_ie = &session->add_ie_params;
7391 uint8_t extracted_buff[DOT11F_IE_HE_OP_MAX_LEN + 2];
7392 QDF_STATUS status;
7393
7394 qdf_mem_zero(extracted_buff, sizeof(extracted_buff));
7395 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
7396 &add_ie->probeRespBCNDataLen,
7397 DOT11F_EID_HE_OP, ONE_BYTE,
7398 HE_OP_OUI_TYPE, (uint8_t)HE_OP_OUI_SIZE,
7399 extracted_buff, DOT11F_IE_HE_OP_MAX_LEN);
7400 if (QDF_STATUS_SUCCESS != status) {
7401 pe_debug("Failed to strip HE OP IE status: %d", status);
7402 return;
7403 }
7404 he_ops_from_ie = (struct he_ops_network_endian *)
7405 &extracted_buff[HE_OP_OUI_SIZE + 2];
7406
7407 if (he_ops_from_ie->bss_color) {
7408 he_ops.bss_color = he_ops_from_ie->bss_color;
7409 } else {
7410 qdf_get_random_bytes(&color, sizeof(color));
7411 /* make sure color is within 1-63*/
7412 he_ops.bss_color = (color % WNI_CFG_HE_OPS_BSS_COLOR_MAX) + 1;
7413 }
7414 he_ops.default_pe = he_ops_from_ie->default_pe;
7415 he_ops.twt_required = he_ops_from_ie->twt_required;
7416 he_ops.txop_rts_threshold = he_ops_from_ie->txop_rts_threshold;
7417 he_ops.partial_bss_col = he_ops_from_ie->partial_bss_col;
7418
7419 val = mac_ctx->mlme_cfg->he_caps.he_ops_basic_mcs_nss;
7420
7421 *((uint16_t *)he_ops.basic_mcs_nss) = (uint16_t)val;
7422
7423 qdf_mem_copy(&session->he_op, &he_ops, sizeof(tDot11fIEhe_op));
7424
7425 pe_debug("HE Op: bss_color: 0x%0x, default_pe_duration: 0x%0x",
7426 he_ops.bss_color, he_ops.default_pe);
7427 pe_debug("He Op: twt_required: 0x%0x, txop_rts_threshold: 0x%0x",
7428 he_ops.twt_required, he_ops.txop_rts_threshold);
7429 pe_debug("HE Op: partial_bss_color: 0x%0x",
7430 he_ops.partial_bss_col);
7431 pe_debug("HE Op: BSS color disabled: 0x%0x",
7432 he_ops.bss_col_disabled);
7433 pe_debug("HE Op: Basic MCS NSS: 0x%04x",
7434 *((uint16_t *)he_ops.basic_mcs_nss));
7435
7436 wma_update_vdev_he_ops(mlme_he_ops, &he_ops);
7437 }
7438
lim_update_he_caps_mcs(struct mac_context * mac,struct pe_session * session)7439 void lim_update_he_caps_mcs(struct mac_context *mac, struct pe_session *session)
7440 {
7441 uint32_t tx_mcs_map = 0;
7442 uint32_t rx_mcs_map = 0;
7443 uint32_t mcs_map = 0;
7444 struct wlan_objmgr_vdev *vdev = session->vdev;
7445 struct mlme_legacy_priv *mlme_priv;
7446 struct wlan_mlme_cfg *mlme_cfg = mac->mlme_cfg;
7447
7448 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
7449 if (!mlme_priv)
7450 return;
7451
7452 rx_mcs_map = mlme_cfg->he_caps.dot11_he_cap.rx_he_mcs_map_lt_80;
7453 tx_mcs_map = mlme_cfg->he_caps.dot11_he_cap.tx_he_mcs_map_lt_80;
7454 mcs_map = rx_mcs_map & 0x3;
7455
7456 if (session->nss == 1) {
7457 tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, HE_MCS_DISABLE, 2);
7458 rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, HE_MCS_DISABLE, 2);
7459 } else {
7460 tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, mcs_map, 2);
7461 rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, mcs_map, 2);
7462 }
7463
7464 mlme_priv->he_config.tx_he_mcs_map_lt_80 = tx_mcs_map;
7465 mlme_priv->he_config.rx_he_mcs_map_lt_80 = rx_mcs_map;
7466 *((uint16_t *)mlme_priv->he_config.tx_he_mcs_map_160) = tx_mcs_map;
7467 *((uint16_t *)mlme_priv->he_config.rx_he_mcs_map_160) = rx_mcs_map;
7468 qdf_mem_copy(mlme_priv->he_config.tx_he_mcs_map_160, &tx_mcs_map,
7469 sizeof(u_int16_t));
7470 qdf_mem_copy(mlme_priv->he_config.rx_he_mcs_map_160, &rx_mcs_map,
7471 sizeof(u_int16_t));
7472 }
7473
7474 static void
lim_revise_req_he_cap_per_band(struct mlme_legacy_priv * mlme_priv,struct pe_session * session)7475 lim_revise_req_he_cap_per_band(struct mlme_legacy_priv *mlme_priv,
7476 struct pe_session *session)
7477 {
7478 struct mac_context *mac = session->mac_ctx;
7479 tDot11fIEhe_cap *he_config;
7480 struct wlan_objmgr_psoc *psoc;
7481 uint32_t max_ampdu_len_exp;
7482
7483 psoc = wlan_vdev_get_psoc(session->vdev);
7484 if (!psoc) {
7485 pe_err("Failed to get psoc");
7486 return;
7487 }
7488 max_ampdu_len_exp = cfg_get(psoc, CFG_HE_MAX_AMPDU_LEN);
7489
7490 he_config = &mlme_priv->he_config;
7491 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) {
7492 he_config->bfee_sts_lt_80 =
7493 mac->he_cap_2g.bfee_sts_lt_80;
7494 he_config->tx_he_mcs_map_lt_80 =
7495 mac->he_cap_2g.tx_he_mcs_map_lt_80;
7496 he_config->rx_he_mcs_map_lt_80 =
7497 mac->he_cap_2g.rx_he_mcs_map_lt_80;
7498 he_config->max_ampdu_len_exp_ext =
7499 QDF_MIN(max_ampdu_len_exp,
7500 mac->he_cap_2g.max_ampdu_len_exp_ext);
7501 he_config->ul_2x996_tone_ru_supp = 0;
7502 he_config->num_sounding_gt_80 = 0;
7503 he_config->bfee_sts_gt_80 = 0;
7504 he_config->tb_ppdu_tx_stbc_gt_80mhz = 0;
7505 he_config->rx_stbc_gt_80mhz = 0;
7506 he_config->he_ppdu_20_in_160_80p80Mhz = 0;
7507 he_config->he_ppdu_80_in_160_80p80Mhz = 0;
7508 } else {
7509 he_config->bfee_sts_lt_80 =
7510 mac->he_cap_5g.bfee_sts_lt_80;
7511 he_config->tx_he_mcs_map_lt_80 =
7512 mac->he_cap_5g.tx_he_mcs_map_lt_80;
7513 he_config->rx_he_mcs_map_lt_80 =
7514 mac->he_cap_5g.rx_he_mcs_map_lt_80;
7515
7516 he_config->num_sounding_lt_80 =
7517 mac->he_cap_5g.num_sounding_lt_80;
7518 he_config->max_ampdu_len_exp_ext =
7519 QDF_MIN(max_ampdu_len_exp,
7520 mac->he_cap_5g.max_ampdu_len_exp_ext);
7521 if (he_config->chan_width_2 ||
7522 he_config->chan_width_3) {
7523 he_config->bfee_sts_gt_80 =
7524 mac->he_cap_5g.bfee_sts_gt_80;
7525 he_config->num_sounding_gt_80 =
7526 mac->he_cap_5g.num_sounding_gt_80;
7527 he_config->he_ppdu_20_in_160_80p80Mhz =
7528 mac->he_cap_5g.he_ppdu_20_in_160_80p80Mhz;
7529 he_config->he_ppdu_80_in_160_80p80Mhz =
7530 mac->he_cap_5g.he_ppdu_80_in_160_80p80Mhz;
7531 he_config->rx_stbc_gt_80mhz =
7532 mac->he_cap_5g.rx_stbc_gt_80mhz;
7533 he_config->tb_ppdu_tx_stbc_gt_80mhz =
7534 mac->he_cap_5g.tb_ppdu_tx_stbc_gt_80mhz;
7535 he_config->ul_2x996_tone_ru_supp =
7536 mac->he_cap_5g.ul_2x996_tone_ru_supp;
7537 }
7538 he_config->su_feedback_tone16 =
7539 mac->he_cap_5g.su_feedback_tone16;
7540 he_config->mu_feedback_tone16 =
7541 mac->he_cap_5g.mu_feedback_tone16;
7542 he_config->codebook_su = mac->he_cap_5g.codebook_su;
7543 he_config->codebook_mu = mac->he_cap_5g.codebook_mu;
7544 }
7545 }
7546
lim_copy_bss_he_cap(struct pe_session * session)7547 void lim_copy_bss_he_cap(struct pe_session *session)
7548 {
7549 struct mlme_legacy_priv *mlme_priv;
7550
7551 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
7552 if (!mlme_priv)
7553 return;
7554 lim_revise_req_he_cap_per_band(mlme_priv, session);
7555 lim_update_he_caps_mcs(session->mac_ctx, session);
7556 qdf_mem_copy(&(session->he_config), &(mlme_priv->he_config),
7557 sizeof(session->he_config));
7558 }
7559
lim_copy_join_req_he_cap(struct pe_session * session)7560 void lim_copy_join_req_he_cap(struct pe_session *session)
7561 {
7562 struct mlme_legacy_priv *mlme_priv;
7563
7564 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
7565 if (!mlme_priv)
7566 return;
7567 if (!session->mac_ctx->usr_cfg_tx_bfee_nsts)
7568 lim_revise_req_he_cap_per_band(mlme_priv, session);
7569 qdf_mem_copy(&(session->he_config), &(mlme_priv->he_config),
7570 sizeof(session->he_config));
7571 if (WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq)) {
7572 session->he_config.chan_width_1 = 0;
7573 session->he_config.chan_width_2 = 0;
7574 session->he_config.chan_width_3 = 0;
7575 session->he_config.chan_width_5 = 0;
7576 session->he_config.chan_width_6 = 0;
7577 } else {
7578 session->he_config.chan_width_0 = 0;
7579 session->he_config.chan_width_4 = 0;
7580 session->he_config.chan_width_6 = 0;
7581 }
7582 }
7583
lim_log_he_cap(struct mac_context * mac,tDot11fIEhe_cap * he_cap)7584 void lim_log_he_cap(struct mac_context *mac, tDot11fIEhe_cap *he_cap)
7585 {
7586 uint8_t chan_width;
7587 struct ppet_hdr *hdr;
7588
7589 if (!he_cap->present)
7590 return;
7591
7592 pe_nofl_debug("HE Capabilities: htc_he 0x%x twt_req 0x%x twt_res 0x%x fragmentation 0x%x max frag msdu amsdu 0x%x min frag 0x%x",
7593 he_cap->htc_he, he_cap->twt_request,
7594 he_cap->twt_responder, he_cap->fragmentation,
7595 he_cap->max_num_frag_msdu_amsdu_exp,
7596 he_cap->min_frag_size);
7597 pe_nofl_debug("\ttrig frm mac pad 0x%x multi tid aggr supp 0x%x link adaptation 0x%x all ack 0x%x trigd_rsp_sched 0x%x a_bsr 0x%x",
7598 he_cap->trigger_frm_mac_pad,
7599 he_cap->multi_tid_aggr_rx_supp,
7600 he_cap->he_link_adaptation, he_cap->all_ack,
7601 he_cap->trigd_rsp_sched, he_cap->a_bsr);
7602 pe_nofl_debug("\tBC twt 0x%x ba_32bit_bitmap supp 0x%x mu_cascade 0x%x ack_enabled_multitid 0x%x omi_a_ctrl 0x%x ofdma_ra 0x%x",
7603 he_cap->broadcast_twt, he_cap->ba_32bit_bitmap,
7604 he_cap->mu_cascade, he_cap->ack_enabled_multitid,
7605 he_cap->omi_a_ctrl, he_cap->ofdma_ra);
7606 pe_nofl_debug("\tmax_ampdu_len exp ext 0x%x amsdu_frag 0x%x flex_twt_sched 0x%x rx_ctrl frm 0x%x bsrp_ampdu_aggr 0x%x qtp 0x%x a_bqr 0x%x",
7607 he_cap->max_ampdu_len_exp_ext, he_cap->amsdu_frag,
7608 he_cap->flex_twt_sched, he_cap->rx_ctrl_frame,
7609 he_cap->bsrp_ampdu_aggr, he_cap->qtp, he_cap->a_bqr);
7610 pe_nofl_debug("\tSR Reponder 0x%x ndp_feedback 0x%x ops_supp 0x%x amsdu_in_ampdu 0x%x multi_tid_aggr_tx 0x%x he_sub_ch_sel_tx 0x%x",
7611 he_cap->spatial_reuse_param_rspder,
7612 he_cap->ndp_feedback_supp,
7613 he_cap->ops_supp, he_cap->amsdu_in_ampdu,
7614 he_cap->multi_tid_aggr_tx_supp,
7615 he_cap->he_sub_ch_sel_tx_supp);
7616
7617 pe_nofl_debug("\tul_2x996_tone_ru 0x%x om_ctrl_ul_mu_data_dis_rx 0x%x dynamic_smps 0x%x punctured_sounding 0x%x ht_vht_trg_frm_rx 0x%x",
7618 he_cap->ul_2x996_tone_ru_supp,
7619 he_cap->om_ctrl_ul_mu_data_dis_rx,
7620 he_cap->he_dynamic_smps, he_cap->punctured_sounding_supp,
7621 he_cap->ht_vht_trg_frm_rx_supp);
7622
7623 chan_width = HE_CH_WIDTH_COMBINE(he_cap->chan_width_0,
7624 he_cap->chan_width_1, he_cap->chan_width_2,
7625 he_cap->chan_width_3, he_cap->chan_width_4,
7626 he_cap->chan_width_5, he_cap->chan_width_6);
7627
7628 pe_nofl_debug("\tchan width %d rx_pream_puncturing 0x%x device_class 0x%x ldpc_coding 0x%x 1x_ltf_800_gi_ppdu 0x%x midamble_tx_rx_max_nsts 0x%x",
7629 chan_width, he_cap->rx_pream_puncturing,
7630 he_cap->device_class,
7631 he_cap->ldpc_coding, he_cap->he_1x_ltf_800_gi_ppdu,
7632 he_cap->midamble_tx_rx_max_nsts);
7633
7634 pe_nofl_debug("\t4x_ltf_3200_gi_ndp 0x%x tb_ppdu_tx_stbc_lt_80mhz 0x%x rx_stbc_lt_80mhz 0x%x doppler 0x%x ul_mu 0x%x dcm_enc_tx 0x%x dcm_enc_rx 0x%x",
7635 he_cap->he_4x_ltf_3200_gi_ndp,
7636 he_cap->tb_ppdu_tx_stbc_lt_80mhz,
7637 he_cap->rx_stbc_lt_80mhz, he_cap->doppler, he_cap->ul_mu,
7638 he_cap->dcm_enc_tx, he_cap->dcm_enc_rx);
7639
7640 pe_nofl_debug("\tul_he_mu 0x%x su_bfer 0x%x su_fee 0x%x mu_bfer 0x%x bfee_sts_lt_80 0x%x bfee_sts_gt_80 0x%x num_sd_lt_80 0x%x num_sd_gt_80 0x%x",
7641 he_cap->ul_he_mu, he_cap->su_beamformer,
7642 he_cap->su_beamformee,
7643 he_cap->mu_beamformer, he_cap->bfee_sts_lt_80,
7644 he_cap->bfee_sts_gt_80, he_cap->num_sounding_lt_80,
7645 he_cap->num_sounding_gt_80);
7646
7647 pe_nofl_debug("\tsu_fb_tone16 0x%x mu_fb_tone16 0x%x codebook_su 0x%x codebook_mu 0x%x bforming_feedback 0x%x he_er_su_ppdu 0x%x dl_mu_mimo_part_bw 0x%x",
7648 he_cap->su_feedback_tone16, he_cap->mu_feedback_tone16,
7649 he_cap->codebook_su, he_cap->codebook_mu,
7650 he_cap->beamforming_feedback, he_cap->he_er_su_ppdu,
7651 he_cap->dl_mu_mimo_part_bw);
7652
7653 pe_nofl_debug("\tppet_present 0x%x srp 0x%x power_boost 0x%x ltf_800_gi_4x 0x%x tb_ppdu_tx_stbc_gt_80mhz 0x%x rx_stbc_gt_80mhz 0x%x max_nc 0x%x",
7654 he_cap->ppet_present, he_cap->srp,
7655 he_cap->power_boost, he_cap->he_ltf_800_gi_4x,
7656 he_cap->tb_ppdu_tx_stbc_gt_80mhz,
7657 he_cap->rx_stbc_gt_80mhz, he_cap->max_nc);
7658
7659 pe_nofl_debug("\ter_ltf_800_gi_4x 0x%x ppdu_20_in_40Mhz_2G 0x%x ppdu_20_in_160_80p80Mhz 0x%x ppdu_80_in_160_80p80Mhz 0x%x er_1x_ltf_gi 0x%x",
7660 he_cap->er_he_ltf_800_gi_4x,
7661 he_cap->he_ppdu_20_in_40Mhz_2G,
7662 he_cap->he_ppdu_20_in_160_80p80Mhz,
7663 he_cap->he_ppdu_80_in_160_80p80Mhz,
7664 he_cap->er_1x_he_ltf_gi);
7665
7666 pe_nofl_debug("\tmidamble_tx_rx_1x_ltf 0x%x dcm_max_bw 0x%x longer_than_16_he_sigb_ofdm_sym 0x%x non_trig_cqi_feedback 0x%x tx_1024_qam_lt_242_tone_ru 0x%x",
7667 he_cap->midamble_tx_rx_1x_he_ltf, he_cap->dcm_max_bw,
7668 he_cap->longer_than_16_he_sigb_ofdm_sym,
7669 he_cap->non_trig_cqi_feedback,
7670 he_cap->tx_1024_qam_lt_242_tone_ru);
7671
7672 pe_nofl_debug("\trx_1024_qam_lt_242_tone_ru 0x%x rx_full_bw_su_he_mu_compress_sigb 0x%x rx_he_mcs_map_lt_80 0x%x tx_he_mcs_map_lt_80 0x%x",
7673 he_cap->rx_1024_qam_lt_242_tone_ru,
7674 he_cap->rx_full_bw_su_he_mu_compress_sigb,
7675 he_cap->rx_he_mcs_map_lt_80,
7676 he_cap->tx_he_mcs_map_lt_80);
7677
7678 hdr = (struct ppet_hdr *)&he_cap->ppet;
7679 pe_nofl_debug("\tRx MCS map 160 Mhz: 0x%x Tx MCS map 160 Mhz: 0x%x Rx MCS map 80+80 Mhz: 0x%x Tx MCS map 80+80 Mhz: 0x%x ppe_th:: nss_count: %d, ru_idx_msk: %d",
7680 *((uint16_t *)he_cap->rx_he_mcs_map_160),
7681 *((uint16_t *)he_cap->tx_he_mcs_map_160),
7682 *((uint16_t *)he_cap->rx_he_mcs_map_80_80),
7683 *((uint16_t *)he_cap->tx_he_mcs_map_80_80),
7684 hdr->nss, hdr->ru_idx_mask);
7685
7686 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
7687 &he_cap->ppet, HE_MAX_PPET_SIZE);
7688 }
7689
lim_log_he_op(struct mac_context * mac,tDot11fIEhe_op * he_ops,struct pe_session * session)7690 void lim_log_he_op(struct mac_context *mac, tDot11fIEhe_op *he_ops,
7691 struct pe_session *session)
7692 {
7693 pe_debug("bss_color 0x%x pe_dur 0x%x twt req 0x%x txop_rts_thres 0x%x vht_op 0x%x part color 0x%x Co-located 0x%x color dis 0x%x basic mcs nss 0x%x",
7694 he_ops->bss_color, he_ops->default_pe,
7695 he_ops->twt_required, he_ops->txop_rts_threshold,
7696 he_ops->vht_oper_present, he_ops->partial_bss_col,\
7697 he_ops->co_located_bss, he_ops->bss_col_disabled,
7698 *((uint16_t *)he_ops->basic_mcs_nss));
7699
7700 if (!session->he_6ghz_band && he_ops->vht_oper_present)
7701 pe_debug("VHT Info: ch_bw %d cntr_freq0 %d cntr_freq1 %d",
7702 he_ops->vht_oper.info.chan_width,
7703 he_ops->vht_oper.info.center_freq_seg0,
7704 he_ops->vht_oper.info.center_freq_seg1);
7705 else if (he_ops->oper_info_6g_present)
7706 pe_debug("6G_op_info:ch_bw %d cntr_freq0 %d cntr_freq1 %d dup_bcon %d, min_rate %d",
7707 he_ops->oper_info_6g.info.ch_width,
7708 he_ops->oper_info_6g.info.center_freq_seg0,
7709 he_ops->oper_info_6g.info.center_freq_seg1,
7710 he_ops->oper_info_6g.info.dup_bcon,
7711 he_ops->oper_info_6g.info.min_rate);
7712 }
7713
lim_log_he_6g_cap(struct mac_context * mac,tDot11fIEhe_6ghz_band_cap * he_6g_cap)7714 void lim_log_he_6g_cap(struct mac_context *mac,
7715 tDot11fIEhe_6ghz_band_cap *he_6g_cap)
7716 {
7717 pe_debug("min_mpdu_space: %0d, max_mpdu_len_exp: %0x, max_mpdu_len %0x, smps %0x, rd %0x rx_ant_ptn %d tx_ant_ptn %d",
7718 he_6g_cap->min_mpdu_start_spacing,
7719 he_6g_cap->max_ampdu_len_exp, he_6g_cap->max_mpdu_len,
7720 he_6g_cap->sm_pow_save, he_6g_cap->rd_responder,
7721 he_6g_cap->rx_ant_pattern_consistency,
7722 he_6g_cap->tx_ant_pattern_consistency);
7723 }
7724
7725 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
lim_log_he_bss_color(struct mac_context * mac,tDot11fIEbss_color_change * he_bss_color)7726 void lim_log_he_bss_color(struct mac_context *mac,
7727 tDot11fIEbss_color_change *he_bss_color)
7728 {
7729 pe_debug("countdown: %d, new_color: %d",
7730 he_bss_color->countdown, he_bss_color->new_color);
7731 }
7732 #endif
7733
lim_update_sta_he_capable(struct mac_context * mac,tpAddStaParams add_sta_params,tpDphHashNode sta_ds,struct pe_session * session_entry)7734 void lim_update_sta_he_capable(struct mac_context *mac,
7735 tpAddStaParams add_sta_params, tpDphHashNode sta_ds,
7736 struct pe_session *session_entry)
7737 {
7738 if (LIM_IS_AP_ROLE(session_entry))
7739 add_sta_params->he_capable = sta_ds->mlmStaContext.he_capable &&
7740 session_entry->he_capable;
7741 #ifdef FEATURE_WLAN_TDLS
7742 else if (STA_ENTRY_TDLS_PEER == sta_ds->staType)
7743 add_sta_params->he_capable = sta_ds->mlmStaContext.he_capable;
7744 #endif
7745 else
7746 add_sta_params->he_capable = session_entry->he_capable;
7747
7748 add_sta_params->he_mcs_12_13_map = sta_ds->he_mcs_12_13_map;
7749 pe_debug("he_capable: %d", add_sta_params->he_capable);
7750 }
7751
lim_update_bss_he_capable(struct mac_context * mac,struct bss_params * add_bss)7752 void lim_update_bss_he_capable(struct mac_context *mac,
7753 struct bss_params *add_bss)
7754 {
7755 add_bss->he_capable = true;
7756 pe_debug("he_capable: %d", add_bss->he_capable);
7757 }
7758
lim_update_stads_he_capable(tpDphHashNode sta_ds,tpSirAssocReq assoc_req)7759 void lim_update_stads_he_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req)
7760 {
7761 sta_ds->mlmStaContext.he_capable = assoc_req->he_cap.present;
7762 }
7763
lim_update_session_he_capable(struct mac_context * mac,struct pe_session * session)7764 void lim_update_session_he_capable(struct mac_context *mac, struct pe_session *session)
7765 {
7766 session->he_capable = true;
7767 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
7768 session->htCapability = 0;
7769 session->vhtCapability = 0;
7770 session->he_6ghz_band = 1;
7771 }
7772
7773 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) {
7774 session->he_config.ul_mu = mac->he_cap_2g.ul_mu;
7775 if (!mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band)
7776 session->vhtCapability = 0;
7777 }
7778
7779 if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) {
7780 session->he_config.ul_mu = mac->he_cap_5g.ul_mu;
7781 session->he_config.rx_pream_puncturing =
7782 mac->he_cap_5g.rx_pream_puncturing;
7783 }
7784 }
7785
lim_update_session_he_capable_chan_switch(struct mac_context * mac,struct pe_session * session,uint32_t new_chan_freq)7786 void lim_update_session_he_capable_chan_switch(struct mac_context *mac,
7787 struct pe_session *session,
7788 uint32_t new_chan_freq)
7789 {
7790 session->he_capable = true;
7791 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) &&
7792 !wlan_reg_is_6ghz_chan_freq(new_chan_freq)) {
7793 session->htCapability = 1;
7794 session->vhtCapability = 1;
7795 session->he_6ghz_band = 0;
7796 } else if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) &&
7797 wlan_reg_is_6ghz_chan_freq(new_chan_freq)) {
7798 session->htCapability = 0;
7799 session->vhtCapability = 0;
7800 session->he_6ghz_band = 1;
7801 }
7802
7803 /*
7804 * If new channel is 2.4gh set VHT as per the b24ghz_band INI
7805 * if new channel is 5Ghz set the vht, this will happen if we move from
7806 * 2.4Ghz to 5Ghz.
7807 */
7808 if (wlan_reg_is_24ghz_ch_freq(new_chan_freq) &&
7809 !mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band)
7810 session->vhtCapability = 0;
7811 else if (wlan_reg_is_5ghz_ch_freq(new_chan_freq))
7812 session->vhtCapability = 1;
7813 /*
7814 * Re-initialize color bss parameters during channel change
7815 */
7816
7817 session->he_op.bss_col_disabled = 1;
7818 session->bss_color_changing = 1;
7819 session->he_bss_color_change.new_color = session->he_op.bss_color;
7820 session->he_bss_color_change.countdown = BSS_COLOR_SWITCH_COUNTDOWN;
7821 pe_debug("he_capable: %d ht %d vht %d 6ghz_band %d new freq %d vht in 2.4gh %d",
7822 session->he_capable, session->htCapability,
7823 session->vhtCapability, session->he_6ghz_band, new_chan_freq,
7824 mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band);
7825 }
7826
lim_set_he_caps(struct mac_context * mac,uint8_t * ie_start,uint32_t num_bytes,uint8_t band)7827 void lim_set_he_caps(struct mac_context *mac, uint8_t *ie_start,
7828 uint32_t num_bytes, uint8_t band)
7829 {
7830 const uint8_t *ie = NULL;
7831 tDot11fIEhe_cap dot11_cap;
7832 struct he_capability_info *he_cap;
7833 bool is_band_2g = false;
7834
7835 if (band == CDS_BAND_2GHZ)
7836 is_band_2g = true;
7837
7838 populate_dot11f_he_caps_by_band(mac, is_band_2g, &dot11_cap,
7839 NULL);
7840 lim_log_he_cap(mac, &dot11_cap);
7841 ie = wlan_get_ext_ie_ptr_from_ext_id(HE_CAP_OUI_TYPE,
7842 HE_CAP_OUI_SIZE, ie_start, num_bytes);
7843 if (ie) {
7844 /* convert from unpacked to packed structure */
7845 he_cap = (struct he_capability_info *) &ie[2 + HE_CAP_OUI_SIZE];
7846
7847 he_cap->htc_he = dot11_cap.htc_he;
7848 he_cap->twt_request = dot11_cap.twt_request;
7849 he_cap->twt_responder = dot11_cap.twt_responder;
7850 he_cap->fragmentation = dot11_cap.fragmentation;
7851 he_cap->max_num_frag_msdu_amsdu_exp =
7852 dot11_cap.max_num_frag_msdu_amsdu_exp;
7853 he_cap->min_frag_size = dot11_cap.min_frag_size;
7854 he_cap->trigger_frm_mac_pad = dot11_cap.trigger_frm_mac_pad;
7855 he_cap->multi_tid_aggr_rx_supp =
7856 dot11_cap.multi_tid_aggr_rx_supp;
7857 he_cap->he_link_adaptation = dot11_cap.he_link_adaptation;
7858 he_cap->all_ack = dot11_cap.all_ack;
7859 he_cap->trigd_rsp_sched = dot11_cap.trigd_rsp_sched;
7860 he_cap->a_bsr = dot11_cap.a_bsr;
7861 he_cap->broadcast_twt = dot11_cap.broadcast_twt;
7862 he_cap->ba_32bit_bitmap = dot11_cap.ba_32bit_bitmap;
7863 he_cap->mu_cascade = dot11_cap.mu_cascade;
7864 he_cap->ack_enabled_multitid = dot11_cap.ack_enabled_multitid;
7865 he_cap->omi_a_ctrl = dot11_cap.omi_a_ctrl;
7866 he_cap->ofdma_ra = dot11_cap.ofdma_ra;
7867 he_cap->max_ampdu_len_exp_ext = dot11_cap.max_ampdu_len_exp_ext;
7868 he_cap->amsdu_frag = dot11_cap.amsdu_frag;
7869 he_cap->flex_twt_sched = dot11_cap.flex_twt_sched;
7870 he_cap->rx_ctrl_frame = dot11_cap.rx_ctrl_frame;
7871
7872 he_cap->bsrp_ampdu_aggr = dot11_cap.bsrp_ampdu_aggr;
7873 he_cap->qtp = dot11_cap.qtp;
7874 he_cap->a_bqr = dot11_cap.a_bqr;
7875 he_cap->spatial_reuse_param_rspder =
7876 dot11_cap.spatial_reuse_param_rspder;
7877 he_cap->ops_supp = dot11_cap.ops_supp;
7878 he_cap->ndp_feedback_supp = dot11_cap.ndp_feedback_supp;
7879 he_cap->amsdu_in_ampdu = dot11_cap.amsdu_in_ampdu;
7880
7881 if (!mac->roam.configParam.channelBondingMode5GHz) {
7882 /*
7883 * clearing bits for setting 20MHz support
7884 */
7885 dot11_cap.chan_width_1 =
7886 HE_CH_WIDTH_CLR_BIT(dot11_cap.chan_width_1, 0);
7887 dot11_cap.chan_width_2 =
7888 HE_CH_WIDTH_CLR_BIT(dot11_cap.chan_width_2, 0);
7889 dot11_cap.chan_width_3 =
7890 HE_CH_WIDTH_CLR_BIT(dot11_cap.chan_width_3, 0);
7891 he_cap->he_ppdu_20_in_160_80p80Mhz = 0;
7892 }
7893 he_cap->chan_width = HE_CH_WIDTH_COMBINE(dot11_cap.chan_width_0,
7894 dot11_cap.chan_width_1, dot11_cap.chan_width_2,
7895 dot11_cap.chan_width_3, dot11_cap.chan_width_4,
7896 dot11_cap.chan_width_5, dot11_cap.chan_width_6);
7897
7898 he_cap->rx_pream_puncturing = dot11_cap.rx_pream_puncturing;
7899 he_cap->device_class = dot11_cap.device_class;
7900 he_cap->ldpc_coding = dot11_cap.ldpc_coding;
7901 he_cap->he_1x_ltf_800_gi_ppdu = dot11_cap.he_1x_ltf_800_gi_ppdu;
7902 he_cap->midamble_tx_rx_max_nsts =
7903 dot11_cap.midamble_tx_rx_max_nsts;
7904 he_cap->he_4x_ltf_3200_gi_ndp = dot11_cap.he_4x_ltf_3200_gi_ndp;
7905 he_cap->tb_ppdu_tx_stbc_lt_80mhz =
7906 dot11_cap.tb_ppdu_tx_stbc_lt_80mhz;
7907 he_cap->rx_stbc_lt_80mhz = dot11_cap.rx_stbc_lt_80mhz;
7908 he_cap->tb_ppdu_tx_stbc_gt_80mhz =
7909 dot11_cap.tb_ppdu_tx_stbc_gt_80mhz;
7910 he_cap->rx_stbc_gt_80mhz = dot11_cap.rx_stbc_gt_80mhz;
7911 he_cap->doppler = dot11_cap.doppler;
7912 he_cap->ul_mu = dot11_cap.ul_mu;
7913 he_cap->dcm_enc_tx = dot11_cap.dcm_enc_tx;
7914 he_cap->dcm_enc_rx = dot11_cap.dcm_enc_rx;
7915 he_cap->ul_he_mu = dot11_cap.ul_he_mu;
7916 he_cap->su_beamformer = dot11_cap.su_beamformer;
7917
7918 he_cap->su_beamformee = dot11_cap.su_beamformee;
7919 he_cap->mu_beamformer = dot11_cap.mu_beamformer;
7920 he_cap->bfee_sts_lt_80 = dot11_cap.bfee_sts_lt_80;
7921 he_cap->bfee_sts_gt_80 = dot11_cap.bfee_sts_gt_80;
7922 he_cap->num_sounding_lt_80 = dot11_cap.num_sounding_lt_80;
7923 he_cap->num_sounding_gt_80 = dot11_cap.num_sounding_gt_80;
7924 he_cap->su_feedback_tone16 = dot11_cap.su_feedback_tone16;
7925 he_cap->mu_feedback_tone16 = dot11_cap.mu_feedback_tone16;
7926 he_cap->codebook_su = dot11_cap.codebook_su;
7927 he_cap->codebook_mu = dot11_cap.codebook_mu;
7928 he_cap->beamforming_feedback = dot11_cap.beamforming_feedback;
7929 he_cap->he_er_su_ppdu = dot11_cap.he_er_su_ppdu;
7930 he_cap->dl_mu_mimo_part_bw = dot11_cap.dl_mu_mimo_part_bw;
7931 he_cap->ppet_present = dot11_cap.ppet_present;
7932 he_cap->srp = dot11_cap.srp;
7933 he_cap->power_boost = dot11_cap.power_boost;
7934
7935 he_cap->tx_1024_qam_lt_242_tone_ru =
7936 dot11_cap.tx_1024_qam_lt_242_tone_ru;
7937 he_cap->rx_1024_qam_lt_242_tone_ru =
7938 dot11_cap.rx_1024_qam_lt_242_tone_ru;
7939
7940 he_cap->he_ltf_800_gi_4x = dot11_cap.he_ltf_800_gi_4x;
7941 he_cap->max_nc = dot11_cap.max_nc;
7942 he_cap->er_he_ltf_800_gi_4x = dot11_cap.er_he_ltf_800_gi_4x;
7943 he_cap->he_ppdu_20_in_40Mhz_2G =
7944 dot11_cap.he_ppdu_20_in_40Mhz_2G;
7945 he_cap->he_ppdu_20_in_160_80p80Mhz =
7946 dot11_cap.he_ppdu_20_in_160_80p80Mhz;
7947 he_cap->he_ppdu_80_in_160_80p80Mhz =
7948 dot11_cap.he_ppdu_80_in_160_80p80Mhz;
7949 he_cap->er_1x_he_ltf_gi =
7950 dot11_cap.er_1x_he_ltf_gi;
7951 he_cap->midamble_tx_rx_1x_he_ltf =
7952 dot11_cap.midamble_tx_rx_1x_he_ltf;
7953 he_cap->reserved2 = dot11_cap.reserved2;
7954
7955 he_cap->rx_he_mcs_map_lt_80 = dot11_cap.rx_he_mcs_map_lt_80;
7956 he_cap->tx_he_mcs_map_lt_80 = dot11_cap.tx_he_mcs_map_lt_80;
7957 if (dot11_cap.chan_width_2) {
7958 he_cap->rx_he_mcs_map_160 =
7959 *((uint16_t *)dot11_cap.rx_he_mcs_map_160);
7960 he_cap->tx_he_mcs_map_160 =
7961 *((uint16_t *)dot11_cap.tx_he_mcs_map_160);
7962 ie_start[1] += HE_CAP_160M_MCS_MAP_LEN;
7963 }
7964 if (dot11_cap.chan_width_3) {
7965 he_cap->rx_he_mcs_map_80_80 =
7966 *((uint16_t *)dot11_cap.rx_he_mcs_map_80_80);
7967 he_cap->tx_he_mcs_map_80_80 =
7968 *((uint16_t *)dot11_cap.tx_he_mcs_map_80_80);
7969 ie_start[1] += HE_CAP_80P80_MCS_MAP_LEN;
7970 }
7971 }
7972 }
7973
lim_intersect_he_ch_width_2g(struct mac_context * mac,struct he_capability_info * he_cap,uint8_t vdev_id)7974 static void lim_intersect_he_ch_width_2g(struct mac_context *mac,
7975 struct he_capability_info *he_cap,
7976 uint8_t vdev_id)
7977 {
7978 struct wlan_objmgr_psoc *psoc;
7979 uint32_t cbm_24ghz;
7980
7981 psoc = mac->psoc;
7982 if (!psoc)
7983 return;
7984
7985 cbm_24ghz = lim_get_sta_cb_mode_for_24ghz(mac, vdev_id);
7986
7987 pe_debug("channel bonding mode 2.4GHz %d", cbm_24ghz);
7988
7989 if (!cbm_24ghz) {
7990 /* B0: 40Mhz channel width in the 2.4GHz band */
7991 he_cap->chan_width = HE_CH_WIDTH_CLR_BIT(he_cap->chan_width, 0);
7992 he_cap->he_ppdu_20_in_40Mhz_2G = 0;
7993 }
7994
7995 pe_debug("HE cap: chan_width: 0x%07x he_ppdu_20_in_40Mhz_2G %d",
7996 he_cap->chan_width, he_cap->he_ppdu_20_in_40Mhz_2G);
7997 }
7998
lim_set_he_caps_ppet(struct mac_context * mac,uint8_t * ie,enum cds_band_type band)7999 static uint8_t lim_set_he_caps_ppet(struct mac_context *mac, uint8_t *ie,
8000 enum cds_band_type band)
8001 {
8002 uint8_t ppe_th[WNI_CFG_HE_PPET_LEN] = {0};
8003 /* Append at the end after ID + LEN + OUI + IE_Data */
8004 uint8_t offset = ie[1] + 1 + 1 + 1;
8005 uint8_t num_ppe_th;
8006
8007 if (band == CDS_BAND_2GHZ)
8008 qdf_mem_copy(ppe_th, mac->mlme_cfg->he_caps.he_ppet_2g,
8009 WNI_CFG_HE_PPET_LEN);
8010 else if (band == CDS_BAND_5GHZ)
8011 qdf_mem_copy(ppe_th, mac->mlme_cfg->he_caps.he_ppet_5g,
8012 WNI_CFG_HE_PPET_LEN);
8013 else
8014 return 0;
8015
8016 num_ppe_th = lim_truncate_ppet(ppe_th, WNI_CFG_HE_PPET_LEN);
8017
8018 qdf_mem_copy(ie + offset, ppe_th, num_ppe_th);
8019
8020 return num_ppe_th;
8021 }
8022
lim_send_he_caps_ie(struct mac_context * mac_ctx,enum QDF_OPMODE device_mode,uint8_t vdev_id)8023 QDF_STATUS lim_send_he_caps_ie(struct mac_context *mac_ctx,
8024 enum QDF_OPMODE device_mode,
8025 uint8_t vdev_id)
8026 {
8027 uint8_t he_caps[SIR_MAC_HE_CAP_MIN_LEN + HE_CAP_OUI_LEN +
8028 HE_CAP_160M_MCS_MAP_LEN + HE_CAP_80P80_MCS_MAP_LEN +
8029 WNI_CFG_HE_PPET_LEN];
8030 struct he_capability_info *he_cap;
8031 QDF_STATUS status_5g, status_2g;
8032 uint8_t he_cap_total_len = SIR_MAC_HE_CAP_MIN_LEN + HE_CAP_OUI_LEN +
8033 HE_CAP_160M_MCS_MAP_LEN +
8034 HE_CAP_80P80_MCS_MAP_LEN;
8035 uint8_t num_ppe_th = 0;
8036 bool nan_beamforming_supported;
8037 bool disable_nan_tx_bf = false, value = false;
8038
8039 /* Sending only minimal info(no PPET) to FW now, update if required */
8040 qdf_mem_zero(he_caps, he_cap_total_len);
8041 he_caps[0] = DOT11F_EID_HE_CAP;
8042 he_caps[1] = SIR_MAC_HE_CAP_MIN_LEN;
8043 qdf_mem_copy(&he_caps[2], HE_CAP_OUI_TYPE, HE_CAP_OUI_SIZE);
8044 lim_set_he_caps(mac_ctx, he_caps, he_cap_total_len,
8045 CDS_BAND_5GHZ);
8046 he_cap = (struct he_capability_info *) (&he_caps[2 + HE_CAP_OUI_SIZE]);
8047
8048 nan_beamforming_supported =
8049 ucfg_nan_is_beamforming_supported(mac_ctx->psoc);
8050 if (device_mode == QDF_NDI_MODE && !nan_beamforming_supported) {
8051 he_cap->su_beamformee = 0;
8052 he_cap->su_beamformer = 0;
8053 he_cap->mu_beamformer = 0;
8054 he_cap->bfee_sts_gt_80 = 0;
8055 he_cap->bfee_sts_lt_80 = 0;
8056 he_cap->num_sounding_gt_80 = 0;
8057 he_cap->num_sounding_lt_80 = 0;
8058 he_cap->su_feedback_tone16 = 0;
8059 he_cap->mu_feedback_tone16 = 0;
8060 disable_nan_tx_bf = true;
8061 }
8062
8063 /*
8064 * For 5G band HE cap, set the beamformee STS <= 80Mhz to
8065 * mac->he_cap_5g.bfee_sts_lt_80 to keep the values same
8066 * as initial connection
8067 */
8068 if (!disable_nan_tx_bf) {
8069 he_cap->bfee_sts_lt_80 = mac_ctx->he_cap_5g.bfee_sts_lt_80;
8070 he_cap->bfee_sts_gt_80 = mac_ctx->he_cap_5g.bfee_sts_gt_80;
8071 he_cap->num_sounding_gt_80 =
8072 mac_ctx->he_cap_5g.num_sounding_gt_80;
8073 pe_debug("he_cap_5g: bfee_sts_gt_80 %d num_sounding_gt_80 %d",
8074 he_cap->bfee_sts_gt_80, he_cap->num_sounding_gt_80);
8075 }
8076
8077 if (he_cap->ppet_present)
8078 num_ppe_th = lim_set_he_caps_ppet(mac_ctx, he_caps,
8079 CDS_BAND_5GHZ);
8080
8081 if ((device_mode == QDF_STA_MODE) ||
8082 (device_mode == QDF_P2P_CLIENT_MODE)) {
8083 ucfg_twt_cfg_get_requestor(mac_ctx->psoc, &value);
8084 if (!value) {
8085 he_cap->twt_request = false;
8086 he_cap->flex_twt_sched = false;
8087 }
8088 he_cap->twt_responder = false;
8089 } else if ((device_mode == QDF_SAP_MODE) ||
8090 (device_mode == QDF_P2P_GO_MODE)) {
8091 ucfg_twt_cfg_get_responder(mac_ctx->psoc, &value);
8092 if (!value) {
8093 he_cap->twt_responder = false;
8094 he_cap->flex_twt_sched = false;
8095 }
8096 he_cap->twt_request = false;
8097 }
8098
8099 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_CAP,
8100 CDS_BAND_5GHZ, &he_caps[2],
8101 he_caps[1] + 1 + num_ppe_th);
8102 if (QDF_IS_STATUS_ERROR(status_5g))
8103 pe_err("Unable send HE Cap IE for 5GHZ band, status: %d",
8104 status_5g);
8105
8106 qdf_mem_zero(he_caps, he_cap_total_len);
8107 he_caps[0] = DOT11F_EID_HE_CAP;
8108 he_caps[1] = SIR_MAC_HE_CAP_MIN_LEN;
8109 qdf_mem_copy(&he_caps[2], HE_CAP_OUI_TYPE, HE_CAP_OUI_SIZE);
8110 lim_set_he_caps(mac_ctx, he_caps, he_cap_total_len,
8111 CDS_BAND_2GHZ);
8112 he_cap = (struct he_capability_info *)(&he_caps[2 + HE_CAP_OUI_SIZE]);
8113
8114 /*
8115 * For 5G band HE cap, set the beamformee STS <= 80Mhz to
8116 * mac->he_cap_5g.bfee_sts_lt_80 to keep the values same
8117 * as initial connection
8118 */
8119 if (!disable_nan_tx_bf) {
8120 he_cap->bfee_sts_lt_80 = mac_ctx->he_cap_2g.bfee_sts_lt_80;
8121 he_cap->bfee_sts_gt_80 = mac_ctx->he_cap_2g.bfee_sts_gt_80;
8122 he_cap->num_sounding_gt_80 =
8123 mac_ctx->he_cap_2g.num_sounding_gt_80;
8124 pe_debug("he_cap_2g: bfee_sts_gt_80 %d num_sounding_gt_80 %d",
8125 he_cap->bfee_sts_gt_80, he_cap->num_sounding_gt_80);
8126 }
8127 lim_intersect_he_ch_width_2g(mac_ctx, he_cap, vdev_id);
8128
8129 if (he_cap->ppet_present)
8130 num_ppe_th = lim_set_he_caps_ppet(mac_ctx, he_caps,
8131 CDS_BAND_2GHZ);
8132
8133 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_CAP,
8134 CDS_BAND_2GHZ, &he_caps[2],
8135 he_caps[1] + 1 + num_ppe_th);
8136 if (QDF_IS_STATUS_ERROR(status_2g))
8137 pe_err("Unable send HE Cap IE for 2GHZ band, status: %d",
8138 status_2g);
8139
8140 if (QDF_IS_STATUS_SUCCESS(status_2g) &&
8141 QDF_IS_STATUS_SUCCESS(status_5g))
8142 return QDF_STATUS_SUCCESS;
8143
8144 return QDF_STATUS_E_FAILURE;
8145 }
8146
8147 /**
8148 * lim_populate_he_mcs_per_bw() - pouldate HE mcs set per BW (le 80, 160, 80+80)
8149 * @mac_ctx: Global MAC context
8150 * @self_rx: self rx mcs set
8151 * @self_tx: self tx mcs set
8152 * @peer_rx: peer rx mcs set
8153 * @peer_tx: peer tx mcs set
8154 * @nss: nss
8155 * @cfg_rx_param: rx wni param to read
8156 * @cfg_tx_param: tx wni param to read
8157 *
8158 * MCS values are interpreted as in IEEE 11ax-D1.4 spec onwards
8159 * +-----------------------------------------------------+
8160 * | SS8 | SS7 | SS6 | SS5 | SS4 | SS3 | SS2 | SS1 |
8161 * +-----------------------------------------------------+
8162 * | 15-14 | 13-12 | 11-10 | 9-8 | 7-6 | 5-4 | 3-2 | 1-0 |
8163 * +-----------------------------------------------------+
8164 *
8165 * Return: status of operation
8166 */
lim_populate_he_mcs_per_bw(struct mac_context * mac_ctx,uint16_t * supp_rx_mcs,uint16_t * supp_tx_mcs,uint16_t peer_rx,uint16_t peer_tx,uint8_t nss,uint16_t rx_mcs,uint16_t tx_mcs)8167 QDF_STATUS lim_populate_he_mcs_per_bw(struct mac_context *mac_ctx,
8168 uint16_t *supp_rx_mcs,
8169 uint16_t *supp_tx_mcs,
8170 uint16_t peer_rx, uint16_t peer_tx,
8171 uint8_t nss, uint16_t rx_mcs,
8172 uint16_t tx_mcs)
8173 {
8174
8175 pe_debug("peer rates: rx_mcs - 0x%04x tx_mcs - 0x%04x",
8176 peer_rx, peer_tx);
8177
8178 pe_debug("self rates: rx_mcs - 0x%04x tx_mcs - 0x%04x",
8179 rx_mcs, tx_mcs);
8180
8181 *supp_tx_mcs = HE_INTERSECT_MCS(rx_mcs, peer_tx);
8182 *supp_rx_mcs = HE_INTERSECT_MCS(tx_mcs, peer_rx);
8183
8184 if (nss == NSS_1x1_MODE) {
8185 *supp_rx_mcs |= HE_MCS_INV_MSK_4_NSS(1);
8186 *supp_tx_mcs |= HE_MCS_INV_MSK_4_NSS(1);
8187 }
8188 /* if nss is 2, disable higher NSS */
8189 if (nss == NSS_2x2_MODE) {
8190 *supp_rx_mcs |= (HE_MCS_INV_MSK_4_NSS(1) &
8191 HE_MCS_INV_MSK_4_NSS(2));
8192 *supp_tx_mcs |= (HE_MCS_INV_MSK_4_NSS(1) &
8193 HE_MCS_INV_MSK_4_NSS(2));
8194 }
8195
8196 return QDF_STATUS_SUCCESS;
8197 }
8198
lim_populate_he_mcs_set(struct mac_context * mac_ctx,struct supported_rates * rates,tDot11fIEhe_cap * peer_he_caps,struct pe_session * session_entry,uint8_t nss)8199 QDF_STATUS lim_populate_he_mcs_set(struct mac_context *mac_ctx,
8200 struct supported_rates *rates,
8201 tDot11fIEhe_cap *peer_he_caps,
8202 struct pe_session *session_entry, uint8_t nss)
8203 {
8204 bool support_2x2 = false;
8205 uint32_t self_sta_dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode;
8206
8207 if (!IS_DOT11_MODE_HE(self_sta_dot11mode))
8208 return QDF_STATUS_SUCCESS;
8209
8210 if ((!peer_he_caps) || (!peer_he_caps->present)) {
8211 pe_debug("peer not he capable or he_caps NULL");
8212 return QDF_STATUS_SUCCESS;
8213 }
8214
8215 if (!session_entry) {
8216 pe_err("session is NULL");
8217 return QDF_STATUS_E_FAILURE;
8218 }
8219
8220 pe_debug("session chan width: %d", session_entry->ch_width);
8221 pe_debug("PEER: lt 80: rx 0x%04x tx 0x%04x, 160: rx 0x%04x tx 0x%04x, 80+80: rx 0x%04x tx 0x%04x",
8222 peer_he_caps->rx_he_mcs_map_lt_80,
8223 peer_he_caps->tx_he_mcs_map_lt_80,
8224 (*(uint16_t *)peer_he_caps->rx_he_mcs_map_160),
8225 (*(uint16_t *)peer_he_caps->tx_he_mcs_map_160),
8226 (*(uint16_t *)peer_he_caps->rx_he_mcs_map_80_80),
8227 (*(uint16_t *)peer_he_caps->tx_he_mcs_map_80_80));
8228
8229 if (nss == NSS_2x2_MODE) {
8230 if (mac_ctx->mlme_cfg->gen.as_enabled &&
8231 wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq)) {
8232 if (IS_2X2_CHAIN(session_entry->chainMask))
8233 support_2x2 = true;
8234 else
8235 pe_err("2x2 not enabled %d",
8236 session_entry->chainMask);
8237 } else {
8238 support_2x2 = true;
8239 }
8240 }
8241
8242 if (wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq))
8243 lim_populate_he_mcs_per_bw(mac_ctx,
8244 &rates->rx_he_mcs_map_lt_80,
8245 &rates->tx_he_mcs_map_lt_80,
8246 peer_he_caps->rx_he_mcs_map_lt_80,
8247 peer_he_caps->tx_he_mcs_map_lt_80, nss,
8248 mac_ctx->he_cap_2g.rx_he_mcs_map_lt_80,
8249 mac_ctx->he_cap_2g.tx_he_mcs_map_lt_80);
8250 else
8251 lim_populate_he_mcs_per_bw(mac_ctx,
8252 &rates->rx_he_mcs_map_lt_80,
8253 &rates->tx_he_mcs_map_lt_80,
8254 peer_he_caps->rx_he_mcs_map_lt_80,
8255 peer_he_caps->tx_he_mcs_map_lt_80, nss,
8256 mac_ctx->he_cap_5g.rx_he_mcs_map_lt_80,
8257 mac_ctx->he_cap_5g.tx_he_mcs_map_lt_80);
8258
8259 if ((session_entry->ch_width == CH_WIDTH_160MHZ ||
8260 lim_is_session_chwidth_320mhz(session_entry)) &&
8261 peer_he_caps->chan_width_2) {
8262 lim_populate_he_mcs_per_bw(
8263 mac_ctx, &rates->rx_he_mcs_map_160,
8264 &rates->tx_he_mcs_map_160,
8265 *((uint16_t *)peer_he_caps->rx_he_mcs_map_160),
8266 *((uint16_t *)peer_he_caps->tx_he_mcs_map_160),
8267 nss,
8268 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
8269 rx_he_mcs_map_160),
8270 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
8271 tx_he_mcs_map_160));
8272 } else {
8273 rates->tx_he_mcs_map_160 = HE_MCS_ALL_DISABLED;
8274 rates->rx_he_mcs_map_160 = HE_MCS_ALL_DISABLED;
8275 }
8276 if (session_entry->ch_width == CH_WIDTH_80P80MHZ) {
8277 lim_populate_he_mcs_per_bw(
8278 mac_ctx, &rates->rx_he_mcs_map_80_80,
8279 &rates->tx_he_mcs_map_80_80,
8280 *((uint16_t *)peer_he_caps->rx_he_mcs_map_80_80),
8281 *((uint16_t *)peer_he_caps->tx_he_mcs_map_80_80), nss,
8282 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
8283 rx_he_mcs_map_80_80),
8284 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap.
8285 tx_he_mcs_map_80_80));
8286 } else {
8287 rates->tx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED;
8288 rates->rx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED;
8289 }
8290 if (!support_2x2) {
8291 /* disable 2 and higher NSS MCS sets */
8292 rates->rx_he_mcs_map_lt_80 |= HE_MCS_INV_MSK_4_NSS(1);
8293 rates->tx_he_mcs_map_lt_80 |= HE_MCS_INV_MSK_4_NSS(1);
8294 rates->rx_he_mcs_map_160 |= HE_MCS_INV_MSK_4_NSS(1);
8295 rates->tx_he_mcs_map_160 |= HE_MCS_INV_MSK_4_NSS(1);
8296 rates->rx_he_mcs_map_80_80 |= HE_MCS_INV_MSK_4_NSS(1);
8297 rates->tx_he_mcs_map_80_80 |= HE_MCS_INV_MSK_4_NSS(1);
8298 }
8299
8300 pe_debug("lt 80: rx 0x%x tx 0x%x, 160: rx 0x%x tx 0x%x, 80_80: rx 0x%x tx 0x%x",
8301 rates->rx_he_mcs_map_lt_80, rates->tx_he_mcs_map_lt_80,
8302 rates->rx_he_mcs_map_160, rates->tx_he_mcs_map_160,
8303 rates->rx_he_mcs_map_80_80, rates->tx_he_mcs_map_80_80);
8304
8305 return QDF_STATUS_SUCCESS;
8306 }
8307 #endif
8308
8309 #ifdef WLAN_FEATURE_11BE_MLO
lim_update_sta_mlo_info(struct pe_session * session,tpAddStaParams add_sta_params,tpDphHashNode sta_ds)8310 void lim_update_sta_mlo_info(struct pe_session *session,
8311 tpAddStaParams add_sta_params,
8312 tpDphHashNode sta_ds)
8313 {
8314 if (lim_is_add_sta_params_eht_capable(add_sta_params) &&
8315 lim_is_mlo_conn(session, sta_ds)) {
8316 WLAN_ADDR_COPY(add_sta_params->mld_mac_addr, sta_ds->mld_addr);
8317 add_sta_params->is_assoc_peer = lim_is_mlo_recv_assoc(sta_ds);
8318 pe_debug("mld mac " QDF_MAC_ADDR_FMT " assoc peer %d",
8319 QDF_MAC_ADDR_REF(add_sta_params->mld_mac_addr),
8320 add_sta_params->is_assoc_peer);
8321 return;
8322 }
8323
8324 pe_debug("is not mlo capable");
8325 }
8326
lim_set_mlo_caps(struct mac_context * mac,struct pe_session * session,uint8_t * ie_start,uint32_t num_bytes)8327 void lim_set_mlo_caps(struct mac_context *mac, struct pe_session *session,
8328 uint8_t *ie_start, uint32_t num_bytes)
8329 {
8330 const uint8_t *ie = NULL;
8331 struct wlan_mlo_ie dot11_cap;
8332 struct wlan_mlo_ie_info *mlo_ie_info;
8333
8334 populate_dot11f_mlo_caps(mac, session, &dot11_cap);
8335
8336 ie = wlan_get_ext_ie_ptr_from_ext_id(MLO_IE_OUI_TYPE,
8337 MLO_IE_OUI_SIZE,
8338 ie_start, num_bytes);
8339
8340 if (ie) {
8341 /* convert from unpacked to packed structure */
8342 mlo_ie_info = (struct wlan_mlo_ie_info *)&ie[2 + MLO_IE_OUI_SIZE];
8343
8344 mlo_ie_info->type = dot11_cap.type;
8345 mlo_ie_info->reserved = dot11_cap.reserved;
8346 mlo_ie_info->link_id_info_present =
8347 dot11_cap.link_id_info_present;
8348 mlo_ie_info->bss_param_change_cnt_present =
8349 dot11_cap.bss_param_change_cnt_present;
8350 mlo_ie_info->medium_sync_delay_info_present =
8351 dot11_cap.medium_sync_delay_info_present;
8352 mlo_ie_info->eml_capab_present = dot11_cap.eml_capab_present;
8353 mlo_ie_info->mld_capab_and_op_present = dot11_cap.mld_capab_and_op_present;
8354 mlo_ie_info->mld_id_present = dot11_cap.mld_id_present;
8355 mlo_ie_info->ext_mld_capab_and_op_present =
8356 dot11_cap.ext_mld_capab_and_op_present;
8357 mlo_ie_info->reserved_1 = dot11_cap.reserved_1;
8358 mlo_ie_info->common_info_length = dot11_cap.common_info_length;
8359 qdf_mem_copy(&mlo_ie_info->mld_mac_addr,
8360 &dot11_cap.mld_mac_addr,
8361 QDF_MAC_ADDR_SIZE);
8362 ie_start[1] += QDF_MAC_ADDR_SIZE;
8363 }
8364 }
8365
lim_send_mlo_caps_ie(struct mac_context * mac_ctx,struct wlan_objmgr_vdev * vdev,enum QDF_OPMODE device_mode,uint8_t vdev_id)8366 QDF_STATUS lim_send_mlo_caps_ie(struct mac_context *mac_ctx,
8367 struct wlan_objmgr_vdev *vdev,
8368 enum QDF_OPMODE device_mode,
8369 uint8_t vdev_id)
8370 {
8371
8372 QDF_STATUS status_2g, status_5g;
8373 struct wlan_mlo_ie mlo_ie;
8374
8375 populate_dot11f_mlo_ie(mac_ctx, vdev, &mlo_ie);
8376 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_MLO_IE,
8377 CDS_BAND_2GHZ, &mlo_ie.data[2],
8378 mlo_ie.num_data - 2);
8379
8380 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_MLO_IE,
8381 CDS_BAND_5GHZ, &mlo_ie.data[2],
8382 mlo_ie.num_data - 2);
8383
8384 if (QDF_IS_STATUS_SUCCESS(status_2g) &&
8385 QDF_IS_STATUS_SUCCESS(status_5g)) {
8386 return QDF_STATUS_SUCCESS;
8387 }
8388 return QDF_STATUS_SUCCESS;
8389 }
8390
lim_strip_mlo_ie(struct mac_context * mac_ctx,uint8_t * add_ie,uint16_t * add_ielen)8391 void lim_strip_mlo_ie(struct mac_context *mac_ctx,
8392 uint8_t *add_ie, uint16_t *add_ielen)
8393 {
8394 uint8_t *mlo_ie_buff = NULL;
8395 uint16_t mlo_ie_buff_len = 0;
8396 QDF_STATUS qdf_status;
8397
8398 /* MLO ext ie in addition IE*/
8399 if (wlan_get_ext_ie_ptr_from_ext_id(MLO_IE_OUI_TYPE, ONE_BYTE,
8400 add_ie, *add_ielen)) {
8401 mlo_ie_buff = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
8402
8403 if (!mlo_ie_buff) {
8404 pe_err("Failed to allocate MLO IE buff");
8405 return;
8406 }
8407
8408 qdf_status = lim_strip_ie(mac_ctx, add_ie, add_ielen,
8409 WLAN_ELEMID_EXTN_ELEM, ONE_BYTE,
8410 MLO_IE_OUI_TYPE, MLO_IE_OUI_SIZE,
8411 mlo_ie_buff, WLAN_MAX_IE_LEN);
8412 if (QDF_IS_STATUS_ERROR(qdf_status)) {
8413 pe_err("Failed to strip MLO IE");
8414 qdf_mem_free(mlo_ie_buff);
8415 return;
8416 }
8417 mlo_ie_buff_len = mlo_ie_buff[1] + 2; /* 2 - EID+LEN */
8418 pe_debug("remove supplicant mlo ie, %d bytes", mlo_ie_buff[1]);
8419 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
8420 mlo_ie_buff, mlo_ie_buff_len);
8421
8422 qdf_mem_free(mlo_ie_buff);
8423 }
8424 }
8425 #endif
8426
8427 #ifdef WLAN_FEATURE_11BE
lim_populate_eht_320_mcs_set(struct mac_context * mac_ctx,struct supported_rates * rates,tDot11fIEeht_cap * peer_eht_caps)8428 static void lim_populate_eht_320_mcs_set(struct mac_context *mac_ctx,
8429 struct supported_rates *rates,
8430 tDot11fIEeht_cap *peer_eht_caps)
8431 {
8432 tDot11fIEeht_cap *fw_5g_eht_cap;
8433
8434 fw_5g_eht_cap = &mac_ctx->eht_cap_5g;
8435
8436 rates->bw_320_tx_max_nss_for_mcs_12_and_13 =
8437 QDF_MIN(peer_eht_caps->bw_320_tx_max_nss_for_mcs_12_and_13,
8438 fw_5g_eht_cap->bw_320_tx_max_nss_for_mcs_12_and_13);
8439 rates->bw_320_rx_max_nss_for_mcs_12_and_13 =
8440 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_12_and_13,
8441 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_12_and_13);
8442 rates->bw_320_tx_max_nss_for_mcs_10_and_11 =
8443 QDF_MIN(peer_eht_caps->bw_320_tx_max_nss_for_mcs_10_and_11,
8444 fw_5g_eht_cap->bw_320_tx_max_nss_for_mcs_10_and_11);
8445 rates->bw_320_rx_max_nss_for_mcs_10_and_11 =
8446 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_10_and_11,
8447 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_10_and_11);
8448 rates->bw_320_rx_max_nss_for_mcs_0_to_9 =
8449 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_0_to_9,
8450 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_0_to_9);
8451 rates->bw_320_tx_max_nss_for_mcs_0_to_9 =
8452 QDF_MIN(peer_eht_caps->bw_320_tx_max_nss_for_mcs_0_to_9,
8453 fw_5g_eht_cap->bw_320_tx_max_nss_for_mcs_0_to_9);
8454 rates->bw_320_rx_max_nss_for_mcs_0_to_9 =
8455 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_0_to_9,
8456 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_0_to_9);
8457 rates->bw_320_rx_max_nss_for_mcs_0_to_9 =
8458 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_0_to_9,
8459 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_0_to_9);
8460 }
8461
lim_populate_eht_160_mcs_set(struct mac_context * mac_ctx,struct supported_rates * rates,tDot11fIEeht_cap * peer_eht_caps)8462 static void lim_populate_eht_160_mcs_set(struct mac_context *mac_ctx,
8463 struct supported_rates *rates,
8464 tDot11fIEeht_cap *peer_eht_caps)
8465 {
8466 tDot11fIEeht_cap *fw_5g_eht_cap;
8467
8468 fw_5g_eht_cap = &mac_ctx->eht_cap_5g;
8469
8470 rates->bw_160_tx_max_nss_for_mcs_12_and_13 =
8471 QDF_MIN(peer_eht_caps->bw_160_tx_max_nss_for_mcs_12_and_13,
8472 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_12_and_13);
8473 rates->bw_160_rx_max_nss_for_mcs_12_and_13 =
8474 QDF_MIN(peer_eht_caps->bw_160_rx_max_nss_for_mcs_12_and_13,
8475 fw_5g_eht_cap->bw_160_rx_max_nss_for_mcs_12_and_13);
8476 rates->bw_160_tx_max_nss_for_mcs_10_and_11 =
8477 QDF_MIN(peer_eht_caps->bw_160_tx_max_nss_for_mcs_10_and_11,
8478 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_10_and_11);
8479 rates->bw_160_rx_max_nss_for_mcs_10_and_11 =
8480 QDF_MIN(peer_eht_caps->bw_160_rx_max_nss_for_mcs_10_and_11,
8481 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_10_and_11);
8482 rates->bw_160_tx_max_nss_for_mcs_0_to_9 =
8483 QDF_MIN(peer_eht_caps->bw_160_tx_max_nss_for_mcs_0_to_9,
8484 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_0_to_9);
8485 rates->bw_160_rx_max_nss_for_mcs_0_to_9 =
8486 QDF_MIN(peer_eht_caps->bw_160_rx_max_nss_for_mcs_0_to_9,
8487 fw_5g_eht_cap->bw_160_rx_max_nss_for_mcs_0_to_9);
8488 }
8489
lim_populate_eht_le80_mcs_set(struct mac_context * mac_ctx,struct supported_rates * rates,tDot11fIEeht_cap * peer_eht_caps)8490 static void lim_populate_eht_le80_mcs_set(struct mac_context *mac_ctx,
8491 struct supported_rates *rates,
8492 tDot11fIEeht_cap *peer_eht_caps)
8493 {
8494 tDot11fIEeht_cap *fw_le80_eht_cap;
8495
8496 fw_le80_eht_cap = &mac_ctx->eht_cap_5g;
8497
8498 rates->bw_le_80_tx_max_nss_for_mcs_12_and_13 =
8499 QDF_MIN(peer_eht_caps->bw_le_80_tx_max_nss_for_mcs_12_and_13,
8500 fw_le80_eht_cap->bw_le_80_tx_max_nss_for_mcs_12_and_13);
8501 rates->bw_le_80_rx_max_nss_for_mcs_12_and_13 =
8502 QDF_MIN(peer_eht_caps->bw_le_80_rx_max_nss_for_mcs_12_and_13,
8503 fw_le80_eht_cap->bw_le_80_rx_max_nss_for_mcs_12_and_13);
8504 rates->bw_le_80_tx_max_nss_for_mcs_10_and_11 =
8505 QDF_MIN(peer_eht_caps->bw_le_80_tx_max_nss_for_mcs_10_and_11,
8506 fw_le80_eht_cap->bw_le_80_tx_max_nss_for_mcs_10_and_11);
8507 rates->bw_le_80_rx_max_nss_for_mcs_10_and_11 =
8508 QDF_MIN(peer_eht_caps->bw_le_80_rx_max_nss_for_mcs_10_and_11,
8509 fw_le80_eht_cap->bw_le_80_rx_max_nss_for_mcs_10_and_11);
8510 rates->bw_le_80_tx_max_nss_for_mcs_0_to_9 =
8511 QDF_MIN(peer_eht_caps->bw_le_80_tx_max_nss_for_mcs_0_to_9,
8512 fw_le80_eht_cap->bw_le_80_tx_max_nss_for_mcs_0_to_9);
8513 rates->bw_le_80_rx_max_nss_for_mcs_0_to_9 =
8514 QDF_MIN(peer_eht_caps->bw_le_80_rx_max_nss_for_mcs_0_to_9,
8515 fw_le80_eht_cap->bw_le_80_rx_max_nss_for_mcs_0_to_9);
8516 }
8517
lim_populate_eht_20only_mcs_set(struct mac_context * mac_ctx,struct supported_rates * rates,tDot11fIEeht_cap * peer_eht_caps)8518 static void lim_populate_eht_20only_mcs_set(struct mac_context *mac_ctx,
8519 struct supported_rates *rates,
8520 tDot11fIEeht_cap *peer_eht_caps)
8521 {
8522 tDot11fIEeht_cap *fw_2g_eht_cap;
8523
8524 fw_2g_eht_cap = &mac_ctx->eht_cap_2g;
8525
8526 rates->bw_20_tx_max_nss_for_mcs_12_and_13 =
8527 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_12_and_13,
8528 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_12_and_13);
8529 rates->bw_20_rx_max_nss_for_mcs_12_and_13 =
8530 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_12_and_13,
8531 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_12_and_13);
8532 rates->bw_20_tx_max_nss_for_mcs_10_and_11 =
8533 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_10_and_11,
8534 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_10_and_11);
8535 rates->bw_20_rx_max_nss_for_mcs_10_and_11 =
8536 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_10_and_11,
8537 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_10_and_11);
8538 rates->bw_20_tx_max_nss_for_mcs_8_and_9 =
8539 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_8_and_9,
8540 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_8_and_9);
8541 rates->bw_20_rx_max_nss_for_mcs_8_and_9 =
8542 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_8_and_9,
8543 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_8_and_9);
8544 rates->bw_20_tx_max_nss_for_mcs_0_to_7 =
8545 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_0_to_7,
8546 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_0_to_7);
8547 rates->bw_20_rx_max_nss_for_mcs_0_to_7 =
8548 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_0_to_7,
8549 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_0_to_7);
8550 }
8551
lim_populate_eht_mcs_set(struct mac_context * mac_ctx,struct supported_rates * rates,tDot11fIEeht_cap * peer_eht_caps,struct pe_session * session_entry,enum phy_ch_width ch_width)8552 QDF_STATUS lim_populate_eht_mcs_set(struct mac_context *mac_ctx,
8553 struct supported_rates *rates,
8554 tDot11fIEeht_cap *peer_eht_caps,
8555 struct pe_session *session_entry,
8556 enum phy_ch_width ch_width)
8557 {
8558 if ((!peer_eht_caps) || (!peer_eht_caps->present)) {
8559 pe_debug("peer not eht capable or eht_caps NULL");
8560 return QDF_STATUS_SUCCESS;
8561 }
8562 if (!lim_is_session_eht_capable(session_entry)) {
8563 pe_debug("session not eht capable");
8564 return QDF_STATUS_SUCCESS;
8565 }
8566
8567 switch (ch_width) {
8568 case CH_WIDTH_320MHZ:
8569 lim_populate_eht_320_mcs_set(mac_ctx, rates, peer_eht_caps);
8570 fallthrough;
8571 case CH_WIDTH_160MHZ:
8572 lim_populate_eht_160_mcs_set(mac_ctx, rates, peer_eht_caps);
8573 fallthrough;
8574 case CH_WIDTH_80MHZ:
8575 case CH_WIDTH_40MHZ:
8576 lim_populate_eht_le80_mcs_set(mac_ctx, rates, peer_eht_caps);
8577 break;
8578 case CH_WIDTH_20MHZ:
8579 lim_populate_eht_20only_mcs_set(mac_ctx, rates, peer_eht_caps);
8580 break;
8581 default:
8582 break;
8583 }
8584
8585 return QDF_STATUS_SUCCESS;
8586 }
8587
lim_add_self_eht_cap(tpAddStaParams add_sta_params,struct pe_session * session)8588 void lim_add_self_eht_cap(tpAddStaParams add_sta_params,
8589 struct pe_session *session)
8590 {
8591 if (!session)
8592 return;
8593
8594 add_sta_params->eht_capable = true;
8595
8596 qdf_mem_copy(&add_sta_params->eht_config, &session->eht_config,
8597 sizeof(add_sta_params->eht_config));
8598 qdf_mem_copy(&add_sta_params->eht_op, &session->eht_op,
8599 sizeof(add_sta_params->eht_op));
8600 }
8601
8602 /**
8603 * lim_intersect_eht_caps() - Intersect peer capability and self capability
8604 * @rcvd_eht: pointer to received peer capability
8605 * @peer_eht: pointer to Intersected capability
8606 * @session: A pointer to session entry.
8607 *
8608 * Return: None
8609 */
lim_intersect_eht_caps(tDot11fIEeht_cap * rcvd_eht,tDot11fIEeht_cap * peer_eht,struct pe_session * session)8610 static void lim_intersect_eht_caps(tDot11fIEeht_cap *rcvd_eht,
8611 tDot11fIEeht_cap *peer_eht,
8612 struct pe_session *session)
8613 {
8614 tDot11fIEeht_cap *session_eht = &session->eht_config;
8615
8616 qdf_mem_copy(peer_eht, rcvd_eht, sizeof(*peer_eht));
8617
8618 peer_eht->su_beamformer = session_eht->su_beamformee ?
8619 peer_eht->su_beamformer : 0;
8620 peer_eht->su_beamformee = (session_eht->su_beamformer ||
8621 session_eht->mu_bformer_le_80mhz ||
8622 session_eht->mu_bformer_160mhz ||
8623 session_eht->mu_bformer_320mhz) ?
8624 peer_eht->su_beamformee : 0;
8625 peer_eht->mu_bformer_le_80mhz = session_eht->su_beamformee ?
8626 peer_eht->mu_bformer_le_80mhz : 0;
8627 peer_eht->mu_bformer_160mhz = session_eht->su_beamformee ?
8628 peer_eht->mu_bformer_160mhz : 0;
8629 peer_eht->mu_bformer_320mhz = session_eht->su_beamformee ?
8630 peer_eht->mu_bformer_320mhz : 0;
8631
8632 if (session_eht->support_320mhz_6ghz && rcvd_eht->support_320mhz_6ghz)
8633 peer_eht->support_320mhz_6ghz = 1;
8634 else
8635 peer_eht->support_320mhz_6ghz = 0;
8636 }
8637
lim_update_usr_eht_cap(struct mac_context * mac_ctx,struct pe_session * session)8638 void lim_update_usr_eht_cap(struct mac_context *mac_ctx,
8639 struct pe_session *session)
8640 {
8641 struct add_ie_params *add_ie = &session->add_ie_params;
8642 tDot11fIEeht_cap *eht_cap = &session->eht_config;
8643 struct wlan_eht_cap_info_network_endian *eht_cap_from_ie;
8644 uint8_t extracted_buff[DOT11F_IE_EHT_CAP_MAX_LEN + 2];
8645 QDF_STATUS status;
8646 struct wlan_vht_config *vht_cfg = &session->vht_config;
8647 tDot11fIEhe_cap *he_cap = &session->he_config;
8648 struct mlme_legacy_priv *mlme_priv;
8649
8650 qdf_mem_zero(extracted_buff, sizeof(extracted_buff));
8651 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
8652 &add_ie->probeRespBCNDataLen,
8653 DOT11F_EID_EHT_CAP, ONE_BYTE,
8654 EHT_CAP_OUI_TYPE, (uint8_t)EHT_CAP_OUI_SIZE,
8655 extracted_buff, DOT11F_IE_EHT_CAP_MAX_LEN);
8656 if (QDF_IS_STATUS_ERROR(status)) {
8657 pe_debug("Failed to strip EHT cap IE status: %d", status);
8658 return;
8659 }
8660
8661 pe_debug("Before update: su_bformer: %d, su_bformee: %d, mu_bformer <= 80MHZ: %d 160MHZ: %d 320MHZ: %d",
8662 eht_cap->su_beamformer, eht_cap->su_beamformee,
8663 eht_cap->mu_bformer_le_80mhz, eht_cap->mu_bformer_160mhz,
8664 eht_cap->mu_bformer_320mhz);
8665
8666 eht_cap_from_ie = (struct wlan_eht_cap_info_network_endian *)
8667 &extracted_buff[EHT_CAP_OUI_SIZE + 2];
8668
8669 eht_cap->su_beamformer =
8670 eht_cap->su_beamformer & eht_cap_from_ie->su_beamformer;
8671 eht_cap->su_beamformee =
8672 eht_cap->su_beamformee & eht_cap_from_ie->su_beamformee;
8673 eht_cap->mu_bformer_le_80mhz =
8674 eht_cap->mu_bformer_le_80mhz &
8675 eht_cap_from_ie->mu_bformer_le_80mhz;
8676 eht_cap->mu_bformer_160mhz =
8677 eht_cap->mu_bformer_160mhz &
8678 eht_cap_from_ie->mu_bformer_160mhz;
8679 eht_cap->mu_bformer_320mhz =
8680 eht_cap->mu_bformer_320mhz &
8681 eht_cap_from_ie->mu_bformer_320mhz;
8682
8683 pe_debug("After update: su_bformer: %d, su_bformee: %d, mu_bformer <= 80MHZ: %d 160MHZ: %d 320MHZ: %d",
8684 eht_cap->su_beamformer, eht_cap->su_beamformee,
8685 eht_cap->mu_bformer_le_80mhz, eht_cap->mu_bformer_160mhz,
8686 eht_cap->mu_bformer_320mhz);
8687 if (!eht_cap->su_beamformer) {
8688 eht_cap->mu_bformer_le_80mhz = 0;
8689 eht_cap->mu_bformer_160mhz = 0;
8690 eht_cap->mu_bformer_320mhz = 0;
8691 eht_cap->num_sounding_dim_le_80mhz = 0;
8692 eht_cap->num_sounding_dim_160mhz = 0;
8693 eht_cap->num_sounding_dim_320mhz = 0;
8694 he_cap->mu_beamformer = 0;
8695 he_cap->num_sounding_lt_80 = 0;
8696 he_cap->num_sounding_gt_80 = 0;
8697 vht_cfg->su_beam_former = 0;
8698 vht_cfg->mu_beam_former = 0;
8699 vht_cfg->num_soundingdim = 0;
8700 }
8701 if (!eht_cap->su_beamformee) {
8702 eht_cap->bfee_ss_le_80mhz = 0;
8703 eht_cap->bfee_ss_160mhz = 0;
8704 eht_cap->bfee_ss_320mhz = 0;
8705 he_cap->bfee_sts_lt_80 = 0;
8706 he_cap->bfee_sts_gt_80 = 0;
8707 vht_cfg->su_beam_formee = 0;
8708 vht_cfg->mu_beam_formee = 0;
8709 vht_cfg->csnof_beamformer_antSup = 0;
8710 }
8711
8712 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
8713 if (mlme_priv) {
8714 mlme_priv->eht_config.mu_bformer_le_80mhz =
8715 eht_cap->mu_bformer_le_80mhz;
8716 mlme_priv->eht_config.mu_bformer_160mhz =
8717 eht_cap->mu_bformer_160mhz;
8718 mlme_priv->eht_config.mu_bformer_320mhz =
8719 eht_cap->mu_bformer_320mhz;
8720 mlme_priv->eht_config.su_beamformer = eht_cap->su_beamformer;
8721 mlme_priv->eht_config.su_beamformee = eht_cap->su_beamformee;
8722 mlme_priv->eht_config.bfee_ss_le_80mhz =
8723 eht_cap->bfee_ss_le_80mhz;
8724 mlme_priv->eht_config.bfee_ss_160mhz = eht_cap->bfee_ss_160mhz;
8725 mlme_priv->eht_config.bfee_ss_320mhz = eht_cap->bfee_ss_320mhz;
8726 mlme_priv->eht_config.num_sounding_dim_le_80mhz =
8727 eht_cap->num_sounding_dim_le_80mhz;
8728 mlme_priv->eht_config.num_sounding_dim_160mhz =
8729 eht_cap->num_sounding_dim_160mhz;
8730 mlme_priv->eht_config.num_sounding_dim_320mhz =
8731 eht_cap->num_sounding_dim_320mhz;
8732 }
8733 wma_set_eht_txbf_params(session->vdev_id, eht_cap->su_beamformer,
8734 eht_cap->su_beamformee,
8735 eht_cap->mu_bformer_le_80mhz ||
8736 eht_cap->mu_bformer_160mhz ||
8737 eht_cap->mu_bformer_320mhz);
8738 }
8739
8740 static void
lim_revise_req_eht_cap_per_band(struct mlme_legacy_priv * mlme_priv,struct pe_session * session)8741 lim_revise_req_eht_cap_per_band(struct mlme_legacy_priv *mlme_priv,
8742 struct pe_session *session)
8743 {
8744 struct mac_context *mac = session->mac_ctx;
8745
8746 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq))
8747 mlme_priv->eht_config = mac->eht_cap_2g;
8748 else
8749 mlme_priv->eht_config = mac->eht_cap_5g;
8750 }
8751
8752 /**
8753 * lim_revise_req_eht_cap_per_mode() - revise eht capabilities per device mode
8754 * @mlme_legacy_priv: vdev mlme legacy priv object
8755 * @session: pointer to session entry.
8756 *
8757 * Return: None
8758 */
lim_revise_req_eht_cap_per_mode(struct mlme_legacy_priv * mlme_priv,struct pe_session * session)8759 static void lim_revise_req_eht_cap_per_mode(struct mlme_legacy_priv *mlme_priv,
8760 struct pe_session *session)
8761 {
8762 if (session->opmode == QDF_SAP_MODE ||
8763 session->opmode == QDF_P2P_GO_MODE) {
8764 pe_debug("Disable eht cap for SAP/GO");
8765 mlme_priv->eht_config.tx_1024_4096_qam_lt_242_tone_ru = 0;
8766 mlme_priv->eht_config.rx_1024_4096_qam_lt_242_tone_ru = 0;
8767 }
8768
8769 mlme_priv->eht_config.non_ofdma_ul_mu_mimo_le_80mhz = 0;
8770 mlme_priv->eht_config.non_ofdma_ul_mu_mimo_160mhz = 0;
8771 mlme_priv->eht_config.non_ofdma_ul_mu_mimo_320mhz = 0;
8772 }
8773
lim_copy_bss_eht_cap(struct pe_session * session)8774 void lim_copy_bss_eht_cap(struct pe_session *session)
8775 {
8776 struct mlme_legacy_priv *mlme_priv;
8777
8778 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
8779 if (!mlme_priv)
8780 return;
8781
8782 lim_revise_req_eht_cap_per_band(mlme_priv, session);
8783
8784 /*
8785 * As per firmware, SAP/GO doesn’t support some EHT capabilities. So if
8786 * unsupported capabilities are advertised in beacon, probe rsp and
8787 * assoc rsp can cause IOT issues.
8788 * Disable unsupported capabilities per mode.
8789 */
8790 lim_revise_req_eht_cap_per_mode(mlme_priv, session);
8791 lim_update_eht_caps_mcs(session->mac_ctx, session);
8792 qdf_mem_copy(&session->eht_config, &mlme_priv->eht_config,
8793 sizeof(session->eht_config));
8794
8795 if (wlan_epcs_get_config(session->vdev))
8796 session->eht_config.epcs_pri_access = 1;
8797 else
8798 session->eht_config.epcs_pri_access = 0;
8799 }
8800
lim_copy_join_req_eht_cap(struct pe_session * session)8801 void lim_copy_join_req_eht_cap(struct pe_session *session)
8802 {
8803 struct mlme_legacy_priv *mlme_priv;
8804
8805 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
8806 if (!mlme_priv)
8807 return;
8808 lim_revise_req_eht_cap_per_band(mlme_priv, session);
8809 lim_revise_req_eht_cap_per_mode(mlme_priv, session);
8810 qdf_mem_copy(&session->eht_config, &mlme_priv->eht_config,
8811 sizeof(session->eht_config));
8812 }
8813
lim_add_eht_cap(struct mac_context * mac_ctx,struct pe_session * pe_session,tpAddStaParams add_sta_params,tpSirAssocReq assoc_req)8814 void lim_add_eht_cap(struct mac_context *mac_ctx, struct pe_session *pe_session,
8815 tpAddStaParams add_sta_params, tpSirAssocReq assoc_req)
8816 {
8817 if (!add_sta_params->eht_capable || !assoc_req)
8818 return;
8819
8820 qdf_mem_copy(&add_sta_params->eht_config, &assoc_req->eht_cap,
8821 sizeof(add_sta_params->eht_config));
8822 }
8823
lim_intersect_ap_eht_caps(struct pe_session * session,struct bss_params * add_bss,tSchBeaconStruct * beacon,tpSirAssocRsp assoc_rsp)8824 void lim_intersect_ap_eht_caps(struct pe_session *session,
8825 struct bss_params *add_bss,
8826 tSchBeaconStruct *beacon,
8827 tpSirAssocRsp assoc_rsp)
8828 {
8829 tDot11fIEeht_cap *rcvd_eht;
8830 tDot11fIEeht_cap *peer_eht = &add_bss->staContext.eht_config;
8831
8832 if (assoc_rsp && assoc_rsp->eht_cap.present)
8833 rcvd_eht = &assoc_rsp->eht_cap;
8834 else
8835 rcvd_eht = &beacon->eht_cap;
8836
8837 lim_intersect_eht_caps(rcvd_eht, peer_eht, session);
8838 add_bss->staContext.eht_capable = true;
8839 }
8840
lim_add_bss_eht_cap(struct bss_params * add_bss,tpSirAssocRsp assoc_rsp)8841 void lim_add_bss_eht_cap(struct bss_params *add_bss, tpSirAssocRsp assoc_rsp)
8842 {
8843 tDot11fIEeht_cap *eht_cap;
8844 tDot11fIEeht_op *eht_op;
8845
8846 eht_cap = &assoc_rsp->eht_cap;
8847 eht_op = &assoc_rsp->eht_op;
8848 add_bss->eht_capable = eht_cap->present;
8849 if (eht_cap)
8850 qdf_mem_copy(&add_bss->staContext.eht_config,
8851 eht_cap, sizeof(*eht_cap));
8852 if (eht_op)
8853 qdf_mem_copy(&add_bss->staContext.eht_op,
8854 eht_op, sizeof(*eht_op));
8855 }
8856
lim_intersect_sta_eht_caps(struct mac_context * mac_ctx,tpSirAssocReq assoc_req,struct pe_session * session,tpDphHashNode sta_ds)8857 void lim_intersect_sta_eht_caps(struct mac_context *mac_ctx,
8858 tpSirAssocReq assoc_req,
8859 struct pe_session *session,
8860 tpDphHashNode sta_ds)
8861 {
8862 tDot11fIEeht_cap *rcvd_eht = &assoc_req->eht_cap;
8863 tDot11fIEeht_cap *peer_eht = &sta_ds->eht_config;
8864
8865 if (!sta_ds->mlmStaContext.eht_capable)
8866 return;
8867
8868 /* If EHT is not supported, do not fill sta_ds and return */
8869 if (!IS_DOT11_MODE_EHT(session->dot11mode))
8870 return;
8871
8872 lim_intersect_eht_caps(rcvd_eht, peer_eht, session);
8873 }
8874
lim_update_session_eht_capable(struct mac_context * mac,struct pe_session * session)8875 void lim_update_session_eht_capable(struct mac_context *mac,
8876 struct pe_session *session)
8877 {
8878 session->eht_capable = true;
8879 }
8880
lim_add_bss_eht_cfg(struct bss_params * add_bss,struct pe_session * session)8881 void lim_add_bss_eht_cfg(struct bss_params *add_bss, struct pe_session *session)
8882 {
8883 }
8884
8885 #define EHT_OP_LEN (DOT11F_IE_EHT_OP_MAX_LEN + EHT_OP_OUI_SIZE * 2 + ONE_BYTE)
lim_decide_eht_op(struct mac_context * mac_ctx,uint32_t * mlme_eht_ops,struct pe_session * session)8886 void lim_decide_eht_op(struct mac_context *mac_ctx, uint32_t *mlme_eht_ops,
8887 struct pe_session *session)
8888 {
8889 struct add_ie_params *add_ie = &session->add_ie_params;
8890 uint8_t extracted_buff[EHT_OP_LEN + 2];
8891 QDF_STATUS status;
8892 uint16_t ori_puncture_bitmap;
8893 uint8_t len;
8894
8895 pe_debug("beacon ie:");
8896 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
8897 add_ie->probeRespBCNData_buff,
8898 add_ie->probeRespBCNDataLen);
8899
8900 qdf_mem_zero(extracted_buff, sizeof(extracted_buff));
8901 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
8902 &add_ie->probeRespBCNDataLen,
8903 DOT11F_EID_EHT_OP, ONE_BYTE,
8904 EHT_OP_OUI_TYPE, (uint8_t)EHT_OP_OUI_SIZE,
8905 extracted_buff, EHT_OP_LEN);
8906 if (QDF_STATUS_SUCCESS != status) {
8907 pe_debug("Failed to strip EHT OP IE status: %d", status);
8908 return;
8909 }
8910
8911 pe_debug("eht op:");
8912 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
8913 extracted_buff, EHT_OP_LEN);
8914
8915 session->eht_op.present = 1;
8916
8917 len = qdf_min((uint8_t)(sizeof(tDot11fIEeht_op) - 1),
8918 (uint8_t)(DOT11F_IE_EHT_OP_MAX_LEN));
8919 qdf_mem_copy((uint8_t *)(&session->eht_op) + 1,
8920 &extracted_buff[EHT_OP_OUI_SIZE * 2 + ONE_BYTE],
8921 len);
8922
8923 ori_puncture_bitmap =
8924 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap;
8925 pe_debug("puncture bitmap: %d, ch width: %d, ccfs0: %d, ccfs1: %d",
8926 ori_puncture_bitmap, session->eht_op.channel_width,
8927 session->eht_op.ccfs0, session->eht_op.ccfs1);
8928
8929 wma_update_vdev_eht_ops(mlme_eht_ops, &session->eht_op);
8930 }
8931
lim_update_stads_eht_capable(tpDphHashNode sta_ds,tpSirAssocReq assoc_req)8932 void lim_update_stads_eht_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req)
8933 {
8934 sta_ds->mlmStaContext.eht_capable = assoc_req->eht_cap.present;
8935 }
8936
8937 #ifdef FEATURE_WLAN_TDLS
8938 #ifdef WLAN_FEATURE_11BE
lim_update_tdls_sta_eht_capable(struct mac_context * mac,tpAddStaParams add_sta_params,tpDphHashNode sta_ds,struct pe_session * session_entry)8939 void lim_update_tdls_sta_eht_capable(struct mac_context *mac,
8940 tpAddStaParams add_sta_params,
8941 tpDphHashNode sta_ds,
8942 struct pe_session *session_entry)
8943 {
8944 if (sta_ds->staType == STA_ENTRY_TDLS_PEER) {
8945 if (!sta_ds->eht_config.present)
8946 add_sta_params->eht_capable = 0;
8947 }
8948
8949 pe_debug("tdls eht_capable: %d", add_sta_params->eht_capable);
8950 }
8951 #endif
8952 #endif
8953
lim_update_sta_eht_capable(struct mac_context * mac,tpAddStaParams add_sta_params,tpDphHashNode sta_ds,struct pe_session * session_entry)8954 void lim_update_sta_eht_capable(struct mac_context *mac,
8955 tpAddStaParams add_sta_params,
8956 tpDphHashNode sta_ds,
8957 struct pe_session *session_entry)
8958 {
8959 if (LIM_IS_AP_ROLE(session_entry))
8960 add_sta_params->eht_capable =
8961 sta_ds->mlmStaContext.eht_capable &&
8962 session_entry->eht_capable;
8963 else
8964 add_sta_params->eht_capable = session_entry->eht_capable;
8965
8966 pe_debug("eht_capable: %d", add_sta_params->eht_capable);
8967 }
8968
lim_update_session_eht_capable_chan_switch(struct mac_context * mac,struct pe_session * session,uint32_t new_chan_freq)8969 void lim_update_session_eht_capable_chan_switch(struct mac_context *mac,
8970 struct pe_session *session,
8971 uint32_t new_chan_freq)
8972 {
8973 session->eht_capable = true;
8974 session->he_capable = true;
8975 /* TODO: Update */
8976 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) &&
8977 !wlan_reg_is_6ghz_chan_freq(new_chan_freq)) {
8978 session->htCapability = 1;
8979 session->vhtCapability = 1;
8980 session->he_6ghz_band = 0;
8981 } else if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) &&
8982 wlan_reg_is_6ghz_chan_freq(new_chan_freq)) {
8983 session->htCapability = 0;
8984 session->vhtCapability = 0;
8985 session->he_6ghz_band = 1;
8986 }
8987
8988 /*
8989 * If new channel is 2.4gh set VHT as per the b24ghz_band INI
8990 * if new channel is 5Ghz set the vht, this will happen if we move from
8991 * 2.4Ghz to 5Ghz.
8992 */
8993 if (wlan_reg_is_24ghz_ch_freq(new_chan_freq) &&
8994 !mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band)
8995 session->vhtCapability = 0;
8996 else if (wlan_reg_is_5ghz_ch_freq(new_chan_freq))
8997 session->vhtCapability = 1;
8998
8999 pe_debug("eht_capable:%d he_capable:%d ht:%d vht:%d 6ghz_band:%d new freq:%d vht in 2.4gh:%d",
9000 session->eht_capable, session->he_capable,
9001 session->htCapability, session->vhtCapability,
9002 session->he_6ghz_band, new_chan_freq,
9003 mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band);
9004 }
9005
lim_update_bss_eht_capable(struct mac_context * mac,struct bss_params * add_bss)9006 void lim_update_bss_eht_capable(struct mac_context *mac,
9007 struct bss_params *add_bss)
9008 {
9009 add_bss->eht_capable = true;
9010 pe_debug("eht_capable: %d", add_bss->eht_capable);
9011 }
9012
lim_log_eht_cap(struct mac_context * mac,tDot11fIEeht_cap * eht_cap)9013 void lim_log_eht_cap(struct mac_context *mac, tDot11fIEeht_cap *eht_cap)
9014 {
9015 if (!eht_cap->present)
9016 return;
9017
9018 pe_nofl_debug("EHT Capabilities:");
9019 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
9020 eht_cap, sizeof(tDot11fIEeht_cap));
9021 }
9022
lim_log_eht_op(struct mac_context * mac,tDot11fIEeht_op * eht_ops,struct pe_session * session)9023 void lim_log_eht_op(struct mac_context *mac, tDot11fIEeht_op *eht_ops,
9024 struct pe_session *session)
9025 {
9026 if (!eht_ops->present)
9027 return;
9028
9029 pe_nofl_debug("EHT operation element:");
9030 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
9031 eht_ops, sizeof(tDot11fIEeht_op));
9032 }
9033
9034 static void
lim_revise_eht_caps(struct mac_context * mac,tDot11fIEeht_cap * eht_cap)9035 lim_revise_eht_caps(struct mac_context *mac, tDot11fIEeht_cap *eht_cap)
9036 {
9037 uint32_t country_max_allowed_bw;
9038
9039 country_max_allowed_bw = wlan_reg_get_country_max_allowed_bw(mac->pdev);
9040 if (!country_max_allowed_bw) {
9041 pe_debug("Failed to get country_max_allowed_bw");
9042 return;
9043 }
9044
9045 if (country_max_allowed_bw < BW_320_MHZ)
9046 eht_cap->support_320mhz_6ghz = 0;
9047 }
9048
lim_set_eht_caps(struct mac_context * mac,uint8_t * ie_start,uint32_t num_bytes,uint8_t band,uint8_t vdev_id)9049 void lim_set_eht_caps(struct mac_context *mac,
9050 uint8_t *ie_start, uint32_t num_bytes, uint8_t band,
9051 uint8_t vdev_id)
9052 {
9053 const uint8_t *ie = NULL;
9054 uint8_t offset = 0;
9055 uint8_t offset_1 = 0;
9056 tDot11fIEeht_cap dot11_cap;
9057 tDot11fIEhe_cap dot11_he_cap;
9058 struct wlan_eht_cap_info *eht_cap;
9059 struct wlan_eht_cap_info eht_mcs_cap;
9060 bool is_band_2g = false;
9061 uint32_t cbm_24ghz;
9062 struct wlan_objmgr_vdev *vdev;
9063
9064 if (band == CDS_BAND_2GHZ)
9065 is_band_2g = true;
9066
9067 populate_dot11f_eht_caps_by_band(mac, is_band_2g, &dot11_cap, NULL);
9068 lim_revise_eht_caps(mac, &dot11_cap);
9069 populate_dot11f_he_caps_by_band(mac, is_band_2g, &dot11_he_cap,
9070 NULL);
9071 lim_log_eht_cap(mac, &dot11_cap);
9072
9073 if (is_band_2g) {
9074 cbm_24ghz = lim_get_sta_cb_mode_for_24ghz(mac, vdev_id);
9075 if (!cbm_24ghz) {
9076 /* B0: 40Mhz channel width in the 2.4GHz band */
9077 dot11_he_cap.chan_width_0 = 0;
9078 dot11_he_cap.he_ppdu_20_in_40Mhz_2G = 0;
9079 }
9080 }
9081
9082 ie = wlan_get_ext_ie_ptr_from_ext_id(EHT_CAP_OUI_TYPE,
9083 EHT_CAP_OUI_SIZE,
9084 ie_start, num_bytes);
9085
9086 if (ie) {
9087 /* convert from unpacked to packed structure */
9088 eht_cap = (struct wlan_eht_cap_info *)&ie[2 + EHT_CAP_OUI_SIZE];
9089
9090 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
9091 WLAN_MLME_CM_ID);
9092 if (wlan_epcs_get_config(vdev))
9093 eht_cap->epcs_pri_access = 1;
9094 else
9095 eht_cap->epcs_pri_access = 0;
9096
9097 if (vdev)
9098 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
9099
9100 eht_cap->eht_om_ctl = dot11_cap.eht_om_ctl;
9101 eht_cap->triggered_txop_sharing_mode1 =
9102 dot11_cap.triggered_txop_sharing_mode1;
9103 eht_cap->triggered_txop_sharing_mode2 =
9104 dot11_cap.triggered_txop_sharing_mode2;
9105 eht_cap->restricted_twt =
9106 dot11_cap.restricted_twt;
9107 eht_cap->scs_traffic_desc =
9108 dot11_cap.scs_traffic_desc;
9109 eht_cap->max_mpdu_len =
9110 dot11_cap.max_mpdu_len;
9111 eht_cap->max_a_mpdu_len_exponent_ext =
9112 dot11_cap.max_a_mpdu_len_exponent_ext;
9113 eht_cap->eht_trs_support = dot11_cap.eht_trs_support;
9114 eht_cap->txop_return_support_txop_share_m2 =
9115 dot11_cap.txop_return_support_txop_share_m2;
9116 eht_cap->two_bqrs_support =
9117 dot11_cap.two_bqrs_support;
9118 eht_cap->eht_link_adaptation_support =
9119 dot11_cap.eht_link_adaptation_support;
9120 eht_cap->support_320mhz_6ghz = dot11_cap.support_320mhz_6ghz;
9121 eht_cap->ru_242tone_wt_20mhz = dot11_cap.ru_242tone_wt_20mhz;
9122 eht_cap->ndp_4x_eht_ltf_3dot2_us_gi =
9123 dot11_cap.ndp_4x_eht_ltf_3dot2_us_gi;
9124 eht_cap->partial_bw_mu_mimo = dot11_cap.partial_bw_mu_mimo;
9125 eht_cap->su_beamformer = dot11_cap.su_beamformer;
9126 eht_cap->su_beamformee = dot11_cap.su_beamformee;
9127 eht_cap->bfee_ss_le_80mhz = dot11_cap.bfee_ss_le_80mhz;
9128 eht_cap->bfee_ss_160mhz = dot11_cap.bfee_ss_160mhz;
9129 eht_cap->bfee_ss_320mhz = dot11_cap.bfee_ss_320mhz;
9130 eht_cap->num_sounding_dim_le_80mhz =
9131 dot11_cap.num_sounding_dim_le_80mhz;
9132 eht_cap->num_sounding_dim_160mhz =
9133 dot11_cap.num_sounding_dim_160mhz;
9134 eht_cap->num_sounding_dim_320mhz =
9135 dot11_cap.num_sounding_dim_320mhz;
9136 eht_cap->ng_16_su_feedback = dot11_cap.ng_16_su_feedback;
9137 eht_cap->ng_16_mu_feedback = dot11_cap.ng_16_mu_feedback;
9138 eht_cap->cb_sz_4_2_su_feedback =
9139 dot11_cap.cb_sz_4_2_su_feedback;
9140 eht_cap->cb_sz_7_5_su_feedback =
9141 dot11_cap.cb_sz_7_5_su_feedback;
9142 eht_cap->trig_su_bforming_feedback =
9143 dot11_cap.trig_su_bforming_feedback;
9144 eht_cap->trig_mu_bforming_partial_bw_feedback =
9145 dot11_cap.trig_mu_bforming_partial_bw_feedback;
9146 eht_cap->triggered_cqi_feedback =
9147 dot11_cap.triggered_cqi_feedback;
9148 eht_cap->partial_bw_dl_mu_mimo =
9149 dot11_cap.partial_bw_dl_mu_mimo;
9150 eht_cap->psr_based_sr = dot11_cap.psr_based_sr;
9151 eht_cap->power_boost_factor = dot11_cap.power_boost_factor;
9152 eht_cap->eht_mu_ppdu_4x_ltf_0_8_us_gi =
9153 dot11_cap.eht_mu_ppdu_4x_ltf_0_8_us_gi;
9154 eht_cap->max_nc = dot11_cap.max_nc;
9155 eht_cap->non_trig_cqi_feedback =
9156 dot11_cap.non_trig_cqi_feedback;
9157 eht_cap->tx_1024_4096_qam_lt_242_tone_ru =
9158 dot11_cap.tx_1024_4096_qam_lt_242_tone_ru;
9159 eht_cap->rx_1024_4096_qam_lt_242_tone_ru =
9160 dot11_cap.rx_1024_4096_qam_lt_242_tone_ru;
9161 eht_cap->ppet_present = dot11_cap.ppet_present;
9162 eht_cap->common_nominal_pkt_padding =
9163 dot11_cap.common_nominal_pkt_padding;
9164 eht_cap->max_num_eht_ltf = dot11_cap.max_num_eht_ltf;
9165 eht_cap->mcs_15 = dot11_cap.mcs_15;
9166 eht_cap->eht_dup_6ghz = dot11_cap.eht_dup_6ghz;
9167 eht_cap->op_sta_rx_ndp_wider_bw_20mhz =
9168 dot11_cap.op_sta_rx_ndp_wider_bw_20mhz;
9169 eht_cap->non_ofdma_ul_mu_mimo_le_80mhz =
9170 dot11_cap.non_ofdma_ul_mu_mimo_le_80mhz;
9171 eht_cap->non_ofdma_ul_mu_mimo_160mhz =
9172 dot11_cap.non_ofdma_ul_mu_mimo_160mhz;
9173 eht_cap->non_ofdma_ul_mu_mimo_320mhz =
9174 dot11_cap.non_ofdma_ul_mu_mimo_320mhz;
9175 eht_cap->mu_bformer_le_80mhz =
9176 dot11_cap.mu_bformer_le_80mhz;
9177 eht_cap->mu_bformer_160mhz = dot11_cap.mu_bformer_160mhz;
9178 eht_cap->mu_bformer_320mhz = dot11_cap.mu_bformer_320mhz;
9179 eht_cap->tb_sounding_feedback_rl =
9180 dot11_cap.tb_sounding_feedback_rl;
9181 eht_cap->rx_1k_qam_in_wider_bw_dl_ofdma =
9182 dot11_cap.rx_1k_qam_in_wider_bw_dl_ofdma;
9183 eht_cap->rx_4k_qam_in_wider_bw_dl_ofdma =
9184 dot11_cap.rx_4k_qam_in_wider_bw_dl_ofdma;
9185 eht_cap->limited_cap_support_20mhz =
9186 dot11_cap.limited_cap_support_20mhz;
9187 eht_cap->triggered_mu_bf_full_bw_fb_and_dl_mumimo =
9188 dot11_cap.triggered_mu_bf_full_bw_fb_and_dl_mumimo;
9189 eht_cap->mru_support_20mhz =
9190 dot11_cap.mru_support_20mhz;
9191
9192 if ((is_band_2g && !dot11_he_cap.chan_width_0) ||
9193 (!is_band_2g && !dot11_he_cap.chan_width_1 &&
9194 !dot11_he_cap.chan_width_2 &&
9195 !dot11_he_cap.chan_width_3)) {
9196 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_0_to_7 =
9197 dot11_cap.bw_20_rx_max_nss_for_mcs_0_to_7;
9198 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_0_to_7 =
9199 dot11_cap.bw_20_tx_max_nss_for_mcs_0_to_7;
9200 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_8_and_9 =
9201 dot11_cap.bw_20_rx_max_nss_for_mcs_8_and_9;
9202 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_8_and_9 =
9203 dot11_cap.bw_20_tx_max_nss_for_mcs_8_and_9;
9204 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_10_and_11 =
9205 dot11_cap.bw_20_rx_max_nss_for_mcs_10_and_11;
9206 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_10_and_11 =
9207 dot11_cap.bw_20_tx_max_nss_for_mcs_10_and_11;
9208 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_12_and_13 =
9209 dot11_cap.bw_20_rx_max_nss_for_mcs_12_and_13;
9210 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_12_and_13 =
9211 dot11_cap.bw_20_tx_max_nss_for_mcs_12_and_13;
9212 offset = ie_start[1] + 3;
9213 qdf_mem_copy(&ie_start[offset],
9214 (((uint8_t *)&eht_mcs_cap) +
9215 EHT_CAP_FIXED_FIELDS),
9216 EHT_CAP_20M_MCS_MAP_LEN);
9217 ie_start[1] += EHT_CAP_20M_MCS_MAP_LEN;
9218
9219 return;
9220 }
9221
9222 if ((is_band_2g && dot11_he_cap.chan_width_0) ||
9223 (!is_band_2g && dot11_he_cap.chan_width_1)) {
9224 eht_mcs_cap.bw_le_80_rx_max_nss_for_mcs_0_to_9 =
9225 dot11_cap.bw_le_80_rx_max_nss_for_mcs_0_to_9;
9226 eht_mcs_cap.bw_le_80_tx_max_nss_for_mcs_0_to_9 =
9227 dot11_cap.bw_le_80_tx_max_nss_for_mcs_0_to_9;
9228 eht_mcs_cap.bw_le_80_rx_max_nss_for_mcs_10_and_11 =
9229 dot11_cap.bw_le_80_rx_max_nss_for_mcs_10_and_11;
9230 eht_mcs_cap.bw_le_80_tx_max_nss_for_mcs_10_and_11 =
9231 dot11_cap.bw_le_80_tx_max_nss_for_mcs_10_and_11;
9232 eht_mcs_cap.bw_le_80_rx_max_nss_for_mcs_12_and_13 =
9233 dot11_cap.bw_le_80_rx_max_nss_for_mcs_12_and_13;
9234 eht_mcs_cap.bw_le_80_tx_max_nss_for_mcs_12_and_13 =
9235 dot11_cap.bw_le_80_tx_max_nss_for_mcs_12_and_13;
9236 offset = ie_start[1] + 3;
9237 offset_1 = EHT_CAP_FIXED_FIELDS +
9238 EHT_CAP_20M_MCS_MAP_LEN;
9239 qdf_mem_copy(&ie_start[offset],
9240 (((uint8_t *)&eht_mcs_cap) + offset_1),
9241 EHT_CAP_80M_MCS_MAP_LEN);
9242 ie_start[1] += EHT_CAP_80M_MCS_MAP_LEN;
9243 }
9244
9245 if (!is_band_2g && dot11_he_cap.chan_width_2) {
9246 eht_mcs_cap.bw_160_rx_max_nss_for_mcs_0_to_9 =
9247 dot11_cap.bw_160_rx_max_nss_for_mcs_0_to_9;
9248 eht_mcs_cap.bw_160_tx_max_nss_for_mcs_0_to_9 =
9249 dot11_cap.bw_160_tx_max_nss_for_mcs_0_to_9;
9250 eht_mcs_cap.bw_160_rx_max_nss_for_mcs_10_and_11 =
9251 dot11_cap.bw_160_rx_max_nss_for_mcs_10_and_11;
9252 eht_mcs_cap.bw_160_tx_max_nss_for_mcs_10_and_11 =
9253 dot11_cap.bw_160_tx_max_nss_for_mcs_10_and_11;
9254 eht_mcs_cap.bw_160_rx_max_nss_for_mcs_12_and_13 =
9255 dot11_cap.bw_160_rx_max_nss_for_mcs_12_and_13;
9256 eht_mcs_cap.bw_160_tx_max_nss_for_mcs_12_and_13 =
9257 dot11_cap.bw_160_tx_max_nss_for_mcs_12_and_13;
9258 offset = ie_start[1] + 3;
9259 offset_1 = EHT_CAP_FIXED_FIELDS +
9260 EHT_CAP_20M_MCS_MAP_LEN +
9261 EHT_CAP_80M_MCS_MAP_LEN;
9262 qdf_mem_copy(&ie_start[offset],
9263 (((uint8_t *)&eht_mcs_cap) + offset_1),
9264 EHT_CAP_160M_MCS_MAP_LEN);
9265 ie_start[1] += EHT_CAP_160M_MCS_MAP_LEN;
9266
9267 }
9268
9269 if (!is_band_2g && eht_cap->support_320mhz_6ghz) {
9270 eht_mcs_cap.bw_320_rx_max_nss_for_mcs_0_to_9 =
9271 dot11_cap.bw_320_rx_max_nss_for_mcs_0_to_9;
9272 eht_mcs_cap.bw_320_tx_max_nss_for_mcs_0_to_9 =
9273 dot11_cap.bw_320_tx_max_nss_for_mcs_0_to_9;
9274 eht_mcs_cap.bw_320_rx_max_nss_for_mcs_10_and_11 =
9275 dot11_cap.bw_320_rx_max_nss_for_mcs_10_and_11;
9276 eht_mcs_cap.bw_320_tx_max_nss_for_mcs_10_and_11 =
9277 dot11_cap.bw_320_tx_max_nss_for_mcs_10_and_11;
9278 eht_mcs_cap.bw_320_rx_max_nss_for_mcs_12_and_13 =
9279 dot11_cap.bw_320_rx_max_nss_for_mcs_12_and_13;
9280 eht_mcs_cap.bw_320_tx_max_nss_for_mcs_12_and_13 =
9281 dot11_cap.bw_320_tx_max_nss_for_mcs_12_and_13;
9282 offset = ie_start[1] + 3;
9283 offset_1 = EHT_CAP_FIXED_FIELDS +
9284 EHT_CAP_20M_MCS_MAP_LEN +
9285 EHT_CAP_80M_MCS_MAP_LEN +
9286 EHT_CAP_160M_MCS_MAP_LEN;
9287 qdf_mem_copy(&ie_start[offset],
9288 (((uint8_t *)&eht_mcs_cap) + offset_1),
9289 EHT_CAP_320M_MCS_MAP_LEN);
9290 ie_start[1] += EHT_CAP_320M_MCS_MAP_LEN;
9291 }
9292 }
9293 }
9294
lim_send_eht_caps_ie(struct mac_context * mac_ctx,enum QDF_OPMODE device_mode,uint8_t vdev_id)9295 QDF_STATUS lim_send_eht_caps_ie(struct mac_context *mac_ctx,
9296 enum QDF_OPMODE device_mode,
9297 uint8_t vdev_id)
9298 {
9299 uint8_t eht_cap_total_len = DOT11F_IE_EHT_CAP_MIN_LEN +
9300 EHT_CAP_OUI_LEN + EHT_CAP_20M_MCS_MAP_LEN +
9301 EHT_CAP_80M_MCS_MAP_LEN +
9302 EHT_CAP_160M_MCS_MAP_LEN +
9303 EHT_CAP_320M_MCS_MAP_LEN;
9304 QDF_STATUS status_2g, status_5g;
9305 uint8_t eht_caps_2g[DOT11F_IE_EHT_CAP_MIN_LEN +
9306 EHT_CAP_OUI_LEN + EHT_CAP_20M_MCS_MAP_LEN +
9307 EHT_CAP_80M_MCS_MAP_LEN +
9308 EHT_CAP_160M_MCS_MAP_LEN +
9309 EHT_CAP_320M_MCS_MAP_LEN] = {0};
9310
9311 uint8_t eht_caps_5g[DOT11F_IE_EHT_CAP_MIN_LEN +
9312 EHT_CAP_OUI_LEN + EHT_CAP_20M_MCS_MAP_LEN +
9313 EHT_CAP_80M_MCS_MAP_LEN +
9314 EHT_CAP_160M_MCS_MAP_LEN +
9315 EHT_CAP_320M_MCS_MAP_LEN] = {0};
9316
9317 eht_caps_2g[0] = DOT11F_EID_EHT_CAP;
9318 eht_caps_2g[1] = EHT_CAP_FIXED_FIELDS;
9319
9320 qdf_mem_copy(&eht_caps_2g[2], EHT_CAP_OUI_TYPE, EHT_CAP_OUI_SIZE);
9321
9322 lim_set_eht_caps(mac_ctx, eht_caps_2g, eht_cap_total_len,
9323 CDS_BAND_2GHZ, vdev_id);
9324 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_EHT_CAP,
9325 CDS_BAND_2GHZ, &eht_caps_2g[2],
9326 eht_caps_2g[1] + 1);
9327
9328 eht_caps_5g[0] = DOT11F_EID_EHT_CAP;
9329 eht_caps_5g[1] = EHT_CAP_FIXED_FIELDS;
9330
9331 qdf_mem_copy(&eht_caps_5g[2], EHT_CAP_OUI_TYPE, EHT_CAP_OUI_SIZE);
9332
9333 lim_set_eht_caps(mac_ctx, eht_caps_5g, eht_cap_total_len,
9334 CDS_BAND_5GHZ, vdev_id);
9335 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_EHT_CAP,
9336 CDS_BAND_5GHZ, &eht_caps_5g[2],
9337 eht_caps_5g[1] + 1);
9338
9339 if (QDF_IS_STATUS_SUCCESS(status_2g) &&
9340 QDF_IS_STATUS_SUCCESS(status_5g)) {
9341 return QDF_STATUS_SUCCESS;
9342 }
9343 return QDF_STATUS_SUCCESS;
9344 }
9345
lim_update_stads_eht_caps(struct mac_context * mac_ctx,tpDphHashNode sta_ds,tpSirAssocRsp assoc_rsp,struct pe_session * session_entry,tSchBeaconStruct * beacon)9346 void lim_update_stads_eht_caps(struct mac_context *mac_ctx,
9347 tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
9348 struct pe_session *session_entry,
9349 tSchBeaconStruct *beacon)
9350 {
9351 /* If EHT is not supported, do not fill sta_ds and return */
9352 if (!IS_DOT11_MODE_EHT(session_entry->dot11mode))
9353 return;
9354
9355 if (!assoc_rsp->eht_cap.present && beacon && beacon->eht_cap.present) {
9356 /* Use beacon EHT caps if assoc resp doesn't have he caps */
9357 pe_debug("eht_caps missing in assoc rsp");
9358 qdf_mem_copy(&assoc_rsp->eht_cap, &beacon->eht_cap,
9359 sizeof(tDot11fIEeht_cap));
9360 }
9361
9362 /* assoc resp and beacon doesn't have eht caps */
9363 if (!assoc_rsp->eht_cap.present)
9364 return;
9365
9366 sta_ds->mlmStaContext.eht_capable = assoc_rsp->eht_cap.present;
9367
9368 qdf_mem_copy(&sta_ds->eht_config, &assoc_rsp->eht_cap,
9369 sizeof(tDot11fIEeht_cap));
9370 }
9371
lim_update_stads_eht_bw_320mhz(struct pe_session * session,tpDphHashNode sta_ds)9372 void lim_update_stads_eht_bw_320mhz(struct pe_session *session,
9373 tpDphHashNode sta_ds)
9374 {
9375 tDot11fIEeht_cap *peer_eht = &sta_ds->eht_config;
9376
9377 if (!IS_DOT11_MODE_EHT(session->dot11mode) || !peer_eht->present)
9378 return;
9379
9380 /* EHT only defines 320 MHz. If session is not in 320 MHz, BW will be
9381 * set in HE mode.
9382 *
9383 * Set ch_width to 320 MHz only when session is in 320 MHz and peer eht
9384 * caps support 320 MHz after eht caps intersection.
9385 */
9386 if (session->ch_width == CH_WIDTH_320MHZ &&
9387 peer_eht->support_320mhz_6ghz) {
9388 sta_ds->ch_width = CH_WIDTH_320MHZ;
9389 pe_debug("ch_width %d", sta_ds->ch_width);
9390 }
9391 }
9392
9393 #endif
9394
9395 #ifdef WLAN_FEATURE_11BE_MLO
lim_extract_per_link_id(struct pe_session * session,struct bss_params * add_bss,tpSirAssocRsp assoc_rsp)9396 void lim_extract_per_link_id(struct pe_session *session,
9397 struct bss_params *add_bss,
9398 tpSirAssocRsp assoc_rsp)
9399 {
9400 uint8_t vdev_id = wlan_vdev_get_id(session->vdev);
9401
9402 if (!wlan_vdev_mlme_is_mlo_link_vdev(session->vdev) &&
9403 assoc_rsp->mlo_ie.mlo_ie.link_id_info_present)
9404 add_bss->staContext.link_id =
9405 assoc_rsp->mlo_ie.mlo_ie.link_id;
9406 else
9407 add_bss->staContext.link_id =
9408 wlan_vdev_get_link_id(session->vdev);
9409
9410 pe_debug("vdev: %d, link id: %d", vdev_id, add_bss->staContext.link_id);
9411 }
9412
lim_extract_ml_info(struct pe_session * session,struct bss_params * add_bss,tpSirAssocRsp assoc_rsp)9413 void lim_extract_ml_info(struct pe_session *session,
9414 struct bss_params *add_bss,
9415 tpSirAssocRsp assoc_rsp)
9416 {
9417 uint8_t i, link_id, partner_idx = 0;
9418 struct mlo_partner_info *ml_partner_info;
9419 struct mlo_link_info *link_info;
9420 struct peer_ml_info *ml_link;
9421
9422 if (!wlan_vdev_mlme_is_mlo_vdev(session->vdev))
9423 return;
9424
9425 ml_link = &add_bss->staContext.ml_info;
9426 ml_partner_info = &session->ml_partner_info;
9427
9428 ml_link->vdev_id = wlan_vdev_get_id(session->vdev);
9429 ml_link->link_id = wlan_vdev_get_link_id(session->vdev);
9430
9431 ml_link->rec_max_simultaneous_links =
9432 session->vdev->mlo_dev_ctx->mlo_max_recom_simult_links;
9433
9434 link_info = mlo_mgr_get_ap_link_by_link_id(session->vdev->mlo_dev_ctx,
9435 ml_link->link_id);
9436 if (!link_info)
9437 return;
9438
9439 qdf_mem_copy(&ml_link->channel_info, link_info->link_chan_info,
9440 sizeof(ml_link->channel_info));
9441 qdf_mem_copy(&ml_link->link_addr, &link_info->ap_link_addr,
9442 QDF_MAC_ADDR_SIZE);
9443 qdf_mem_copy(&ml_link->self_mac_addr, &link_info->link_addr,
9444 QDF_MAC_ADDR_SIZE);
9445
9446 if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev))
9447 return;
9448
9449 for (i = 0; i < ml_partner_info->num_partner_links; i++) {
9450 link_id = ml_partner_info->partner_link_info[i].link_id;
9451 link_info = mlo_mgr_get_ap_link_by_link_id(
9452 session->vdev->mlo_dev_ctx,
9453 link_id);
9454 if (!link_info)
9455 continue;
9456
9457 ml_link->partner_info[partner_idx].vdev_id = link_info->vdev_id;
9458 ml_link->partner_info[partner_idx].link_id = link_info->link_id;
9459
9460 qdf_mem_copy(&ml_link->partner_info[partner_idx].channel_info,
9461 link_info->link_chan_info,
9462 sizeof(ml_link->partner_info[partner_idx].channel_info));
9463 qdf_mem_copy(&ml_link->partner_info[partner_idx].link_addr,
9464 &link_info->ap_link_addr, QDF_MAC_ADDR_SIZE);
9465 qdf_mem_copy(&ml_link->partner_info[partner_idx].self_mac_addr,
9466 &link_info->link_addr, QDF_MAC_ADDR_SIZE);
9467
9468 partner_idx++;
9469 }
9470
9471 ml_link->num_links = partner_idx;
9472 pe_debug("vdev:%d Num of partner links: %d", session->vdev_id,
9473 ml_link->num_links);
9474 }
9475
lim_intersect_ap_emlsr_caps(struct mac_context * mac_ctx,struct pe_session * session,struct bss_params * add_bss,tpSirAssocRsp assoc_rsp)9476 void lim_intersect_ap_emlsr_caps(struct mac_context *mac_ctx,
9477 struct pe_session *session,
9478 struct bss_params *add_bss,
9479 tpSirAssocRsp assoc_rsp)
9480 {
9481 struct wlan_mlo_sta *sta_ctx;
9482 struct wlan_objmgr_vdev *vdev = session->vdev;
9483 struct emlsr_capability *ml_emlcap;
9484
9485 wlan_objmgr_vdev_get_ref(vdev, WLAN_MLME_NB_ID);
9486 if (!vdev) {
9487 pe_err("vdev is null");
9488 return;
9489 }
9490
9491 if (!vdev->mlo_dev_ctx) {
9492 pe_err("mlo dev ctx is null");
9493 goto end;
9494 }
9495
9496 sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
9497 if (!sta_ctx) {
9498 pe_err("sta ctx is null");
9499 goto end;
9500 }
9501
9502 ml_emlcap = &sta_ctx->emlsr_cap;
9503
9504 if (!wlan_vdev_mlme_cap_get(vdev, WLAN_VDEV_C_EMLSR_CAP)) {
9505 add_bss->staContext.emlsr_support = false;
9506 goto end;
9507 }
9508
9509 if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev)) {
9510 add_bss->staContext.emlsr_support = ml_emlcap->emlsr_supp;
9511 add_bss->staContext.emlsr_trans_timeout =
9512 ml_emlcap->trans_timeout;
9513 } else {
9514 add_bss->staContext.emlsr_support = true;
9515 add_bss->staContext.emlsr_trans_timeout =
9516 assoc_rsp->mlo_ie.mlo_ie.eml_capabilities_info.transition_timeout;
9517
9518 ml_emlcap->emlsr_supp = add_bss->staContext.emlsr_support;
9519 ml_emlcap->trans_timeout =
9520 add_bss->staContext.emlsr_trans_timeout;
9521 }
9522
9523 end:
9524 pe_debug("emlsr support: %d, transition timeout:%d",
9525 add_bss->staContext.emlsr_support,
9526 add_bss->staContext.emlsr_trans_timeout);
9527
9528 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
9529 }
9530
9531 #define MAX_MSD_OFDM_ED_THRESHOLD 10
9532
lim_extract_msd_caps(struct mac_context * mac_ctx,struct pe_session * session,struct bss_params * add_bss,tpSirAssocRsp assoc_rsp)9533 void lim_extract_msd_caps(struct mac_context *mac_ctx,
9534 struct pe_session *session,
9535 struct bss_params *add_bss,
9536 tpSirAssocRsp assoc_rsp)
9537 {
9538 struct wlan_objmgr_peer *peer;
9539 struct wlan_mlo_peer_context *mlo_peer_ctx;
9540
9541 peer = wlan_objmgr_get_peer_by_mac(mac_ctx->psoc, add_bss->bssId,
9542 WLAN_LEGACY_MAC_ID);
9543 if (!peer) {
9544 pe_err("peer is null");
9545 return;
9546 }
9547
9548 mlo_peer_ctx = peer->mlo_peer_ctx;
9549 if (!mlo_peer_ctx) {
9550 pe_err("mlo peer ctx is null");
9551 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
9552 return;
9553 }
9554
9555 if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev)) {
9556 add_bss->staContext.msd_caps_present =
9557 mlo_peer_ctx->msd_cap_present;
9558 add_bss->staContext.msd_caps.med_sync_duration =
9559 mlo_peer_ctx->mlpeer_msdcap.medium_sync_duration;
9560 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh =
9561 mlo_peer_ctx->mlpeer_msdcap.medium_sync_ofdm_ed_thresh;
9562 add_bss->staContext.msd_caps.med_sync_max_txop_num =
9563 mlo_peer_ctx->mlpeer_msdcap.medium_sync_max_txop_num;
9564 } else {
9565 add_bss->staContext.msd_caps_present =
9566 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info_present;
9567 if (add_bss->staContext.msd_caps_present) {
9568 add_bss->staContext.msd_caps.med_sync_duration =
9569 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info.medium_sync_duration;
9570 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh =
9571 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info.medium_sync_ofdm_ed_thresh;
9572 if (add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh >
9573 MAX_MSD_OFDM_ED_THRESHOLD)
9574 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh = 0;
9575 add_bss->staContext.msd_caps.med_sync_max_txop_num =
9576 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info.medium_sync_max_txop_num;
9577 } else {
9578 /**
9579 * Fill MSD params with default values if MSD caps are
9580 * absent.
9581 * MSD duration = 5484usec / 32 = 171.
9582 * OFDM ED threshold = 0. FW adds -72 to Host value.
9583 * Maximum number of TXOPs = AP value (default = 0).
9584 */
9585 add_bss->staContext.msd_caps.med_sync_duration = 171;
9586 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh = 0;
9587 add_bss->staContext.msd_caps.med_sync_max_txop_num = 0;
9588 }
9589 mlo_peer_ctx->msd_cap_present =
9590 add_bss->staContext.msd_caps_present;
9591 mlo_peer_ctx->mlpeer_msdcap.medium_sync_duration =
9592 add_bss->staContext.msd_caps.med_sync_duration;
9593 mlo_peer_ctx->mlpeer_msdcap.medium_sync_ofdm_ed_thresh =
9594 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh;
9595 mlo_peer_ctx->mlpeer_msdcap.medium_sync_max_txop_num =
9596 add_bss->staContext.msd_caps.med_sync_max_txop_num;
9597 }
9598
9599 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
9600 pe_debug("MSD caps: %d, Duration: %d, Threshold:%d, TXOP num: %d",
9601 add_bss->staContext.msd_caps_present,
9602 add_bss->staContext.msd_caps.med_sync_duration,
9603 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh,
9604 add_bss->staContext.msd_caps.med_sync_max_txop_num);
9605 }
9606 #endif
9607
9608 #if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX)
lim_send_he_6g_band_caps_ie(struct mac_context * mac_ctx,uint8_t vdev_id)9609 QDF_STATUS lim_send_he_6g_band_caps_ie(struct mac_context *mac_ctx,
9610 uint8_t vdev_id)
9611 {
9612 uint8_t he_6g_band_caps_ie[DOT11F_IE_HE_6GHZ_BAND_CAP_MIN_LEN + 3];
9613 tDot11fIEhe_6ghz_band_cap he_6g_band_cap;
9614 QDF_STATUS status;
9615 uint32_t size = 0;
9616 uint32_t result;
9617
9618 qdf_mem_zero(&he_6g_band_cap, sizeof(he_6g_band_cap));
9619 populate_dot11f_he_6ghz_cap(mac_ctx, NULL, &he_6g_band_cap);
9620 if (!he_6g_band_cap.present) {
9621 pe_debug("no HE 6g band cap for vdev %d", vdev_id);
9622 return QDF_STATUS_SUCCESS;
9623 }
9624
9625 qdf_mem_zero(he_6g_band_caps_ie, sizeof(he_6g_band_caps_ie));
9626 result = dot11f_pack_ie_he_6ghz_band_cap(mac_ctx, &he_6g_band_cap,
9627 he_6g_band_caps_ie,
9628 sizeof(he_6g_band_caps_ie),
9629 &size);
9630 if (result != DOT11F_PARSE_SUCCESS) {
9631 pe_err("pack error for HE 6g band cap for vdev %d", vdev_id);
9632 return QDF_STATUS_E_FAILURE;
9633 }
9634 pe_debug("send HE 6ghz band cap: 0x%01x 0x%01x for vdev %d",
9635 he_6g_band_caps_ie[3], he_6g_band_caps_ie[4],
9636 vdev_id);
9637 status = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_6GHZ_BAND_CAP,
9638 CDS_BAND_5GHZ, &he_6g_band_caps_ie[2],
9639 DOT11F_IE_HE_6GHZ_BAND_CAP_MIN_LEN + 1);
9640 if (QDF_IS_STATUS_ERROR(status))
9641 pe_err("Unable send HE 6g band Cap IE for 5GHZ band, status: %d",
9642 status);
9643
9644 return status;
9645 }
9646 #endif
9647
9648 int
lim_assoc_rej_get_remaining_delta(struct sir_rssi_disallow_lst * node)9649 lim_assoc_rej_get_remaining_delta(struct sir_rssi_disallow_lst *node)
9650 {
9651 qdf_time_t cur_time;
9652 uint32_t time_diff;
9653
9654 cur_time = qdf_do_div(qdf_get_monotonic_boottime(),
9655 QDF_MC_TIMER_TO_MS_UNIT);
9656 time_diff = cur_time - node->time_during_rejection;
9657
9658 return node->retry_delay - time_diff;
9659 }
9660
9661 QDF_STATUS
lim_rem_denylist_entry_with_lowest_delta(qdf_list_t * list)9662 lim_rem_denylist_entry_with_lowest_delta(qdf_list_t *list)
9663 {
9664 struct sir_rssi_disallow_lst *oldest_node = NULL;
9665 struct sir_rssi_disallow_lst *cur_node;
9666 qdf_list_node_t *cur_list = NULL;
9667 qdf_list_node_t *next_list = NULL;
9668
9669 qdf_list_peek_front(list, &cur_list);
9670 while (cur_list) {
9671 cur_node = qdf_container_of(cur_list,
9672 struct sir_rssi_disallow_lst, node);
9673 if (!oldest_node ||
9674 (lim_assoc_rej_get_remaining_delta(oldest_node) >
9675 lim_assoc_rej_get_remaining_delta(cur_node)))
9676 oldest_node = cur_node;
9677
9678 qdf_list_peek_next(list, cur_list, &next_list);
9679 cur_list = next_list;
9680 next_list = NULL;
9681 }
9682
9683 if (oldest_node) {
9684 pe_debug("remove node "QDF_MAC_ADDR_FMT" with lowest delta %d",
9685 QDF_MAC_ADDR_REF(oldest_node->bssid.bytes),
9686 lim_assoc_rej_get_remaining_delta(oldest_node));
9687 qdf_list_remove_node(list, &oldest_node->node);
9688 qdf_mem_free(oldest_node);
9689 return QDF_STATUS_SUCCESS;
9690 }
9691
9692 return QDF_STATUS_E_INVAL;
9693 }
9694
9695 void
lim_add_bssid_to_reject_list(struct wlan_objmgr_pdev * pdev,struct sir_rssi_disallow_lst * entry)9696 lim_add_bssid_to_reject_list(struct wlan_objmgr_pdev *pdev,
9697 struct sir_rssi_disallow_lst *entry)
9698 {
9699 struct reject_ap_info ap_info;
9700
9701 qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
9702 ap_info.bssid = entry->bssid;
9703 ap_info.reject_ap_type = DRIVER_RSSI_REJECT_TYPE;
9704 ap_info.rssi_reject_params.expected_rssi = entry->expected_rssi;
9705 ap_info.rssi_reject_params.retry_delay = entry->retry_delay;
9706 ap_info.reject_reason = entry->reject_reason;
9707 ap_info.source = entry->source;
9708 ap_info.rssi_reject_params.received_time = entry->received_time;
9709 ap_info.rssi_reject_params.original_timeout = entry->original_timeout;
9710 /* Add this ap info to the rssi reject ap type in denylist manager */
9711 wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info);
9712 }
9713
lim_decrement_pending_mgmt_count(struct mac_context * mac_ctx)9714 void lim_decrement_pending_mgmt_count(struct mac_context *mac_ctx)
9715 {
9716 qdf_spin_lock(&mac_ctx->sys.bbt_mgmt_lock);
9717 if (!mac_ctx->sys.sys_bbt_pending_mgmt_count) {
9718 qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
9719 return;
9720 }
9721 mac_ctx->sys.sys_bbt_pending_mgmt_count--;
9722 qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
9723 }
9724
lim_check_if_vendor_oui_match(struct mac_context * mac_ctx,uint8_t * oui,uint8_t oui_len,uint8_t * ie,uint8_t ie_len)9725 bool lim_check_if_vendor_oui_match(struct mac_context *mac_ctx,
9726 uint8_t *oui, uint8_t oui_len,
9727 uint8_t *ie, uint8_t ie_len)
9728 {
9729 uint8_t *ptr = ie;
9730 uint8_t elem_id;
9731
9732 if (!ie || 0 == ie_len) {
9733 pe_err("IE Null or ie len zero %d", ie_len);
9734 return false;
9735 }
9736
9737 elem_id = *ie;
9738
9739 if (elem_id == WLAN_ELEMID_VENDOR &&
9740 !qdf_mem_cmp(&ptr[2], oui, oui_len))
9741 return true;
9742 else
9743 return false;
9744 }
9745
lim_util_get_type_subtype(void * pkt,uint8_t * type,uint8_t * subtype)9746 QDF_STATUS lim_util_get_type_subtype(void *pkt, uint8_t *type,
9747 uint8_t *subtype)
9748 {
9749 cds_pkt_t *cds_pkt;
9750 QDF_STATUS status;
9751 tpSirMacMgmtHdr hdr;
9752 uint8_t *rxpktinfor;
9753
9754 cds_pkt = (cds_pkt_t *) pkt;
9755 if (!cds_pkt) {
9756 pe_err("NULL packet received");
9757 return QDF_STATUS_E_FAILURE;
9758 }
9759 status = wma_ds_peek_rx_packet_info(cds_pkt, (void *)&rxpktinfor);
9760 if (!QDF_IS_STATUS_SUCCESS(status)) {
9761 pe_err("Failed extract cds packet. status %d", status);
9762 return QDF_STATUS_E_FAILURE;
9763 }
9764
9765 hdr = WMA_GET_RX_MAC_HEADER(rxpktinfor);
9766 if (hdr->fc.type == SIR_MAC_MGMT_FRAME) {
9767 pe_debug("RxBd: %pK mHdr: %pK Type: %d Subtype: %d SizeFC: %zu",
9768 rxpktinfor, hdr, hdr->fc.type, hdr->fc.subType,
9769 sizeof(tSirMacFrameCtl));
9770 *type = hdr->fc.type;
9771 *subtype = hdr->fc.subType;
9772 } else {
9773 pe_err("Not a management packet type %d", hdr->fc.type);
9774 return QDF_STATUS_E_INVAL;
9775 }
9776 return QDF_STATUS_SUCCESS;
9777 }
9778
lim_get_min_rate(uint8_t * min_rate,tSirMacRateSet * rateset)9779 static void lim_get_min_rate(uint8_t *min_rate, tSirMacRateSet *rateset)
9780 {
9781 uint8_t curr_rate, i;
9782
9783 for (i = 0; i < rateset->numRates; i++) {
9784 /* Ignore MSB - set to indicate basic rate */
9785 curr_rate = rateset->rate[i] & 0x7F;
9786 *min_rate = (curr_rate < *min_rate) ? curr_rate :
9787 *min_rate;
9788 }
9789
9790 pe_debug("supported min_rate: %0x(%d)", *min_rate, *min_rate);
9791 }
9792
lim_is_enable_he_mcs0_for_6ghz_mgmt(struct pe_session * session,qdf_freq_t freq)9793 static bool lim_is_enable_he_mcs0_for_6ghz_mgmt(struct pe_session *session,
9794 qdf_freq_t freq)
9795 {
9796 bool enable_he_mcs0_for_6ghz_mgmt = false;
9797
9798 if (!wlan_reg_is_6ghz_chan_freq(freq))
9799 return enable_he_mcs0_for_6ghz_mgmt;
9800
9801 /*
9802 * For 6GHz freq and if enable_he_mcs0_for_mgmt_6ghz INI is
9803 * enabled then FW will use rate of MCS0 for 11AX and configured
9804 * via WMI_MGMT_TX_SEND_CMDID
9805 */
9806 wlan_mlme_get_mgmt_6ghz_rate_support(
9807 session->mac_ctx->psoc,
9808 &enable_he_mcs0_for_6ghz_mgmt);
9809
9810 return enable_he_mcs0_for_6ghz_mgmt;
9811 }
9812
lim_get_min_session_txrate(struct pe_session * session,qdf_freq_t * pre_auth_freq)9813 enum rateid lim_get_min_session_txrate(struct pe_session *session,
9814 qdf_freq_t *pre_auth_freq)
9815 {
9816 enum rateid rid = RATEID_DEFAULT;
9817 uint8_t min_rate = SIR_MAC_RATE_54;
9818 tSirMacRateSet *rateset;
9819 qdf_freq_t op_freq;
9820
9821 if (!session)
9822 return rid;
9823
9824 rateset = &session->rateSet;
9825
9826 if (pre_auth_freq) {
9827 pe_debug("updated rateset to pre auth freq %d",
9828 *pre_auth_freq);
9829 if (*pre_auth_freq &&
9830 !lim_is_enable_he_mcs0_for_6ghz_mgmt(session,
9831 *pre_auth_freq))
9832 lim_get_basic_rates(rateset, *pre_auth_freq);
9833 else
9834 return rid;
9835 }
9836
9837 op_freq = wlan_get_operation_chan_freq(session->vdev);
9838 if (lim_is_enable_he_mcs0_for_6ghz_mgmt(session, op_freq))
9839 return rid;
9840
9841 lim_get_min_rate(&min_rate, rateset);
9842
9843 if (session->is_oui_auth_assoc_6mbps_2ghz_enable)
9844 min_rate = SIR_MAC_RATE_6;
9845
9846 switch (min_rate) {
9847 case SIR_MAC_RATE_1:
9848 rid = RATEID_1MBPS;
9849 break;
9850 case SIR_MAC_RATE_2:
9851 rid = RATEID_2MBPS;
9852 break;
9853 case SIR_MAC_RATE_5_5:
9854 rid = RATEID_5_5MBPS;
9855 break;
9856 case SIR_MAC_RATE_11:
9857 rid = RATEID_11MBPS;
9858 break;
9859 case SIR_MAC_RATE_6:
9860 rid = RATEID_6MBPS;
9861 break;
9862 case SIR_MAC_RATE_9:
9863 rid = RATEID_9MBPS;
9864 break;
9865 case SIR_MAC_RATE_12:
9866 rid = RATEID_12MBPS;
9867 break;
9868 case SIR_MAC_RATE_18:
9869 rid = RATEID_18MBPS;
9870 break;
9871 case SIR_MAC_RATE_24:
9872 rid = RATEID_24MBPS;
9873 break;
9874 case SIR_MAC_RATE_36:
9875 rid = RATEID_36MBPS;
9876 break;
9877 case SIR_MAC_RATE_48:
9878 rid = RATEID_48MBPS;
9879 break;
9880 case SIR_MAC_RATE_54:
9881 rid = RATEID_54MBPS;
9882 break;
9883 default:
9884 rid = RATEID_DEFAULT;
9885 break;
9886 }
9887
9888 return rid;
9889 }
9890
lim_send_sme_mgmt_frame_ind(struct mac_context * mac_ctx,uint8_t frame_type,uint8_t * frame,uint32_t frame_len,uint16_t vdev_id,uint32_t rx_freq,int8_t rx_rssi,enum rxmgmt_flags rx_flags)9891 void lim_send_sme_mgmt_frame_ind(struct mac_context *mac_ctx, uint8_t frame_type,
9892 uint8_t *frame, uint32_t frame_len,
9893 uint16_t vdev_id, uint32_t rx_freq,
9894 int8_t rx_rssi, enum rxmgmt_flags rx_flags)
9895 {
9896 tpSirSmeMgmtFrameInd sme_mgmt_frame = NULL;
9897 uint16_t length;
9898 struct wlan_objmgr_vdev *vdev;
9899
9900 length = sizeof(tSirSmeMgmtFrameInd) + frame_len;
9901
9902 sme_mgmt_frame = qdf_mem_malloc(length);
9903 if (!sme_mgmt_frame)
9904 return;
9905
9906 if (qdf_is_macaddr_broadcast(
9907 (struct qdf_mac_addr *)(frame + 4)) &&
9908 !vdev_id) {
9909 pe_debug("Broadcast action frame");
9910 vdev_id = SME_SESSION_ID_BROADCAST;
9911 }
9912
9913 sme_mgmt_frame->frame_len = frame_len;
9914 sme_mgmt_frame->sessionId = vdev_id;
9915 sme_mgmt_frame->frameType = frame_type;
9916 sme_mgmt_frame->rxRssi = rx_rssi;
9917 sme_mgmt_frame->rx_freq = rx_freq;
9918 sme_mgmt_frame->rx_flags = rx_flags;
9919
9920 qdf_mem_zero(sme_mgmt_frame->frameBuf, frame_len);
9921 qdf_mem_copy(sme_mgmt_frame->frameBuf, frame, frame_len);
9922
9923 if (vdev_id != SME_SESSION_ID_BROADCAST &&
9924 frame_type == SIR_MAC_MGMT_ACTION) {
9925 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
9926 vdev_id,
9927 WLAN_LEGACY_MAC_ID);
9928 if (!vdev) {
9929 pe_debug("Invalid VDEV %d", vdev_id);
9930 goto send_frame;
9931 }
9932
9933 wlan_mlo_update_action_frame_to_user(vdev,
9934 sme_mgmt_frame->frameBuf,
9935 sme_mgmt_frame->frame_len);
9936 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
9937 }
9938
9939 send_frame:
9940 if (mac_ctx->mgmt_frame_ind_cb)
9941 mac_ctx->mgmt_frame_ind_cb(sme_mgmt_frame);
9942 else
9943 pe_debug_rl("Management indication callback not registered!!");
9944
9945 qdf_mem_free(sme_mgmt_frame);
9946
9947 return;
9948 }
9949
9950 void
lim_send_dfs_chan_sw_ie_update(struct mac_context * mac_ctx,struct pe_session * session)9951 lim_send_dfs_chan_sw_ie_update(struct mac_context *mac_ctx, struct pe_session *session)
9952 {
9953 /* Update the beacon template and send to FW */
9954 if (sch_set_fixed_beacon_fields(mac_ctx, session) !=
9955 QDF_STATUS_SUCCESS) {
9956 pe_err("Unable to set CSA IE in beacon");
9957 return;
9958 }
9959
9960 /* Send update beacon template message */
9961 lim_send_beacon_ind(mac_ctx, session, REASON_CHANNEL_SWITCH);
9962 pe_debug("Updated CSA IE, IE COUNT: %d",
9963 session->gLimChannelSwitch.switchCount);
9964 }
9965
lim_is_csa_tx_pending(uint8_t vdev_id)9966 bool lim_is_csa_tx_pending(uint8_t vdev_id)
9967 {
9968 struct pe_session *session;
9969 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
9970 bool csa_tx_offload;
9971
9972 if (!mac_ctx) {
9973 mlme_err("Invalid mac context");
9974 return false;
9975 }
9976
9977 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
9978 if (!session) {
9979 pe_err("Session does not exist for given vdev_id %d", vdev_id);
9980 return false;
9981 }
9982
9983 csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc,
9984 WLAN_SOC_CEXT_CSA_TX_OFFLOAD);
9985 if (session->dfsIncludeChanSwIe &&
9986 (session->gLimChannelSwitch.switchCount ==
9987 mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt) &&
9988 csa_tx_offload)
9989 return true;
9990
9991 return false;
9992 }
9993
lim_send_csa_tx_complete(uint8_t vdev_id)9994 void lim_send_csa_tx_complete(uint8_t vdev_id)
9995 {
9996 QDF_STATUS status;
9997 tSirSmeCSAIeTxCompleteRsp *chan_switch_tx_rsp;
9998 struct pe_session *session;
9999 struct scheduler_msg msg = {0};
10000 bool csa_tx_offload;
10001 uint8_t length = sizeof(*chan_switch_tx_rsp);
10002 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10003
10004 if (!mac_ctx) {
10005 mlme_err("Invalid mac context");
10006 return;
10007 }
10008
10009 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
10010 if (!session) {
10011 pe_err("Session does not exist for given vdev_id %d", vdev_id);
10012 return;
10013 }
10014
10015 /* Stop the timer if already running in case of csa*/
10016 csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc,
10017 WLAN_SOC_CEXT_CSA_TX_OFFLOAD);
10018 if (csa_tx_offload)
10019 qdf_mc_timer_stop(&session->ap_ecsa_timer);
10020
10021 /* Done with CSA IE update, send response back to SME */
10022 session->gLimChannelSwitch.switchCount = 0;
10023 if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false)
10024 session->gLimChannelSwitch.switchMode = 0;
10025
10026 session->dfsIncludeChanSwIe = false;
10027 session->dfsIncludeChanWrapperIe = false;
10028
10029 chan_switch_tx_rsp = qdf_mem_malloc(length);
10030 if (!chan_switch_tx_rsp)
10031 return;
10032
10033 chan_switch_tx_rsp->sessionId = session->smeSessionId;
10034 chan_switch_tx_rsp->chanSwIeTxStatus = QDF_STATUS_SUCCESS;
10035
10036 msg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND;
10037 msg.bodyptr = chan_switch_tx_rsp;
10038
10039 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_SME,
10040 QDF_MODULE_ID_SME, &msg);
10041 if (QDF_IS_STATUS_ERROR(status))
10042 qdf_mem_free(chan_switch_tx_rsp);
10043 }
10044
lim_process_ap_ecsa_timeout(void * data)10045 void lim_process_ap_ecsa_timeout(void *data)
10046 {
10047 struct pe_session *session = (struct pe_session *)data;
10048 struct mac_context *mac_ctx;
10049 uint8_t bcn_int, ch_width;
10050 uint32_t ch_freq;
10051 bool csa_tx_offload;
10052 QDF_STATUS status;
10053
10054 if (!session || !session->valid) {
10055 pe_err("Session is not valid");
10056 return;
10057 }
10058
10059 mac_ctx = session->mac_ctx;
10060
10061 if (!session->dfsIncludeChanSwIe &&
10062 !session->bw_update_include_ch_sw_ie) {
10063 pe_debug("session->dfsIncludeChanSwIe/chWidthUpdateIncludeChanSwIe not set");
10064 return;
10065 }
10066
10067 if (session->bw_update_include_ch_sw_ie) {
10068 /* Stop the timer if already running */
10069 qdf_mc_timer_stop(&session->ap_ecsa_timer);
10070
10071 lim_nss_or_ch_width_update_rsp(mac_ctx,
10072 session->vdev_id,
10073 QDF_STATUS_SUCCESS,
10074 REASON_CH_WIDTH_UPDATE);
10075 session->gLimChannelSwitch.switchCount = 0;
10076 session->bw_update_include_ch_sw_ie = false;
10077
10078 /* Clear CSA IE count and update beacon */
10079 lim_send_dfs_chan_sw_ie_update(mac_ctx, session);
10080
10081 return;
10082 }
10083
10084 if (lim_is_csa_tx_pending(session->vdev_id))
10085 return lim_send_csa_tx_complete(session->vdev_id);
10086
10087 csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc,
10088 WLAN_SOC_CEXT_CSA_TX_OFFLOAD);
10089
10090 if (csa_tx_offload)
10091 return;
10092
10093 /* Stop the timer if already running */
10094 qdf_mc_timer_stop(&session->ap_ecsa_timer);
10095
10096 if (session->gLimChannelSwitch.switchCount)
10097 /* Decrement the beacon switch count */
10098 session->gLimChannelSwitch.switchCount--;
10099
10100 /*
10101 * Send only g_sap_chanswitch_beacon_cnt beacons with CSA IE Set in
10102 * when a radar is detected
10103 */
10104 if (session->gLimChannelSwitch.switchCount > 0) {
10105 /* Send the next beacon with updated CSA IE count */
10106 lim_send_dfs_chan_sw_ie_update(mac_ctx, session);
10107
10108 ch_freq = session->gLimChannelSwitch.sw_target_freq;
10109 ch_width = session->gLimChannelSwitch.ch_width;
10110 if (mac_ctx->mlme_cfg->dfs_cfg.dfs_beacon_tx_enhanced) {
10111 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(ch_freq)) {
10112 send_extended_chan_switch_action_frame
10113 (mac_ctx, ch_freq, ch_width,
10114 session);
10115 } else {
10116 /* Send Action frame after updating beacon */
10117 lim_send_chan_switch_action_frame
10118 (mac_ctx, ch_freq, ch_width,
10119 session);
10120 }
10121 }
10122
10123 /* Restart the timer */
10124 if (session->beaconParams.beaconInterval)
10125 bcn_int = session->beaconParams.beaconInterval;
10126 else
10127 bcn_int = MLME_CFG_BEACON_INTERVAL_DEF;
10128
10129 status = qdf_mc_timer_start(&session->ap_ecsa_timer,
10130 bcn_int);
10131 if (QDF_IS_STATUS_ERROR(status)) {
10132 pe_err("cannot start ap_ecsa_timer");
10133 lim_process_ap_ecsa_timeout(session);
10134 }
10135 } else {
10136 lim_send_csa_tx_complete(session->vdev_id);
10137 /* Clear CSA IE count and update beacon */
10138 lim_send_dfs_chan_sw_ie_update(mac_ctx, session);
10139 }
10140 }
10141
lim_sta_mlme_vdev_start_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10142 QDF_STATUS lim_sta_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme,
10143 uint16_t data_len, void *data)
10144 {
10145 struct mac_context *mac_ctx;
10146 enum vdev_assoc_type assoc_type;
10147
10148 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10149 if (!mac_ctx) {
10150 if (data)
10151 qdf_mem_free(data);
10152 return QDF_STATUS_E_INVAL;
10153 }
10154
10155 assoc_type = mlme_get_assoc_type(vdev_mlme->vdev);
10156 switch (assoc_type) {
10157 case VDEV_ASSOC:
10158 lim_process_mlm_join_req(mac_ctx, (tLimMlmJoinReq *)data);
10159 break;
10160 case VDEV_REASSOC:
10161 lim_process_mlm_reassoc_req(mac_ctx, (tLimMlmReassocReq *)data);
10162 break;
10163 case VDEV_FT_REASSOC:
10164 lim_process_mlm_ft_reassoc_req(mac_ctx,
10165 (tLimMlmReassocReq *)data);
10166 break;
10167 default:
10168 pe_err("assoc_type %d is invalid", assoc_type);
10169 }
10170 return QDF_STATUS_SUCCESS;
10171 }
10172
lim_sta_mlme_vdev_restart_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10173 QDF_STATUS lim_sta_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
10174 uint16_t data_len, void *data)
10175 {
10176 struct pe_session *session;
10177 QDF_STATUS status = QDF_STATUS_SUCCESS;
10178
10179 session = (struct pe_session *)data;
10180 if (!session) {
10181 pe_err("Invalid session");
10182 return QDF_STATUS_E_INVAL;
10183 }
10184 if (!vdev_mlme) {
10185 pe_err("vdev_mlme is NULL");
10186 return QDF_STATUS_E_INVAL;
10187 }
10188 if (!data) {
10189 pe_err("event_data is NULL");
10190 return QDF_STATUS_E_INVAL;
10191 }
10192 if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev)) {
10193 switch (session->channelChangeReasonCode) {
10194 case LIM_SWITCH_CHANNEL_OPERATION:
10195 status = __lim_process_channel_switch_timeout(session);
10196 break;
10197 case LIM_SWITCH_CHANNEL_HT_WIDTH:
10198 status = lim_ht_switch_chnl_params(session);
10199 break;
10200 case LIM_SWITCH_CHANNEL_REASSOC:
10201 status = lim_send_switch_chnl_params(session->mac_ctx,
10202 session);
10203 break;
10204 default:
10205 break;
10206 }
10207 }
10208 if (QDF_IS_STATUS_ERROR(status)) {
10209 pe_err_rl("Failed to send VDEV_RESTART for chan switch vdev %d",
10210 wlan_vdev_get_id(vdev_mlme->vdev));
10211 mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
10212 }
10213
10214 return status;
10215 }
10216
lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10217 QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
10218 uint16_t data_len, void *data)
10219 {
10220 QDF_STATUS status = QDF_STATUS_SUCCESS;
10221 bool connection_fail = false;
10222 enum vdev_assoc_type assoc_type;
10223
10224 if (!vdev_mlme) {
10225 pe_err("vdev_mlme is NULL");
10226 return QDF_STATUS_E_INVAL;
10227 }
10228 if (!data) {
10229 pe_err("event_data is NULL");
10230 return QDF_STATUS_E_INVAL;
10231 }
10232
10233 connection_fail = mlme_is_connection_fail(vdev_mlme->vdev);
10234 pe_debug("Send vdev stop, connection_fail %d", connection_fail);
10235 if (connection_fail) {
10236 assoc_type = mlme_get_assoc_type(vdev_mlme->vdev);
10237 switch (assoc_type) {
10238 case VDEV_ASSOC:
10239 status =
10240 lim_sta_handle_connect_fail((join_params *)data);
10241 break;
10242 case VDEV_REASSOC:
10243 case VDEV_FT_REASSOC:
10244 status = lim_sta_reassoc_error_handler(
10245 (struct reassoc_params *)data);
10246 break;
10247 default:
10248 pe_info("Invalid assoc_type %d", assoc_type);
10249 status = QDF_STATUS_E_INVAL;
10250 break;
10251 }
10252 mlme_set_connection_fail(vdev_mlme->vdev, false);
10253 } else {
10254 status = lim_sta_send_del_bss((struct pe_session *)data);
10255 }
10256
10257 return status;
10258 }
10259
10260 QDF_STATUS
lim_sta_mlme_vdev_sta_disconnect_start(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10261 lim_sta_mlme_vdev_sta_disconnect_start(struct vdev_mlme_obj *vdev_mlme,
10262 uint16_t data_len, void *data)
10263 {
10264 tpDphHashNode stads;
10265 struct pe_session *session;
10266 struct mac_context *mac_ctx;
10267 uint8_t vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
10268
10269 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10270 if (!mac_ctx)
10271 return QDF_STATUS_E_INVAL;
10272
10273 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
10274 if (!session) {
10275 pe_err("session is NULL for vdevid %d", vdev_id);
10276 return QDF_STATUS_E_INVAL;
10277 }
10278 stads = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
10279 &session->dph.dphHashTable);
10280 if (!stads)
10281 return QDF_STATUS_E_INVAL;
10282 mlme_set_connection_fail(vdev_mlme->vdev, false);
10283
10284 session->limPrevSmeState = session->limSmeState;
10285 session->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
10286
10287 stads->mlmStaContext.disassocReason = REASON_UNSPEC_FAILURE;
10288 stads->mlmStaContext.cleanupTrigger = eLIM_HOST_DISASSOC;
10289
10290 stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
10291
10292 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10293 WLAN_VDEV_SM_EV_CONNECTION_FAIL,
10294 sizeof(*session), session);
10295
10296 return QDF_STATUS_SUCCESS;
10297 }
10298
lim_sta_mlme_vdev_req_fail(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10299 QDF_STATUS lim_sta_mlme_vdev_req_fail(struct vdev_mlme_obj *vdev_mlme,
10300 uint16_t data_len, void *data)
10301 {
10302 QDF_STATUS status = QDF_STATUS_SUCCESS;
10303 enum vdev_assoc_type assoc_type;
10304
10305 if (!vdev_mlme) {
10306 pe_err("vdev_mlme is NULL");
10307 return QDF_STATUS_E_INVAL;
10308 }
10309 if (!data) {
10310 pe_err("event_data is NULL");
10311 return QDF_STATUS_E_INVAL;
10312 }
10313
10314 assoc_type = mlme_get_assoc_type(vdev_mlme->vdev);
10315 switch (assoc_type) {
10316 case VDEV_ASSOC:
10317 status = lim_sta_handle_connect_fail((join_params *)data);
10318 break;
10319 case VDEV_REASSOC:
10320 case VDEV_FT_REASSOC:
10321 status = lim_sta_reassoc_error_handler(
10322 (struct reassoc_params *)data);
10323 break;
10324 default:
10325 pe_info("Invalid assoc_type %d", assoc_type);
10326 status = QDF_STATUS_E_INVAL;
10327 break;
10328 }
10329
10330 return status;
10331 }
10332
lim_send_beacon(struct mac_context * mac_ctx,struct pe_session * session)10333 void lim_send_beacon(struct mac_context *mac_ctx, struct pe_session *session)
10334 {
10335 if (wlan_vdev_mlme_get_state(session->vdev) ==
10336 WLAN_VDEV_S_DFS_CAC_WAIT)
10337 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10338 WLAN_VDEV_SM_EV_DFS_CAC_COMPLETED,
10339 sizeof(*session), session);
10340 else if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch &&
10341 (wlan_vdev_mlme_get_substate(session->vdev) ==
10342 WLAN_VDEV_SS_SUSPEND_CSA_RESTART))
10343 wlan_vdev_mlme_sm_deliver_evt(
10344 session->vdev,
10345 WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED,
10346 sizeof(*session), session);
10347 else
10348 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10349 WLAN_VDEV_SM_EV_START_SUCCESS,
10350 sizeof(*session), session);
10351 }
10352
lim_ndi_mlme_vdev_up_transition(struct pe_session * session)10353 void lim_ndi_mlme_vdev_up_transition(struct pe_session *session)
10354 {
10355 if (!LIM_IS_NDI_ROLE(session))
10356 return;
10357
10358 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10359 WLAN_VDEV_SM_EV_START_SUCCESS,
10360 sizeof(*session), session);
10361 }
10362
lim_sap_move_to_cac_wait_state(struct pe_session * session)10363 QDF_STATUS lim_sap_move_to_cac_wait_state(struct pe_session *session)
10364 {
10365 QDF_STATUS status;
10366
10367 status =
10368 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10369 WLAN_VDEV_SM_EV_DFS_CAC_WAIT,
10370 sizeof(*session), session);
10371 return status;
10372 }
10373
lim_ap_mlme_vdev_start_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10374 QDF_STATUS lim_ap_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme,
10375 uint16_t data_len, void *data)
10376 {
10377 struct pe_session *session;
10378 tpLimMlmStartReq start_req = (tLimMlmStartReq *)data;
10379 struct mac_context *mac_ctx;
10380
10381 if (!data) {
10382 pe_err("data is NULL");
10383 return QDF_STATUS_E_INVAL;
10384 }
10385
10386 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10387 if (!mac_ctx)
10388 return QDF_STATUS_E_INVAL;
10389
10390 session = pe_find_session_by_session_id(mac_ctx,
10391 start_req->sessionId);
10392 if (!session) {
10393 pe_err("session is NULL");
10394 return QDF_STATUS_E_INVAL;
10395 }
10396
10397 lim_process_mlm_start_req(session->mac_ctx, start_req);
10398
10399 return QDF_STATUS_SUCCESS;
10400 }
10401
lim_send_csa_restart_resp(struct mac_context * mac_ctx,struct pe_session * session)10402 static inline void lim_send_csa_restart_resp(struct mac_context *mac_ctx,
10403 struct pe_session *session)
10404 {
10405 struct scheduler_msg msg = {0};
10406 QDF_STATUS status;
10407
10408 msg.type = eWNI_SME_CSA_RESTART_RSP;
10409 msg.bodyptr = NULL;
10410 msg.bodyval = session->smeSessionId;
10411
10412 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_SME,
10413 QDF_MODULE_ID_SME, &msg);
10414 }
10415
lim_ap_mlme_vdev_update_beacon(struct vdev_mlme_obj * vdev_mlme,enum beacon_update_op op,uint16_t data_len,void * data)10416 QDF_STATUS lim_ap_mlme_vdev_update_beacon(struct vdev_mlme_obj *vdev_mlme,
10417 enum beacon_update_op op,
10418 uint16_t data_len, void *data)
10419 {
10420 struct pe_session *session;
10421 struct mac_context *mac_ctx;
10422
10423 if (!data) {
10424 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10425 if (!mac_ctx) {
10426 pe_err("mac ctx is null");
10427 return QDF_STATUS_E_INVAL;
10428 }
10429 session = pe_find_session_by_vdev_id(
10430 mac_ctx, vdev_mlme->vdev->vdev_objmgr.vdev_id);
10431 if (!session) {
10432 pe_err("session is NULL");
10433 return QDF_STATUS_E_INVAL;
10434 }
10435 } else {
10436 session = (struct pe_session *)data;
10437 }
10438 if (LIM_IS_NDI_ROLE(session))
10439 return QDF_STATUS_SUCCESS;
10440
10441 if (op == BEACON_INIT)
10442 lim_send_beacon_ind(session->mac_ctx, session, REASON_DEFAULT);
10443 else if (op == BEACON_UPDATE)
10444 lim_send_beacon_ind(session->mac_ctx,
10445 session,
10446 REASON_CONFIG_UPDATE);
10447 else if (op == BEACON_CSA)
10448 lim_send_csa_restart_resp(session->mac_ctx, session);
10449
10450 return QDF_STATUS_SUCCESS;
10451 }
10452
lim_ap_mlme_vdev_up_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10453 QDF_STATUS lim_ap_mlme_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
10454 uint16_t data_len, void *data)
10455 {
10456 struct scheduler_msg msg = {0};
10457 QDF_STATUS status;
10458 struct pe_session *session;
10459 struct mac_context *mac_ctx;
10460
10461 if (!data) {
10462 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10463 if (!mac_ctx) {
10464 pe_err("mac ctx is null");
10465 return QDF_STATUS_E_INVAL;
10466 }
10467 session = pe_find_session_by_vdev_id(
10468 mac_ctx, vdev_mlme->vdev->vdev_objmgr.vdev_id);
10469 if (!session) {
10470 pe_err("session is NULL");
10471 return QDF_STATUS_E_INVAL;
10472 }
10473 } else {
10474 session = (struct pe_session *)data;
10475 }
10476
10477 if (LIM_IS_NDI_ROLE(session))
10478 return QDF_STATUS_SUCCESS;
10479
10480 if (!wlan_vdev_mlme_is_mlo_ap(vdev_mlme->vdev))
10481 lim_configure_fd_for_existing_6ghz_sap(session, true);
10482
10483 msg.type = SIR_HAL_SEND_AP_VDEV_UP;
10484 msg.bodyval = session->smeSessionId;
10485
10486 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_WMA,
10487 QDF_MODULE_ID_WMA, &msg);
10488
10489 return status;
10490 }
10491
lim_ap_mlme_vdev_rnr_notify(struct pe_session * session)10492 QDF_STATUS lim_ap_mlme_vdev_rnr_notify(struct pe_session *session)
10493 {
10494 struct mac_context *mac_ctx;
10495 uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
10496 qdf_freq_t freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
10497 uint8_t vdev_num;
10498 uint8_t i;
10499 struct pe_session *co_session;
10500 QDF_STATUS status = QDF_STATUS_SUCCESS;
10501
10502 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10503 if (!mac_ctx) {
10504 pe_err("mac ctx is null");
10505 return QDF_STATUS_E_INVAL;
10506 }
10507 if (!session) {
10508 pe_err("session is NULL");
10509 return QDF_STATUS_E_INVAL;
10510 }
10511 if (!mlme_is_notify_co_located_ap_update_rnr(session->vdev))
10512 return status;
10513 mlme_set_notify_co_located_ap_update_rnr(session->vdev, false);
10514 // Only 6G SAP need to notify co-located SAP to add RNR
10515 if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq))
10516 return status;
10517 pe_debug("vdev id %d non mlo 6G AP notify co-located AP to update RNR",
10518 wlan_vdev_get_id(session->vdev));
10519 vdev_num = policy_mgr_get_sap_mode_info(mac_ctx->psoc, freq_list,
10520 vdev_id_list);
10521 for (i = 0; i < vdev_num; i++) {
10522 if (vdev_id_list[i] == session->vdev_id)
10523 continue;
10524 if (wlan_reg_is_6ghz_chan_freq(freq_list[i]))
10525 continue;
10526 co_session = pe_find_session_by_vdev_id(mac_ctx,
10527 vdev_id_list[i]);
10528 if (!co_session)
10529 continue;
10530
10531 status = sch_set_fixed_beacon_fields(mac_ctx, co_session);
10532 if (QDF_IS_STATUS_ERROR(status)) {
10533 pe_err("Unable to update 6g co located RNR in beacon");
10534 return status;
10535 }
10536
10537 status = lim_send_beacon_ind(mac_ctx, co_session,
10538 REASON_RNR_UPDATE);
10539 if (QDF_IS_STATUS_ERROR(status)) {
10540 pe_err("Unable to send beacon indication");
10541 return status;
10542 }
10543 }
10544
10545 return status;
10546 }
10547
lim_ap_mlme_vdev_disconnect_peers(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10548 QDF_STATUS lim_ap_mlme_vdev_disconnect_peers(struct vdev_mlme_obj *vdev_mlme,
10549 uint16_t data_len, void *data)
10550 {
10551 struct pe_session *session;
10552 struct mac_context *mac_ctx;
10553
10554 if (!data) {
10555 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10556 if (!mac_ctx) {
10557 pe_err("mac ctx is null");
10558 return QDF_STATUS_E_INVAL;
10559 }
10560 session = pe_find_session_by_vdev_id(
10561 mac_ctx, vdev_mlme->vdev->vdev_objmgr.vdev_id);
10562 if (!session) {
10563 pe_err("session is NULL");
10564 return QDF_STATUS_E_INVAL;
10565 }
10566 } else {
10567 session = (struct pe_session *)data;
10568 }
10569
10570 lim_delete_all_peers(session);
10571
10572 return QDF_STATUS_SUCCESS;
10573 }
10574
10575 #ifdef WLAN_FEATURE_11BE
10576 static
lim_apply_puncture(struct mac_context * mac,struct pe_session * session,qdf_freq_t sec_chan_freq)10577 void lim_apply_puncture(struct mac_context *mac,
10578 struct pe_session *session,
10579 qdf_freq_t sec_chan_freq)
10580 {
10581 uint16_t puncture_bitmap;
10582
10583 puncture_bitmap =
10584 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap;
10585
10586 if (puncture_bitmap) {
10587 pe_debug("Apply puncture to reg: bitmap 0x%x, freq: %d, bw %d, mhz_freq_seg1: %d",
10588 puncture_bitmap,
10589 session->curr_op_freq,
10590 session->ch_width,
10591 sec_chan_freq);
10592 wlan_reg_apply_puncture(mac->pdev,
10593 puncture_bitmap,
10594 session->curr_op_freq,
10595 session->ch_width,
10596 sec_chan_freq);
10597 }
10598 }
10599
10600 static
lim_remove_puncture(struct mac_context * mac,struct pe_session * session)10601 void lim_remove_puncture(struct mac_context *mac,
10602 struct pe_session *session)
10603 {
10604 uint16_t puncture_bitmap;
10605
10606 puncture_bitmap =
10607 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap;
10608 if (puncture_bitmap) {
10609 pe_debug("Remove puncture from reg: bitmap 0x%x",
10610 puncture_bitmap);
10611 wlan_reg_remove_puncture(mac->pdev);
10612 }
10613 }
10614 #else
10615 static inline
lim_apply_puncture(struct mac_context * mac,struct pe_session * session,qdf_freq_t sec_chan_freq)10616 void lim_apply_puncture(struct mac_context *mac,
10617 struct pe_session *session,
10618 qdf_freq_t sec_chan_freq)
10619 {
10620 }
10621
10622 static inline
lim_remove_puncture(struct mac_context * mac,struct pe_session * session)10623 void lim_remove_puncture(struct mac_context *mac,
10624 struct pe_session *session)
10625 {
10626 }
10627 #endif
10628
lim_ap_mlme_vdev_stop_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10629 QDF_STATUS lim_ap_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
10630 uint16_t data_len, void *data)
10631 {
10632 struct pe_session *session = (struct pe_session *)data;
10633 QDF_STATUS status = QDF_STATUS_SUCCESS;
10634 struct mac_context *mac_ctx = session->mac_ctx;
10635
10636 if (!data) {
10637 pe_err("data is NULL");
10638 return QDF_STATUS_E_INVAL;
10639 }
10640
10641 lim_remove_puncture(mac_ctx, session);
10642
10643 if (!wlan_vdev_mlme_is_mlo_ap(vdev_mlme->vdev)) {
10644 mlme_set_notify_co_located_ap_update_rnr(vdev_mlme->vdev, true);
10645 lim_ap_mlme_vdev_rnr_notify(session);
10646 lim_configure_fd_for_existing_6ghz_sap(session, false);
10647 }
10648
10649 status = lim_send_vdev_stop(session);
10650
10651 return status;
10652 }
10653
lim_ap_mlme_vdev_restart_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10654 QDF_STATUS lim_ap_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
10655 uint16_t data_len, void *data)
10656 {
10657 struct pe_session *session = (struct pe_session *)data;
10658
10659 if (!data) {
10660 pe_err("data is NULL");
10661 return QDF_STATUS_E_INVAL;
10662 }
10663
10664 if (ap_mlme_is_hidden_ssid_restart_in_progress(vdev_mlme->vdev))
10665 lim_send_vdev_restart(session->mac_ctx, session,
10666 session->smeSessionId);
10667 else
10668 lim_send_switch_chnl_params(session->mac_ctx, session);
10669
10670 return QDF_STATUS_SUCCESS;
10671 }
10672
lim_ap_mlme_vdev_start_req_failed(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10673 QDF_STATUS lim_ap_mlme_vdev_start_req_failed(struct vdev_mlme_obj *vdev_mlme,
10674 uint16_t data_len, void *data)
10675 {
10676 struct mac_context *mac_ctx;
10677
10678 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10679 if (!mac_ctx) {
10680 if (data)
10681 qdf_mem_free(data);
10682 return QDF_STATUS_E_INVAL;
10683 }
10684
10685 lim_process_mlm_start_cnf(mac_ctx, data);
10686
10687 return QDF_STATUS_SUCCESS;
10688 }
10689
lim_mon_mlme_vdev_start_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)10690 QDF_STATUS lim_mon_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme,
10691 uint16_t data_len, void *data)
10692 {
10693 struct mac_context *mac_ctx;
10694 struct pe_session *session = (struct pe_session *)data;
10695
10696 if (!data) {
10697 pe_err("data is NULL");
10698 return QDF_STATUS_E_INVAL;
10699 }
10700
10701 mac_ctx = session->mac_ctx;
10702 if (!mac_ctx) {
10703 pe_err("mac_ctx is NULL");
10704 return QDF_STATUS_E_INVAL;
10705 }
10706
10707 lim_send_switch_chnl_params(mac_ctx, session);
10708
10709 return QDF_STATUS_SUCCESS;
10710 }
10711
lim_send_start_bss_confirm(struct mac_context * mac_ctx,tLimMlmStartCnf * start_cnf)10712 void lim_send_start_bss_confirm(struct mac_context *mac_ctx,
10713 tLimMlmStartCnf *start_cnf)
10714 {
10715 if (start_cnf->resultCode == eSIR_SME_SUCCESS) {
10716 lim_post_sme_message(mac_ctx, LIM_MLM_START_CNF,
10717 (uint32_t *)start_cnf);
10718 } else {
10719 struct pe_session *session;
10720
10721 session = pe_find_session_by_session_id(mac_ctx,
10722 start_cnf->sessionId);
10723 if (!session) {
10724 pe_err("session is NULL");
10725 return;
10726 }
10727 mlme_set_vdev_start_failed(session->vdev, true);
10728 wlan_vdev_mlme_sm_deliver_evt(session->vdev,
10729 WLAN_VDEV_SM_EV_START_REQ_FAIL,
10730 sizeof(*start_cnf), start_cnf);
10731 }
10732 }
10733
lim_get_capability_info(struct mac_context * mac,uint16_t * pcap,struct pe_session * pe_session)10734 QDF_STATUS lim_get_capability_info(struct mac_context *mac, uint16_t *pcap,
10735 struct pe_session *pe_session)
10736 {
10737 uint32_t val = 0;
10738 tpSirMacCapabilityInfo pcap_info;
10739
10740 *pcap = 0;
10741 pcap_info = (tpSirMacCapabilityInfo)pcap;
10742
10743 if (LIM_IS_AP_ROLE(pe_session) ||
10744 LIM_IS_STA_ROLE(pe_session))
10745 pcap_info->ess = 1; /* ESS bit */
10746 else if (LIM_IS_P2P_DEVICE_ROLE(pe_session) ||
10747 LIM_IS_NDI_ROLE(pe_session)) {
10748 pcap_info->ess = 0;
10749 pcap_info->ibss = 0;
10750 } else
10751 pe_warn("can't get capability, role is UNKNOWN!!");
10752
10753 if (LIM_IS_AP_ROLE(pe_session)) {
10754 val = pe_session->privacy;
10755 } else {
10756 /* PRIVACY bit */
10757 val = mac->mlme_cfg->wep_params.is_privacy_enabled;
10758 }
10759 if (val)
10760 pcap_info->privacy = 1;
10761
10762 /* Short preamble bit */
10763 if (mac->mlme_cfg->ht_caps.short_preamble)
10764 pcap_info->shortPreamble =
10765 mac->mlme_cfg->ht_caps.short_preamble;
10766
10767 /* criticalUpdateFlag bit */
10768 pcap_info->criticalUpdateFlag = 0;
10769
10770 /* Channel agility bit */
10771 pcap_info->channelAgility = 0;
10772 /* If STA/AP operating in 11B mode, don't set rest of the
10773 * capability info bits.
10774 */
10775 if (pe_session->dot11mode == MLME_DOT11_MODE_11B)
10776 return QDF_STATUS_SUCCESS;
10777
10778 /* Short slot time bit */
10779 if (LIM_IS_AP_ROLE(pe_session)) {
10780 pcap_info->shortSlotTime = pe_session->shortSlotTimeSupported;
10781 } else {
10782 /* When in STA mode, we need to check if short slot is
10783 * enabled as well as check if the current operating
10784 * mode is short slot time and then decide whether to
10785 * enable short slot or not. It is safe to check both
10786 * cfg values to determine short slot value in this
10787 * funcn since this funcn is always used after assoc
10788 * when these cfg values are already set based on
10789 * peer's capability. Even in case of IBSS, its value
10790 * is set to correct value either in delBSS as part of
10791 * deleting the previous IBSS or in start BSS as part
10792 * of coalescing
10793 */
10794 if (mac->mlme_cfg->feature_flags.enable_short_slot_time_11g) {
10795 pcap_info->shortSlotTime =
10796 pe_session->shortSlotTimeSupported;
10797 }
10798 }
10799
10800 /* Spectrum Management bit */
10801 if (pe_session->lim11hEnable) {
10802 if (mac->mlme_cfg->gen.enabled_11h)
10803 pcap_info->spectrumMgt = 1;
10804 }
10805 /* QoS bit */
10806 if (mac->mlme_cfg->wmm_params.qos_enabled)
10807 pcap_info->qos = 1;
10808
10809 /* APSD bit */
10810 if (mac->mlme_cfg->roam_scoring.apsd_enabled)
10811 pcap_info->apsd = 1;
10812
10813 pcap_info->rrm = mac->rrm.rrmConfig.rrm_enabled;
10814 pe_debug("RRM: %d", pcap_info->rrm);
10815 /* DSSS-OFDM */
10816 /* FIXME : no config defined yet. */
10817
10818 /* Block ack bit */
10819 val = mac->mlme_cfg->feature_flags.enable_block_ack;
10820 pcap_info->delayedBA =
10821 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1);
10822 pcap_info->immediateBA =
10823 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1);
10824
10825 return QDF_STATUS_SUCCESS;
10826 }
10827
lim_flush_bssid(struct mac_context * mac_ctx,uint8_t * bssid)10828 void lim_flush_bssid(struct mac_context *mac_ctx, uint8_t *bssid)
10829 {
10830 struct scan_filter *filter;
10831 struct wlan_objmgr_pdev *pdev = NULL;
10832 QDF_STATUS status;
10833
10834 if (!bssid)
10835 return;
10836
10837 filter = qdf_mem_malloc(sizeof(*filter));
10838 if (!filter)
10839 return;
10840
10841 filter->num_of_bssid = 1;
10842 qdf_mem_copy(filter->bssid_list[0].bytes, bssid, QDF_MAC_ADDR_SIZE);
10843
10844 pdev = wlan_objmgr_get_pdev_by_id(mac_ctx->psoc, 0, WLAN_LEGACY_MAC_ID);
10845 if (!pdev) {
10846 pe_err("pdev is NULL");
10847 qdf_mem_free(filter);
10848 return;
10849 }
10850 status = ucfg_scan_flush_results(pdev, filter);
10851
10852 wlan_objmgr_pdev_release_ref(pdev, WLAN_LEGACY_MAC_ID);
10853
10854 if (QDF_IS_STATUS_SUCCESS(status))
10855 pe_debug("Removed BSS entry:"QDF_MAC_ADDR_FMT" from scan cache",
10856 QDF_MAC_ADDR_REF(bssid));
10857
10858 if (filter)
10859 qdf_mem_free(filter);
10860 }
10861
lim_is_sha384_akm(enum ani_akm_type akm)10862 bool lim_is_sha384_akm(enum ani_akm_type akm)
10863 {
10864 switch (akm) {
10865 case ANI_AKM_TYPE_FILS_SHA384:
10866 case ANI_AKM_TYPE_FT_FILS_SHA384:
10867 case ANI_AKM_TYPE_SUITEB_EAP_SHA384:
10868 case ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384:
10869 return true;
10870 default:
10871 return false;
10872 }
10873 }
10874
lim_set_ch_phy_mode(struct wlan_objmgr_vdev * vdev,uint8_t dot11mode)10875 QDF_STATUS lim_set_ch_phy_mode(struct wlan_objmgr_vdev *vdev, uint8_t dot11mode)
10876 {
10877 struct vdev_mlme_obj *mlme_obj;
10878 struct wlan_channel *des_chan;
10879 uint32_t chan_mode;
10880 enum phy_ch_width ch_width;
10881 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
10882 uint16_t bw_val;
10883 enum reg_wifi_band band;
10884 uint8_t band_mask;
10885 enum channel_state ch_state;
10886 uint32_t start_ch_freq;
10887 struct ch_params ch_params = {0};
10888
10889 if (!mac_ctx)
10890 return QDF_STATUS_E_FAILURE;
10891
10892 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
10893 if (!mlme_obj) {
10894 pe_err("vdev component object is NULL");
10895 return QDF_STATUS_E_FAILURE;
10896 }
10897 des_chan = vdev->vdev_mlme.des_chan;
10898 /*
10899 * Set ch_cfreq1 to ch_freq for 20Mhz. If BW is greater than 20 it
10900 * will be updated from ch_freq_seg1.
10901 */
10902 des_chan->ch_cfreq1 = des_chan->ch_freq;
10903 band = wlan_reg_freq_to_band(des_chan->ch_freq);
10904 band_mask = 1 << band;
10905 ch_width = des_chan->ch_width;
10906 bw_val = wlan_reg_get_bw_value(ch_width);
10907 if (bw_val > 20) {
10908 if (des_chan->ch_freq_seg1) {
10909 des_chan->ch_cfreq1 =
10910 wlan_reg_chan_band_to_freq(mac_ctx->pdev,
10911 des_chan->ch_freq_seg1,
10912 band_mask);
10913 } else if (bw_val >= 160) {
10914 pe_debug("Skip center_freq check for bw %d", bw_val);
10915 } else {
10916 pe_err("Invalid cntr_freq for bw %d, drop to 20",
10917 bw_val);
10918 ch_width = CH_WIDTH_20MHZ;
10919 bw_val = 20;
10920 if (des_chan->ch_cfreq1)
10921 des_chan->ch_freq_seg1 =
10922 wlan_reg_freq_to_chan(
10923 mac_ctx->pdev,
10924 des_chan->ch_cfreq1);
10925 }
10926 } else if (des_chan->ch_cfreq1) {
10927 des_chan->ch_freq_seg1 =
10928 wlan_reg_freq_to_chan(mac_ctx->pdev,
10929 des_chan->ch_cfreq1);
10930 }
10931 if (bw_val > 80) {
10932 if (des_chan->ch_freq_seg2) {
10933 des_chan->ch_cfreq2 =
10934 wlan_reg_chan_band_to_freq(mac_ctx->pdev,
10935 des_chan->ch_freq_seg2,
10936 band_mask);
10937 } else {
10938 pe_err("Invalid cntr_freq for bw %d, drop to 80",
10939 bw_val);
10940 des_chan->ch_cfreq2 = 0;
10941 des_chan->ch_freq_seg2 = 0;
10942 ch_width = CH_WIDTH_80MHZ;
10943 }
10944 } else {
10945 des_chan->ch_cfreq2 = 0;
10946 des_chan->ch_freq_seg2 = 0;
10947 }
10948
10949 des_chan->ch_width = ch_width;
10950
10951 des_chan->ch_flags = 0;
10952 switch (ch_width) {
10953 case CH_WIDTH_20MHZ:
10954 des_chan->ch_flags |= IEEE80211_CHAN_VHT20;
10955 break;
10956 case CH_WIDTH_40MHZ:
10957 des_chan->ch_flags |= IEEE80211_CHAN_VHT40PLUS;
10958 break;
10959 case CH_WIDTH_80MHZ:
10960 des_chan->ch_flags |= IEEE80211_CHAN_VHT80;
10961 break;
10962 case CH_WIDTH_80P80MHZ:
10963 des_chan->ch_flags |= IEEE80211_CHAN_VHT80_80;
10964 break;
10965 case CH_WIDTH_160MHZ:
10966 des_chan->ch_flags |= IEEE80211_CHAN_VHT160;
10967 break;
10968 default:
10969 break;
10970 }
10971
10972 if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq))
10973 des_chan->ch_flags |= IEEE80211_CHAN_2GHZ;
10974 else
10975 des_chan->ch_flags |= IEEE80211_CHAN_5GHZ;
10976
10977 des_chan->ch_flagext = 0;
10978 if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev, des_chan->ch_freq))
10979 des_chan->ch_flagext |= IEEE80211_CHAN_DFS;
10980 if (des_chan->ch_cfreq2) {
10981 if (CH_WIDTH_80P80MHZ == des_chan->ch_width)
10982 start_ch_freq = des_chan->ch_cfreq2 - 30;
10983 else
10984 start_ch_freq = des_chan->ch_freq;
10985
10986 if (IS_DOT11_MODE_EHT(dot11mode))
10987 wlan_reg_set_create_punc_bitmap(&ch_params, true);
10988 ch_params.ch_width = des_chan->ch_width;
10989 ch_state =
10990 wlan_reg_get_5g_bonded_channel_state_for_pwrmode(mac_ctx->pdev,
10991 start_ch_freq,
10992 &ch_params,
10993 REG_CURRENT_PWR_MODE);
10994 if (CHANNEL_STATE_DFS == ch_state)
10995 des_chan->ch_flagext |= IEEE80211_CHAN_DFS_CFREQ2;
10996 }
10997
10998 chan_mode = wma_chan_phy_mode(des_chan->ch_freq, ch_width,
10999 dot11mode);
11000
11001 if (chan_mode == WLAN_PHYMODE_AUTO || chan_mode == WLAN_PHYMODE_MAX) {
11002 pe_err("Invalid phy mode!");
11003 return QDF_STATUS_E_FAILURE;
11004 }
11005 if (!des_chan->ch_cfreq1) {
11006 pe_err("Invalid center freq1");
11007 return QDF_STATUS_E_FAILURE;
11008 }
11009
11010 if ((ch_width == CH_WIDTH_160MHZ ||
11011 ch_width == CH_WIDTH_80P80MHZ) && !des_chan->ch_cfreq2) {
11012 pe_err("Invalid center freq2 for 160MHz");
11013 return QDF_STATUS_E_FAILURE;
11014 }
11015 /* Till conversion is not done in WMI we need to fill fw phy mode */
11016 mlme_obj->mgmt.generic.phy_mode = wmi_host_to_fw_phymode(chan_mode);
11017 des_chan->ch_phymode = chan_mode;
11018
11019 return QDF_STATUS_SUCCESS;
11020 }
11021
11022 #ifdef WLAN_FEATURE_11BE
11023 /**
11024 * lim_update_ap_puncture() - set puncture_bitmap for ap session
11025 * @session: session
11026 * @ch_params: pointer to ch_params
11027 *
11028 * Return: void
11029 */
lim_update_ap_puncture(struct pe_session * session,struct ch_params * ch_params)11030 static void lim_update_ap_puncture(struct pe_session *session,
11031 struct ch_params *ch_params)
11032 {
11033 if (ch_params->reg_punc_bitmap) {
11034 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap =
11035 ch_params->reg_punc_bitmap;
11036 session->eht_op.disabled_sub_chan_bitmap_present = true;
11037 pe_debug("vdev %d, puncture %d", session->vdev_id,
11038 ch_params->reg_punc_bitmap);
11039 }
11040 }
11041
lim_update_des_chan_puncture(struct wlan_channel * des_chan,struct ch_params * ch_params)11042 void lim_update_des_chan_puncture(struct wlan_channel *des_chan,
11043 struct ch_params *ch_params)
11044 {
11045 des_chan->puncture_bitmap = ch_params->reg_punc_bitmap;
11046 }
11047
lim_overwrite_sta_puncture(struct pe_session * session,struct ch_params * ch_param)11048 void lim_overwrite_sta_puncture(struct pe_session *session,
11049 struct ch_params *ch_param)
11050 {
11051 uint16_t new_punc = 0;
11052
11053 wlan_reg_extract_puncture_by_bw(session->ch_width,
11054 session->puncture_bitmap,
11055 session->curr_op_freq,
11056 ch_param->mhz_freq_seg1,
11057 ch_param->ch_width,
11058 &new_punc);
11059
11060 ch_param->reg_punc_bitmap = new_punc;
11061 session->puncture_bitmap = new_punc;
11062 }
11063
11064 #else
lim_update_ap_puncture(struct pe_session * session,struct ch_params * ch_params)11065 static void lim_update_ap_puncture(struct pe_session *session,
11066 struct ch_params *ch_params)
11067 {
11068 }
11069 #endif
11070
lim_pre_vdev_start(struct mac_context * mac,struct vdev_mlme_obj * mlme_obj,struct pe_session * session)11071 QDF_STATUS lim_pre_vdev_start(struct mac_context *mac,
11072 struct vdev_mlme_obj *mlme_obj,
11073 struct pe_session *session)
11074 {
11075 struct wlan_channel *des_chan;
11076 enum reg_wifi_band band;
11077 uint8_t band_mask;
11078 struct ch_params ch_params = {0};
11079 qdf_freq_t sec_chan_freq = 0;
11080
11081 band = wlan_reg_freq_to_band(session->curr_op_freq);
11082 band_mask = 1 << band;
11083
11084 ch_params.ch_width = session->ch_width;
11085 ch_params.mhz_freq_seg0 =
11086 wlan_reg_chan_band_to_freq(mac->pdev,
11087 session->ch_center_freq_seg0,
11088 band_mask);
11089
11090 if (session->ch_center_freq_seg1)
11091 ch_params.mhz_freq_seg1 =
11092 wlan_reg_chan_band_to_freq(mac->pdev,
11093 session->ch_center_freq_seg1,
11094 band_mask);
11095
11096 if (band == (REG_BAND_2G) && (ch_params.ch_width == CH_WIDTH_40MHZ)) {
11097 if (ch_params.mhz_freq_seg0 == session->curr_op_freq + 10)
11098 sec_chan_freq = session->curr_op_freq + 20;
11099 if (ch_params.mhz_freq_seg0 == session->curr_op_freq - 10)
11100 sec_chan_freq = session->curr_op_freq - 20;
11101 }
11102 if (LIM_IS_AP_ROLE(session) &&
11103 !mlme_is_chan_switch_in_progress(mlme_obj->vdev))
11104 lim_apply_puncture(mac, session, ch_params.mhz_freq_seg1);
11105
11106 if (LIM_IS_STA_ROLE(session))
11107 wlan_cdp_set_peer_freq(mac->psoc, session->bssId,
11108 session->curr_op_freq,
11109 wlan_vdev_get_id(session->vdev));
11110
11111 if (IS_DOT11_MODE_EHT(session->dot11mode))
11112 wlan_reg_set_create_punc_bitmap(&ch_params, true);
11113
11114 wlan_reg_set_channel_params_for_pwrmode(mac->pdev,
11115 session->curr_op_freq,
11116 sec_chan_freq, &ch_params,
11117 REG_CURRENT_PWR_MODE);
11118
11119 pe_debug("vdev id %d freq %d seg0 %d seg1 %d ch_width %d cac_duration_ms %d beacon_interval %d hidden_ssid: %d dtimPeriod %d slot_time %d bcn tx rate %d mhz seg0 %d mhz seg1 %d",
11120 session->vdev_id, session->curr_op_freq,
11121 ch_params.center_freq_seg0,
11122 ch_params.center_freq_seg1, ch_params.ch_width,
11123 session->cac_duration_ms,
11124 session->beaconParams.beaconInterval,
11125 session->ssidHidden, session->dtimPeriod,
11126 session->shortSlotTimeSupported,
11127 session->beacon_tx_rate,
11128 ch_params.mhz_freq_seg0,
11129 ch_params.mhz_freq_seg1);
11130
11131 /* Invalid channel width means no suitable channel bonding in current
11132 * regdomain for requested channel frequency. Abort vdev start.
11133 */
11134 if (ch_params.ch_width == CH_WIDTH_INVALID) {
11135 pe_debug("abort vdev start invalid chan parameters");
11136 return QDF_STATUS_E_INVAL;
11137 }
11138
11139 if (LIM_IS_STA_ROLE(session))
11140 lim_overwrite_sta_puncture(session, &ch_params);
11141
11142 des_chan = mlme_obj->vdev->vdev_mlme.des_chan;
11143 des_chan->ch_freq = session->curr_op_freq;
11144 des_chan->ch_width = ch_params.ch_width;
11145 des_chan->ch_freq_seg1 = ch_params.center_freq_seg0;
11146 des_chan->ch_freq_seg2 = ch_params.center_freq_seg1;
11147 des_chan->ch_ieee = wlan_reg_freq_to_chan(mac->pdev, des_chan->ch_freq);
11148 lim_update_des_chan_puncture(des_chan, &ch_params);
11149 if (LIM_IS_AP_ROLE(session))
11150 lim_update_ap_puncture(session, &ch_params);
11151 session->ch_width = ch_params.ch_width;
11152 session->ch_center_freq_seg0 = ch_params.center_freq_seg0;
11153 session->ch_center_freq_seg1 = ch_params.center_freq_seg1;
11154 if (LIM_IS_AP_ROLE(session)) {
11155 /* Update he ops for puncture */
11156 wlan_reg_set_create_punc_bitmap(&ch_params, false);
11157 wlan_reg_set_channel_params_for_pwrmode(mac->pdev,
11158 session->curr_op_freq,
11159 sec_chan_freq,
11160 &ch_params,
11161 REG_CURRENT_PWR_MODE);
11162 lim_update_ap_he_op(session, &ch_params);
11163
11164 wlan_mlme_set_ap_oper_ch_width(session->vdev,
11165 session->ch_width);
11166 if (session->ch_width == CH_WIDTH_320MHZ &&
11167 policy_mgr_is_conn_lead_to_dbs_sbs(mac->psoc,
11168 session->vdev_id,
11169 session->curr_op_freq))
11170 wlan_mlme_set_ap_oper_ch_width(session->vdev,
11171 CH_WIDTH_160MHZ);
11172 }
11173 mlme_obj->mgmt.generic.maxregpower = session->maxTxPower;
11174 mlme_obj->proto.generic.beacon_interval =
11175 session->beaconParams.beaconInterval;
11176 if (mlme_obj->mgmt.generic.type == WLAN_VDEV_MLME_TYPE_AP) {
11177 mlme_obj->mgmt.ap.hidden_ssid = session->ssidHidden;
11178 wlan_util_vdev_mgr_set_cac_timeout_for_vdev(
11179 mlme_obj->vdev, session->cac_duration_ms);
11180 }
11181 mlme_obj->proto.generic.dtim_period = session->dtimPeriod;
11182 mlme_obj->proto.generic.slot_time = session->shortSlotTimeSupported;
11183 mlme_obj->mgmt.rate_info.bcn_tx_rate = session->beacon_tx_rate;
11184
11185 mlme_obj->proto.ht_info.allow_ht = !!session->htCapability;
11186 mlme_obj->proto.vht_info.allow_vht = !!session->vhtCapability;
11187 mlme_obj->ext_vdev_ptr->connect_info.uapsd_per_ac_bitmask =
11188 session->gUapsdPerAcBitmask;
11189
11190 if (cds_is_5_mhz_enabled())
11191 mlme_obj->mgmt.rate_info.quarter_rate = 1;
11192 else if (cds_is_10_mhz_enabled())
11193 mlme_obj->mgmt.rate_info.half_rate = 1;
11194
11195 if (session->nss == 2) {
11196 mlme_obj->mgmt.chainmask_info.num_rx_chain = 2;
11197 mlme_obj->mgmt.chainmask_info.num_tx_chain = 2;
11198 } else {
11199 mlme_obj->mgmt.chainmask_info.num_rx_chain = 1;
11200 mlme_obj->mgmt.chainmask_info.num_tx_chain = 1;
11201 }
11202 wlan_vdev_mlme_set_ssid(mlme_obj->vdev, session->ssId.ssId,
11203 session->ssId.length);
11204
11205 return lim_set_ch_phy_mode(mlme_obj->vdev, session->dot11mode);
11206 }
11207
lim_get_he_max_mcs_idx(enum phy_ch_width ch_width,tDot11fIEhe_cap * he_cap)11208 uint8_t lim_get_he_max_mcs_idx(enum phy_ch_width ch_width,
11209 tDot11fIEhe_cap *he_cap)
11210 {
11211 uint16_t hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80 + 1];
11212 uint16_t hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80 + 1];
11213
11214 qdf_mem_zero(hecap_rxmcsnssmap, sizeof(hecap_rxmcsnssmap));
11215 qdf_mem_zero(hecap_txmcsnssmap, sizeof(hecap_txmcsnssmap));
11216
11217 qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80],
11218 &he_cap->rx_he_mcs_map_lt_80,
11219 sizeof(u_int16_t));
11220 qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80],
11221 &he_cap->tx_he_mcs_map_lt_80,
11222 sizeof(u_int16_t));
11223 if (he_cap->chan_width_2) {
11224 qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160],
11225 &he_cap->rx_he_mcs_map_160,
11226 sizeof(u_int16_t));
11227 qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160],
11228 &he_cap->tx_he_mcs_map_160,
11229 sizeof(u_int16_t));
11230 }
11231 if (he_cap->chan_width_3) {
11232 qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80],
11233 &he_cap->rx_he_mcs_map_80_80,
11234 sizeof(u_int16_t));
11235 qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80],
11236 &he_cap->tx_he_mcs_map_80_80,
11237 sizeof(u_int16_t));
11238 }
11239
11240 return mlme_get_max_he_mcs_idx(ch_width, hecap_rxmcsnssmap,
11241 hecap_txmcsnssmap);
11242 }
11243
lim_get_vht_max_mcs_idx(tDot11fIEVHTCaps * vht_cap)11244 uint8_t lim_get_vht_max_mcs_idx(tDot11fIEVHTCaps *vht_cap)
11245 {
11246 return mlme_get_max_vht_mcs_idx(vht_cap->rxMCSMap & 0xff,
11247 vht_cap->txMCSMap & 0xff);
11248 }
11249
lim_get_ht_max_mcs_idx(tDot11fIEHTCaps * ht_cap)11250 uint8_t lim_get_ht_max_mcs_idx(tDot11fIEHTCaps *ht_cap)
11251 {
11252 uint8_t i, maxidx = INVALID_MCS_NSS_INDEX;
11253
11254 for (i = 0; i < 8; i++) {
11255 if (ht_cap->supportedMCSSet[0] & (1 << i))
11256 maxidx = i;
11257 }
11258
11259 return maxidx;
11260 }
11261
lim_get_max_rate_idx(tSirMacRateSet * rateset)11262 uint8_t lim_get_max_rate_idx(tSirMacRateSet *rateset)
11263 {
11264 uint8_t maxidx;
11265 int i;
11266
11267 maxidx = rateset->rate[0] & 0x7f;
11268 for (i = 1; i < rateset->numRates; i++) {
11269 if ((rateset->rate[i] & 0x7f) > maxidx)
11270 maxidx = rateset->rate[i] & 0x7f;
11271 }
11272
11273 return maxidx;
11274 }
11275
lim_update_nss(struct mac_context * mac_ctx,tpDphHashNode sta_ds,uint8_t rx_nss,struct pe_session * session)11276 void lim_update_nss(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
11277 uint8_t rx_nss, struct pe_session *session)
11278 {
11279 if (sta_ds->vhtSupportedRxNss != (rx_nss + 1)) {
11280 if (session->nss_forced_1x1) {
11281 pe_debug("Not Updating NSS for special AP");
11282 return;
11283 }
11284 sta_ds->vhtSupportedRxNss = rx_nss + 1;
11285 lim_set_nss_change(mac_ctx, session,
11286 sta_ds->vhtSupportedRxNss,
11287 sta_ds->staAddr);
11288 }
11289 }
11290
11291
lim_update_channel_width(struct mac_context * mac_ctx,tpDphHashNode sta_ptr,struct pe_session * session,enum phy_ch_width ch_width,enum phy_ch_width * new_ch_width)11292 bool lim_update_channel_width(struct mac_context *mac_ctx,
11293 tpDphHashNode sta_ptr,
11294 struct pe_session *session,
11295 enum phy_ch_width ch_width,
11296 enum phy_ch_width *new_ch_width)
11297 {
11298 uint8_t cb_mode;
11299 enum phy_ch_width oper_mode;
11300 enum phy_ch_width fw_vht_ch_wd;
11301
11302 cb_mode = lim_get_cb_mode_for_freq(mac_ctx, session,
11303 session->curr_op_freq);
11304 /*
11305 * Do not update the channel bonding mode if channel bonding
11306 * mode is disabled in INI.
11307 */
11308 if (cb_mode == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE)
11309 return false;
11310
11311 if (sta_ptr->htSupportedChannelWidthSet) {
11312 if (sta_ptr->vhtSupportedChannelWidthSet >
11313 WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ)
11314 oper_mode = CH_WIDTH_160MHZ;
11315 else
11316 oper_mode = sta_ptr->vhtSupportedChannelWidthSet + 1;
11317 } else {
11318 oper_mode = CH_WIDTH_20MHZ;
11319 }
11320
11321 fw_vht_ch_wd = wlan_mlme_get_max_bw();
11322
11323 if (ch_width > fw_vht_ch_wd) {
11324 pe_debug_rl(QDF_MAC_ADDR_FMT ": Downgrade new bw: %d to max %d",
11325 QDF_MAC_ADDR_REF(sta_ptr->staAddr),
11326 ch_width, fw_vht_ch_wd);
11327 ch_width = fw_vht_ch_wd;
11328 }
11329 if (oper_mode == ch_width)
11330 return false;
11331
11332 pe_debug(QDF_MAC_ADDR_FMT ": Current : %d, New: %d max %d ",
11333 QDF_MAC_ADDR_REF(sta_ptr->staAddr), oper_mode,
11334 ch_width, fw_vht_ch_wd);
11335
11336 if (ch_width >= CH_WIDTH_160MHZ) {
11337 sta_ptr->vhtSupportedChannelWidthSet =
11338 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
11339 ch_width = CH_WIDTH_160MHZ;
11340 } else if (ch_width == CH_WIDTH_80MHZ) {
11341 sta_ptr->vhtSupportedChannelWidthSet =
11342 WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
11343 } else if (ch_width == CH_WIDTH_40MHZ) {
11344 sta_ptr->vhtSupportedChannelWidthSet =
11345 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
11346 } else if (ch_width == CH_WIDTH_20MHZ) {
11347 sta_ptr->vhtSupportedChannelWidthSet =
11348 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
11349 } else {
11350 return false;
11351 }
11352 if (ch_width >= CH_WIDTH_40MHZ)
11353 sta_ptr->htSupportedChannelWidthSet = CH_WIDTH_40MHZ;
11354 else
11355 sta_ptr->htSupportedChannelWidthSet = CH_WIDTH_20MHZ;
11356 *new_ch_width = ch_width;
11357
11358 return lim_check_vht_op_mode_change(mac_ctx, session, *new_ch_width,
11359 sta_ptr->staAddr);
11360 }
11361
lim_get_vht_ch_width(tDot11fIEVHTCaps * vht_cap,tDot11fIEVHTOperation * vht_op,tDot11fIEHTInfo * ht_info)11362 uint8_t lim_get_vht_ch_width(tDot11fIEVHTCaps *vht_cap,
11363 tDot11fIEVHTOperation *vht_op,
11364 tDot11fIEHTInfo *ht_info)
11365 {
11366 uint8_t ccfs0, ccfs1, offset;
11367 uint8_t ch_width;
11368
11369 ccfs0 = vht_op->chan_center_freq_seg0;
11370 ccfs1 = vht_op->chan_center_freq_seg1;
11371 ch_width = vht_op->chanWidth;
11372
11373 if (ch_width > WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ) {
11374 pe_err("Invalid ch width in vht operation IE %d", ch_width);
11375 return WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
11376 }
11377
11378 if (vht_cap->vht_extended_nss_bw_cap &&
11379 vht_cap->extended_nss_bw_supp && ht_info && ht_info->present)
11380 ccfs1 = ht_info->chan_center_freq_seg2;
11381
11382 /* According to new VHTOP IE definition, vht ch_width will
11383 * be 1 for 80MHz, 160MHz and 80+80MHz.
11384 *
11385 * To get the correct operation ch_width, find center
11386 * frequency difference.
11387 */
11388 if (ch_width == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ && ccfs1) {
11389 offset = abs(ccfs0 - ccfs1);
11390
11391 if (offset == 8)
11392 ch_width = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
11393 else if (offset > 16)
11394 ch_width = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
11395 }
11396 return ch_width;
11397 }
11398
11399 bool
lim_set_tpc_power(struct mac_context * mac_ctx,struct pe_session * session,struct bss_description * bss_desc)11400 lim_set_tpc_power(struct mac_context *mac_ctx, struct pe_session *session,
11401 struct bss_description *bss_desc)
11402 {
11403 struct wlan_lmac_if_reg_tx_ops *tx_ops;
11404 struct vdev_mlme_obj *mlme_obj;
11405 bool tpe_change = false;
11406
11407 if (!wlan_reg_is_ext_tpc_supported(mac_ctx->psoc))
11408 return true;
11409 tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc);
11410
11411 if (!tx_ops || !tx_ops->set_tpc_power)
11412 return false;
11413
11414 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
11415 if (!mlme_obj)
11416 return false;
11417
11418 if ((session->opmode == QDF_STA_MODE ||
11419 session->opmode == QDF_P2P_CLIENT_MODE) &&
11420 bss_desc)
11421 lim_process_tpe_ie_from_beacon(mac_ctx, session,
11422 bss_desc, &tpe_change);
11423
11424 if (session->opmode == QDF_SAP_MODE ||
11425 session->opmode == QDF_P2P_GO_MODE)
11426 mlme_obj->reg_tpc_obj.num_pwr_levels = 0;
11427
11428 lim_calculate_tpc(mac_ctx, session);
11429
11430 tx_ops->set_tpc_power(mac_ctx->psoc, session->vdev_id,
11431 &mlme_obj->reg_tpc_obj);
11432 return true;
11433 }
11434
11435 /*
11436 * lim_get_tx_power() - Function to get the Tx power of the center frequency
11437 * of the sap interface.
11438 *
11439 * @reg_tpc: reg_tpc mlme obj pointer
11440 * @freq: center frequency of the SAP.
11441 *
11442 * Return: tx power
11443 */
11444 static uint8_t
lim_get_tx_power(struct reg_tpc_power_info * reg_tpc,qdf_freq_t freq)11445 lim_get_tx_power(struct reg_tpc_power_info *reg_tpc, qdf_freq_t freq)
11446 {
11447 int i;
11448
11449 for (i = 0; i < reg_tpc->num_pwr_levels; i++) {
11450 if (reg_tpc->chan_power_info[i].chan_cfreq == freq)
11451 return reg_tpc->chan_power_info[i].tx_power;
11452 }
11453
11454 return 0;
11455 }
11456
11457 struct pe_session *
lim_get_concurrent_session(struct mac_context * mac_ctx,uint8_t vdev_id,enum QDF_OPMODE opmode)11458 lim_get_concurrent_session(struct mac_context *mac_ctx, uint8_t vdev_id,
11459 enum QDF_OPMODE opmode)
11460 {
11461 uint8_t mac_id, conc_vdev_id;
11462 struct pe_session *session;
11463
11464 policy_mgr_get_mac_id_by_session_id(mac_ctx->psoc, vdev_id, &mac_id);
11465
11466 conc_vdev_id = policy_mgr_get_conc_vdev_on_same_mac(mac_ctx->psoc,
11467 vdev_id, mac_id);
11468
11469 session = pe_find_session_by_vdev_id(mac_ctx, conc_vdev_id);
11470 if (!session)
11471 return NULL;
11472
11473 switch (opmode) {
11474 case QDF_STA_MODE:
11475 case QDF_P2P_CLIENT_MODE:
11476 if (session->opmode != QDF_SAP_MODE &&
11477 session->opmode != QDF_P2P_GO_MODE)
11478 return NULL;
11479 break;
11480 case QDF_SAP_MODE:
11481 case QDF_P2P_GO_MODE:
11482 if (session->opmode != QDF_STA_MODE &&
11483 session->opmode != QDF_P2P_CLIENT_MODE)
11484 return NULL;
11485 break;
11486 default:
11487 return NULL;
11488 }
11489
11490 return session;
11491 }
11492
11493 QDF_STATUS
lim_update_tx_power(struct mac_context * mac_ctx,struct pe_session * sap_session,struct pe_session * sta_session,bool restore_sta_power)11494 lim_update_tx_power(struct mac_context *mac_ctx, struct pe_session *sap_session,
11495 struct pe_session *sta_session, bool restore_sta_power)
11496 {
11497 uint8_t pwr_level;
11498 struct vdev_mlme_obj *sta_mlme_obj, *sap_mlme_obj;
11499 struct reg_tpc_power_info *reg_info;
11500 uint8_t tx_power, i;
11501 struct bss_description *bss_desc = NULL;
11502
11503 sta_mlme_obj = wlan_vdev_mlme_get_cmpt_obj(sta_session->vdev);
11504 sap_mlme_obj = wlan_vdev_mlme_get_cmpt_obj(sap_session->vdev);
11505
11506 if (!sta_mlme_obj || !sap_mlme_obj)
11507 return QDF_STATUS_E_FAILURE;
11508
11509 if (restore_sta_power) {
11510 /* SAP interface is removed, restore the STA power */
11511 wlan_set_tpc_update_required_for_sta(sap_session->vdev, false);
11512 sta_session->sta_follows_sap_power = false;
11513
11514 if (sta_session->lim_join_req)
11515 bss_desc = &sta_session->lim_join_req->bssDescription;
11516
11517 lim_set_tpc_power(mac_ctx, sta_session, bss_desc);
11518 } else {
11519 /*
11520 * SAP and STA are in different AP power types. Therefore,
11521 * update the reg_tpc_obj of STA with new power levels.
11522 * Do not send new TPC power to FW.
11523 */
11524 sta_session->sta_follows_sap_power = true;
11525
11526 if (sta_mlme_obj->reg_tpc_obj.power_type_6g ==
11527 sap_mlme_obj->reg_tpc_obj.power_type_6g) {
11528 pe_err("STA and SAP are in same power type");
11529 return QDF_STATUS_E_FAILURE;
11530 }
11531 pe_debug("STA is moved to %d from %d power type",
11532 sap_mlme_obj->reg_tpc_obj.power_type_6g,
11533 sta_mlme_obj->reg_tpc_obj.power_type_6g);
11534 sta_mlme_obj->reg_tpc_obj.power_type_6g =
11535 sap_mlme_obj->reg_tpc_obj.power_type_6g;
11536
11537 tx_power = lim_get_tx_power(&sap_mlme_obj->reg_tpc_obj,
11538 sap_session->curr_op_freq);
11539
11540 reg_info = &sta_mlme_obj->reg_tpc_obj;
11541 pwr_level = reg_info->num_pwr_levels;
11542 for (i = 0; i < pwr_level; i++)
11543 reg_info->chan_power_info[i].tx_power = tx_power;
11544 wlan_set_tpc_update_required_for_sta(sap_session->vdev, true);
11545 }
11546 return QDF_STATUS_SUCCESS;
11547 }
11548
11549 bool
lim_is_power_change_required_for_sta(struct mac_context * mac_ctx,struct pe_session * sta_session,struct pe_session * sap_session)11550 lim_is_power_change_required_for_sta(struct mac_context *mac_ctx,
11551 struct pe_session *sta_session,
11552 struct pe_session *sap_session)
11553 {
11554 enum channel_state channel_state;
11555 struct vdev_mlme_obj *mlme_obj;
11556 uint32_t ap_power_type_6g = 0;
11557
11558 channel_state =
11559 wlan_reg_get_channel_state_for_pwrmode(mac_ctx->pdev,
11560 sap_session->curr_op_freq,
11561 REG_AP_VLP);
11562
11563 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(sap_session->vdev);
11564 if (!mlme_obj) {
11565 pe_err("vdev component object is NULL");
11566 return false;
11567 }
11568
11569 if (sta_session->curr_op_freq != sap_session->curr_op_freq)
11570 return false;
11571
11572 wlan_reg_get_cur_6g_ap_pwr_type(mac_ctx->pdev, &ap_power_type_6g);
11573
11574 if (sta_session->best_6g_power_type == REG_INDOOR_AP &&
11575 channel_state & CHANNEL_STATE_ENABLE &&
11576 ap_power_type_6g == REG_VERY_LOW_POWER_AP) {
11577 pe_debug("Change the power type of STA from LPI to VLP");
11578 return true;
11579 }
11580
11581 return false;
11582 }
11583
11584 void
lim_check_conc_power_for_csa(struct mac_context * mac_ctx,struct pe_session * sap_session)11585 lim_check_conc_power_for_csa(struct mac_context *mac_ctx,
11586 struct pe_session *sap_session)
11587 {
11588 struct pe_session *sta_session;
11589 bool update_required_scc_sta_power =
11590 wlan_get_tpc_update_required_for_sta(sap_session->vdev);
11591
11592 /*
11593 * If SCC power has changed and concurrent session doesn't exist,
11594 * then STA must have got deleted or moved out of 6GHz.
11595 * In that case, reset the change scc power flag for SAP.
11596 */
11597 sta_session = lim_get_concurrent_session(mac_ctx, sap_session->vdev_id,
11598 sap_session->opmode);
11599 if (!sta_session) {
11600 pe_debug("STA session doesn't exist");
11601 return;
11602 }
11603
11604 /* If SCC power has changed and the SAP is moving away from 6GHz,
11605 * reset the scc power flag in SAP vdev and restore the STA
11606 * power
11607 */
11608 if (update_required_scc_sta_power &&
11609 !WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_session->curr_op_freq) &&
11610 WLAN_REG_IS_6GHZ_CHAN_FREQ(sta_session->curr_op_freq)) {
11611 pe_debug("SAP has moved from 6GHz, restore STA power");
11612 lim_update_tx_power(mac_ctx, sap_session, sta_session, true);
11613 return;
11614 }
11615
11616 /* If SAP is moving to 6GHz. Then:
11617 * a) If change scc power is not set, check if it needs to be set
11618 * If it is getting set, then send new tpc power to FW.
11619 * b) If change scc power is already set, then SAP is moving from one
11620 * 6GHz to another 6GHz. Recompute the TPC.
11621 */
11622 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_session->curr_op_freq) &&
11623 sta_session &&
11624 WLAN_REG_IS_6GHZ_CHAN_FREQ(sta_session->curr_op_freq) &&
11625 (wlan_vdev_mlme_get_state(sap_session->vdev) == WLAN_VDEV_S_UP)) {
11626 if (lim_is_power_change_required_for_sta(mac_ctx, sta_session,
11627 sap_session)) {
11628 lim_set_tpc_power(mac_ctx, sap_session, NULL);
11629 if (lim_update_tx_power(mac_ctx, sap_session,
11630 sta_session, false) ==
11631 QDF_STATUS_SUCCESS)
11632 wlan_set_tpc_update_required_for_sta(
11633 sap_session->vdev,
11634 true);
11635 }
11636 }
11637 }
11638
11639 void
lim_cleanup_power_change(struct mac_context * mac_ctx,struct pe_session * session)11640 lim_cleanup_power_change(struct mac_context *mac_ctx,
11641 struct pe_session *session)
11642 {
11643 struct pe_session *sap_session;
11644
11645 if (session->opmode != QDF_STA_MODE &&
11646 session->opmode != QDF_P2P_CLIENT_MODE)
11647 return;
11648
11649 sap_session =
11650 lim_get_concurrent_session(mac_ctx, session->vdev_id,
11651 session->opmode);
11652 if (!sap_session)
11653 return;
11654
11655 wlan_set_tpc_update_required_for_sta(sap_session->vdev, false);
11656 }
11657
11658 void
lim_update_tx_pwr_on_ctry_change_cb(uint8_t vdev_id)11659 lim_update_tx_pwr_on_ctry_change_cb(uint8_t vdev_id)
11660 {
11661 struct mac_context *mac_ctx;
11662 struct pe_session *session;
11663 struct bss_description *bss_desc = NULL;
11664
11665 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
11666 if (!mac_ctx) {
11667 pe_err("mac ctx is null");
11668 return;
11669 }
11670
11671 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
11672 if (!session) {
11673 pe_err("Unable to find session");
11674 return;
11675 }
11676
11677 if (session->lim_join_req)
11678 bss_desc = &session->lim_join_req->bssDescription;
11679
11680 lim_set_tpc_power(mac_ctx, session, bss_desc);
11681 }
11682
11683 struct wlan_channel *
lim_get_connected_chan_for_mode(struct wlan_objmgr_psoc * psoc,enum QDF_OPMODE device_mode,qdf_freq_t start_freq,qdf_freq_t end_freq)11684 lim_get_connected_chan_for_mode(struct wlan_objmgr_psoc *psoc,
11685 enum QDF_OPMODE device_mode,
11686 qdf_freq_t start_freq,
11687 qdf_freq_t end_freq)
11688 {
11689 struct wlan_channel *des_chan;
11690 struct wlan_objmgr_vdev *vdev;
11691 uint8_t vdev_id;
11692
11693 for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) {
11694 vdev =
11695 wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
11696 WLAN_LEGACY_MAC_ID);
11697 if (!vdev)
11698 continue;
11699
11700 if (vdev->vdev_mlme.vdev_opmode != device_mode)
11701 goto next;
11702
11703 if ((device_mode == QDF_STA_MODE ||
11704 device_mode == QDF_P2P_CLIENT_MODE) &&
11705 !wlan_cm_is_vdev_connected(vdev))
11706 goto next;
11707
11708 des_chan = vdev->vdev_mlme.des_chan;
11709 if (!des_chan)
11710 goto next;
11711
11712 if (des_chan->ch_freq < start_freq ||
11713 des_chan->ch_freq > end_freq)
11714 goto next;
11715
11716 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
11717 return des_chan;
11718 next:
11719 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
11720 }
11721
11722 return NULL;
11723 }
11724
11725 enum phy_ch_width
lim_convert_vht_chwidth_to_phy_chwidth(uint8_t ch_width,bool is_40)11726 lim_convert_vht_chwidth_to_phy_chwidth(uint8_t ch_width, bool is_40)
11727 {
11728 switch (ch_width) {
11729 case WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ:
11730 return CH_WIDTH_80P80MHZ;
11731 case WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ:
11732 return CH_WIDTH_160MHZ;
11733 case WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ:
11734 return CH_WIDTH_80MHZ;
11735 case WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ:
11736 if (is_40)
11737 return CH_WIDTH_40MHZ;
11738 else
11739 return CH_WIDTH_20MHZ;
11740 default:
11741 pe_debug("Unknown VHT ch width %d", ch_width);
11742 break;
11743 }
11744 return CH_WIDTH_20MHZ;
11745 }
11746
11747 void
lim_configure_fd_for_existing_6ghz_sap(struct pe_session * session,bool is_sap_starting)11748 lim_configure_fd_for_existing_6ghz_sap(struct pe_session *session,
11749 bool is_sap_starting)
11750 {
11751 uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
11752 qdf_freq_t freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
11753 struct wlan_objmgr_vdev *vdev;
11754 struct vdev_mlme_obj *mlme_obj;
11755 uint8_t vdev_num, i;
11756 bool is_legacy_sap_present = false;
11757
11758 if (session->opmode != QDF_SAP_MODE)
11759 return;
11760
11761 vdev_num = policy_mgr_get_sap_mode_info(session->mac_ctx->psoc,
11762 freq_list, vdev_id_list);
11763
11764 for (i = 0; i < vdev_num; i++) {
11765 if (vdev_id_list[i] == session->vdev_id)
11766 continue;
11767
11768 if (!wlan_reg_is_6ghz_chan_freq(freq_list[i])) {
11769 is_legacy_sap_present = true;
11770 break;
11771 }
11772 }
11773
11774 if (is_sap_starting) {
11775 /*
11776 * The SAP which is coming up is also in 6 GHz, therefore do not
11777 * modify the FD config for other 6 GHz SAPs.
11778 * vdev start will enable/disable the FD config for this SAP.
11779 */
11780 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
11781 wlan_mlme_disable_fd_in_6ghz_band(session->vdev,
11782 is_legacy_sap_present);
11783 return;
11784 }
11785
11786 /*
11787 * Atleast one legacy SAP is present, disable FD for all the
11788 * existing 6 GHz SAPs.
11789 */
11790 for (i = 0; i < vdev_num; i++) {
11791 if (!wlan_reg_is_6ghz_chan_freq(freq_list[i]))
11792 continue;
11793 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
11794 session->mac_ctx->psoc,
11795 vdev_id_list[i],
11796 WLAN_LEGACY_MAC_ID);
11797 if (!vdev)
11798 continue;
11799
11800 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
11801 if (!mlme_obj) {
11802 pe_err("Unable to get mlme obj for vdev %d",
11803 vdev_id_list[i]);
11804 goto rel;
11805 }
11806
11807 if (!wlan_mlme_is_fd_disabled_in_6ghz_band(vdev)) {
11808 wlan_mlme_disable_fd_in_6ghz_band(vdev, true);
11809 vdev_mgr_configure_fd_for_sap(mlme_obj);
11810 }
11811 rel:
11812 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
11813 }
11814 } else {
11815 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
11816 wlan_mlme_disable_fd_in_6ghz_band(session->vdev, false);
11817 return;
11818 }
11819
11820 if (is_legacy_sap_present)
11821 return;
11822 /*
11823 * If no other legacy SAP is present, and the last legacy SAP
11824 * is going down, re-enable FD for all the 6 GHz SAP.
11825 */
11826 for (i = 0; i < vdev_num; i++) {
11827 if (!wlan_reg_is_6ghz_chan_freq(freq_list[i]))
11828 continue;
11829 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
11830 session->mac_ctx->psoc,
11831 vdev_id_list[i],
11832 WLAN_LEGACY_MAC_ID);
11833 if (!vdev)
11834 continue;
11835
11836 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
11837 if (!mlme_obj) {
11838 pe_err("Unable to get mlme obj for vdev %d",
11839 vdev_id_list[i]);
11840 goto rel_vdev;
11841 }
11842
11843 if (wlan_mlme_is_fd_disabled_in_6ghz_band(vdev)) {
11844 wlan_mlme_disable_fd_in_6ghz_band(vdev, false);
11845 vdev_mgr_configure_fd_for_sap(mlme_obj);
11846 }
11847 rel_vdev:
11848 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
11849 }
11850 }
11851 }
11852
11853 #ifdef WLAN_CHIPSET_STATS
lim_cp_stats_cstats_log_assoc_resp_evt(struct pe_session * session_entry,enum cstats_dir dir,uint16_t status_code,uint16_t aid,uint8_t * bssid,uint8_t * da,bool is_ht,bool is_vht,bool is_he,bool is_eht,bool is_reassoc)11854 void lim_cp_stats_cstats_log_assoc_resp_evt(struct pe_session *session_entry,
11855 enum cstats_dir dir,
11856 uint16_t status_code, uint16_t aid,
11857 uint8_t *bssid, uint8_t *da,
11858 bool is_ht, bool is_vht,
11859 bool is_he, bool is_eht,
11860 bool is_reassoc)
11861 {
11862 struct cstats_assoc_resp_mgmt_frm stat = {0};
11863
11864 if (is_reassoc) {
11865 stat.cmn.hdr.evt_id =
11866 WLAN_CHIPSET_STATS_MGMT_REASSOC_RESP_EVENT_ID;
11867 } else {
11868 stat.cmn.hdr.evt_id =
11869 WLAN_CHIPSET_STATS_MGMT_ASSOC_RESP_EVENT_ID;
11870 }
11871
11872 stat.cmn.hdr.length = sizeof(struct cstats_assoc_resp_mgmt_frm) -
11873 sizeof(struct cstats_hdr);
11874 stat.cmn.vdev_id = session_entry->vdev_id;
11875 stat.cmn.opmode = session_entry->opmode;
11876 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
11877 stat.cmn.time_tick = qdf_get_log_timestamp();
11878
11879 stat.direction = dir;
11880 stat.status_code = status_code;
11881 stat.aid = aid;
11882
11883 if (is_ht)
11884 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HT);
11885
11886 if (is_vht)
11887 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_VHT);
11888
11889 if (is_he)
11890 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HE);
11891
11892 if (is_eht)
11893 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_EHT);
11894
11895 CSTATS_MAC_COPY(stat.bssid, bssid);
11896 CSTATS_MAC_COPY(stat.dest_mac, da);
11897
11898 wlan_cstats_host_stats(sizeof(struct cstats_assoc_resp_mgmt_frm),
11899 &stat);
11900 }
11901
11902 void
lim_cp_stats_cstats_log_auth_evt(struct pe_session * pe_session,enum cstats_dir dir,uint16_t algo,uint16_t seq,uint16_t status)11903 lim_cp_stats_cstats_log_auth_evt(struct pe_session *pe_session,
11904 enum cstats_dir dir, uint16_t algo,
11905 uint16_t seq, uint16_t status)
11906 {
11907 struct cstats_auth_mgmt_frm stat = {0};
11908
11909 stat.cmn.hdr.evt_id = WLAN_CHIPSET_STATS_MGMT_AUTH_EVENT_ID;
11910 stat.cmn.hdr.length =
11911 sizeof(struct cstats_auth_mgmt_frm) -
11912 sizeof(struct cstats_hdr);
11913 stat.cmn.opmode = pe_session->opmode;
11914 stat.cmn.vdev_id = pe_session->vdev_id;
11915 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
11916 stat.cmn.time_tick = qdf_get_log_timestamp();
11917
11918 stat.direction = dir;
11919 stat.auth_algo = algo;
11920 stat.auth_seq_num = seq;
11921 stat.status = status;
11922
11923 wlan_cstats_host_stats(sizeof(struct cstats_auth_mgmt_frm), &stat);
11924 }
11925
lim_cp_stats_cstats_log_deauth_evt(struct pe_session * pe_session,enum cstats_dir dir,uint16_t reasonCode)11926 void lim_cp_stats_cstats_log_deauth_evt(struct pe_session *pe_session,
11927 enum cstats_dir dir,
11928 uint16_t reasonCode)
11929 {
11930 struct cstats_deauth_mgmt_frm stat = {0};
11931
11932 stat.cmn.hdr.evt_id = WLAN_CHIPSET_STATS_MGMT_DEAUTH_EVENT_ID;
11933 stat.cmn.hdr.length = sizeof(struct cstats_deauth_mgmt_frm) -
11934 sizeof(struct cstats_hdr);
11935 stat.cmn.opmode = pe_session->opmode;
11936 stat.cmn.vdev_id = pe_session->vdev_id;
11937 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
11938 stat.cmn.time_tick = qdf_get_log_timestamp();
11939
11940 stat.reason = reasonCode;
11941 stat.direction = dir;
11942
11943 wlan_cstats_host_stats(sizeof(struct cstats_deauth_mgmt_frm), &stat);
11944 }
11945
lim_cp_stats_cstats_log_disassoc_evt(struct pe_session * pe_session,enum cstats_dir dir,uint16_t reasonCode)11946 void lim_cp_stats_cstats_log_disassoc_evt(struct pe_session *pe_session,
11947 enum cstats_dir dir,
11948 uint16_t reasonCode)
11949 {
11950 struct cstats_disassoc_mgmt_frm stat = {0};
11951
11952 stat.cmn.hdr.evt_id = WLAN_CHIPSET_STATS_MGMT_DISASSOC_EVENT_ID;
11953 stat.cmn.hdr.length = sizeof(struct cstats_disassoc_mgmt_frm) -
11954 sizeof(struct cstats_hdr);
11955 stat.cmn.opmode = pe_session->opmode;
11956 stat.cmn.vdev_id = pe_session->vdev_id;
11957 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
11958 stat.cmn.time_tick = qdf_get_log_timestamp();
11959
11960 stat.reason = reasonCode;
11961 stat.direction = dir;
11962
11963 wlan_cstats_host_stats(sizeof(struct cstats_disassoc_mgmt_frm), &stat);
11964 }
11965
lim_cp_stats_cstats_log_assoc_req_evt(struct pe_session * pe_session,enum cstats_dir dir,uint8_t * bssid,uint8_t * sa,uint8_t ssid_len,uint8_t * ssid,bool is_ht,bool is_vht,bool is_he,bool is_eht,bool is_reassoc)11966 void lim_cp_stats_cstats_log_assoc_req_evt(struct pe_session *pe_session,
11967 enum cstats_dir dir,
11968 uint8_t *bssid, uint8_t *sa,
11969 uint8_t ssid_len, uint8_t *ssid,
11970 bool is_ht, bool is_vht, bool is_he,
11971 bool is_eht, bool is_reassoc)
11972 {
11973 struct cstats_assoc_req_mgmt_frm stat = {0};
11974
11975 if (is_reassoc) {
11976 stat.cmn.hdr.evt_id =
11977 WLAN_CHIPSET_STATS_MGMT_REASSOC_REQ_EVENT_ID;
11978 } else {
11979 stat.cmn.hdr.evt_id =
11980 WLAN_CHIPSET_STATS_MGMT_ASSOC_REQ_EVENT_ID;
11981 }
11982
11983 stat.cmn.hdr.length = sizeof(struct cstats_assoc_req_mgmt_frm) -
11984 sizeof(struct cstats_hdr);
11985
11986 stat.cmn.opmode = pe_session->opmode;
11987 stat.cmn.vdev_id = pe_session->vdev_id;
11988 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
11989 stat.cmn.time_tick = qdf_get_log_timestamp();
11990
11991 stat.freq = pe_session->curr_op_freq;
11992 stat.ssid_len = ssid_len;
11993 qdf_mem_copy(stat.ssid, ssid, ssid_len);
11994
11995 stat.direction = dir;
11996 CSTATS_MAC_COPY(stat.bssid, bssid);
11997 CSTATS_MAC_COPY(stat.sa, sa);
11998
11999 if (is_ht)
12000 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HT);
12001
12002 if (is_vht)
12003 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_VHT);
12004
12005 if (is_he)
12006 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HE);
12007
12008 if (is_eht)
12009 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_EHT);
12010
12011 wlan_cstats_host_stats(sizeof(struct cstats_assoc_req_mgmt_frm), &stat);
12012 }
12013
lim_cp_stats_cstats_log_disc_req_evt(tDot11fTDLSDisReq * frm,struct pe_session * pe_session)12014 void lim_cp_stats_cstats_log_disc_req_evt(tDot11fTDLSDisReq *frm,
12015 struct pe_session *pe_session)
12016 {
12017 struct cstats_tdls_disc_req stat = {0};
12018
12019 stat.cmn.hdr.evt_id =
12020 WLAN_CHIPSET_STATS_STA_TDLS_DISCOVERY_REQ_EVENT_ID;
12021 stat.cmn.hdr.length = sizeof(struct cstats_tdls_disc_req) -
12022 sizeof(struct cstats_hdr);
12023 stat.cmn.opmode = pe_session->opmode;
12024 stat.cmn.vdev_id = pe_session->vdev_id;
12025 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
12026 stat.cmn.time_tick = qdf_get_log_timestamp();
12027 stat.act_category = frm->Category.category;
12028 stat.act = frm->Action.action;
12029 stat.dt = frm->DialogToken.token;
12030 stat.direction = CSTATS_DIR_TX;
12031
12032 CSTATS_MAC_COPY(stat.init_sta_addr, frm->LinkIdentifier.InitStaAddr);
12033 CSTATS_MAC_COPY(stat.bssid, frm->LinkIdentifier.bssid);
12034 CSTATS_MAC_COPY(stat.resp_sta_addr, frm->LinkIdentifier.RespStaAddr);
12035
12036 wlan_cstats_host_stats(sizeof(struct cstats_tdls_disc_req), &stat);
12037 }
12038
lim_cp_stats_cstats_log_disc_resp_evt(tDot11fTDLSDisRsp * frm,struct pe_session * pe_session)12039 void lim_cp_stats_cstats_log_disc_resp_evt(tDot11fTDLSDisRsp *frm,
12040 struct pe_session *pe_session)
12041 {
12042 struct cstats_tdls_disc_resp stat = {0};
12043
12044 stat.cmn.hdr.evt_id =
12045 WLAN_CHIPSET_STATS_STA_TDLS_DISCOVERY_RESP_EVENT_ID;
12046 stat.cmn.hdr.length = sizeof(struct cstats_tdls_disc_resp) -
12047 sizeof(struct cstats_hdr);
12048 stat.cmn.opmode = pe_session->opmode;
12049 stat.cmn.vdev_id = pe_session->vdev_id;
12050 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
12051 stat.cmn.time_tick = qdf_get_log_timestamp();
12052
12053 stat.act_category = frm->Category.category;
12054 stat.act = frm->Action.action;
12055 stat.dt = frm->DialogToken.token;
12056 stat.direction = CSTATS_DIR_TX;
12057
12058 if (frm->HTCaps.present)
12059 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HT);
12060
12061 if (frm->VHTCaps.present)
12062 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_VHT);
12063
12064 if (frm->he_cap.present)
12065 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HE);
12066
12067 CSTATS_MAC_COPY(stat.init_sta_addr, frm->LinkIdentifier.InitStaAddr);
12068 CSTATS_MAC_COPY(stat.bssid, frm->LinkIdentifier.bssid);
12069 CSTATS_MAC_COPY(stat.resp_sta_addr, frm->LinkIdentifier.RespStaAddr);
12070
12071 wlan_cstats_host_stats(sizeof(struct cstats_tdls_disc_resp), &stat);
12072 }
12073
lim_cp_stats_cstats_log_setup_req_evt(tDot11fTDLSSetupReq * frm,struct pe_session * pe_session)12074 void lim_cp_stats_cstats_log_setup_req_evt(tDot11fTDLSSetupReq *frm,
12075 struct pe_session *pe_session)
12076 {
12077 struct cstats_tdls_setup_req stat = {0};
12078
12079 stat.cmn.hdr.evt_id = WLAN_CHIPSET_STATS_STA_TDLS_SETUP_REQ_EVENT_ID;
12080 stat.cmn.hdr.length = sizeof(struct cstats_tdls_setup_req) -
12081 sizeof(struct cstats_hdr);
12082 stat.cmn.opmode = pe_session->opmode;
12083 stat.cmn.vdev_id = pe_session->vdev_id;
12084 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
12085 stat.cmn.time_tick = qdf_get_log_timestamp();
12086
12087 stat.act_category = frm->Category.category;
12088 stat.act = frm->Action.action;
12089 stat.dt = frm->DialogToken.token;
12090 stat.direction = CSTATS_DIR_TX;
12091
12092 if (frm->HTCaps.present)
12093 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HT);
12094
12095 if (frm->VHTCaps.present)
12096 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_VHT);
12097
12098 if (frm->he_cap.present)
12099 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HE);
12100
12101 CSTATS_MAC_COPY(stat.init_sta_addr, frm->LinkIdentifier.InitStaAddr);
12102 CSTATS_MAC_COPY(stat.bssid, frm->LinkIdentifier.bssid);
12103 CSTATS_MAC_COPY(stat.resp_sta_addr, frm->LinkIdentifier.RespStaAddr);
12104
12105 wlan_cstats_host_stats(sizeof(struct cstats_tdls_setup_req), &stat);
12106 }
12107
12108 void
lim_cp_stats_cstats_log_setup_resp_evt(tDot11fTDLSSetupRsp * frm,struct pe_session * pe_session)12109 lim_cp_stats_cstats_log_setup_resp_evt(tDot11fTDLSSetupRsp *frm,
12110 struct pe_session *pe_session)
12111 {
12112 struct cstats_tdls_setup_resp stat = {0};
12113
12114 stat.cmn.hdr.evt_id = WLAN_CHIPSET_STATS_STA_TDLS_SETUP_RESP_EVENT_ID;
12115 stat.cmn.hdr.length = sizeof(struct cstats_tdls_setup_resp) -
12116 sizeof(struct cstats_hdr);
12117 stat.cmn.opmode = pe_session->opmode;
12118 stat.cmn.vdev_id = pe_session->vdev_id;
12119 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
12120 stat.cmn.time_tick = qdf_get_log_timestamp();
12121
12122 stat.act_category = frm->Category.category;
12123 stat.act = frm->Action.action;
12124 stat.dt = frm->DialogToken.token;
12125 stat.direction = CSTATS_DIR_TX;
12126
12127 if (frm->HTCaps.present)
12128 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HT);
12129
12130 if (frm->VHTCaps.present)
12131 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_VHT);
12132
12133 if (frm->he_cap.present)
12134 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HE);
12135
12136 stat.status = frm->Status.status;
12137
12138 CSTATS_MAC_COPY(stat.init_sta_addr, frm->LinkIdentifier.InitStaAddr);
12139 CSTATS_MAC_COPY(stat.bssid, frm->LinkIdentifier.bssid);
12140 CSTATS_MAC_COPY(stat.resp_sta_addr, frm->LinkIdentifier.RespStaAddr);
12141
12142 wlan_cstats_host_stats(sizeof(struct cstats_tdls_setup_resp), &stat);
12143 }
12144
12145 void
lim_cp_stats_cstats_log_setup_confirm_evt(tDot11fTDLSSetupCnf * frm,struct pe_session * pe_session)12146 lim_cp_stats_cstats_log_setup_confirm_evt(tDot11fTDLSSetupCnf *frm,
12147 struct pe_session *pe_session)
12148 {
12149 struct cstats_tdls_setup_confirm stat = {0};
12150
12151 stat.cmn.hdr.evt_id =
12152 WLAN_CHIPSET_STATS_STA_TDLS_SETUP_CONFIRM_EVENT_ID;
12153 stat.cmn.hdr.length = sizeof(struct cstats_tdls_setup_confirm) -
12154 sizeof(struct cstats_hdr);
12155 stat.cmn.opmode = pe_session->opmode;
12156 stat.cmn.vdev_id = pe_session->vdev_id;
12157 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
12158 stat.cmn.time_tick = qdf_get_log_timestamp();
12159
12160 stat.act_category = frm->Category.category;
12161 stat.act = frm->Action.action;
12162 stat.dt = frm->DialogToken.token;
12163 stat.direction = CSTATS_DIR_TX;
12164
12165 if (frm->HTInfo.present)
12166 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HT);
12167
12168 if (frm->VHTOperation.present)
12169 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_VHT);
12170
12171 if (frm->he_op.present)
12172 CSTATS_SET_BIT(stat.flags, CSTATS_FLAG_HE);
12173
12174 stat.status = frm->Status.status;
12175
12176 CSTATS_MAC_COPY(stat.init_sta_addr, frm->LinkIdentifier.InitStaAddr);
12177 CSTATS_MAC_COPY(stat.bssid, frm->LinkIdentifier.bssid);
12178 CSTATS_MAC_COPY(stat.resp_sta_addr, frm->LinkIdentifier.RespStaAddr);
12179
12180 wlan_cstats_host_stats(sizeof(struct cstats_tdls_setup_confirm), &stat);
12181 }
12182
12183 void
lim_cp_stats_cstats_log_tear_down_evt(tDot11fTDLSTeardown * frm,struct pe_session * pe_session)12184 lim_cp_stats_cstats_log_tear_down_evt(tDot11fTDLSTeardown *frm,
12185 struct pe_session *pe_session)
12186 {
12187 struct cstats_tdls_tear_down stat = {0};
12188
12189 stat.cmn.hdr.evt_id = WLAN_CHIPSET_STATS_STA_TDLS_TEARDOWN_EVENT_ID;
12190 stat.cmn.hdr.length = sizeof(struct cstats_tdls_setup_confirm) -
12191 sizeof(struct cstats_hdr);
12192 stat.cmn.opmode = pe_session->opmode;
12193 stat.cmn.vdev_id = pe_session->vdev_id;
12194 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
12195 stat.cmn.time_tick = qdf_get_log_timestamp();
12196
12197 stat.act_category = frm->Category.category;
12198 stat.act = frm->Action.action;
12199 stat.direction = CSTATS_DIR_TX;
12200
12201 stat.reason = frm->Reason.code;
12202
12203 CSTATS_MAC_COPY(stat.init_sta_addr, frm->LinkIdentifier.InitStaAddr);
12204 CSTATS_MAC_COPY(stat.bssid, frm->LinkIdentifier.bssid);
12205 CSTATS_MAC_COPY(stat.resp_sta_addr, frm->LinkIdentifier.RespStaAddr);
12206
12207 wlan_cstats_host_stats(sizeof(struct cstats_tdls_tear_down), &stat);
12208 }
12209
lim_cp_stats_cstats_log_csa_evt(struct pe_session * pe_session,enum cstats_dir dir,uint16_t target_freq,uint8_t target_ch_width,uint8_t switch_mode)12210 void lim_cp_stats_cstats_log_csa_evt(struct pe_session *pe_session,
12211 enum cstats_dir dir, uint16_t target_freq,
12212 uint8_t target_ch_width,
12213 uint8_t switch_mode)
12214 {
12215 struct cstats_csa_evt stat = {0};
12216
12217 stat.cmn.hdr.evt_id = WLAN_CHIPSET_STATS_CSA_EVENT_ID;
12218 stat.cmn.hdr.length = sizeof(struct cstats_csa_evt) -
12219 sizeof(struct cstats_hdr);
12220 stat.cmn.opmode = pe_session->opmode;
12221 stat.cmn.vdev_id = pe_session->vdev_id;
12222 stat.cmn.timestamp_us = qdf_get_time_of_the_day_us();
12223 stat.cmn.time_tick = qdf_get_log_timestamp();
12224
12225 stat.direction = dir;
12226 stat.target_freq = target_freq;
12227 stat.target_ch_width = target_ch_width;
12228 stat.current_freq = pe_session->curr_op_freq;
12229 stat.current_ch_width = pe_session->ch_width;
12230 stat.switch_mode = switch_mode;
12231
12232 wlan_cstats_host_stats(sizeof(struct cstats_csa_evt), &stat);
12233 }
12234 #endif /* WLAN_CHIPSET_STATS */
12235
lim_get_tpe_ie_length(enum phy_ch_width chan_width,tDot11fIEtransmit_power_env * tpe_ie,uint16_t num_tpe)12236 uint16_t lim_get_tpe_ie_length(enum phy_ch_width chan_width,
12237 tDot11fIEtransmit_power_env *tpe_ie,
12238 uint16_t num_tpe)
12239 {
12240 uint16_t total_ie_len = 0;
12241 uint16_t idx = 0;
12242
12243 for (idx = 0; idx < num_tpe; idx++) {
12244 if (!tpe_ie[idx].present)
12245 return total_ie_len;
12246
12247 /* +2 for including element id and length */
12248 total_ie_len += 2;
12249 /* +1 for including tx power info */
12250 total_ie_len += 1;
12251 total_ie_len += tpe_ie[idx].num_tx_power;
12252
12253 if (!(chan_width == CH_WIDTH_320MHZ &&
12254 tpe_ie[idx].max_tx_pwr_interpret))
12255 continue;
12256
12257 if (tpe_ie[idx].max_tx_pwr_interpret == LOCAL_EIRP ||
12258 tpe_ie[idx].max_tx_pwr_interpret == REGULATORY_CLIENT_EIRP) {
12259 /* Maximum Transmit Power For 320 MHz */
12260 total_ie_len += 1;
12261 } else if (tpe_ie[idx].max_tx_pwr_interpret == LOCAL_EIRP_PSD ||
12262 tpe_ie[idx].max_tx_pwr_interpret == REGULATORY_CLIENT_EIRP_PSD) {
12263 /* Extension Transmit PSD Information */
12264 total_ie_len += 1;
12265 /* Maximum Transmit PSD power */
12266 total_ie_len += MAX_TX_PSD_POWER;
12267 }
12268 }
12269
12270 return total_ie_len;
12271 }
12272
lim_fill_complete_tpe_ie(enum phy_ch_width chan_width,uint16_t tpe_ie_len,tDot11fIEtransmit_power_env * tpe_ptr,uint16_t num_tpe,uint8_t * target)12273 QDF_STATUS lim_fill_complete_tpe_ie(enum phy_ch_width chan_width,
12274 uint16_t tpe_ie_len,
12275 tDot11fIEtransmit_power_env *tpe_ptr,
12276 uint16_t num_tpe, uint8_t *target)
12277 {
12278 uint8_t *ie_len = NULL;
12279 uint32_t consumed = 0;
12280 uint32_t total_consumed = 0;
12281 uint8_t tx_pwr_info = 0U;
12282 uint8_t local_psd = 0U;
12283 uint8_t reg_psd = 0U;
12284 uint8_t *on_entry_target = target;
12285 QDF_STATUS status = QDF_STATUS_SUCCESS;
12286 uint16_t idx = 0;
12287
12288 for (idx = 0; idx < num_tpe; idx++) {
12289 if (!tpe_ptr[idx].present)
12290 return QDF_STATUS_E_INVAL;
12291
12292 consumed = 0;
12293 *target = WLAN_ELEMID_VHT_TX_PWR_ENVLP;
12294 ++target;
12295 ++consumed;
12296
12297 ie_len = target;
12298 ++target;
12299 ++consumed;
12300
12301 tx_pwr_info = 0U;
12302 tx_pwr_info |= (tpe_ptr[idx].max_tx_pwr_count << 0);
12303 tx_pwr_info |= (tpe_ptr[idx].max_tx_pwr_interpret << 3);
12304 tx_pwr_info |= (tpe_ptr[idx].max_tx_pwr_category << 6);
12305 *target = tx_pwr_info;
12306 ++consumed;
12307 ++target;
12308
12309 qdf_mem_copy(target, &tpe_ptr[idx].tx_power, tpe_ptr[idx].num_tx_power);
12310 consumed += tpe_ptr[idx].num_tx_power;
12311 target += tpe_ptr[idx].num_tx_power;
12312
12313 if (!(chan_width == CH_WIDTH_320MHZ &&
12314 tpe_ptr[idx].max_tx_pwr_interpret))
12315 goto end;
12316
12317 switch (tpe_ptr[idx].max_tx_pwr_interpret) {
12318 case LOCAL_EIRP:
12319 /* Maximum Local EIRP Transmit Power For 320 MHz */
12320 *target = tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_local_eirp.max_tx_power_for_320;
12321 target += 1;
12322 consumed += 1;
12323 break;
12324 case LOCAL_EIRP_PSD:
12325 local_psd = 0U;
12326 local_psd |= (tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_local_psd.ext_count << 0);
12327 local_psd |= (tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_local_psd.reserved << 4);
12328 /* Extension Transmit Local PSD Information */
12329 *target = local_psd;
12330 target += 1;
12331 consumed += 1;
12332 /* Maximum Transmit Local PSD power */
12333 qdf_mem_copy(target, tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_local_psd.max_tx_psd_power, MAX_TX_PSD_POWER);
12334 target += MAX_TX_PSD_POWER;
12335 consumed += MAX_TX_PSD_POWER;
12336 break;
12337 case REGULATORY_CLIENT_EIRP:
12338 /* Maximum Regulatory EIRP Transmit Power For 320 MHz */
12339 *target = tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_reg_eirp.max_tx_power_for_320;
12340 target += 1;
12341 consumed += 1;
12342 break;
12343 case REGULATORY_CLIENT_EIRP_PSD:
12344 reg_psd = 0U;
12345 reg_psd |= (tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_reg_psd.ext_count << 0);
12346 reg_psd |= (tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_reg_psd.reserved << 4);
12347 /* Extension Transmit Regulatory PSD Information */
12348 *target = reg_psd;
12349 consumed += 1;
12350 target += 1;
12351 /* Maximum Transmit Regulatory PSD power */
12352 qdf_mem_copy(target, tpe_ptr[idx].ext_max_tx_power.ext_max_tx_power_reg_psd.max_tx_psd_power, MAX_TX_PSD_POWER);
12353 target += MAX_TX_PSD_POWER;
12354 consumed += MAX_TX_PSD_POWER;
12355 break;
12356 }
12357 end:
12358 if (ie_len && consumed >= 2) {
12359 total_consumed += consumed;
12360 /* -2 for element id and length */
12361 *ie_len = consumed - 2;
12362 }
12363 }
12364
12365 pe_debug("pack tpe ie %d bytes, expected to copy %d bytes",
12366 total_consumed, tpe_ie_len);
12367 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
12368 on_entry_target, total_consumed);
12369
12370 return status;
12371 }
12372