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(&params->he_6ghz_band_caps, he_6ghz_band_cap,
6925 		     sizeof(tDot11fIEhe_6ghz_band_cap));
6926 
6927 	lim_log_he_6g_cap(mac, &params->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