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