xref: /wlan-dirver/qcacld-3.0/core/sme/src/csr/csr_api_roam.c (revision e686af65b6176b5b659333daaad8e170b9ef09bc)
1 /*
2  * Copyright (c) 2012-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  * DOC: csr_api_roam.c
22  *
23  * Implementation for the Common Roaming interfaces.
24  */
25 #include "ani_global.h"          /* for struct mac_context **/
26 #include "wma_types.h"
27 #include "wma_if.h"          /* for STA_INVALID_IDX. */
28 #include "csr_inside_api.h"
29 #include <include/wlan_psoc_mlme.h>
30 #include "sme_trace.h"
31 #include "sme_qos_internal.h"
32 #include "sme_inside.h"
33 #include "host_diag_core_event.h"
34 #include "host_diag_core_log.h"
35 #include "csr_api.h"
36 #include "csr_internal.h"
37 #include "cds_reg_service.h"
38 #include "mac_trace.h"
39 #include "cds_regdomain.h"
40 #include "cds_utils.h"
41 #include "sir_types.h"
42 #include "cfg_ucfg_api.h"
43 #include "sme_power_save_api.h"
44 #include "wma.h"
45 #include "wlan_policy_mgr_api.h"
46 #include "sme_nan_datapath.h"
47 #include "pld_common.h"
48 #include "wlan_reg_services_api.h"
49 #include "qdf_crypto.h"
50 #include <wlan_logging_sock_svc.h>
51 #include "wlan_objmgr_psoc_obj.h"
52 #include <wlan_scan_ucfg_api.h>
53 #include <wlan_cp_stats_mc_ucfg_api.h>
54 #include <wlan_tdls_tgt_api.h>
55 #include <wlan_cfg80211_scan.h>
56 #include <wlan_scan_public_structs.h>
57 #include <wlan_action_oui_public_struct.h>
58 #include <wlan_action_oui_ucfg_api.h>
59 #include "wlan_mlme_api.h"
60 #include "wlan_mlme_ucfg_api.h"
61 #include <wlan_utility.h>
62 #include "cfg_mlme.h"
63 #include "wlan_mlme_public_struct.h"
64 #include <wlan_crypto_global_api.h>
65 #include "wlan_qct_sys.h"
66 #include "wlan_dlm_api.h"
67 #include "wlan_policy_mgr_i.h"
68 #include "wlan_scan_utils_api.h"
69 #include "wlan_p2p_cfg_api.h"
70 #include "cfg_nan_api.h"
71 #include "nan_ucfg_api.h"
72 #include <../../core/src/wlan_cm_vdev_api.h>
73 #include "wlan_reg_ucfg_api.h"
74 
75 #include <ol_defines.h>
76 #include "wlan_pkt_capture_ucfg_api.h"
77 #include "wlan_psoc_mlme_api.h"
78 #include "wlan_cm_roam_api.h"
79 #include "wlan_if_mgr_public_struct.h"
80 #include "wlan_if_mgr_ucfg_api.h"
81 #include "wlan_if_mgr_roam.h"
82 #include "wlan_roam_debug.h"
83 #include "wlan_cm_roam_public_struct.h"
84 #include "wlan_mlme_twt_api.h"
85 #include <wlan_serialization_api.h>
86 #include <wlan_vdev_mlme_ser_if.h>
87 #include "wlan_mlo_mgr_sta.h"
88 #include "wlan_mlo_mgr_roam.h"
89 
90 #define MAX_PWR_FCC_CHAN_12 8
91 #define MAX_PWR_FCC_CHAN_13 2
92 #define MAX_CB_VALUE_IN_INI (2)
93 
94 #define MAX_SOCIAL_CHANNELS  3
95 
96 /* packet dump timer duration of 60 secs */
97 #define PKT_DUMP_TIMER_DURATION 60
98 
99 #ifdef WLAN_FEATURE_SAE
100 /**
101  * csr_sae_callback - Update SAE info to CSR roam session
102  * @mac_ctx: MAC context
103  * @msg_ptr: pointer to SAE message
104  *
105  * API to update SAE info to roam csr session
106  *
107  * Return: QDF_STATUS
108  */
109 static QDF_STATUS csr_sae_callback(struct mac_context *mac_ctx,
110 		tSirSmeRsp *msg_ptr)
111 {
112 	struct csr_roam_info *roam_info;
113 	uint32_t session_id;
114 	struct sir_sae_info *sae_info;
115 
116 	sae_info = (struct sir_sae_info *) msg_ptr;
117 	if (!sae_info) {
118 		sme_err("SAE info is NULL");
119 		return QDF_STATUS_E_FAILURE;
120 	}
121 
122 	sme_debug("vdev_id %d "QDF_MAC_ADDR_FMT,
123 		sae_info->vdev_id,
124 		QDF_MAC_ADDR_REF(sae_info->peer_mac_addr.bytes));
125 
126 	session_id = sae_info->vdev_id;
127 	if (session_id == WLAN_UMAC_VDEV_ID_MAX)
128 		return QDF_STATUS_E_INVAL;
129 
130 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
131 	if (!roam_info)
132 		return QDF_STATUS_E_FAILURE;
133 
134 	roam_info->sae_info = sae_info;
135 
136 	csr_roam_call_callback(mac_ctx, session_id, roam_info,
137 			       eCSR_ROAM_SAE_COMPUTE, eCSR_ROAM_RESULT_NONE);
138 	qdf_mem_free(roam_info);
139 
140 	return QDF_STATUS_SUCCESS;
141 }
142 #else
143 static inline QDF_STATUS csr_sae_callback(struct mac_context *mac_ctx,
144 		tSirSmeRsp *msg_ptr)
145 {
146 	return QDF_STATUS_SUCCESS;
147 }
148 #endif
149 
150 static const uint32_t
151 social_channel_freq[MAX_SOCIAL_CHANNELS] = { 2412, 2437, 2462 };
152 
153 static void init_config_param(struct mac_context *mac);
154 static QDF_STATUS csr_roam_open(struct mac_context *mac);
155 static QDF_STATUS csr_roam_close(struct mac_context *mac);
156 static QDF_STATUS csr_init11d_info(struct mac_context *mac, tCsr11dinfo *ps11dinfo);
157 static QDF_STATUS csr_init_channel_power_list(struct mac_context *mac,
158 					      tCsr11dinfo *ps11dinfo);
159 static QDF_STATUS csr_roam_free_connected_info(struct mac_context *mac,
160 					       struct csr_roam_connectedinfo *
161 					       pConnectedInfo);
162 static void csr_init_session(struct mac_context *mac, uint32_t sessionId);
163 
164 static void csr_init_operating_classes(struct mac_context *mac);
165 
166 static void csr_add_len_of_social_channels(struct mac_context *mac,
167 		uint8_t *num_chan);
168 static void csr_add_social_channels(struct mac_context *mac,
169 		tSirUpdateChanList *chan_list, struct csr_scanstruct *pScan,
170 		uint8_t *num_chan);
171 
172 #ifdef WLAN_ALLOCATE_GLOBAL_BUFFERS_DYNAMICALLY
173 static struct csr_roam_session *csr_roam_roam_session;
174 
175 /* Allocate and initialize global variables */
176 static QDF_STATUS csr_roam_init_globals(struct mac_context *mac)
177 {
178 	uint32_t buf_size;
179 	QDF_STATUS status;
180 
181 	buf_size = WLAN_MAX_VDEVS * sizeof(struct csr_roam_session);
182 
183 	csr_roam_roam_session = qdf_mem_malloc(buf_size);
184 	if (csr_roam_roam_session) {
185 		mac->roam.roamSession = csr_roam_roam_session;
186 		status = QDF_STATUS_SUCCESS;
187 	} else {
188 		status = QDF_STATUS_E_NOMEM;
189 	}
190 
191 	return status;
192 }
193 
194 /* Free memory allocated dynamically */
195 static inline void csr_roam_free_globals(void)
196 {
197 	qdf_mem_free(csr_roam_roam_session);
198 	csr_roam_roam_session = NULL;
199 }
200 
201 #else /* WLAN_ALLOCATE_GLOBAL_BUFFERS_DYNAMICALLY */
202 static struct csr_roam_session csr_roam_roam_session[WLAN_MAX_VDEVS];
203 
204 /* Initialize global variables */
205 static QDF_STATUS csr_roam_init_globals(struct mac_context *mac)
206 {
207 	qdf_mem_zero(&csr_roam_roam_session,
208 		     sizeof(csr_roam_roam_session));
209 	mac->roam.roamSession = csr_roam_roam_session;
210 
211 	return QDF_STATUS_SUCCESS;
212 }
213 
214 static inline void csr_roam_free_globals(void)
215 {
216 }
217 #endif /* WLAN_ALLOCATE_GLOBAL_BUFFERS_DYNAMICALLY */
218 
219 static void csr_roam_de_init_globals(struct mac_context *mac)
220 {
221 	csr_roam_free_globals();
222 	mac->roam.roamSession = NULL;
223 }
224 
225 /**
226  * csr_roam_lost_link - Process lost link indication
227  * @mac: MAC context
228  * @session_id: Session id of the current session
229  * @type: Type of the indication
230  * @sir_msg: sme response message
231  *
232  * Return: QDF_STATUS
233  */
234 static
235 QDF_STATUS csr_roam_lost_link(struct mac_context *mac, uint32_t session_id,
236 			      uint32_t type, tSirSmeRsp *sir_msg)
237 {
238 	QDF_STATUS status = QDF_STATUS_SUCCESS;
239 	struct deauth_ind *deauth_ind_msg = NULL;
240 	struct disassoc_ind *disassoc_ind_msg = NULL;
241 
242 	sme_debug("vdev_id %d type %d ", session_id, type);
243 
244 	if (type == eWNI_SME_DISASSOC_IND) {
245 		disassoc_ind_msg = (struct disassoc_ind *)sir_msg;
246 		status = csr_send_mb_disassoc_cnf_msg(mac, disassoc_ind_msg);
247 	} else if (type == eWNI_SME_DEAUTH_IND) {
248 		deauth_ind_msg = (struct deauth_ind *)sir_msg;
249 		status = csr_send_mb_deauth_cnf_msg(mac, deauth_ind_msg);
250 	}
251 
252 	return status;
253 }
254 
255 /**
256  * csr_process_deauth_disassoc_cmd - Process deauth/disassoc command
257  * @mac: MAC context
258  * @sme_cmd: sme command which needs to be processed
259  *
260  * This function processes deauth or disassoc command
261  *
262  * Return: None
263  */
264 static void csr_process_deauth_disassoc_cmd(struct mac_context *mac,
265 					    tSmeCmd *sme_cmd)
266 {
267 	if (sme_cmd->u.roamCmd.roamReason == eCsrForcedDisassocSta) {
268 		sme_debug("Disassoc vdev_id %d with reason: %d peer "
269 			  QDF_MAC_ADDR_FMT, sme_cmd->vdev_id,
270 			  sme_cmd->u.roamCmd.reason,
271 			  QDF_MAC_ADDR_REF(sme_cmd->u.roamCmd.peerMac));
272 		csr_send_mb_disassoc_req_msg(mac, sme_cmd->vdev_id,
273 					     sme_cmd->u.roamCmd.peerMac,
274 					     sme_cmd->u.roamCmd.reason);
275 	} else if (sme_cmd->u.roamCmd.roamReason == eCsrForcedDeauthSta) {
276 		sme_debug("Deauth vdev_id %d with reason: %d peer "
277 			  QDF_MAC_ADDR_FMT, sme_cmd->vdev_id,
278 			  sme_cmd->u.roamCmd.reason,
279 			  QDF_MAC_ADDR_REF(sme_cmd->u.roamCmd.peerMac));
280 		csr_send_mb_deauth_req_msg(mac, sme_cmd->vdev_id,
281 					   sme_cmd->u.roamCmd.peerMac,
282 					   sme_cmd->u.roamCmd.reason);
283 	} else {
284 		sme_info("Invalid command, vdev_id %d reason: %d peer "
285 			  QDF_MAC_ADDR_FMT, sme_cmd->vdev_id,
286 			  sme_cmd->u.roamCmd.reason,
287 			  QDF_MAC_ADDR_REF(sme_cmd->u.roamCmd.peerMac));
288 	}
289 }
290 
291 /**
292  * csr_process_wmm_status_change_cmd - Process wmm status change command
293  * @mac: MAC context
294  * @sme_cmd: sme command which needs to be processed
295  *
296  * Return: None
297  */
298 static void csr_process_wmm_status_change_cmd(struct mac_context *mac,
299 					      tSmeCmd *sme_cmd)
300 {
301 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
302 	tSirSmeRsp *sir_msg;
303 
304 	if (sme_cmd->u.wmStatusChangeCmd.Type == eCsrDisassociated) {
305 		sir_msg =
306 			(tSirSmeRsp *)&sme_cmd->u.wmStatusChangeCmd.u.
307 			DisassocIndMsg;
308 		status = csr_roam_lost_link(mac, sme_cmd->vdev_id,
309 					    eWNI_SME_DISASSOC_IND,
310 					    sir_msg);
311 	} else if (sme_cmd->u.wmStatusChangeCmd.Type == eCsrDeauthenticated) {
312 		sir_msg = (tSirSmeRsp *)&sme_cmd->u.wmStatusChangeCmd.u.
313 								DeauthIndMsg;
314 		status = csr_roam_lost_link(mac, sme_cmd->vdev_id,
315 					    eWNI_SME_DEAUTH_IND,
316 					    sir_msg);
317 	}
318 	if (QDF_IS_STATUS_ERROR(status)) {
319 		sme_info("Failed to issue lost link command, status %d",
320 			 status);
321 		/*
322 		 * As status returned is not success, there is nothing else
323 		 * left to do so release WM status change command here.
324 		 */
325 		csr_roam_wm_status_change_complete(mac, sme_cmd->vdev_id);
326 	}
327 }
328 
329 /**
330  * csr_get_active_peer_disconnect_command - Get active peer disconnect command
331  * from serialization.
332  * @mac: MAC context
333  * @vdev_id: Vdev id for which active command needs to be return
334  *
335  * Return: None
336  */
337 static tSmeCmd *csr_get_active_peer_disconnect_command(struct mac_context *mac,
338 						       uint8_t vdev_id)
339 {
340 	tSmeCmd *sme_cmd;
341 
342 	sme_cmd = wlan_serialization_get_active_cmd(
343 						mac->psoc, vdev_id,
344 						WLAN_SER_CMD_FORCE_DEAUTH_STA);
345 	if (sme_cmd)
346 		return sme_cmd;
347 
348 	sme_cmd = wlan_serialization_get_active_cmd(
349 					mac->psoc, vdev_id,
350 					WLAN_SER_CMD_FORCE_DISASSOC_STA);
351 	if (sme_cmd)
352 		return sme_cmd;
353 
354 	return wlan_serialization_get_active_cmd(mac->psoc, vdev_id,
355 						 WLAN_SER_CMD_WM_STATUS_CHANGE);
356 }
357 
358 /**
359  * csr_continue_peer_disconnect_after_get_stats - Continue peer disconnect after
360  * getting peer disconnect stats
361  * @mac: MAC context
362  *
363  * Process the active serialization command after getting disconnect peer
364  * stats or after peer stats request gets timed out
365  *
366  * Return: None
367  */
368 static void
369 csr_continue_peer_disconnect_after_get_stats(struct mac_context *mac)
370 {
371 	tSmeCmd *sme_cmd;
372 	QDF_STATUS status;
373 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
374 
375 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
376 	if (!mlme_obj) {
377 		sme_err("NULL mlme psoc object");
378 		return;
379 	}
380 
381 	status = sme_acquire_global_lock(&mac->sme);
382 	if (QDF_IS_STATUS_ERROR(status)) {
383 		sme_err("can't acquire sme global lock");
384 		return;
385 	}
386 
387 	sme_cmd = csr_get_active_peer_disconnect_command(
388 				mac,
389 				mlme_obj->disconnect_stats_param.vdev_id);
390 	if (!sme_cmd) {
391 		sme_err("sme_cmd is NULL");
392 		goto release_lock;
393 	}
394 
395 	if (qdf_atomic_inc_return(
396 		&mlme_obj->disconnect_stats_param.is_disconn_stats_completed) >
397 		1) {
398 		sme_info("Command %d already in process", sme_cmd->command);
399 		goto release_lock;
400 	}
401 
402 	switch (sme_cmd->command) {
403 	case eSmeCommandRoam:
404 		csr_process_deauth_disassoc_cmd(mac, sme_cmd);
405 		break;
406 
407 	case eSmeCommandWmStatusChange:
408 		csr_process_wmm_status_change_cmd(mac, sme_cmd);
409 		break;
410 	default:
411 		sme_info("Invalid command %d vdev_id %d", sme_cmd->command,
412 			 mlme_obj->disconnect_stats_param.vdev_id);
413 	}
414 release_lock:
415 	sme_release_global_lock(&mac->sme);
416 }
417 
418 /**
419  * csr_disconnect_stats_timer_cb - Disconnect stats timer callback
420  * @user_data: Void pointer to mac context
421  *
422  * Return: None
423  */
424 static void csr_disconnect_stats_timer_cb(void *user_data)
425 {
426 	struct mac_context *mac = (struct mac_context *)user_data;
427 
428 	if (!mac) {
429 		sme_err("Invalid mac ctx");
430 		return;
431 	}
432 
433 	sme_debug("Disconnect peer stats timed out");
434 	csr_continue_peer_disconnect_after_get_stats(mac);
435 }
436 
437 /**
438  * csr_init_disconnect_stats_timer - Init Disconnect stats timer
439  * @mac: MAC context
440  *
441  * Return: None
442  */
443 static void csr_init_disconnect_stats_timer(struct mac_context *mac)
444 {
445 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
446 
447 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
448 	if (!mlme_obj) {
449 		sme_err("NULL mlme psoc object");
450 		return;
451 	}
452 
453 	qdf_mc_timer_init(&mlme_obj->disconnect_stats_param.disconn_stats_timer,
454 			  QDF_TIMER_TYPE_SW,
455 			  csr_disconnect_stats_timer_cb, mac);
456 
457 	qdf_atomic_init(
458 		&mlme_obj->disconnect_stats_param.is_disconn_stats_completed);
459 }
460 
461 /**
462  * csr_deinit_disconnect_stats_timer - Deinit Disconnect stats timer
463  * @mac: MAC context
464  *
465  * Return: None
466  */
467 static void csr_deinit_disconnect_stats_timer(struct mac_context *mac)
468 {
469 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
470 
471 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
472 	if (!mlme_obj) {
473 		sme_err("NULL mlme psoc object");
474 		return;
475 	}
476 
477 	if (QDF_TIMER_STATE_RUNNING ==
478 		qdf_mc_timer_get_current_state(
479 			&mlme_obj->disconnect_stats_param.disconn_stats_timer))
480 		qdf_mc_timer_stop(
481 			&mlme_obj->disconnect_stats_param.disconn_stats_timer);
482 
483 	qdf_mc_timer_destroy(
484 			&mlme_obj->disconnect_stats_param.disconn_stats_timer);
485 }
486 
487 QDF_STATUS csr_open(struct mac_context *mac)
488 {
489 	QDF_STATUS status = QDF_STATUS_SUCCESS;
490 	uint32_t i;
491 
492 	do {
493 		/* Initialize CSR Roam Globals */
494 		status = csr_roam_init_globals(mac);
495 		if (!QDF_IS_STATUS_SUCCESS(status))
496 			break;
497 
498 		for (i = 0; i < WLAN_MAX_VDEVS; i++)
499 			csr_roam_state_change(mac, eCSR_ROAMING_STATE_STOP, i);
500 
501 		init_config_param(mac);
502 		status = csr_scan_open(mac);
503 		if (!QDF_IS_STATUS_SUCCESS(status)) {
504 			csr_roam_free_globals();
505 			break;
506 		}
507 		status = csr_roam_open(mac);
508 		if (!QDF_IS_STATUS_SUCCESS(status)) {
509 			csr_roam_free_globals();
510 			break;
511 		}
512 		csr_init_disconnect_stats_timer(mac);
513 	} while (0);
514 
515 	return status;
516 }
517 
518 QDF_STATUS csr_init_chan_list(struct mac_context *mac)
519 {
520 	QDF_STATUS status;
521 	uint8_t reg_cc[REG_ALPHA2_LEN + 1];
522 
523 	wlan_reg_read_current_country(mac->psoc, reg_cc);
524 	sme_debug("init time country code %.2s", reg_cc);
525 
526 	status = csr_get_channel_and_power_list(mac);
527 
528 	return status;
529 }
530 
531 QDF_STATUS csr_set_channels(struct mac_context *mac,
532 			    struct csr_config_params *pParam)
533 {
534 	QDF_STATUS status = QDF_STATUS_SUCCESS;
535 	uint8_t index = 0;
536 
537 	for (index = 0; index < mac->scan.base_channels.numChannels;
538 	     index++) {
539 		pParam->Csr11dinfo.Channels.channel_freq_list[index] =
540 			mac->scan.base_channels.channel_freq_list[index];
541 		pParam->Csr11dinfo.ChnPower[index].first_chan_freq =
542 			mac->scan.base_channels.channel_freq_list[index];
543 		pParam->Csr11dinfo.ChnPower[index].numChannels = 1;
544 		pParam->Csr11dinfo.ChnPower[index].maxtxPower =
545 			mac->scan.defaultPowerTable[index].tx_power;
546 	}
547 	pParam->Csr11dinfo.Channels.numChannels =
548 		mac->scan.base_channels.numChannels;
549 
550 	return status;
551 }
552 
553 QDF_STATUS csr_close(struct mac_context *mac)
554 {
555 	QDF_STATUS status = QDF_STATUS_SUCCESS;
556 
557 	csr_deinit_disconnect_stats_timer(mac);
558 
559 	csr_roam_close(mac);
560 	csr_scan_close(mac);
561 	/* DeInit Globals */
562 	csr_roam_de_init_globals(mac);
563 	return status;
564 }
565 
566 static int8_t
567 csr_find_channel_pwr(struct channel_power *pdefaultPowerTable,
568 		     uint32_t chan_freq)
569 {
570 	uint8_t i;
571 	/* TODO: if defaultPowerTable is guaranteed to be in ascending */
572 	/* order of channel numbers, we can employ binary search */
573 	for (i = 0; i < CFG_VALID_CHANNEL_LIST_LEN; i++) {
574 		if (pdefaultPowerTable[i].center_freq == chan_freq)
575 			return pdefaultPowerTable[i].tx_power;
576 	}
577 	/* could not find the channel list in default list */
578 	/* this should not have occurred */
579 	QDF_ASSERT(0);
580 	return 0;
581 }
582 
583 /**
584  * csr_roam_arrange_ch_list() - Updates the channel list modified with greedy
585  * order for 5 Ghz preference and DFS channels.
586  * @mac_ctx: pointer to mac context.
587  * @chan_list:    channel list updated with greedy channel order.
588  * @num_channel:  Number of channels in list
589  *
590  * To allow Early Stop Roaming Scan feature to co-exist with 5G preference,
591  * this function moves 5G channels ahead of 2G channels. This function can
592  * also move 2G channels, ahead of DFS channel or vice versa. Order is
593  * maintained among same category channels
594  *
595  * Return: None
596  */
597 static void csr_roam_arrange_ch_list(struct mac_context *mac_ctx,
598 			tSirUpdateChanParam *chan_list, uint8_t num_channel)
599 {
600 	bool prefer_5g = CSR_IS_ROAM_PREFER_5GHZ(mac_ctx);
601 	bool prefer_dfs = CSR_IS_DFS_CH_ROAM_ALLOWED(mac_ctx);
602 	int i, j = 0;
603 	tSirUpdateChanParam *tmp_list = NULL;
604 
605 	if (!prefer_5g)
606 		return;
607 
608 	tmp_list = qdf_mem_malloc(sizeof(tSirUpdateChanParam) * num_channel);
609 	if (!tmp_list)
610 		return;
611 
612 	/* Fist copy Non-DFS 5g channels */
613 	for (i = 0; i < num_channel; i++) {
614 		if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_list[i].freq) &&
615 			!wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
616 						  chan_list[i].freq)) {
617 			qdf_mem_copy(&tmp_list[j++],
618 				&chan_list[i], sizeof(tSirUpdateChanParam));
619 			chan_list[i].freq = 0;
620 		}
621 	}
622 	if (prefer_dfs) {
623 		/* next copy DFS channels (remaining channels in 5G) */
624 		for (i = 0; i < num_channel; i++) {
625 			if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_list[i].freq)) {
626 				qdf_mem_copy(&tmp_list[j++], &chan_list[i],
627 					sizeof(tSirUpdateChanParam));
628 				chan_list[i].freq = 0;
629 			}
630 		}
631 	} else {
632 		/* next copy 2G channels */
633 		for (i = 0; i < num_channel; i++) {
634 			if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_list[i].freq)) {
635 				qdf_mem_copy(&tmp_list[j++], &chan_list[i],
636 					sizeof(tSirUpdateChanParam));
637 				chan_list[i].freq = 0;
638 			}
639 		}
640 	}
641 	/* copy rest of the channels in same order to tmp list */
642 	for (i = 0; i < num_channel; i++) {
643 		if (chan_list[i].freq) {
644 			qdf_mem_copy(&tmp_list[j++], &chan_list[i],
645 				sizeof(tSirUpdateChanParam));
646 			chan_list[i].freq = 0;
647 		}
648 	}
649 	/* copy tmp list to original channel list buffer */
650 	qdf_mem_copy(chan_list, tmp_list,
651 				 sizeof(tSirUpdateChanParam) * num_channel);
652 	qdf_mem_free(tmp_list);
653 }
654 
655 /**
656  * csr_roam_sort_channel_for_early_stop() - Sort the channels
657  * @mac_ctx:        mac global context
658  * @chan_list:      Original channel list from the upper layers
659  * @num_channel:    Number of original channels
660  *
661  * For Early stop scan feature, the channel list should be in an order,
662  * where-in there is a maximum chance to detect an AP in the initial
663  * channels in the list so that the scanning can be stopped early as the
664  * feature demands.
665  * Below fixed greedy channel list has been provided
666  * based on most of the enterprise wifi installations across the globe.
667  *
668  * Identify all the greedy channels within the channel list from user space.
669  * Identify all the non-greedy channels in the user space channel list.
670  * Merge greedy channels followed by non-greedy channels back into the
671  * chan_list.
672  *
673  * Return: None
674  */
675 static void csr_roam_sort_channel_for_early_stop(struct mac_context *mac_ctx,
676 			tSirUpdateChanList *chan_list, uint8_t num_channel)
677 {
678 	tSirUpdateChanList *chan_list_greedy, *chan_list_non_greedy;
679 	uint8_t i, j;
680 	static const uint32_t fixed_greedy_freq_list[] = {2412, 2437, 2462,
681 		5180, 5240, 5200, 5220, 2457, 2417, 2452, 5745, 5785, 5805,
682 		2422, 2427, 2447, 5765, 5825, 2442, 2432, 5680, 5700, 5260,
683 		5580, 5280, 5520, 5320, 5300, 5500, 5600, 2472, 2484, 5560,
684 		5660, 5755, 5775};
685 	uint8_t num_fixed_greedy_chan;
686 	uint8_t num_greedy_chan = 0;
687 	uint8_t num_non_greedy_chan = 0;
688 	uint8_t match_found = false;
689 	uint32_t buf_size;
690 
691 	buf_size = sizeof(tSirUpdateChanList) +
692 		(sizeof(tSirUpdateChanParam) * num_channel);
693 	chan_list_greedy = qdf_mem_malloc(buf_size);
694 	chan_list_non_greedy = qdf_mem_malloc(buf_size);
695 	if (!chan_list_greedy || !chan_list_non_greedy)
696 		goto scan_list_sort_error;
697 	/*
698 	 * fixed_greedy_freq_list is an evaluated freq list based on most of
699 	 * the enterprise wifi deployments and the order of the channels
700 	 * determines the highest possibility of finding an AP.
701 	 * chan_list is the channel list provided by upper layers based on the
702 	 * regulatory domain.
703 	 */
704 	num_fixed_greedy_chan = sizeof(fixed_greedy_freq_list) /
705 							sizeof(uint32_t);
706 	/*
707 	 * Browse through the chan_list and put all the non-greedy channels
708 	 * into a separate list by name chan_list_non_greedy
709 	 */
710 	for (i = 0; i < num_channel; i++) {
711 		for (j = 0; j < num_fixed_greedy_chan; j++) {
712 			if (chan_list->chanParam[i].freq ==
713 					 fixed_greedy_freq_list[j]) {
714 				match_found = true;
715 				break;
716 			}
717 		}
718 		if (!match_found) {
719 			qdf_mem_copy(
720 			  &chan_list_non_greedy->chanParam[num_non_greedy_chan],
721 			  &chan_list->chanParam[i],
722 			  sizeof(tSirUpdateChanParam));
723 			num_non_greedy_chan++;
724 		} else {
725 			match_found = false;
726 		}
727 	}
728 	/*
729 	 * Browse through the fixed_greedy_chan_list and put all the greedy
730 	 * channels in the chan_list into a separate list by name
731 	 * chan_list_greedy
732 	 */
733 	for (i = 0; i < num_fixed_greedy_chan; i++) {
734 		for (j = 0; j < num_channel; j++) {
735 			if (fixed_greedy_freq_list[i] ==
736 				chan_list->chanParam[j].freq) {
737 				qdf_mem_copy(
738 				  &chan_list_greedy->chanParam[num_greedy_chan],
739 				  &chan_list->chanParam[j],
740 				  sizeof(tSirUpdateChanParam));
741 				num_greedy_chan++;
742 				break;
743 			}
744 		}
745 	}
746 	sme_debug("greedy=%d, non-greedy=%d, tot=%d", num_greedy_chan,
747 		  num_non_greedy_chan, num_channel);
748 	if ((num_greedy_chan + num_non_greedy_chan) != num_channel) {
749 		sme_err("incorrect sorting of channels");
750 		goto scan_list_sort_error;
751 	}
752 	/* Copy the Greedy channels first */
753 	i = 0;
754 	qdf_mem_copy(&chan_list->chanParam[i],
755 		&chan_list_greedy->chanParam[i],
756 		num_greedy_chan * sizeof(tSirUpdateChanParam));
757 	/* Copy the remaining Non Greedy channels */
758 	i = num_greedy_chan;
759 	j = 0;
760 	qdf_mem_copy(&chan_list->chanParam[i],
761 		&chan_list_non_greedy->chanParam[j],
762 		num_non_greedy_chan * sizeof(tSirUpdateChanParam));
763 
764 	/* Update channel list for 5g preference and allow DFS roam */
765 	csr_roam_arrange_ch_list(mac_ctx, chan_list->chanParam, num_channel);
766 scan_list_sort_error:
767 	qdf_mem_free(chan_list_greedy);
768 	qdf_mem_free(chan_list_non_greedy);
769 }
770 
771 /**
772  * csr_emu_chan_req() - update the required channel list for emulation
773  * @channel: channel number to check
774  *
775  * To reduce scan time during emulation platforms, this function
776  * restricts the scanning to be done on selected channels
777  *
778  * Return: QDF_STATUS enumeration
779  */
780 #ifdef QCA_WIFI_EMULATION
781 #define SCAN_CHAN_LIST_5G_LEN 6
782 #define SCAN_CHAN_LIST_2G_LEN 3
783 #define SCAN_CHAN_LIST_6G_LEN 3
784 static const uint16_t
785 csr_scan_chan_list_5g[SCAN_CHAN_LIST_5G_LEN] = { 5180, 5220, 5260, 5280, 5700, 5745 };
786 static const uint16_t
787 csr_scan_chan_list_2g[SCAN_CHAN_LIST_2G_LEN] = { 2412, 2437, 2462 };
788 static const uint16_t
789 csr_scan_chan_list_6g[SCAN_CHAN_LIST_6G_LEN] = { 6055, 6135, 6215 };
790 
791 static QDF_STATUS csr_emu_chan_req(uint32_t channel)
792 {
793 	int i;
794 
795 	if (WLAN_REG_IS_24GHZ_CH_FREQ(channel)) {
796 		for (i = 0; i < QDF_ARRAY_SIZE(csr_scan_chan_list_2g); i++) {
797 			if (csr_scan_chan_list_2g[i] == channel)
798 				return QDF_STATUS_SUCCESS;
799 		}
800 	} else if (WLAN_REG_IS_5GHZ_CH_FREQ(channel)) {
801 		for (i = 0; i < QDF_ARRAY_SIZE(csr_scan_chan_list_5g); i++) {
802 			if (csr_scan_chan_list_5g[i] == channel)
803 				return QDF_STATUS_SUCCESS;
804 		}
805 	} else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(channel)) {
806 		for (i = 0; i < QDF_ARRAY_SIZE(csr_scan_chan_list_6g); i++) {
807 			if (csr_scan_chan_list_6g[i] == channel)
808 				return QDF_STATUS_SUCCESS;
809 		}
810 	}
811 	return QDF_STATUS_E_FAILURE;
812 }
813 #else
814 static QDF_STATUS csr_emu_chan_req(uint32_t channel_num)
815 {
816 	return QDF_STATUS_SUCCESS;
817 }
818 #endif
819 
820 #ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
821 static void csr_add_len_of_social_channels(struct mac_context *mac,
822 		uint8_t *num_chan)
823 {
824 	uint8_t i;
825 	uint8_t no_chan = *num_chan;
826 
827 	sme_debug("add len of social channels, before adding - num_chan:%hu",
828 			*num_chan);
829 	if (CSR_IS_5G_BAND_ONLY(mac)) {
830 		for (i = 0; i < MAX_SOCIAL_CHANNELS; i++) {
831 			if (wlan_reg_get_channel_state_for_pwrmode(
832 				mac->pdev, social_channel_freq[i],
833 				REG_CURRENT_PWR_MODE) ==
834 					CHANNEL_STATE_ENABLE)
835 				no_chan++;
836 		}
837 	}
838 	*num_chan = no_chan;
839 	sme_debug("after adding - num_chan:%hu", *num_chan);
840 }
841 
842 static void csr_add_social_channels(struct mac_context *mac,
843 		tSirUpdateChanList *chan_list, struct csr_scanstruct *pScan,
844 		uint8_t *num_chan)
845 {
846 	uint8_t i;
847 	uint8_t no_chan = *num_chan;
848 
849 	sme_debug("add social channels chan_list %pK, num_chan %hu", chan_list,
850 			*num_chan);
851 	if (CSR_IS_5G_BAND_ONLY(mac)) {
852 		for (i = 0; i < MAX_SOCIAL_CHANNELS; i++) {
853 			if (wlan_reg_get_channel_state_for_pwrmode(
854 					mac->pdev, social_channel_freq[i],
855 					REG_CURRENT_PWR_MODE) !=
856 					CHANNEL_STATE_ENABLE)
857 				continue;
858 			chan_list->chanParam[no_chan].freq =
859 				social_channel_freq[i];
860 			chan_list->chanParam[no_chan].pwr =
861 				csr_find_channel_pwr(pScan->defaultPowerTable,
862 						social_channel_freq[i]);
863 			chan_list->chanParam[no_chan].dfsSet = false;
864 			if (cds_is_5_mhz_enabled())
865 				chan_list->chanParam[no_chan].quarter_rate
866 					= 1;
867 			else if (cds_is_10_mhz_enabled())
868 				chan_list->chanParam[no_chan].half_rate = 1;
869 			no_chan++;
870 		}
871 		sme_debug("after adding -num_chan %hu", no_chan);
872 	}
873 	*num_chan = no_chan;
874 }
875 #else
876 static void csr_add_len_of_social_channels(struct mac_context *mac,
877 		uint8_t *num_chan)
878 {
879 	sme_debug("skip adding len of social channels");
880 }
881 static void csr_add_social_channels(struct mac_context *mac,
882 		tSirUpdateChanList *chan_list, struct csr_scanstruct *pScan,
883 		uint8_t *num_chan)
884 {
885 	sme_debug("skip social channels");
886 }
887 #endif
888 
889 /**
890  * csr_scan_event_handler() - callback for scan event
891  * @vdev: wlan objmgr vdev pointer
892  * @event: scan event
893  * @arg: global mac context pointer
894  *
895  * Return: void
896  */
897 static void csr_scan_event_handler(struct wlan_objmgr_vdev *vdev,
898 					    struct scan_event *event,
899 					    void *arg)
900 {
901 	bool success = false;
902 	QDF_STATUS lock_status;
903 	struct mac_context *mac = arg;
904 
905 	if (!mac)
906 		return;
907 
908 	if (!util_is_scan_completed(event, &success))
909 		return;
910 
911 	lock_status = sme_acquire_global_lock(&mac->sme);
912 	if (QDF_IS_STATUS_ERROR(lock_status))
913 		return;
914 
915 	if (mac->scan.pending_channel_list_req)
916 		csr_update_channel_list(mac);
917 	sme_release_global_lock(&mac->sme);
918 }
919 
920 /**
921  * csr_update_roam_pcl_per_connected_sta_vdev() - Update roam pcl per connected
922  *                                                STA
923  * @psoc: pointer to psoc object
924  *
925  * Return: None
926  */
927 static void csr_update_roam_pcl_per_connected_sta_vdev(
928 						struct wlan_objmgr_psoc *psoc)
929 {
930 	struct wlan_objmgr_vdev *vdev;
931 	uint32_t vdev_id;
932 
933 	for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) {
934 		vdev =
935 		wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
936 						     WLAN_LEGACY_SME_ID);
937 
938 		if (!vdev)
939 			continue;
940 
941 		if (vdev->vdev_mlme.vdev_opmode != QDF_STA_MODE)
942 			goto next;
943 
944 		if (!wlan_cm_is_vdev_connected(vdev))
945 			goto next;
946 
947 		policy_mgr_set_pcl_for_existing_combo(psoc, PM_STA_MODE,
948 						      vdev_id);
949 next:
950 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
951 	}
952 }
953 
954 QDF_STATUS csr_update_channel_list(struct mac_context *mac)
955 {
956 	tSirUpdateChanList *pChanList;
957 	struct csr_scanstruct *pScan = &mac->scan;
958 	uint8_t numChan = pScan->base_channels.numChannels;
959 	uint8_t num_channel = 0;
960 	uint32_t bufLen;
961 	struct scheduler_msg msg = {0};
962 	uint8_t i;
963 	uint8_t channel_state;
964 	uint16_t unsafe_chan[NUM_CHANNELS];
965 	uint16_t unsafe_chan_cnt = 0;
966 	uint16_t cnt = 0;
967 	uint32_t  channel_freq;
968 	bool is_unsafe_chan;
969 	bool is_same_band;
970 	bool is_5mhz_enabled;
971 	bool is_10mhz_enabled;
972 	enum scm_scan_status scan_status;
973 	QDF_STATUS lock_status;
974 	struct rso_roam_policy_params *roam_policy;
975 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
976 
977 	qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
978 
979 	if (!qdf_ctx)
980 		return QDF_STATUS_E_FAILURE;
981 
982 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
983 	if (!mlme_obj)
984 		return QDF_STATUS_E_FAILURE;
985 	roam_policy = &mlme_obj->cfg.lfr.rso_user_config.policy_params;
986 	lock_status = sme_acquire_global_lock(&mac->sme);
987 	if (QDF_IS_STATUS_ERROR(lock_status))
988 		return lock_status;
989 
990 	if (mac->mlme_cfg->reg.enable_pending_chan_list_req) {
991 		scan_status = wlan_get_pdev_status(mac->pdev);
992 		if (scan_status == SCAN_IS_ACTIVE ||
993 		    scan_status == SCAN_IS_ACTIVE_AND_PENDING) {
994 			mac->scan.pending_channel_list_req = true;
995 			sme_release_global_lock(&mac->sme);
996 			sme_debug("scan in progress postpone channel list req ");
997 			return QDF_STATUS_SUCCESS;
998 		}
999 		mac->scan.pending_channel_list_req = false;
1000 	}
1001 	sme_release_global_lock(&mac->sme);
1002 
1003 	pld_get_wlan_unsafe_channel(qdf_ctx->dev, unsafe_chan,
1004 		    &unsafe_chan_cnt,
1005 		    sizeof(unsafe_chan));
1006 
1007 	csr_add_len_of_social_channels(mac, &numChan);
1008 
1009 	bufLen = sizeof(tSirUpdateChanList) +
1010 		 (sizeof(tSirUpdateChanParam) * (numChan));
1011 
1012 	csr_init_operating_classes(mac);
1013 	pChanList = qdf_mem_malloc(bufLen);
1014 	if (!pChanList)
1015 		return QDF_STATUS_E_NOMEM;
1016 
1017 	is_5mhz_enabled = cds_is_5_mhz_enabled();
1018 	if (is_5mhz_enabled)
1019 		sme_nofl_debug("quarter_rate enabled");
1020 	is_10mhz_enabled = cds_is_10_mhz_enabled();
1021 	if (is_10mhz_enabled)
1022 		sme_nofl_debug("half_rate enabled");
1023 
1024 	for (i = 0; i < pScan->base_channels.numChannels; i++) {
1025 		if (QDF_STATUS_SUCCESS !=
1026 			csr_emu_chan_req(pScan->base_channels.channel_freq_list[i]))
1027 			continue;
1028 
1029 		channel_freq = pScan->base_channels.channel_freq_list[i];
1030 		/* Scan is not performed on DSRC channels*/
1031 		if (wlan_reg_is_dsrc_freq(channel_freq))
1032 			continue;
1033 
1034 		channel_state =
1035 			wlan_reg_get_channel_state_for_pwrmode(
1036 				mac->pdev, channel_freq,
1037 				REG_CURRENT_PWR_MODE);
1038 		if ((CHANNEL_STATE_ENABLE == channel_state) ||
1039 		    mac->scan.fEnableDFSChnlScan) {
1040 			if (wlan_reg_is_6ghz_chan_freq(channel_freq) &&
1041 			    !wlan_reg_is_6ghz_band_set(mac->pdev)) {
1042 				sme_debug("skip 6ghz frequency %d",
1043 					  channel_freq);
1044 				continue;
1045 			}
1046 			if ((roam_policy->dfs_mode ==
1047 				STA_ROAM_POLICY_DFS_DISABLED) &&
1048 				(channel_state == CHANNEL_STATE_DFS)) {
1049 				sme_debug("skip dfs channel frequency %d",
1050 					  channel_freq);
1051 				continue;
1052 			}
1053 			if (roam_policy->skip_unsafe_channels &&
1054 			    unsafe_chan_cnt) {
1055 				is_unsafe_chan = false;
1056 				for (cnt = 0; cnt < unsafe_chan_cnt; cnt++) {
1057 					if (unsafe_chan[cnt] == channel_freq) {
1058 						is_unsafe_chan = true;
1059 						break;
1060 					}
1061 				}
1062 				is_same_band =
1063 					(WLAN_REG_IS_24GHZ_CH_FREQ(
1064 							channel_freq) &&
1065 					roam_policy->sap_operating_band ==
1066 							BAND_2G) ||
1067 					(WLAN_REG_IS_5GHZ_CH_FREQ(
1068 							channel_freq) &&
1069 					roam_policy->sap_operating_band ==
1070 							BAND_5G);
1071 				if (is_unsafe_chan && is_same_band) {
1072 					sme_debug("ignoring unsafe channel freq %d",
1073 						  channel_freq);
1074 					continue;
1075 				}
1076 			}
1077 			pChanList->chanParam[num_channel].freq =
1078 				pScan->base_channels.channel_freq_list[i];
1079 			pChanList->chanParam[num_channel].pwr =
1080 				csr_find_channel_pwr(
1081 				pScan->defaultPowerTable,
1082 				pScan->base_channels.channel_freq_list[i]);
1083 
1084 			if (pScan->fcc_constraint) {
1085 				if (2467 ==
1086 					pScan->base_channels.channel_freq_list[i]) {
1087 					pChanList->chanParam[num_channel].pwr =
1088 						MAX_PWR_FCC_CHAN_12;
1089 					sme_debug("txpow for channel 12 is %d",
1090 						  MAX_PWR_FCC_CHAN_12);
1091 				}
1092 				if (2472 ==
1093 					pScan->base_channels.channel_freq_list[i]) {
1094 					pChanList->chanParam[num_channel].pwr =
1095 						MAX_PWR_FCC_CHAN_13;
1096 					sme_debug("txpow for channel 13 is %d",
1097 						  MAX_PWR_FCC_CHAN_13);
1098 				}
1099 			}
1100 
1101 			if (!ucfg_is_nan_allowed_on_freq(mac->pdev,
1102 				pChanList->chanParam[num_channel].freq))
1103 				pChanList->chanParam[num_channel].nan_disabled =
1104 					true;
1105 
1106 			if (CHANNEL_STATE_DFS == channel_state)
1107 				pChanList->chanParam[num_channel].dfsSet =
1108 					true;
1109 
1110 			pChanList->chanParam[num_channel].quarter_rate =
1111 							is_5mhz_enabled;
1112 
1113 			pChanList->chanParam[num_channel].half_rate =
1114 							is_10mhz_enabled;
1115 
1116 			num_channel++;
1117 		}
1118 	}
1119 
1120 	csr_add_social_channels(mac, pChanList, pScan, &num_channel);
1121 
1122 	if (mac->mlme_cfg->lfr.early_stop_scan_enable)
1123 		csr_roam_sort_channel_for_early_stop(mac, pChanList,
1124 						     num_channel);
1125 	else
1126 		sme_debug("Early Stop Scan Feature not supported");
1127 
1128 	if ((mac->roam.configParam.uCfgDot11Mode ==
1129 				eCSR_CFG_DOT11_MODE_AUTO) ||
1130 			(mac->roam.configParam.uCfgDot11Mode ==
1131 			 eCSR_CFG_DOT11_MODE_11AC) ||
1132 			(mac->roam.configParam.uCfgDot11Mode ==
1133 			 eCSR_CFG_DOT11_MODE_11AC_ONLY)) {
1134 		pChanList->vht_en = true;
1135 		if (mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band)
1136 			pChanList->vht_24_en = true;
1137 	}
1138 	if ((mac->roam.configParam.uCfgDot11Mode ==
1139 				eCSR_CFG_DOT11_MODE_AUTO) ||
1140 			(mac->roam.configParam.uCfgDot11Mode ==
1141 			 eCSR_CFG_DOT11_MODE_11N) ||
1142 			(mac->roam.configParam.uCfgDot11Mode ==
1143 			 eCSR_CFG_DOT11_MODE_11N_ONLY)) {
1144 		pChanList->ht_en = true;
1145 	}
1146 	if ((mac->roam.configParam.uCfgDot11Mode == eCSR_CFG_DOT11_MODE_AUTO) ||
1147 	    (mac->roam.configParam.uCfgDot11Mode == eCSR_CFG_DOT11_MODE_11AX) ||
1148 	    (mac->roam.configParam.uCfgDot11Mode ==
1149 	     eCSR_CFG_DOT11_MODE_11AX_ONLY))
1150 		pChanList->he_en = true;
1151 #ifdef WLAN_FEATURE_11BE
1152 	if ((mac->roam.configParam.uCfgDot11Mode == eCSR_CFG_DOT11_MODE_AUTO) ||
1153 	    CSR_IS_CFG_DOT11_PHY_MODE_11BE(
1154 		mac->roam.configParam.uCfgDot11Mode) ||
1155 	    CSR_IS_CFG_DOT11_PHY_MODE_11BE_ONLY(
1156 		mac->roam.configParam.uCfgDot11Mode))
1157 		pChanList->eht_en = true;
1158 #endif
1159 
1160 	pChanList->numChan = num_channel;
1161 	mlme_store_fw_scan_channels(mac->psoc, pChanList);
1162 
1163 	msg.type = WMA_UPDATE_CHAN_LIST_REQ;
1164 	msg.reserved = 0;
1165 	msg.bodyptr = pChanList;
1166 	MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
1167 			 NO_SESSION, msg.type));
1168 	if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME,
1169 							 QDF_MODULE_ID_WMA,
1170 							 QDF_MODULE_ID_WMA,
1171 							 &msg)) {
1172 		qdf_mem_free(pChanList);
1173 		return QDF_STATUS_E_FAILURE;
1174 	}
1175 
1176 	csr_update_roam_pcl_per_connected_sta_vdev(mac->psoc);
1177 	return QDF_STATUS_SUCCESS;
1178 }
1179 
1180 QDF_STATUS csr_start(struct mac_context *mac)
1181 {
1182 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1183 	uint32_t i;
1184 
1185 	do {
1186 		for (i = 0; i < WLAN_MAX_VDEVS; i++)
1187 			csr_roam_state_change(mac, eCSR_ROAMING_STATE_IDLE, i);
1188 
1189 		mac->roam.sPendingCommands = 0;
1190 
1191 		if (mac->mlme_cfg->reg.enable_pending_chan_list_req) {
1192 			status = ucfg_scan_register_event_handler(mac->pdev,
1193 					csr_scan_event_handler, mac);
1194 
1195 			if (QDF_IS_STATUS_ERROR(status))
1196 				sme_err("scan event registration failed ");
1197 		}
1198 	} while (0);
1199 	return status;
1200 }
1201 
1202 QDF_STATUS csr_stop(struct mac_context *mac)
1203 {
1204 	uint32_t sessionId;
1205 
1206 	if (mac->mlme_cfg->reg.enable_pending_chan_list_req)
1207 		ucfg_scan_unregister_event_handler(mac->pdev,
1208 						   csr_scan_event_handler,
1209 						   mac);
1210 	wlan_scan_psoc_set_disable(mac->psoc, REASON_SYSTEM_DOWN);
1211 
1212 	/*
1213 	 * purge all serialization command if there are any pending to make
1214 	 * sure memory and vdev ref are freed.
1215 	 */
1216 	csr_purge_pdev_all_ser_cmd_list(mac);
1217 	for (sessionId = 0; sessionId < WLAN_MAX_VDEVS; sessionId++)
1218 		csr_cleanup_vdev_session(mac, sessionId);
1219 
1220 	for (sessionId = 0; sessionId < WLAN_MAX_VDEVS; sessionId++)
1221 		if (CSR_IS_SESSION_VALID(mac, sessionId))
1222 			ucfg_scan_flush_results(mac->pdev, NULL);
1223 
1224 	for (sessionId = 0; sessionId < WLAN_MAX_VDEVS; sessionId++) {
1225 		csr_roam_state_change(mac, eCSR_ROAMING_STATE_STOP, sessionId);
1226 		csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_NONE,
1227 					 sessionId);
1228 	}
1229 
1230 	return QDF_STATUS_SUCCESS;
1231 }
1232 
1233 QDF_STATUS csr_ready(struct mac_context *mac)
1234 {
1235 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1236 	/* If the gScanAgingTime is set to '0' then scan results aging timeout
1237 	 * based  on timer feature is not enabled
1238 	 */
1239 	status = csr_apply_channel_and_power_list(mac);
1240 	if (!QDF_IS_STATUS_SUCCESS(status))
1241 		sme_err("csr_apply_channel_and_power_list failed status: %d",
1242 			status);
1243 
1244 	return status;
1245 }
1246 
1247 void csr_set_default_dot11_mode(struct mac_context *mac)
1248 {
1249 	mac->mlme_cfg->dot11_mode.dot11_mode =
1250 			csr_translate_to_wni_cfg_dot11_mode(mac,
1251 					  mac->roam.configParam.uCfgDot11Mode);
1252 }
1253 
1254 void csr_set_global_cfgs(struct mac_context *mac)
1255 {
1256 	wlan_mlme_set_frag_threshold(mac->psoc, csr_get_frag_thresh(mac));
1257 	wlan_mlme_set_rts_threshold(mac->psoc, csr_get_rts_thresh(mac));
1258 	/* For now we will just use the 5GHz CB mode ini parameter to decide
1259 	 * whether CB supported or not in Probes when there is no session
1260 	 * Once session is established we will use the session related params
1261 	 * stored in PE session for CB mode
1262 	 */
1263 	if (cfg_in_range(CFG_CHANNEL_BONDING_MODE_5GHZ,
1264 			 mac->roam.configParam.channelBondingMode5GHz))
1265 		ucfg_mlme_set_channel_bonding_5ghz(mac->psoc,
1266 						   mac->roam.configParam.
1267 						   channelBondingMode5GHz);
1268 	if (cfg_in_range(CFG_CHANNEL_BONDING_MODE_24GHZ,
1269 			 mac->roam.configParam.channelBondingMode24GHz))
1270 		ucfg_mlme_set_channel_bonding_24ghz(mac->psoc,
1271 						    mac->roam.configParam.
1272 						    channelBondingMode24GHz);
1273 
1274 	mac->mlme_cfg->timeouts.heart_beat_threshold =
1275 			cfg_default(CFG_HEART_BEAT_THRESHOLD);
1276 
1277 	/* Update the operating mode to configured value during
1278 	 *  initialization, So that client can advertise full
1279 	 *  capabilities in Probe request frame.
1280 	 */
1281 	csr_set_default_dot11_mode(mac);
1282 }
1283 
1284 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && \
1285 	defined(CONNECTIVITY_PKTLOG)
1286 /**
1287  * csr_packetdump_timer_handler() - packet dump timer
1288  * handler
1289  * @pv: user data
1290  *
1291  * This function is used to handle packet dump timer
1292  *
1293  * Return: None
1294  *
1295  */
1296 static void csr_packetdump_timer_handler(void *pv)
1297 {
1298 	sme_debug("Invoking packetdump deregistration API");
1299 	wlan_deregister_txrx_packetdump(OL_TXRX_PDEV_ID);
1300 }
1301 
1302 void csr_packetdump_timer_start(void)
1303 {
1304 	QDF_STATUS status;
1305 	mac_handle_t mac_handle;
1306 	struct mac_context *mac;
1307 	QDF_TIMER_STATE cur_state;
1308 
1309 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
1310 	mac = MAC_CONTEXT(mac_handle);
1311 	if (!mac) {
1312 		QDF_ASSERT(0);
1313 		return;
1314 	}
1315 	cur_state = qdf_mc_timer_get_current_state(&mac->roam.packetdump_timer);
1316 	if (cur_state == QDF_TIMER_STATE_STARTING ||
1317 	    cur_state == QDF_TIMER_STATE_STARTING) {
1318 		sme_debug("packetdump_timer is already started: %d", cur_state);
1319 		return;
1320 	}
1321 
1322 	status = qdf_mc_timer_start(&mac->roam.packetdump_timer,
1323 				    (PKT_DUMP_TIMER_DURATION *
1324 				     QDF_MC_TIMER_TO_SEC_UNIT) /
1325 				    QDF_MC_TIMER_TO_MS_UNIT);
1326 	if (!QDF_IS_STATUS_SUCCESS(status))
1327 		sme_debug("cannot start packetdump timer status: %d", status);
1328 }
1329 
1330 void csr_packetdump_timer_stop(void)
1331 {
1332 	QDF_STATUS status;
1333 	mac_handle_t mac_handle;
1334 	struct mac_context *mac;
1335 
1336 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
1337 	mac = MAC_CONTEXT(mac_handle);
1338 	if (!mac) {
1339 		QDF_ASSERT(0);
1340 		return;
1341 	}
1342 
1343 	status = qdf_mc_timer_stop(&mac->roam.packetdump_timer);
1344 	if (!QDF_IS_STATUS_SUCCESS(status))
1345 		sme_err("cannot stop packetdump timer");
1346 }
1347 
1348 static QDF_STATUS csr_packetdump_timer_init(struct mac_context *mac)
1349 {
1350 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1351 
1352 	if (!mac) {
1353 		QDF_ASSERT(0);
1354 		return -EINVAL;
1355 	}
1356 
1357 	status = qdf_mc_timer_init(&mac->roam.packetdump_timer,
1358 				   QDF_TIMER_TYPE_SW,
1359 				   csr_packetdump_timer_handler,
1360 				   mac);
1361 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1362 		sme_err("cannot allocate memory for packetdump timer");
1363 		return status;
1364 	}
1365 
1366 	return status;
1367 }
1368 
1369 static void csr_packetdump_timer_deinit(struct mac_context *mac)
1370 {
1371 	if (!mac) {
1372 		QDF_ASSERT(0);
1373 		return;
1374 	}
1375 
1376 	qdf_mc_timer_stop(&mac->roam.packetdump_timer);
1377 	qdf_mc_timer_destroy(&mac->roam.packetdump_timer);
1378 }
1379 #else
1380 static inline QDF_STATUS csr_packetdump_timer_init(struct mac_context *mac)
1381 {
1382 	return QDF_STATUS_SUCCESS;
1383 }
1384 
1385 static inline void csr_packetdump_timer_deinit(struct mac_context *mac) {}
1386 #endif
1387 
1388 static QDF_STATUS csr_roam_open(struct mac_context *mac)
1389 {
1390 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1391 
1392 	status = csr_packetdump_timer_init(mac);
1393 	if (QDF_IS_STATUS_ERROR(status))
1394 		return status;
1395 
1396 	spin_lock_init(&mac->roam.roam_state_lock);
1397 
1398 	return status;
1399 }
1400 
1401 static QDF_STATUS csr_roam_close(struct mac_context *mac)
1402 {
1403 	uint32_t sessionId;
1404 	struct csr_roam_session *session;
1405 
1406 	/*
1407 	 * purge all serialization command if there are any pending to make
1408 	 * sure memory and vdev ref are freed.
1409 	 */
1410 	csr_purge_pdev_all_ser_cmd_list(mac);
1411 	for (sessionId = 0; sessionId < WLAN_MAX_VDEVS; sessionId++) {
1412 		session = CSR_GET_SESSION(mac, sessionId);
1413 		if (!session)
1414 			continue;
1415 		csr_cleanup_vdev_session(mac, sessionId);
1416 	}
1417 
1418 	csr_packetdump_timer_deinit(mac);
1419 	return QDF_STATUS_SUCCESS;
1420 }
1421 
1422 static QDF_STATUS csr_roam_free_connected_info(struct mac_context *mac,
1423 					       struct csr_roam_connectedinfo *
1424 					       pConnectedInfo)
1425 {
1426 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1427 
1428 	if (pConnectedInfo->pbFrames) {
1429 		qdf_mem_free(pConnectedInfo->pbFrames);
1430 		pConnectedInfo->pbFrames = NULL;
1431 	}
1432 	pConnectedInfo->nBeaconLength = 0;
1433 	pConnectedInfo->nAssocReqLength = 0;
1434 	pConnectedInfo->nAssocRspLength = 0;
1435 	pConnectedInfo->nRICRspLength = 0;
1436 #ifdef FEATURE_WLAN_ESE
1437 	pConnectedInfo->nTspecIeLength = 0;
1438 #endif
1439 	return status;
1440 }
1441 
1442 void csr_release_command_roam(struct mac_context *mac, tSmeCmd *pCommand)
1443 {
1444 	csr_reinit_roam_cmd(mac, pCommand);
1445 }
1446 
1447 void csr_release_command_wm_status_change(struct mac_context *mac,
1448 					  tSmeCmd *pCommand)
1449 {
1450 	csr_reinit_wm_status_change_cmd(mac, pCommand);
1451 }
1452 
1453 void csr_roam_substate_change(struct mac_context *mac,
1454 		enum csr_roam_substate NewSubstate, uint32_t sessionId)
1455 {
1456 	if (sessionId >= WLAN_MAX_VDEVS) {
1457 		sme_err("Invalid no of concurrent sessions %d",
1458 			  sessionId);
1459 		return;
1460 	}
1461 	if (mac->roam.curSubState[sessionId] == NewSubstate)
1462 		return;
1463 	sme_nofl_debug("CSR RoamSubstate: [ %s <== %s ]",
1464 		       mac_trace_getcsr_roam_sub_state(NewSubstate),
1465 		       mac_trace_getcsr_roam_sub_state(mac->roam.
1466 		       curSubState[sessionId]));
1467 	spin_lock(&mac->roam.roam_state_lock);
1468 	mac->roam.curSubState[sessionId] = NewSubstate;
1469 	spin_unlock(&mac->roam.roam_state_lock);
1470 }
1471 
1472 enum csr_roam_state csr_roam_state_change(struct mac_context *mac,
1473 				    enum csr_roam_state NewRoamState,
1474 				uint8_t sessionId)
1475 {
1476 	enum csr_roam_state PreviousState;
1477 
1478 	PreviousState = mac->roam.curState[sessionId];
1479 
1480 	if (NewRoamState == mac->roam.curState[sessionId])
1481 		return PreviousState;
1482 
1483 	sme_nofl_debug("CSR RoamState[%d]: [ %s <== %s ]", sessionId,
1484 		       mac_trace_getcsr_roam_state(NewRoamState),
1485 		       mac_trace_getcsr_roam_state(
1486 		       mac->roam.curState[sessionId]));
1487 	/*
1488 	 * Whenever we transition OUT of the Roaming state,
1489 	 * clear the Roaming substate.
1490 	 */
1491 	if (CSR_IS_ROAM_JOINING(mac, sessionId)) {
1492 		csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_NONE,
1493 					 sessionId);
1494 	}
1495 
1496 	mac->roam.curState[sessionId] = NewRoamState;
1497 
1498 	return PreviousState;
1499 }
1500 
1501 static void init_config_param(struct mac_context *mac)
1502 {
1503 	mac->roam.configParam.channelBondingMode24GHz =
1504 		WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
1505 	mac->roam.configParam.channelBondingMode5GHz =
1506 		WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
1507 
1508 	mac->roam.configParam.phyMode = eCSR_DOT11_MODE_AUTO;
1509 	mac->roam.configParam.uCfgDot11Mode = eCSR_CFG_DOT11_MODE_AUTO;
1510 	mac->roam.configParam.HeartbeatThresh50 = 40;
1511 	mac->roam.configParam.Is11eSupportEnabled = true;
1512 	mac->roam.configParam.WMMSupportMode = WMM_USER_MODE_AUTO;
1513 	mac->roam.configParam.ProprietaryRatesEnabled = true;
1514 
1515 	mac->roam.configParam.nVhtChannelWidth =
1516 		WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ + 1;
1517 }
1518 
1519 /**
1520  * csr_flush_roam_scan_chan_lists() - Flush the roam channel lists
1521  * @mac: Global MAC context
1522  * @vdev_id: vdev id
1523  *
1524  * Flush the roam channel lists pref_chan_info and specific_chan_info.
1525  *
1526  * Return: None
1527  */
1528 static void
1529 csr_flush_roam_scan_chan_lists(struct mac_context *mac, uint8_t vdev_id)
1530 {
1531 	struct wlan_objmgr_vdev *vdev;
1532 	struct rso_config *rso_cfg;
1533 	struct rso_cfg_params *cfg_params;
1534 
1535 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac->pdev, vdev_id,
1536 						    WLAN_LEGACY_SME_ID);
1537 	if (!vdev)
1538 		return;
1539 
1540 	rso_cfg = wlan_cm_get_rso_config(vdev);
1541 	if (!rso_cfg) {
1542 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1543 		return;
1544 	}
1545 	cfg_params = &rso_cfg->cfg_param;
1546 	wlan_cm_flush_roam_channel_list(&cfg_params->pref_chan_info);
1547 	wlan_cm_flush_roam_channel_list(&cfg_params->specific_chan_info);
1548 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1549 }
1550 
1551 #ifdef FEATURE_WLAN_ESE
1552 /**
1553  * csr_roam_is_ese_assoc() - is this ese association
1554  * @mac_ctx: Global MAC context
1555  * @session_id: session identifier
1556  *
1557  * Returns whether the current association is a ESE assoc or not.
1558  *
1559  * Return: true if ese association; false otherwise
1560  */
1561 bool csr_roam_is_ese_assoc(struct mac_context *mac_ctx, uint32_t session_id)
1562 {
1563 	return wlan_cm_get_ese_assoc(mac_ctx->pdev, session_id);
1564 }
1565 
1566 
1567 /**
1568  * csr_tsm_stats_rsp_processor() - tsm stats response processor
1569  * @mac: Global MAC context
1570  * @pMsg: Message pointer
1571  *
1572  * Return: None
1573  */
1574 static void csr_tsm_stats_rsp_processor(struct mac_context *mac, void *pMsg)
1575 {
1576 	tAniGetTsmStatsRsp *pTsmStatsRsp = (tAniGetTsmStatsRsp *) pMsg;
1577 
1578 	if (pTsmStatsRsp) {
1579 		/*
1580 		 * Get roam Rssi request is backed up and passed back
1581 		 * to the response, Extract the request message
1582 		 * to fetch callback.
1583 		 */
1584 		tpAniGetTsmStatsReq reqBkp
1585 			= (tAniGetTsmStatsReq *) pTsmStatsRsp->tsmStatsReq;
1586 
1587 		if (reqBkp) {
1588 			if (reqBkp->tsmStatsCallback) {
1589 				((tCsrTsmStatsCallback)
1590 				 (reqBkp->tsmStatsCallback))(pTsmStatsRsp->
1591 							     tsmMetrics,
1592 							     reqBkp->
1593 							     pDevContext);
1594 				reqBkp->tsmStatsCallback = NULL;
1595 			}
1596 			qdf_mem_free(reqBkp);
1597 			pTsmStatsRsp->tsmStatsReq = NULL;
1598 		} else {
1599 			if (reqBkp) {
1600 				qdf_mem_free(reqBkp);
1601 				pTsmStatsRsp->tsmStatsReq = NULL;
1602 			}
1603 		}
1604 	} else {
1605 		sme_err("pTsmStatsRsp is NULL");
1606 	}
1607 }
1608 
1609 /**
1610  * csr_send_ese_adjacent_ap_rep_ind() - ese send adjacent ap report
1611  * @mac: Global MAC context
1612  * @pSession: Session pointer
1613  *
1614  * Return: None
1615  */
1616 static void csr_send_ese_adjacent_ap_rep_ind(struct mac_context *mac,
1617 					struct csr_roam_session *pSession)
1618 {
1619 	uint32_t roamTS2 = 0;
1620 	struct csr_roam_info *roam_info;
1621 	struct pe_session *pe_session = NULL;
1622 	uint8_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
1623 	struct qdf_mac_addr connected_bssid;
1624 
1625 	if (!pSession) {
1626 		sme_err("pSession is NULL");
1627 		return;
1628 	}
1629 
1630 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
1631 	if (!roam_info)
1632 		return;
1633 	roamTS2 = qdf_mc_timer_get_system_time();
1634 	roam_info->tsmRoamDelay = roamTS2 - pSession->roamTS1;
1635 	wlan_mlme_get_bssid_vdev_id(mac->pdev, pSession->vdev_id,
1636 				    &connected_bssid);
1637 	sme_debug("Bssid(" QDF_MAC_ADDR_FMT ") Roaming Delay(%u ms)",
1638 		QDF_MAC_ADDR_REF(connected_bssid.bytes),
1639 		roam_info->tsmRoamDelay);
1640 
1641 	pe_session = pe_find_session_by_bssid(mac, connected_bssid.bytes,
1642 					      &sessionId);
1643 	if (!pe_session) {
1644 		sme_err("session %d not found", sessionId);
1645 		qdf_mem_free(roam_info);
1646 		return;
1647 	}
1648 
1649 	pe_session->eseContext.tsm.tsmMetrics.RoamingDly
1650 		= roam_info->tsmRoamDelay;
1651 
1652 	csr_roam_call_callback(mac, pSession->vdev_id, roam_info,
1653 			       eCSR_ROAM_ESE_ADJ_AP_REPORT_IND, 0);
1654 	qdf_mem_free(roam_info);
1655 }
1656 
1657 /**
1658  * csr_get_tsm_stats() - get tsm stats
1659  * @mac: Global MAC context
1660  * @callback: TSM stats callback
1661  * @staId: Station id
1662  * @bssId: bssid
1663  * @pContext: pointer to context
1664  * @tid: traffic id
1665  *
1666  * Return: QDF_STATUS enumeration
1667  */
1668 QDF_STATUS csr_get_tsm_stats(struct mac_context *mac,
1669 			     tCsrTsmStatsCallback callback,
1670 			     struct qdf_mac_addr bssId,
1671 			     void *pContext, uint8_t tid)
1672 {
1673 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1674 	tAniGetTsmStatsReq *pMsg = NULL;
1675 
1676 	pMsg = qdf_mem_malloc(sizeof(tAniGetTsmStatsReq));
1677 	if (!pMsg) {
1678 		return QDF_STATUS_E_NOMEM;
1679 	}
1680 	/* need to initiate a stats request to PE */
1681 	pMsg->msgType = eWNI_SME_GET_TSM_STATS_REQ;
1682 	pMsg->msgLen = (uint16_t) sizeof(tAniGetTsmStatsReq);
1683 	pMsg->tid = tid;
1684 	qdf_copy_macaddr(&pMsg->bssId, &bssId);
1685 	pMsg->tsmStatsCallback = callback;
1686 	pMsg->pDevContext = pContext;
1687 	status = umac_send_mb_message_to_mac(pMsg);
1688 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1689 		sme_debug("Failed to send down the TSM req (status=%d)", status);
1690 		/* pMsg is freed by cds_send_mb_message_to_mac */
1691 		status = QDF_STATUS_E_FAILURE;
1692 	}
1693 	return status;
1694 }
1695 #endif /* FEATURE_WLAN_ESE */
1696 
1697 /* The funcns csr_convert_cb_ini_value_to_phy_cb_state and
1698  * csr_convert_phy_cb_state_to_ini_value have been introduced
1699  * to convert the ini value to the ENUM used in csr and MAC for CB state
1700  * Ideally we should have kept the ini value and enum value same and
1701  * representing the same cb values as in 11n standard i.e.
1702  * Set to 1 (SCA) if the secondary channel is above the primary channel
1703  * Set to 3 (SCB) if the secondary channel is below the primary channel
1704  * Set to 0 (SCN) if no secondary channel is present
1705  * However, since our driver is already distributed we will keep the ini
1706  * definition as it is which is:
1707  * 0 - secondary none
1708  * 1 - secondary LOW
1709  * 2 - secondary HIGH
1710  * and convert to enum value used within the driver in
1711  * csr_change_default_config_param using this funcn
1712  * The enum values are as follows:
1713  * PHY_SINGLE_CHANNEL_CENTERED          = 0
1714  * PHY_DOUBLE_CHANNEL_LOW_PRIMARY   = 1
1715  * PHY_DOUBLE_CHANNEL_HIGH_PRIMARY  = 3
1716  */
1717 ePhyChanBondState csr_convert_cb_ini_value_to_phy_cb_state(uint32_t cbIniValue)
1718 {
1719 
1720 	ePhyChanBondState phyCbState;
1721 
1722 	switch (cbIniValue) {
1723 	/* secondary none */
1724 	case eCSR_INI_SINGLE_CHANNEL_CENTERED:
1725 		phyCbState = PHY_SINGLE_CHANNEL_CENTERED;
1726 		break;
1727 	/* secondary LOW */
1728 	case eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY:
1729 		phyCbState = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
1730 		break;
1731 	/* secondary HIGH */
1732 	case eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY:
1733 		phyCbState = PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
1734 		break;
1735 	case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
1736 		phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED;
1737 		break;
1738 	case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
1739 		phyCbState =
1740 			PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED;
1741 		break;
1742 	case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
1743 		phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED;
1744 		break;
1745 	case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
1746 		phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW;
1747 		break;
1748 	case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
1749 		phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW;
1750 		break;
1751 	case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
1752 		phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH;
1753 		break;
1754 	case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
1755 		phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH;
1756 		break;
1757 	default:
1758 		/* If an invalid value is passed, disable CHANNEL BONDING */
1759 		phyCbState = PHY_SINGLE_CHANNEL_CENTERED;
1760 		break;
1761 	}
1762 	return phyCbState;
1763 }
1764 
1765 static
1766 uint32_t csr_convert_phy_cb_state_to_ini_value(ePhyChanBondState phyCbState)
1767 {
1768 	uint32_t cbIniValue;
1769 
1770 	switch (phyCbState) {
1771 	/* secondary none */
1772 	case PHY_SINGLE_CHANNEL_CENTERED:
1773 		cbIniValue = eCSR_INI_SINGLE_CHANNEL_CENTERED;
1774 		break;
1775 	/* secondary LOW */
1776 	case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
1777 		cbIniValue = eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
1778 		break;
1779 	/* secondary HIGH */
1780 	case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
1781 		cbIniValue = eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
1782 		break;
1783 	case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
1784 		cbIniValue =
1785 			eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED;
1786 		break;
1787 	case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
1788 		cbIniValue =
1789 		eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED;
1790 		break;
1791 	case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
1792 		cbIniValue =
1793 			eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED;
1794 		break;
1795 	case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
1796 		cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW;
1797 		break;
1798 	case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
1799 		cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW;
1800 		break;
1801 	case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
1802 		cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH;
1803 		break;
1804 	case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
1805 		cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH;
1806 		break;
1807 	default:
1808 		/* return some invalid value */
1809 		cbIniValue = eCSR_INI_CHANNEL_BONDING_STATE_MAX;
1810 		break;
1811 	}
1812 	return cbIniValue;
1813 }
1814 
1815 #ifdef WLAN_FEATURE_11BE
1816 void csr_update_session_eht_cap(struct mac_context *mac_ctx,
1817 				struct csr_roam_session *session)
1818 {
1819 	tDot11fIEeht_cap *eht_cap;
1820 	struct wlan_objmgr_vdev *vdev;
1821 	struct mlme_legacy_priv *mlme_priv;
1822 
1823 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
1824 						    session->vdev_id,
1825 						    WLAN_LEGACY_SME_ID);
1826 	if (!vdev)
1827 		return;
1828 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
1829 	if (!mlme_priv) {
1830 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1831 		return;
1832 	}
1833 	qdf_mem_copy(&mlme_priv->eht_config,
1834 		     &mac_ctx->mlme_cfg->eht_caps.dot11_eht_cap,
1835 		     sizeof(mlme_priv->eht_config));
1836 	eht_cap = &mlme_priv->eht_config;
1837 	eht_cap->present = true;
1838 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1839 }
1840 #endif
1841 
1842 #ifdef WLAN_FEATURE_11AX
1843 void csr_update_session_he_cap(struct mac_context *mac_ctx,
1844 			       struct csr_roam_session *session)
1845 {
1846 	enum QDF_OPMODE persona;
1847 	tDot11fIEhe_cap *he_cap;
1848 	struct wlan_objmgr_vdev *vdev;
1849 	struct mlme_legacy_priv *mlme_priv;
1850 
1851 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
1852 						    session->vdev_id,
1853 						    WLAN_LEGACY_SME_ID);
1854 	if (!vdev)
1855 		return;
1856 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
1857 	if (!mlme_priv) {
1858 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1859 		return;
1860 	}
1861 	qdf_mem_copy(&mlme_priv->he_config,
1862 		     &mac_ctx->mlme_cfg->he_caps.dot11_he_cap,
1863 		     sizeof(mlme_priv->he_config));
1864 	he_cap = &mlme_priv->he_config;
1865 	he_cap->present = true;
1866 	/*
1867 	 * Do not advertise requester role for SAP & responder role
1868 	 * for STA
1869 	 */
1870 	persona = wlan_vdev_mlme_get_opmode(vdev);
1871 	if (persona == QDF_SAP_MODE || persona == QDF_P2P_GO_MODE) {
1872 		he_cap->twt_request = false;
1873 		if (!he_cap->twt_responder)
1874 			he_cap->flex_twt_sched = false;
1875 
1876 	} else if (persona == QDF_STA_MODE || persona == QDF_P2P_CLIENT_MODE) {
1877 		he_cap->twt_responder = false;
1878 		if (!he_cap->twt_request)
1879 			he_cap->flex_twt_sched = false;
1880 	}
1881 
1882 	if (he_cap->ppet_present) {
1883 		/* till now operating channel is not decided yet, use 5g cap */
1884 		qdf_mem_copy(he_cap->ppet.ppe_threshold.ppe_th,
1885 			     mac_ctx->mlme_cfg->he_caps.he_ppet_5g,
1886 			     WNI_CFG_HE_PPET_LEN);
1887 		he_cap->ppet.ppe_threshold.num_ppe_th =
1888 			lim_truncate_ppet(he_cap->ppet.ppe_threshold.ppe_th,
1889 					  WNI_CFG_HE_PPET_LEN);
1890 	} else {
1891 		he_cap->ppet.ppe_threshold.num_ppe_th = 0;
1892 	}
1893 	mlme_priv->he_sta_obsspd = mac_ctx->mlme_cfg->he_caps.he_sta_obsspd;
1894 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1895 }
1896 #endif
1897 
1898 QDF_STATUS csr_change_default_config_param(struct mac_context *mac,
1899 					   struct csr_config_params *pParam)
1900 {
1901 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1902 
1903 	if (pParam) {
1904 		mac->roam.configParam.is_force_1x1 =
1905 			pParam->is_force_1x1;
1906 		mac->roam.configParam.WMMSupportMode = pParam->WMMSupportMode;
1907 		mac->mlme_cfg->wmm_params.wme_enabled =
1908 			(pParam->WMMSupportMode == WMM_USER_MODE_NO_QOS) ? 0 : 1;
1909 		mac->roam.configParam.Is11eSupportEnabled =
1910 			pParam->Is11eSupportEnabled;
1911 
1912 		mac->roam.configParam.fenableMCCMode = pParam->fEnableMCCMode;
1913 		mac->roam.configParam.mcc_rts_cts_prot_enable =
1914 						pParam->mcc_rts_cts_prot_enable;
1915 		mac->roam.configParam.mcc_bcast_prob_resp_enable =
1916 					pParam->mcc_bcast_prob_resp_enable;
1917 		mac->roam.configParam.fAllowMCCGODiffBI =
1918 			pParam->fAllowMCCGODiffBI;
1919 
1920 		/* channelBondingMode5GHz plays a dual role right now
1921 		 * INFRA STA will use this non zero value as CB enabled
1922 		 * and SOFTAP will use this non-zero value to determine
1923 		 * the secondary channel offset. This is how
1924 		 * channelBondingMode5GHz works now and this is kept intact
1925 		 * to avoid any cfg.ini change.
1926 		 */
1927 		if (pParam->channelBondingMode24GHz > MAX_CB_VALUE_IN_INI)
1928 			sme_warn("Invalid CB value from ini in 2.4GHz band %d, CB DISABLED",
1929 				pParam->channelBondingMode24GHz);
1930 		mac->roam.configParam.channelBondingMode24GHz =
1931 			csr_convert_cb_ini_value_to_phy_cb_state(pParam->
1932 						channelBondingMode24GHz);
1933 		if (pParam->channelBondingMode5GHz > MAX_CB_VALUE_IN_INI)
1934 			sme_warn("Invalid CB value from ini in 5GHz band %d, CB DISABLED",
1935 				pParam->channelBondingMode5GHz);
1936 		mac->roam.configParam.channelBondingMode5GHz =
1937 			csr_convert_cb_ini_value_to_phy_cb_state(pParam->
1938 							channelBondingMode5GHz);
1939 		sme_debug("cb mode 2g %d 5g %d",
1940 			  mac->roam.configParam.channelBondingMode24GHz,
1941 			  mac->roam.configParam.channelBondingMode5GHz);
1942 		mac->roam.configParam.phyMode = pParam->phyMode;
1943 		mac->roam.configParam.HeartbeatThresh50 =
1944 			pParam->HeartbeatThresh50;
1945 		mac->roam.configParam.ProprietaryRatesEnabled =
1946 			pParam->ProprietaryRatesEnabled;
1947 
1948 		mac->roam.configParam.wep_tkip_in_he = pParam->wep_tkip_in_he;
1949 
1950 		mac->roam.configParam.uCfgDot11Mode =
1951 			csr_get_cfg_dot11_mode_from_csr_phy_mode(false,
1952 							mac->roam.configParam.
1953 							phyMode);
1954 
1955 		/* Assign this before calling csr_init11d_info */
1956 		if (wlan_reg_11d_enabled_on_host(mac->psoc))
1957 			status = csr_init11d_info(mac, &pParam->Csr11dinfo);
1958 
1959 		/* Initialize the power + channel information if 11h is
1960 		 * enabled. If 11d is enabled this information has already
1961 		 * been initialized
1962 		 */
1963 		if (csr_is11h_supported(mac) &&
1964 				!wlan_reg_11d_enabled_on_host(mac->psoc))
1965 			csr_init_channel_power_list(mac, &pParam->Csr11dinfo);
1966 
1967 		mac->scan.fEnableDFSChnlScan = pParam->fEnableDFSChnlScan;
1968 		mac->roam.configParam.send_smps_action =
1969 			pParam->send_smps_action;
1970 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
1971 		mac->roam.configParam.cc_switch_mode = pParam->cc_switch_mode;
1972 #endif
1973 		mac->roam.configParam.obssEnabled = pParam->obssEnabled;
1974 		mac->roam.configParam.conc_custom_rule1 =
1975 			pParam->conc_custom_rule1;
1976 		mac->roam.configParam.conc_custom_rule2 =
1977 			pParam->conc_custom_rule2;
1978 		mac->roam.configParam.is_sta_connection_in_5gz_enabled =
1979 			pParam->is_sta_connection_in_5gz_enabled;
1980 
1981 		/* update interface configuration */
1982 		mac->sme.max_intf_count = pParam->max_intf_count;
1983 
1984 		mac->f_sta_miracast_mcc_rest_time_val =
1985 			pParam->f_sta_miracast_mcc_rest_time_val;
1986 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
1987 		mac->sap.sap_channel_avoidance =
1988 			pParam->sap_channel_avoidance;
1989 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
1990 	}
1991 	return status;
1992 }
1993 
1994 QDF_STATUS csr_get_config_param(struct mac_context *mac,
1995 				struct csr_config_params *pParam)
1996 {
1997 	struct csr_config *cfg_params = &mac->roam.configParam;
1998 
1999 	if (!pParam)
2000 		return QDF_STATUS_E_INVAL;
2001 
2002 	pParam->is_force_1x1 = cfg_params->is_force_1x1;
2003 	pParam->WMMSupportMode = cfg_params->WMMSupportMode;
2004 	pParam->Is11eSupportEnabled = cfg_params->Is11eSupportEnabled;
2005 	pParam->channelBondingMode24GHz = csr_convert_phy_cb_state_to_ini_value(
2006 					cfg_params->channelBondingMode24GHz);
2007 	pParam->channelBondingMode5GHz = csr_convert_phy_cb_state_to_ini_value(
2008 					cfg_params->channelBondingMode5GHz);
2009 	pParam->phyMode = cfg_params->phyMode;
2010 	pParam->HeartbeatThresh50 = cfg_params->HeartbeatThresh50;
2011 	pParam->ProprietaryRatesEnabled = cfg_params->ProprietaryRatesEnabled;
2012 	pParam->fEnableDFSChnlScan = mac->scan.fEnableDFSChnlScan;
2013 	pParam->fEnableMCCMode = cfg_params->fenableMCCMode;
2014 	pParam->fAllowMCCGODiffBI = cfg_params->fAllowMCCGODiffBI;
2015 
2016 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
2017 	pParam->cc_switch_mode = cfg_params->cc_switch_mode;
2018 #endif
2019 	pParam->wep_tkip_in_he = cfg_params->wep_tkip_in_he;
2020 	csr_set_channels(mac, pParam);
2021 	pParam->obssEnabled = cfg_params->obssEnabled;
2022 	pParam->conc_custom_rule1 = cfg_params->conc_custom_rule1;
2023 	pParam->conc_custom_rule2 = cfg_params->conc_custom_rule2;
2024 	pParam->is_sta_connection_in_5gz_enabled =
2025 		cfg_params->is_sta_connection_in_5gz_enabled;
2026 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
2027 	pParam->sap_channel_avoidance = mac->sap.sap_channel_avoidance;
2028 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
2029 	pParam->max_intf_count = mac->sme.max_intf_count;
2030 	pParam->f_sta_miracast_mcc_rest_time_val =
2031 		mac->f_sta_miracast_mcc_rest_time_val;
2032 	pParam->send_smps_action = mac->roam.configParam.send_smps_action;
2033 
2034 	return QDF_STATUS_SUCCESS;
2035 }
2036 
2037 /**
2038  * csr_prune_ch_list() - prunes the channel list to keep only a type of channels
2039  * @ch_lst:        existing channel list
2040  * @is_24_GHz:     indicates if 2.5 GHz or 5 GHz channels are required
2041  *
2042  * Return: void
2043  */
2044 static void csr_prune_ch_list(struct csr_channel *ch_lst, bool is_24_GHz)
2045 {
2046 	uint8_t idx = 0, num_channels = 0;
2047 
2048 	for ( ; idx < ch_lst->numChannels; idx++) {
2049 		if (is_24_GHz) {
2050 			if (WLAN_REG_IS_24GHZ_CH_FREQ(ch_lst->channel_freq_list[idx])) {
2051 				ch_lst->channel_freq_list[num_channels] =
2052 					ch_lst->channel_freq_list[idx];
2053 				num_channels++;
2054 			}
2055 		} else {
2056 			if (WLAN_REG_IS_5GHZ_CH_FREQ(ch_lst->channel_freq_list[idx])) {
2057 				ch_lst->channel_freq_list[num_channels] =
2058 					ch_lst->channel_freq_list[idx];
2059 				num_channels++;
2060 			}
2061 		}
2062 	}
2063 	/*
2064 	 * Cleanup the rest of channels. Note we only need to clean up the
2065 	 * channels if we had to trim the list. Calling qdf_mem_set() with a 0
2066 	 * size is going to throw asserts on the debug builds so let's be a bit
2067 	 * smarter about that. Zero out the reset of the channels only if we
2068 	 * need to. The amount of memory to clear is the number of channesl that
2069 	 * we trimmed (ch_lst->numChannels - num_channels) times the size of a
2070 	 * channel in the structure.
2071 	 */
2072 	if (ch_lst->numChannels > num_channels) {
2073 		qdf_mem_zero(&ch_lst->channel_freq_list[num_channels],
2074 			     sizeof(ch_lst->channel_freq_list[0]) *
2075 			     (ch_lst->numChannels - num_channels));
2076 	}
2077 	ch_lst->numChannels = num_channels;
2078 }
2079 
2080 /**
2081  * csr_prune_channel_list_for_mode() - prunes the channel list
2082  * @mac_ctx:       global mac context
2083  * @ch_lst:        existing channel list
2084  *
2085  * Prunes the channel list according to band stored in mac_ctx
2086  *
2087  * Return: void
2088  */
2089 void csr_prune_channel_list_for_mode(struct mac_context *mac_ctx,
2090 				     struct csr_channel *ch_lst)
2091 {
2092 	/* for dual band NICs, don't need to trim the channel list.... */
2093 	if (CSR_IS_OPEARTING_DUAL_BAND(mac_ctx))
2094 		return;
2095 	/*
2096 	 * 2.4 GHz band operation requires the channel list to be trimmed to
2097 	 * the 2.4 GHz channels only
2098 	 */
2099 	if (CSR_IS_24_BAND_ONLY(mac_ctx))
2100 		csr_prune_ch_list(ch_lst, true);
2101 	else if (CSR_IS_5G_BAND_ONLY(mac_ctx))
2102 		csr_prune_ch_list(ch_lst, false);
2103 }
2104 
2105 #define INFRA_AP_DEFAULT_CHAN_FREQ 2437
2106 
2107 QDF_STATUS csr_get_channel_and_power_list(struct mac_context *mac)
2108 {
2109 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2110 	uint8_t num20MHzChannelsFound = 0;
2111 	QDF_STATUS qdf_status;
2112 	uint8_t Index = 0;
2113 
2114 	qdf_status = wlan_reg_get_channel_list_with_power_for_freq(
2115 				mac->pdev,
2116 				mac->scan.defaultPowerTable,
2117 				&num20MHzChannelsFound);
2118 
2119 	if ((QDF_STATUS_SUCCESS != qdf_status) ||
2120 	    (num20MHzChannelsFound == 0)) {
2121 		sme_err("failed to get channels");
2122 		status = QDF_STATUS_E_FAILURE;
2123 	} else {
2124 		if (num20MHzChannelsFound > CFG_VALID_CHANNEL_LIST_LEN)
2125 			num20MHzChannelsFound = CFG_VALID_CHANNEL_LIST_LEN;
2126 		/* Move the channel list to the global data */
2127 		/* structure -- this will be used as the scan list */
2128 		for (Index = 0; Index < num20MHzChannelsFound; Index++)
2129 			mac->scan.base_channels.channel_freq_list[Index] =
2130 				mac->scan.defaultPowerTable[Index].center_freq;
2131 		mac->scan.base_channels.numChannels =
2132 			num20MHzChannelsFound;
2133 	}
2134 	return status;
2135 }
2136 
2137 QDF_STATUS csr_apply_channel_and_power_list(struct mac_context *mac)
2138 {
2139 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2140 
2141 	csr_prune_channel_list_for_mode(mac, &mac->scan.base_channels);
2142 	csr_save_channel_power_for_band(mac, false);
2143 	csr_save_channel_power_for_band(mac, true);
2144 	csr_apply_channel_power_info_to_fw(mac,
2145 					   &mac->scan.base_channels);
2146 
2147 	csr_init_operating_classes(mac);
2148 	return status;
2149 }
2150 
2151 static QDF_STATUS csr_init11d_info(struct mac_context *mac, tCsr11dinfo *ps11dinfo)
2152 {
2153 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
2154 	uint8_t index;
2155 	uint32_t count = 0;
2156 	struct pwr_channel_info *pChanInfo;
2157 	struct pwr_channel_info *pChanInfoStart;
2158 	bool applyConfig = true;
2159 
2160 	if (!ps11dinfo)
2161 		return status;
2162 
2163 	if (ps11dinfo->Channels.numChannels
2164 	    && (CFG_VALID_CHANNEL_LIST_LEN >=
2165 		ps11dinfo->Channels.numChannels)) {
2166 		mac->scan.base_channels.numChannels =
2167 			ps11dinfo->Channels.numChannels;
2168 		qdf_mem_copy(mac->scan.base_channels.channel_freq_list,
2169 			     ps11dinfo->Channels.channel_freq_list,
2170 			     ps11dinfo->Channels.numChannels);
2171 	} else {
2172 		/* No change */
2173 		return QDF_STATUS_SUCCESS;
2174 	}
2175 	/* legacy maintenance */
2176 
2177 	/* need to add the max power channel list */
2178 	pChanInfo =
2179 		qdf_mem_malloc(sizeof(struct pwr_channel_info) *
2180 			       CFG_VALID_CHANNEL_LIST_LEN);
2181 	if (pChanInfo) {
2182 		pChanInfoStart = pChanInfo;
2183 		for (index = 0; index < ps11dinfo->Channels.numChannels;
2184 		     index++) {
2185 			pChanInfo->first_freq = ps11dinfo->ChnPower[index].first_chan_freq;
2186 			pChanInfo->num_chan =
2187 				ps11dinfo->ChnPower[index].numChannels;
2188 			pChanInfo->max_tx_pwr =
2189 				ps11dinfo->ChnPower[index].maxtxPower;
2190 			pChanInfo++;
2191 			count++;
2192 		}
2193 		if (count) {
2194 			status = csr_save_to_channel_power2_g_5_g(mac,
2195 						count *
2196 						sizeof(struct pwr_channel_info),
2197 						pChanInfoStart);
2198 		}
2199 		qdf_mem_free(pChanInfoStart);
2200 	}
2201 	/* Only apply them to CFG when not in STOP state.
2202 	 * Otherwise they will be applied later
2203 	 */
2204 	if (QDF_IS_STATUS_SUCCESS(status)) {
2205 		for (index = 0; index < WLAN_MAX_VDEVS; index++) {
2206 			if ((CSR_IS_SESSION_VALID(mac, index))
2207 			    && CSR_IS_ROAM_STOP(mac, index)) {
2208 				applyConfig = false;
2209 			}
2210 		}
2211 
2212 		if (true == applyConfig) {
2213 			/* Apply the base channel list, power info,
2214 			 * and set the Country code.
2215 			 */
2216 			csr_apply_channel_power_info_to_fw(mac,
2217 							   &mac->scan.
2218 							   base_channels);
2219 		}
2220 	}
2221 	return status;
2222 }
2223 
2224 /* Initialize the Channel + Power List in the local cache and in the CFG */
2225 QDF_STATUS csr_init_channel_power_list(struct mac_context *mac,
2226 					tCsr11dinfo *ps11dinfo)
2227 {
2228 	uint8_t index;
2229 	uint32_t count = 0;
2230 	struct pwr_channel_info *pChanInfo;
2231 	struct pwr_channel_info *pChanInfoStart;
2232 
2233 	if (!ps11dinfo || !mac)
2234 		return QDF_STATUS_E_FAILURE;
2235 
2236 	pChanInfo =
2237 		qdf_mem_malloc(sizeof(struct pwr_channel_info) *
2238 			       CFG_VALID_CHANNEL_LIST_LEN);
2239 	if (pChanInfo) {
2240 		pChanInfoStart = pChanInfo;
2241 
2242 		for (index = 0; index < ps11dinfo->Channels.numChannels;
2243 		     index++) {
2244 			pChanInfo->first_freq = ps11dinfo->ChnPower[index].first_chan_freq;
2245 			pChanInfo->num_chan =
2246 				ps11dinfo->ChnPower[index].numChannels;
2247 			pChanInfo->max_tx_pwr =
2248 				ps11dinfo->ChnPower[index].maxtxPower;
2249 			pChanInfo++;
2250 			count++;
2251 		}
2252 		if (count) {
2253 			csr_save_to_channel_power2_g_5_g(mac,
2254 						count *
2255 						sizeof(struct pwr_channel_info),
2256 						pChanInfoStart);
2257 		}
2258 		qdf_mem_free(pChanInfoStart);
2259 	}
2260 
2261 	return QDF_STATUS_SUCCESS;
2262 }
2263 
2264 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
2265 #ifdef WLAN_UNIT_TEST
2266 void csr_cm_get_sta_cxn_info(struct mac_context *mac_ctx, uint8_t vdev_id,
2267 			     char *buf, uint32_t buf_sz)
2268 {
2269 	struct wlan_objmgr_vdev *vdev;
2270 
2271 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
2272 						    WLAN_LEGACY_MAC_ID);
2273 	if (!vdev) {
2274 		sme_err("vdev object is NULL for vdev %d", vdev_id);
2275 		return;
2276 	}
2277 
2278 	cm_get_sta_cxn_info(vdev, buf, buf_sz);
2279 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
2280 
2281 }
2282 #endif
2283 #endif
2284 
2285 QDF_STATUS csr_roam_call_callback(struct mac_context *mac, uint32_t sessionId,
2286 				  struct csr_roam_info *roam_info,
2287 				  eRoamCmdStatus u1, eCsrRoamResult u2)
2288 {
2289 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2290 	struct csr_roam_session *pSession;
2291 	qdf_freq_t chan_freq;
2292 
2293 	if (!CSR_IS_SESSION_VALID(mac, sessionId)) {
2294 		sme_err("Session ID: %d is not valid", sessionId);
2295 		QDF_ASSERT(0);
2296 		return QDF_STATUS_E_FAILURE;
2297 	}
2298 	pSession = CSR_GET_SESSION(mac, sessionId);
2299 
2300 	if (false == pSession->sessionActive) {
2301 		sme_debug("Session is not Active");
2302 		return QDF_STATUS_E_FAILURE;
2303 	}
2304 	chan_freq = wlan_get_operation_chan_freq_vdev_id(mac->pdev, sessionId);
2305 
2306 	if (mac->session_roam_complete_cb)
2307 		status = mac->session_roam_complete_cb(mac->psoc, sessionId,
2308 						       roam_info, u1, u2);
2309 
2310 	return status;
2311 }
2312 
2313 static bool csr_peer_mac_match_cmd(tSmeCmd *sme_cmd,
2314 				   struct qdf_mac_addr peer_macaddr,
2315 				   uint8_t vdev_id)
2316 {
2317 	if (sme_cmd->command == eSmeCommandRoam &&
2318 	    (sme_cmd->u.roamCmd.roamReason == eCsrForcedDisassocSta ||
2319 	     sme_cmd->u.roamCmd.roamReason == eCsrForcedDeauthSta) &&
2320 	    !qdf_mem_cmp(peer_macaddr.bytes, sme_cmd->u.roamCmd.peerMac,
2321 			 QDF_MAC_ADDR_SIZE))
2322 		return true;
2323 
2324 	if (sme_cmd->command == eSmeCommandWmStatusChange) {
2325 		struct wmstatus_changecmd *wms_cmd;
2326 
2327 		wms_cmd = &sme_cmd->u.wmStatusChangeCmd;
2328 		if (wms_cmd->Type == eCsrDisassociated &&
2329 		    !qdf_mem_cmp(peer_macaddr.bytes,
2330 				 wms_cmd->u.DisassocIndMsg.peer_macaddr.bytes,
2331 				 QDF_MAC_ADDR_SIZE))
2332 			return true;
2333 
2334 		if (wms_cmd->Type == eCsrDeauthenticated &&
2335 		    !qdf_mem_cmp(peer_macaddr.bytes,
2336 				 wms_cmd->u.DeauthIndMsg.peer_macaddr.bytes,
2337 				 QDF_MAC_ADDR_SIZE))
2338 			return true;
2339 	}
2340 
2341 	return false;
2342 }
2343 
2344 static bool
2345 csr_is_deauth_disassoc_in_pending_q(struct mac_context *mac_ctx,
2346 				    uint8_t vdev_id,
2347 				    struct qdf_mac_addr peer_macaddr)
2348 {
2349 	tListElem *entry = NULL;
2350 	tSmeCmd *sme_cmd;
2351 
2352 	entry = csr_nonscan_pending_ll_peek_head(mac_ctx, LL_ACCESS_NOLOCK);
2353 	while (entry) {
2354 		sme_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
2355 		if ((sme_cmd->vdev_id == vdev_id) &&
2356 		    csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
2357 			return true;
2358 		entry = csr_nonscan_pending_ll_next(mac_ctx, entry,
2359 						    LL_ACCESS_NOLOCK);
2360 	}
2361 
2362 	return false;
2363 }
2364 
2365 static bool
2366 csr_is_deauth_disassoc_in_active_q(struct mac_context *mac_ctx,
2367 				   uint8_t vdev_id,
2368 				   struct qdf_mac_addr peer_macaddr)
2369 {
2370 	tSmeCmd *sme_cmd;
2371 
2372 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
2373 						WLAN_SER_CMD_FORCE_DEAUTH_STA);
2374 
2375 	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
2376 		return true;
2377 
2378 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
2379 					WLAN_SER_CMD_FORCE_DISASSOC_STA);
2380 
2381 	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
2382 		return true;
2383 
2384 	/*
2385 	 * WLAN_SER_CMD_WM_STATUS_CHANGE is of two type, the handling
2386 	 * should take care of both the types.
2387 	 */
2388 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
2389 						WLAN_SER_CMD_WM_STATUS_CHANGE);
2390 	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
2391 		return true;
2392 
2393 	return false;
2394 }
2395 
2396 /*
2397  * csr_is_deauth_disassoc_already_active() - Function to check if deauth or
2398  *  disassoc is already in progress.
2399  * @mac_ctx: Global MAC context
2400  * @vdev_id: vdev id
2401  * @peer_macaddr: Peer MAC address
2402  *
2403  * Return: True if deauth/disassoc indication can be dropped
2404  *  else false
2405  */
2406 static bool
2407 csr_is_deauth_disassoc_already_active(struct mac_context *mac_ctx,
2408 				      uint8_t vdev_id,
2409 				      struct qdf_mac_addr peer_macaddr)
2410 {
2411 	bool ret = csr_is_deauth_disassoc_in_pending_q(mac_ctx,
2412 						      vdev_id,
2413 						      peer_macaddr);
2414 	if (!ret)
2415 		/**
2416 		 * commands are not found in pending queue, check in active
2417 		 * queue as well
2418 		 */
2419 		ret = csr_is_deauth_disassoc_in_active_q(mac_ctx,
2420 							  vdev_id,
2421 							  peer_macaddr);
2422 
2423 	if (ret)
2424 		sme_debug("Deauth/Disassoc already in progress for "QDF_MAC_ADDR_FMT,
2425 			  QDF_MAC_ADDR_REF(peer_macaddr.bytes));
2426 
2427 	return ret;
2428 }
2429 
2430 /**
2431  * csr_roam_issue_disassociate_sta_cmd() - disassociate a associated station
2432  * @sessionId:     Session Id for Soft AP
2433  * @p_del_sta_params: Pointer to parameters of the station to disassoc
2434  *
2435  * CSR function that HDD calls to delete a associated station
2436  *
2437  * Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS_* on error
2438  */
2439 QDF_STATUS csr_roam_issue_disassociate_sta_cmd(struct mac_context *mac,
2440 					       uint32_t sessionId,
2441 					       struct csr_del_sta_params
2442 					       *p_del_sta_params)
2443 
2444 {
2445 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2446 	tSmeCmd *pCommand;
2447 
2448 	do {
2449 		if (csr_is_deauth_disassoc_already_active(mac, sessionId,
2450 					      p_del_sta_params->peerMacAddr))
2451 			break;
2452 		pCommand = csr_get_command_buffer(mac);
2453 		if (!pCommand) {
2454 			sme_err("fail to get command buffer");
2455 			status = QDF_STATUS_E_RESOURCES;
2456 			break;
2457 		}
2458 		pCommand->command = eSmeCommandRoam;
2459 		pCommand->vdev_id = (uint8_t) sessionId;
2460 		pCommand->u.roamCmd.roamReason = eCsrForcedDisassocSta;
2461 		qdf_mem_copy(pCommand->u.roamCmd.peerMac,
2462 				p_del_sta_params->peerMacAddr.bytes,
2463 				sizeof(pCommand->u.roamCmd.peerMac));
2464 		pCommand->u.roamCmd.reason = p_del_sta_params->reason_code;
2465 
2466 		status = csr_queue_sme_command(mac, pCommand, false);
2467 		if (!QDF_IS_STATUS_SUCCESS(status))
2468 			sme_err("fail to send message status: %d", status);
2469 	} while (0);
2470 
2471 	return status;
2472 }
2473 
2474 /**
2475  * csr_roam_issue_deauthSta() - delete a associated station
2476  * @sessionId:     Session Id for Soft AP
2477  * @pDelStaParams: Pointer to parameters of the station to deauthenticate
2478  *
2479  * CSR function that HDD calls to delete a associated station
2480  *
2481  * Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS_** on error
2482  */
2483 QDF_STATUS csr_roam_issue_deauth_sta_cmd(struct mac_context *mac,
2484 		uint32_t sessionId,
2485 		struct csr_del_sta_params *pDelStaParams)
2486 {
2487 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2488 	tSmeCmd *pCommand;
2489 
2490 	do {
2491 		if (csr_is_deauth_disassoc_already_active(mac, sessionId,
2492 					      pDelStaParams->peerMacAddr))
2493 			break;
2494 		pCommand = csr_get_command_buffer(mac);
2495 		if (!pCommand) {
2496 			sme_err("fail to get command buffer");
2497 			status = QDF_STATUS_E_RESOURCES;
2498 			break;
2499 		}
2500 		pCommand->command = eSmeCommandRoam;
2501 		pCommand->vdev_id = (uint8_t) sessionId;
2502 		pCommand->u.roamCmd.roamReason = eCsrForcedDeauthSta;
2503 		qdf_mem_copy(pCommand->u.roamCmd.peerMac,
2504 			     pDelStaParams->peerMacAddr.bytes,
2505 			     sizeof(tSirMacAddr));
2506 		pCommand->u.roamCmd.reason = pDelStaParams->reason_code;
2507 
2508 		status = csr_queue_sme_command(mac, pCommand, false);
2509 		if (!QDF_IS_STATUS_SUCCESS(status))
2510 			sme_err("fail to send message status: %d", status);
2511 	} while (0);
2512 
2513 	return status;
2514 }
2515 
2516 /**
2517  * csr_get_peer_stats_cb - Peer stats callback
2518  * @ev: stats event
2519  * @cookie: Void pointer to mac contaxt
2520  *
2521  * Return: None
2522  */
2523 static void csr_get_peer_stats_cb(struct stats_event *ev, void *cookie)
2524 {
2525 	struct mac_context *mac = (struct mac_context *)cookie;
2526 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2527 
2528 	if (!mac) {
2529 		sme_err("Invalid mac ctx");
2530 		return;
2531 	}
2532 
2533 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
2534 	if (!mlme_obj) {
2535 		sme_err("NULL mlme psoc object");
2536 		return;
2537 	}
2538 
2539 	qdf_mc_timer_stop(
2540 		&mlme_obj->disconnect_stats_param.disconn_stats_timer);
2541 
2542 	if (!ev->peer_stats) {
2543 		sme_debug("no peer stats");
2544 		goto disconnect_stats_complete;
2545 	}
2546 
2547 	mac->peer_rssi = ev->peer_stats->peer_rssi;
2548 	mac->peer_txrate = ev->peer_stats->tx_rate;
2549 	mac->peer_rxrate = ev->peer_stats->rx_rate;
2550 	if (!ev->peer_extended_stats) {
2551 		sme_debug("no peer extended stats");
2552 		goto disconnect_stats_complete;
2553 	}
2554 	mac->rx_mc_bc_cnt = ev->peer_extended_stats->rx_mc_bc_cnt;
2555 
2556 disconnect_stats_complete:
2557 	sme_debug("peer rssi %d tx_rate %d rx_rate %d rx_mc_bc_cnt %d",
2558 		  mac->peer_rssi, mac->peer_txrate, mac->peer_rxrate,
2559 		  mac->rx_mc_bc_cnt);
2560 	csr_continue_peer_disconnect_after_get_stats(mac);
2561 }
2562 
2563 /**
2564  * csr_get_peer_stats - Get Peer stats
2565  * @mac: MAC contaxt
2566  * @session_id: Current session id
2567  * @peer_mac: Peer mac address
2568  *
2569  * Return: None
2570  */
2571 static void csr_get_peer_stats(struct mac_context *mac, uint32_t session_id,
2572 			       struct qdf_mac_addr peer_mac)
2573 {
2574 	struct wlan_objmgr_vdev *vdev;
2575 	struct request_info info = {0};
2576 	QDF_STATUS status;
2577 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2578 
2579 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
2580 	if (!mlme_obj) {
2581 		sme_err("NULL mlme psoc object");
2582 		return;
2583 	}
2584 	/* Reset is_disconn_stats_completed before error handing. */
2585 	qdf_atomic_set(
2586 		&mlme_obj->disconnect_stats_param.is_disconn_stats_completed,
2587 		0);
2588 
2589 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, session_id,
2590 						    WLAN_LEGACY_SME_ID);
2591 
2592 	if (!vdev) {
2593 		csr_continue_peer_disconnect_after_get_stats(mac);
2594 		return;
2595 	}
2596 
2597 	info.cookie = mac;
2598 	info.u.get_peer_rssi_cb = csr_get_peer_stats_cb;
2599 	info.vdev_id = wlan_vdev_get_id(vdev);
2600 	info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
2601 	qdf_mem_copy(info.peer_mac_addr, &peer_mac, QDF_MAC_ADDR_SIZE);
2602 	sme_debug("peer_mac" QDF_MAC_ADDR_FMT,
2603 		  QDF_MAC_ADDR_REF(peer_mac.bytes));
2604 	mlme_obj->disconnect_stats_param.vdev_id = info.vdev_id;
2605 	status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_PEER_STATS,
2606 						     &info);
2607 	if (QDF_IS_STATUS_ERROR(status)) {
2608 		sme_err("stats req failed: %d", status);
2609 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
2610 		csr_continue_peer_disconnect_after_get_stats(mac);
2611 		return;
2612 	}
2613 
2614 	qdf_mc_timer_start(
2615 		&mlme_obj->disconnect_stats_param.disconn_stats_timer,
2616 		SME_CMD_GET_DISCONNECT_STATS_TIMEOUT);
2617 
2618 	wma_get_rx_retry_cnt(mac, session_id, info.peer_mac_addr);
2619 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
2620 }
2621 
2622 QDF_STATUS csr_roam_process_command(struct mac_context *mac, tSmeCmd *pCommand)
2623 {
2624 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2625 	uint32_t sessionId = pCommand->vdev_id;
2626 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
2627 	struct qdf_mac_addr peer_mac;
2628 
2629 	if (!pSession) {
2630 		sme_err("session %d not found", sessionId);
2631 		return QDF_STATUS_E_FAILURE;
2632 	}
2633 	sme_debug("Roam Reason: %d sessionId: %d",
2634 		pCommand->u.roamCmd.roamReason, sessionId);
2635 
2636 	switch (pCommand->u.roamCmd.roamReason) {
2637 	case eCsrForcedDisassocSta:
2638 	case eCsrForcedDeauthSta:
2639 		csr_roam_state_change(mac, eCSR_ROAMING_STATE_JOINING,
2640 				      sessionId);
2641 		if (pCommand->u.roamCmd.roamReason == eCsrForcedDeauthSta)
2642 			csr_roam_substate_change(mac,
2643 						 eCSR_ROAM_SUBSTATE_DEAUTH_REQ,
2644 						 sessionId);
2645 		else
2646 			csr_roam_substate_change(
2647 						mac,
2648 						eCSR_ROAM_SUBSTATE_DISASSOC_REQ,
2649 						sessionId);
2650 
2651 		qdf_mem_copy(&peer_mac, &pCommand->u.roamCmd.peerMac,
2652 			     QDF_MAC_ADDR_SIZE);
2653 		/*
2654 		 * Get peer stats before peer gets deleted so that these stats
2655 		 * can be given to user space when big data stats are queried.
2656 		 * Once peer stats are retrieved deauth sta will continue
2657 		 */
2658 		csr_get_peer_stats(mac, sessionId, peer_mac);
2659 		break;
2660 	}
2661 	return status;
2662 }
2663 
2664 void csr_reinit_roam_cmd(struct mac_context *mac, tSmeCmd *pCommand)
2665 {
2666 	/* Because u.roamCmd is union and share with scanCmd and StatusChange */
2667 	qdf_mem_zero(&pCommand->u.roamCmd, sizeof(struct roam_cmd));
2668 }
2669 
2670 void csr_reinit_wm_status_change_cmd(struct mac_context *mac,
2671 			tSmeCmd *pCommand)
2672 {
2673 	qdf_mem_zero(&pCommand->u.wmStatusChangeCmd,
2674 			sizeof(struct wmstatus_changecmd));
2675 }
2676 
2677 void csr_roam_complete(struct mac_context *mac_ctx, uint8_t session_id)
2678 {
2679 	tSmeCmd *sme_cmd;
2680 	struct wlan_serialization_command *cmd;
2681 
2682 	cmd = wlan_serialization_peek_head_active_cmd_using_psoc(
2683 				mac_ctx->psoc, false);
2684 	if (!cmd) {
2685 		sme_err("Roam completion called but cmd is not active");
2686 		return;
2687 	}
2688 	sme_cmd = cmd->umac_cmd;
2689 	if (!sme_cmd) {
2690 		sme_err("sme_cmd is NULL");
2691 		return;
2692 	}
2693 	if (eSmeCommandRoam == sme_cmd->command) {
2694 		csr_roam_process_results_default(mac_ctx, sme_cmd);
2695 		csr_release_command(mac_ctx, sme_cmd);
2696 	}
2697 }
2698 
2699 /* Returns whether the current association is a 11r assoc or not */
2700 bool csr_roam_is11r_assoc(struct mac_context *mac, uint8_t sessionId)
2701 {
2702 	struct cm_roam_values_copy config;
2703 
2704 	wlan_cm_roam_cfg_get_value(mac->psoc, sessionId, IS_11R_CONNECTION,
2705 				   &config);
2706 
2707 	return config.bool_value;
2708 }
2709 
2710 void csr_roam_process_results_default(struct mac_context *mac_ctx,
2711 				      tSmeCmd *cmd)
2712 {
2713 	uint32_t session_id = cmd->vdev_id;
2714 	struct csr_roam_session *session;
2715 	struct csr_roam_info *roam_info;
2716 	QDF_STATUS status;
2717 	enum QDF_OPMODE opmode;
2718 
2719 	if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
2720 		sme_err("Invalid session id %d", session_id);
2721 		return;
2722 	}
2723 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, session_id);
2724 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
2725 	if (!roam_info)
2726 		return;
2727 	session = CSR_GET_SESSION(mac_ctx, session_id);
2728 	if (CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac_ctx, session_id)) {
2729 		/*
2730 		 * do not free for the other profiles as we need
2731 		 * to send down stop BSS later
2732 		 */
2733 		csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
2734 		csr_set_default_dot11_mode(mac_ctx);
2735 	}
2736 
2737 	switch (cmd->u.roamCmd.roamReason) {
2738 	case eCsrForcedDisassocSta:
2739 	case eCsrForcedDeauthSta:
2740 		roam_info->rssi = mac_ctx->peer_rssi;
2741 		roam_info->tx_rate = mac_ctx->peer_txrate;
2742 		roam_info->rx_rate = mac_ctx->peer_rxrate;
2743 		roam_info->rx_mc_bc_cnt = mac_ctx->rx_mc_bc_cnt;
2744 		roam_info->rx_retry_cnt = mac_ctx->rx_retry_cnt;
2745 
2746 		csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED,
2747 				      session_id);
2748 		if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
2749 			qdf_mem_copy(roam_info->peerMac.bytes,
2750 				     cmd->u.roamCmd.peerMac,
2751 				     sizeof(tSirMacAddr));
2752 			roam_info->reasonCode = eCSR_ROAM_RESULT_FORCED;
2753 			/* Update the MAC reason code */
2754 			roam_info->disassoc_reason = cmd->u.roamCmd.reason;
2755 			roam_info->status_code = eSIR_SME_SUCCESS;
2756 			status = csr_roam_call_callback(mac_ctx, session_id,
2757 							roam_info,
2758 							eCSR_ROAM_LOSTLINK,
2759 							eCSR_ROAM_RESULT_FORCED);
2760 		}
2761 		break;
2762 	default:
2763 		csr_roam_state_change(mac_ctx,
2764 			eCSR_ROAMING_STATE_IDLE, session_id);
2765 		break;
2766 	}
2767 	qdf_mem_free(roam_info);
2768 }
2769 
2770 /**
2771  * csr_roam_process_start_bss_success() - Process the result for start bss
2772  * @mac_ctx:   Global MAC Context
2773  * @context:   Additional data in context of the cmd
2774  * @vdev_id:   vdev id
2775  *
2776  * Return: None
2777  */
2778 static void csr_roam_process_start_bss_success(struct mac_context *mac_ctx,
2779 					       struct csr_roam_info *roam_info,
2780 					       void *context, uint8_t vdev_id)
2781 {
2782 	struct csr_roam_session *session;
2783 	struct start_bss_rsp *start_bss_rsp = NULL;
2784 	eRoamCmdStatus roam_status = eCSR_ROAM_INFRA_IND;
2785 	eCsrRoamResult roam_result = eCSR_ROAM_RESULT_INFRA_STARTED;
2786 	tSirMacAddr bcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2787 	QDF_STATUS status;
2788 	enum QDF_OPMODE opmode;
2789 	uint8_t wmm_mode = 0, value = 0;
2790 
2791 	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
2792 		sme_err("Invalid session id %d", vdev_id);
2793 		return;
2794 	}
2795 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
2796 
2797 	sme_debug("Start BSS success");
2798 	start_bss_rsp = (struct start_bss_rsp *)context;
2799 
2800 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
2801 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE)
2802 		session->connectState =
2803 				eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED;
2804 	else if (opmode == QDF_NDI_MODE)
2805 		session->connectState = eCSR_CONNECT_STATE_TYPE_NDI_STARTED;
2806 	else
2807 		session->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED;
2808 
2809 	if (opmode == QDF_NDI_MODE) {
2810 		status = ucfg_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode);
2811 		if (!QDF_IS_STATUS_SUCCESS(status))
2812 			return;
2813 		if (wmm_mode == WMM_USER_MODE_NO_QOS) {
2814 			session->modifyProfileFields.uapsd_mask = 0;
2815 		} else {
2816 			status =
2817 			   ucfg_mlme_get_wmm_uapsd_mask(mac_ctx->psoc, &value);
2818 			if (!QDF_IS_STATUS_SUCCESS(status))
2819 				return;
2820 			session->modifyProfileFields.uapsd_mask = value;
2821 		}
2822 	}
2823 	csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, vdev_id);
2824 	csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
2825 	wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, vdev_id, &roam_info->bssid);
2826 
2827 	/* We are done with the IEs so free it */
2828 	/*
2829 	 * Only set context for non-WDS_STA. We don't even need it for
2830 	 * WDS_AP. But since the encryption.
2831 	 * is WPA2-PSK so it won't matter.
2832 	 */
2833 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
2834 		if (wlan_is_open_wep_cipher(mac_ctx->pdev, vdev_id)) {
2835 			csr_issue_set_context_req_helper(mac_ctx, vdev_id,
2836 							 &bcast_mac, false,
2837 							 false, 0);
2838 		}
2839 	}
2840 
2841 	/*
2842 	 * Only tell upper layer is we start the BSS because Vista doesn't like
2843 	 * multiple connection indications. If we don't start the BSS ourself,
2844 	 * handler of eSIR_SME_JOINED_NEW_BSS will trigger the connection start
2845 	 * indication in Vista
2846 	 */
2847 	roam_info->staId = (uint8_t)start_bss_rsp->staId;
2848 	if (opmode == QDF_NDI_MODE) {
2849 		csr_roam_update_ndp_return_params(mac_ctx,
2850 						  CSR_SAP_START_BSS_SUCCESS,
2851 						   &roam_status,
2852 						   &roam_result,
2853 						    roam_info);
2854 	}
2855 	/*
2856 	 * Only tell upper layer is we start the BSS because Vista
2857 	 * doesn't like multiple connection indications. If we don't
2858 	 * start the BSS ourself, handler of eSIR_SME_JOINED_NEW_BSS
2859 	 * will trigger the connection start indication in Vista
2860 	 */
2861 	roam_info->status_code = eSIR_SME_SUCCESS;
2862 	csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
2863 			       roam_status, roam_result);
2864 }
2865 
2866 static void csr_flush_pending_start_bss_cmd(struct mac_context *mac_ctx,
2867 					     uint8_t vdev_id)
2868 {
2869 	struct wlan_serialization_queued_cmd_info cmd = {0};
2870 	struct wlan_objmgr_vdev *vdev;
2871 
2872 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
2873 						    WLAN_LEGACY_SME_ID);
2874 	if (!vdev) {
2875 		sme_err("vdev not found for id %d", vdev_id);
2876 		return;
2877 	}
2878 
2879 	/* Flush any pending vdev start command */
2880 	cmd.vdev = vdev;
2881 	cmd.cmd_type = WLAN_SER_CMD_VDEV_START_BSS;
2882 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
2883 	cmd.requestor = WLAN_UMAC_COMP_MLME;
2884 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
2885 
2886 	wlan_serialization_cancel_request(&cmd);
2887 
2888 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
2889 }
2890 
2891 bool cm_csr_is_ss_wait_for_key(uint8_t vdev_id)
2892 {
2893 	struct mac_context *mac;
2894 	bool is_wait_for_key = false;
2895 
2896 	mac = sme_get_mac_context();
2897 	if (!mac) {
2898 		sme_err("mac_ctx is NULL");
2899 		return is_wait_for_key;
2900 	}
2901 
2902 	spin_lock(&mac->roam.roam_state_lock);
2903 	if (CSR_IS_WAIT_FOR_KEY(mac, vdev_id))
2904 		is_wait_for_key = true;
2905 	spin_unlock(&mac->roam.roam_state_lock);
2906 
2907 	return is_wait_for_key;
2908 }
2909 
2910 void cm_csr_set_ss_wait_for_key(uint8_t vdev_id)
2911 {
2912 	struct mac_context *mac;
2913 
2914 	mac = sme_get_mac_context();
2915 	if (!mac) {
2916 		sme_err("mac_ctx is NULL");
2917 		return;
2918 	}
2919 
2920 	csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY,
2921 				 vdev_id);
2922 }
2923 
2924 void cm_csr_set_joining(uint8_t vdev_id)
2925 {
2926 	struct mac_context *mac;
2927 
2928 	mac = sme_get_mac_context();
2929 	if (!mac) {
2930 		sme_err("mac_ctx is NULL");
2931 		return;
2932 	}
2933 
2934 	csr_roam_state_change(mac, eCSR_ROAMING_STATE_JOINING, vdev_id);
2935 }
2936 
2937 void cm_csr_set_joined(uint8_t vdev_id)
2938 {
2939 	struct mac_context *mac;
2940 
2941 	mac = sme_get_mac_context();
2942 	if (!mac) {
2943 		sme_err("mac_ctx is NULL");
2944 		return;
2945 	}
2946 
2947 	csr_roam_state_change(mac, eCSR_ROAMING_STATE_JOINED, vdev_id);
2948 }
2949 
2950 void cm_csr_set_idle(uint8_t vdev_id)
2951 {
2952 	struct mac_context *mac;
2953 
2954 	mac = sme_get_mac_context();
2955 	if (!mac) {
2956 		sme_err("mac_ctx is NULL");
2957 		return;
2958 	}
2959 
2960 	csr_roam_state_change(mac, eCSR_ROAMING_STATE_IDLE, vdev_id);
2961 }
2962 
2963 void cm_csr_set_ss_none(uint8_t vdev_id)
2964 {
2965 	struct mac_context *mac;
2966 
2967 	mac = sme_get_mac_context();
2968 	if (!mac) {
2969 		sme_err("mac_ctx is NULL");
2970 		return;
2971 	}
2972 
2973 	csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_NONE,
2974 				 vdev_id);
2975 }
2976 
2977 QDF_STATUS csr_roam_ndi_stop(struct mac_context *mac_ctx, uint8_t vdev_id)
2978 {
2979 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
2980 	bool is_vdev_up;
2981 	bool is_start_bss_in_active_q = false;
2982 
2983 	csr_flush_pending_start_bss_cmd(mac_ctx, vdev_id);
2984 
2985 	is_vdev_up = wlan_is_vdev_id_up(mac_ctx->pdev, vdev_id);
2986 	if (wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
2987 					      WLAN_SER_CMD_VDEV_START_BSS))
2988 		is_start_bss_in_active_q = true;
2989 
2990 	sme_debug("vdev_id: %d is_vdev_up %d is_start_bss_in_active_q %d",
2991 		  vdev_id, is_vdev_up, is_start_bss_in_active_q);
2992 
2993 	if (is_vdev_up || is_start_bss_in_active_q)
2994 		status = csr_roam_issue_stop_bss_cmd(mac_ctx, vdev_id,
2995 						     eCSR_BSS_TYPE_NDI);
2996 	return status;
2997 }
2998 
2999 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
3000 static void csr_fill_single_pmk(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
3001 				struct bss_description *bss_desc)
3002 {
3003 	struct cm_roam_values_copy src_cfg = {};
3004 
3005 	src_cfg.bool_value = bss_desc->is_single_pmk;
3006 	wlan_cm_roam_cfg_set_value(psoc, vdev_id,
3007 				   IS_SINGLE_PMK, &src_cfg);
3008 }
3009 #else
3010 static inline void
3011 csr_fill_single_pmk(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
3012 		    struct bss_description *bss_desc)
3013 {}
3014 #endif
3015 
3016 void csr_roam_roaming_state_stop_bss_rsp_processor(struct mac_context *mac,
3017 						   void *msg)
3018 {
3019 	struct stop_bss_rsp *stop_bss_rsp = (struct stop_bss_rsp *)msg;
3020 	uint8_t vdev_id = stop_bss_rsp->vdev_id;
3021 	enum csr_sap_response_type result_code = CSR_SAP_STOP_BSS_SUCCESS;
3022 
3023 	sme_debug("Received stop bss rsp on vdev: %d", vdev_id);
3024 	mac->roam.roamSession[vdev_id].connectState =
3025 					eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
3026 	if (CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac, vdev_id)) {
3027 		if (stop_bss_rsp->status_code != eSIR_SME_SUCCESS)
3028 			result_code = CSR_SAP_STOP_BSS_FAILURE;
3029 		csr_process_sap_response(mac, result_code, NULL, vdev_id);
3030 	}
3031 }
3032 
3033 static
3034 void csr_roam_roaming_state_disassoc_rsp_processor(struct mac_context *mac,
3035 						   struct disassoc_rsp *rsp)
3036 {
3037 	struct csr_roam_session *pSession;
3038 
3039 	sme_debug("Received disassoc response for vdev : %d status : %d",
3040 		  rsp->sessionId, rsp->status_code);
3041 
3042 	pSession = CSR_GET_SESSION(mac, rsp->sessionId);
3043 	if (!pSession) {
3044 		sme_err("session not found");
3045 		return;
3046 	}
3047 
3048 	csr_roam_complete(mac, rsp->sessionId);
3049 }
3050 
3051 static void csr_roam_roaming_state_deauth_rsp_processor(struct mac_context *mac,
3052 						struct deauth_rsp *rsp)
3053 {
3054 	csr_roam_complete(mac, rsp->sessionId);
3055 }
3056 
3057 void
3058 csr_roam_roaming_state_start_bss_rsp_processor(struct mac_context *mac,
3059 					       void *msg)
3060 {
3061 	enum csr_sap_response_type result;
3062 	struct start_bss_rsp *start_bss_rsp = (struct start_bss_rsp *)msg;
3063 
3064 	if (!CSR_IS_ROAM_SUBSTATE_START_BSS_REQ(mac, start_bss_rsp->vdev_id)) {
3065 		sme_err(" Start bss received in invalid state");
3066 		return;
3067 	}
3068 
3069 	sme_debug("Start Bss response status : %d",
3070 		  start_bss_rsp->status_code);
3071 	if (start_bss_rsp->status_code == eSIR_SME_SUCCESS)
3072 		result = CSR_SAP_START_BSS_SUCCESS;
3073 	else
3074 		result = CSR_SAP_START_BSS_FAILURE;
3075 
3076 	csr_process_sap_response(mac, result, start_bss_rsp,
3077 				 start_bss_rsp->vdev_id);
3078 }
3079 
3080 
3081 /**
3082  * csr_roam_send_disconnect_done_indication() - Send disconnect ind to HDD.
3083  *
3084  * @mac_ctx: mac global context
3085  * @msg_ptr: incoming message
3086  *
3087  * This function gives final disconnect event to HDD after all cleanup in
3088  * lower layers is done.
3089  *
3090  * Return: None
3091  */
3092 static void
3093 csr_roam_send_disconnect_done_indication(struct mac_context *mac_ctx,
3094 					 tSirSmeRsp *msg_ptr)
3095 {
3096 	struct sir_sme_discon_done_ind *discon_ind =
3097 				(struct sir_sme_discon_done_ind *)(msg_ptr);
3098 	struct csr_roam_info *roam_info;
3099 	uint8_t vdev_id;
3100 
3101 	vdev_id = discon_ind->session_id;
3102 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
3103 	if (!roam_info)
3104 		return;
3105 
3106 	sme_debug("DISCONNECT_DONE_IND RC:%d", discon_ind->reason_code);
3107 
3108 	if (CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
3109 		roam_info->reasonCode = discon_ind->reason_code;
3110 		roam_info->status_code = eSIR_SME_STA_NOT_ASSOCIATED;
3111 		qdf_mem_copy(roam_info->peerMac.bytes, discon_ind->peer_mac,
3112 			     ETH_ALEN);
3113 
3114 		roam_info->rssi = mac_ctx->peer_rssi;
3115 		roam_info->tx_rate = mac_ctx->peer_txrate;
3116 		roam_info->rx_rate = mac_ctx->peer_rxrate;
3117 		roam_info->disassoc_reason = discon_ind->reason_code;
3118 		roam_info->rx_mc_bc_cnt = mac_ctx->rx_mc_bc_cnt;
3119 		roam_info->rx_retry_cnt = mac_ctx->rx_retry_cnt;
3120 		csr_roam_call_callback(mac_ctx, vdev_id,
3121 				       roam_info, eCSR_ROAM_LOSTLINK,
3122 				       eCSR_ROAM_RESULT_DISASSOC_IND);
3123 	} else {
3124 		sme_err("Inactive vdev_id %d", vdev_id);
3125 	}
3126 
3127 	/*
3128 	 * Release WM status change command as eWNI_SME_DISCONNECT_DONE_IND
3129 	 * has been sent to HDD and there is nothing else left to do.
3130 	 */
3131 	csr_roam_wm_status_change_complete(mac_ctx, vdev_id);
3132 	qdf_mem_free(roam_info);
3133 }
3134 
3135 /**
3136  * csr_roaming_state_msg_processor() - process roaming messages
3137  * @mac:       mac global context
3138  * @msg_buf:    message buffer
3139  *
3140  * We need to be careful on whether to cast msg_buf (pSmeRsp) to other type of
3141  * structures. It depends on how the message is constructed. If the message is
3142  * sent by lim_send_sme_rsp, the msg_buf is only a generic response and can only
3143  * be used as pointer to tSirSmeRsp. For the messages where sender allocates
3144  * memory for specific structures, then it can be cast accordingly.
3145  *
3146  * Return: status of operation
3147  */
3148 void csr_roaming_state_msg_processor(struct mac_context *mac, void *msg_buf)
3149 {
3150 	tSirSmeRsp *pSmeRsp;
3151 
3152 	pSmeRsp = (tSirSmeRsp *)msg_buf;
3153 
3154 	switch (pSmeRsp->messageType) {
3155 	case eWNI_SME_DISASSOC_RSP:
3156 		/* or the Disassociate response message... */
3157 		if (CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ(mac, pSmeRsp->vdev_id)) {
3158 			sme_debug("eWNI_SME_DISASSOC_RSP subState = %s",
3159 				  mac_trace_getcsr_roam_sub_state(
3160 				  mac->roam.curSubState[pSmeRsp->vdev_id]));
3161 			csr_roam_roaming_state_disassoc_rsp_processor(mac,
3162 						(struct disassoc_rsp *) pSmeRsp);
3163 		}
3164 		break;
3165 	case eWNI_SME_DEAUTH_RSP:
3166 		/* or the Deauthentication response message... */
3167 		if (CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ(mac, pSmeRsp->vdev_id))
3168 			csr_roam_roaming_state_deauth_rsp_processor(mac,
3169 						(struct deauth_rsp *) pSmeRsp);
3170 		break;
3171 	/* In case CSR issues STOP_BSS, we need to tell HDD about peer departed
3172 	 * because PE is removing them
3173 	 */
3174 	case eWNI_SME_TRIGGER_SAE:
3175 		sme_debug("Invoke SAE callback");
3176 		csr_sae_callback(mac, pSmeRsp);
3177 		break;
3178 
3179 	case eWNI_SME_SETCONTEXT_RSP:
3180 		csr_roam_check_for_link_status_change(mac, pSmeRsp);
3181 		break;
3182 
3183 	case eWNI_SME_DISCONNECT_DONE_IND:
3184 		csr_roam_send_disconnect_done_indication(mac, pSmeRsp);
3185 		break;
3186 
3187 	case eWNI_SME_UPPER_LAYER_ASSOC_CNF:
3188 		csr_roam_joined_state_msg_processor(mac, pSmeRsp);
3189 		break;
3190 	default:
3191 		sme_debug("Unexpected message type: %d[0x%X] received in substate %s",
3192 			pSmeRsp->messageType, pSmeRsp->messageType,
3193 			mac_trace_getcsr_roam_sub_state(
3194 				mac->roam.curSubState[pSmeRsp->vdev_id]));
3195 		/* If we are connected, check the link status change */
3196 		if (!csr_is_conn_state_disconnected(mac, pSmeRsp->vdev_id))
3197 			csr_roam_check_for_link_status_change(mac, pSmeRsp);
3198 		break;
3199 	}
3200 }
3201 
3202 #ifdef WLAN_FEATURE_11BE_MLO
3203 static void
3204 csr_roam_assoc_cnf_mld_copy(struct csr_roam_info *roam_info,
3205 			    tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf,
3206 			    uint32_t num_bytes)
3207 {
3208 	qdf_mem_copy(roam_info->peer_mld.bytes,
3209 		     pUpperLayerAssocCnf->peer_mld_addr,
3210 		     num_bytes);
3211 }
3212 #else /* WLAN_FEATURE_11BE_MLO */
3213 static inline void
3214 csr_roam_assoc_cnf_mld_copy(struct csr_roam_info *roam_info,
3215 			    tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf,
3216 			    uint32_t num_bytes)
3217 {
3218 }
3219 #endif /* WLAN_FEATURE_11BE_MLO */
3220 
3221 void csr_roam_joined_state_msg_processor(struct mac_context *mac, void *msg_buf)
3222 {
3223 	tSirSmeRsp *pSirMsg = (tSirSmeRsp *)msg_buf;
3224 
3225 	switch (pSirMsg->messageType) {
3226 	case eWNI_SME_UPPER_LAYER_ASSOC_CNF:
3227 	{
3228 		struct csr_roam_session *pSession;
3229 		tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf;
3230 		struct csr_roam_info *roam_info;
3231 		uint32_t sessionId;
3232 		QDF_STATUS status;
3233 		enum QDF_OPMODE opmode;
3234 
3235 		sme_debug("ASSOCIATION confirmation can be given to upper layer ");
3236 		pUpperLayerAssocCnf =
3237 			(tSirSmeAssocIndToUpperLayerCnf *)msg_buf;
3238 		status = csr_roam_get_session_id_from_bssid(mac,
3239 							(struct qdf_mac_addr *)
3240 							   pUpperLayerAssocCnf->
3241 							   bssId, &sessionId);
3242 		pSession = CSR_GET_SESSION(mac, sessionId);
3243 
3244 		if (!pSession) {
3245 			sme_err("session %d not found", sessionId);
3246 			if (pUpperLayerAssocCnf->ies)
3247 				qdf_mem_free(pUpperLayerAssocCnf->ies);
3248 			return;
3249 		}
3250 
3251 		roam_info = qdf_mem_malloc(sizeof(*roam_info));
3252 		if (!roam_info) {
3253 			if (pUpperLayerAssocCnf->ies)
3254 				qdf_mem_free(pUpperLayerAssocCnf->ies);
3255 			return;
3256 		}
3257 		opmode = wlan_get_opmode_from_vdev_id(mac->pdev, sessionId);
3258 		/* send the status code as Success */
3259 		roam_info->status_code = eSIR_SME_SUCCESS;
3260 		roam_info->staId = (uint8_t) pUpperLayerAssocCnf->aid;
3261 		roam_info->rsnIELen =
3262 			(uint8_t) pUpperLayerAssocCnf->rsnIE.length;
3263 		roam_info->prsnIE =
3264 			pUpperLayerAssocCnf->rsnIE.rsnIEdata;
3265 #ifdef FEATURE_WLAN_WAPI
3266 		roam_info->wapiIELen =
3267 			(uint8_t) pUpperLayerAssocCnf->wapiIE.length;
3268 		roam_info->pwapiIE =
3269 			pUpperLayerAssocCnf->wapiIE.wapiIEdata;
3270 #endif
3271 		roam_info->addIELen =
3272 			(uint8_t) pUpperLayerAssocCnf->addIE.length;
3273 		roam_info->paddIE =
3274 			pUpperLayerAssocCnf->addIE.addIEdata;
3275 		qdf_mem_copy(roam_info->peerMac.bytes,
3276 			     pUpperLayerAssocCnf->peerMacAddr,
3277 			     sizeof(tSirMacAddr));
3278 		csr_roam_assoc_cnf_mld_copy(roam_info,
3279 					    pUpperLayerAssocCnf,
3280 					    sizeof(tSirMacAddr));
3281 		qdf_mem_copy(&roam_info->bssid,
3282 			     pUpperLayerAssocCnf->bssId,
3283 			     sizeof(struct qdf_mac_addr));
3284 		roam_info->wmmEnabledSta =
3285 			pUpperLayerAssocCnf->wmmEnabledSta;
3286 		roam_info->timingMeasCap =
3287 			pUpperLayerAssocCnf->timingMeasCap;
3288 		qdf_mem_copy(&roam_info->chan_info,
3289 			     &pUpperLayerAssocCnf->chan_info,
3290 			     sizeof(struct oem_channel_info));
3291 
3292 		roam_info->ampdu = pUpperLayerAssocCnf->ampdu;
3293 		roam_info->sgi_enable = pUpperLayerAssocCnf->sgi_enable;
3294 		roam_info->tx_stbc = pUpperLayerAssocCnf->tx_stbc;
3295 		roam_info->rx_stbc = pUpperLayerAssocCnf->rx_stbc;
3296 		roam_info->ch_width = pUpperLayerAssocCnf->ch_width;
3297 		roam_info->mode = pUpperLayerAssocCnf->mode;
3298 		roam_info->max_supp_idx = pUpperLayerAssocCnf->max_supp_idx;
3299 		roam_info->max_ext_idx = pUpperLayerAssocCnf->max_ext_idx;
3300 		roam_info->max_mcs_idx = pUpperLayerAssocCnf->max_mcs_idx;
3301 		roam_info->max_real_mcs_idx =
3302 					pUpperLayerAssocCnf->max_real_mcs_idx;
3303 		roam_info->rx_mcs_map = pUpperLayerAssocCnf->rx_mcs_map;
3304 		roam_info->tx_mcs_map = pUpperLayerAssocCnf->tx_mcs_map;
3305 		roam_info->ecsa_capable = pUpperLayerAssocCnf->ecsa_capable;
3306 		roam_info->ext_cap = pUpperLayerAssocCnf->ext_cap;
3307 		roam_info->supported_band =
3308 					pUpperLayerAssocCnf->supported_band;
3309 		if (pUpperLayerAssocCnf->ht_caps.present)
3310 			roam_info->ht_caps = pUpperLayerAssocCnf->ht_caps;
3311 		if (pUpperLayerAssocCnf->vht_caps.present)
3312 			roam_info->vht_caps = pUpperLayerAssocCnf->vht_caps;
3313 		roam_info->capability_info =
3314 					pUpperLayerAssocCnf->capability_info;
3315 		roam_info->he_caps_present =
3316 					pUpperLayerAssocCnf->he_caps_present;
3317 		roam_info->eht_caps_present =
3318 			pUpperLayerAssocCnf->eht_caps_present;
3319 		if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
3320 			if (pUpperLayerAssocCnf->ies_len > 0) {
3321 				roam_info->assocReqLength =
3322 						pUpperLayerAssocCnf->ies_len;
3323 				roam_info->assocReqPtr =
3324 						pUpperLayerAssocCnf->ies;
3325 			}
3326 
3327 			mac->roam.roamSession[sessionId].connectState =
3328 				eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED;
3329 			roam_info->fReassocReq =
3330 				pUpperLayerAssocCnf->reassocReq;
3331 			status = csr_roam_call_callback(mac, sessionId,
3332 						       roam_info,
3333 						       eCSR_ROAM_INFRA_IND,
3334 					eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF);
3335 		}
3336 		if (pUpperLayerAssocCnf->ies)
3337 			qdf_mem_free(pUpperLayerAssocCnf->ies);
3338 		qdf_mem_free(roam_info);
3339 	}
3340 	break;
3341 	default:
3342 		csr_roam_check_for_link_status_change(mac, pSirMsg);
3343 		break;
3344 	}
3345 }
3346 
3347 /**
3348  * csr_update_wep_key_peer_macaddr() - Update wep key peer mac addr
3349  * @vdev: vdev object
3350  * @crypto_key: crypto key info
3351  * @unicast: uncast or broadcast
3352  * @mac_addr: peer mac address
3353  *
3354  * Update peer mac address to key context before set wep key to target.
3355  *
3356  * Return void
3357  */
3358 static void
3359 csr_update_wep_key_peer_macaddr(struct wlan_objmgr_vdev *vdev,
3360 				struct wlan_crypto_key *crypto_key,
3361 				bool unicast,
3362 				struct qdf_mac_addr *mac_addr)
3363 {
3364 	if (!crypto_key || !vdev) {
3365 		sme_err("vdev or crytpo_key null");
3366 		return;
3367 	}
3368 
3369 	if (unicast) {
3370 		qdf_mem_copy(&crypto_key->macaddr, mac_addr,
3371 			     QDF_MAC_ADDR_SIZE);
3372 	} else {
3373 		if (vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE ||
3374 		    vdev->vdev_mlme.vdev_opmode == QDF_P2P_CLIENT_MODE)
3375 			qdf_mem_copy(&crypto_key->macaddr, mac_addr,
3376 				     QDF_MAC_ADDR_SIZE);
3377 		else
3378 			qdf_mem_copy(&crypto_key->macaddr,
3379 				     vdev->vdev_mlme.macaddr,
3380 				     QDF_MAC_ADDR_SIZE);
3381 	}
3382 }
3383 
3384 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3385 static void
3386 csr_roam_diag_set_ctx_rsp(struct mac_context *mac_ctx,
3387 			  struct csr_roam_session *session,
3388 			  struct set_context_rsp *pRsp)
3389 {
3390 	WLAN_HOST_DIAG_EVENT_DEF(setKeyEvent,
3391 				 host_event_wlan_security_payload_type);
3392 	struct wlan_objmgr_vdev *vdev;
3393 
3394 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev,
3395 						    session->vdev_id,
3396 						    WLAN_LEGACY_SME_ID);
3397 	if (!vdev)
3398 		return;
3399 	if (cm_is_open_mode(vdev)) {
3400 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
3401 		return;
3402 	}
3403 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
3404 
3405 	qdf_mem_zero(&setKeyEvent,
3406 		     sizeof(host_event_wlan_security_payload_type));
3407 	if (qdf_is_macaddr_group(&pRsp->peer_macaddr))
3408 		setKeyEvent.eventId =
3409 			WLAN_SECURITY_EVENT_SET_BCAST_RSP;
3410 	else
3411 		setKeyEvent.eventId =
3412 			WLAN_SECURITY_EVENT_SET_UNICAST_RSP;
3413 	cm_diag_get_auth_enc_type_vdev_id(mac_ctx->psoc,
3414 					  &setKeyEvent.authMode,
3415 					  &setKeyEvent.encryptionModeUnicast,
3416 					  &setKeyEvent.encryptionModeMulticast,
3417 					  session->vdev_id);
3418 	wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, session->vdev_id,
3419 				    (struct qdf_mac_addr *)&setKeyEvent.bssid);
3420 	if (eSIR_SME_SUCCESS != pRsp->status_code)
3421 		setKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE;
3422 	WLAN_HOST_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY);
3423 }
3424 #else /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3425 static void
3426 csr_roam_diag_set_ctx_rsp(struct mac_context *mac_ctx,
3427 			  struct csr_roam_session *session,
3428 			  struct set_context_rsp *pRsp)
3429 {
3430 }
3431 #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3432 
3433 #ifdef WLAN_FEATURE_11BE_MLO
3434 static QDF_STATUS
3435 csr_roam_send_rso_enable(struct mac_context *mac_ctx, uint8_t vdev_id)
3436 {
3437 	struct wlan_objmgr_vdev *vdev = NULL;
3438 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
3439 
3440 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
3441 						    vdev_id,
3442 						    WLAN_MLME_OBJMGR_ID);
3443 	if (!vdev) {
3444 		sme_err("vdev object is NULL for vdev %d", vdev_id);
3445 		return QDF_STATUS_E_FAILURE;
3446 	}
3447 
3448 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
3449 	    mlo_check_if_all_links_up(vdev)) {
3450 		assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev);
3451 		if (!assoc_vdev) {
3452 			sme_err("Assoc vdev is null");
3453 			wlan_objmgr_vdev_release_ref(vdev,
3454 						     WLAN_MLME_OBJMGR_ID);
3455 			return QDF_STATUS_E_FAILURE;
3456 		}
3457 		cm_roam_start_init_on_connect(mac_ctx->pdev,
3458 					      wlan_vdev_get_id(assoc_vdev));
3459 	} else if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
3460 		cm_roam_start_init_on_connect(mac_ctx->pdev, vdev_id);
3461 	}
3462 	wlan_objmgr_vdev_release_ref(vdev,
3463 				     WLAN_MLME_OBJMGR_ID);
3464 	return QDF_STATUS_SUCCESS;
3465 }
3466 #else
3467 static QDF_STATUS
3468 csr_roam_send_rso_enable(struct mac_context *mac_ctx, uint8_t vdev_id)
3469 {
3470 	cm_roam_start_init_on_connect(mac_ctx->pdev, vdev_id);
3471 	return QDF_STATUS_SUCCESS;
3472 }
3473 #endif
3474 
3475 static void
3476 csr_roam_chk_lnk_set_ctx_rsp(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
3477 {
3478 	struct csr_roam_session *session;
3479 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
3480 	QDF_STATUS status;
3481 	qdf_freq_t chan_freq;
3482 	struct csr_roam_info *roam_info;
3483 	eCsrRoamResult result = eCSR_ROAM_RESULT_NONE;
3484 	struct set_context_rsp *pRsp = (struct set_context_rsp *)msg_ptr;
3485 	struct qdf_mac_addr connected_bssid;
3486 
3487 	if (!pRsp) {
3488 		sme_err("set key response is NULL");
3489 		return;
3490 	}
3491 
3492 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
3493 	if (!roam_info)
3494 		return;
3495 	sessionId = pRsp->sessionId;
3496 	session = CSR_GET_SESSION(mac_ctx, sessionId);
3497 	if (!session) {
3498 		sme_err("session %d not found", sessionId);
3499 		qdf_mem_free(roam_info);
3500 		return;
3501 	}
3502 
3503 	csr_roam_diag_set_ctx_rsp(mac_ctx, session, pRsp);
3504 	chan_freq = wlan_get_operation_chan_freq_vdev_id(mac_ctx->pdev,
3505 							 sessionId);
3506 	wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, sessionId,
3507 				    &connected_bssid);
3508 	sme_debug("vdev %d, Status %d, peer_macaddr "QDF_MAC_ADDR_FMT " obss offload %d freq %d opmode %d",
3509 		  pRsp->sessionId, pRsp->status_code,
3510 		  QDF_MAC_ADDR_REF(pRsp->peer_macaddr.bytes),
3511 		  mac_ctx->obss_scan_offload, chan_freq,
3512 		  wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId));
3513 
3514 	if (CSR_IS_WAIT_FOR_KEY(mac_ctx, sessionId)) {
3515 		/* We are done with authentication, whethere succeed or not */
3516 		csr_roam_substate_change(mac_ctx, eCSR_ROAM_SUBSTATE_NONE,
3517 					 sessionId);
3518 		cm_stop_wait_for_key_timer(mac_ctx->psoc, sessionId);
3519 		if (QDF_IS_STATUS_ERROR(csr_roam_send_rso_enable(mac_ctx,
3520 								 sessionId))) {
3521 			qdf_mem_free(roam_info);
3522 			return;
3523 		}
3524 	}
3525 	if (eSIR_SME_SUCCESS == pRsp->status_code) {
3526 		qdf_copy_macaddr(&roam_info->peerMac, &pRsp->peer_macaddr);
3527 		/* Make sure we install the GTK before indicating to HDD as
3528 		 * authenticated. This is to prevent broadcast packets go out
3529 		 * after PTK and before GTK.
3530 		 */
3531 		if (qdf_is_macaddr_broadcast(&pRsp->peer_macaddr)) {
3532 			/*
3533 			 * OBSS SCAN Indication will be sent to Firmware
3534 			 * to start OBSS Scan
3535 			 */
3536 			if (mac_ctx->obss_scan_offload &&
3537 			    wlan_reg_is_24ghz_ch_freq(chan_freq) &&
3538 			    cm_is_vdevid_connected(mac_ctx->pdev, sessionId)) {
3539 				struct sme_obss_ht40_scanind_msg *msg;
3540 
3541 				msg = qdf_mem_malloc(sizeof(
3542 					struct sme_obss_ht40_scanind_msg));
3543 				if (!msg) {
3544 					qdf_mem_free(roam_info);
3545 					return;
3546 				}
3547 
3548 				msg->msg_type = eWNI_SME_HT40_OBSS_SCAN_IND;
3549 				msg->length =
3550 				      sizeof(struct sme_obss_ht40_scanind_msg);
3551 				qdf_copy_macaddr(&msg->mac_addr,
3552 					&connected_bssid);
3553 				status = umac_send_mb_message_to_mac(msg);
3554 			}
3555 			result = eCSR_ROAM_RESULT_AUTHENTICATED;
3556 		} else {
3557 			result = eCSR_ROAM_RESULT_NONE;
3558 		}
3559 	} else {
3560 		result = eCSR_ROAM_RESULT_FAILURE;
3561 		sme_err(
3562 			"CSR: setkey command failed(err=%d) PeerMac "
3563 			QDF_MAC_ADDR_FMT,
3564 			pRsp->status_code,
3565 			QDF_MAC_ADDR_REF(pRsp->peer_macaddr.bytes));
3566 	}
3567 	csr_roam_call_callback(mac_ctx, sessionId, roam_info,
3568 			       eCSR_ROAM_SET_KEY_COMPLETE, result);
3569 	/* Indicate SME_QOS that the SET_KEY is completed, so that SME_QOS
3570 	 * can go ahead and initiate the TSPEC if any are pending
3571 	 */
3572 	sme_qos_csr_event_ind(mac_ctx, (uint8_t)sessionId,
3573 			      SME_QOS_CSR_SET_KEY_SUCCESS_IND, NULL);
3574 #ifdef FEATURE_WLAN_ESE
3575 	/* Send Adjacent AP repot to new AP. */
3576 	if (result == eCSR_ROAM_RESULT_AUTHENTICATED &&
3577 	    session->isPrevApInfoValid &&
3578 	    wlan_cm_get_ese_assoc(mac_ctx->pdev, sessionId)) {
3579 		csr_send_ese_adjacent_ap_rep_ind(mac_ctx, session);
3580 		session->isPrevApInfoValid = false;
3581 	}
3582 #endif
3583 	qdf_mem_free(roam_info);
3584 }
3585 
3586 static QDF_STATUS csr_roam_issue_set_context_req(struct mac_context *mac_ctx,
3587 						 uint32_t session_id,
3588 						 bool add_key, bool unicast,
3589 						 uint8_t key_idx,
3590 						 struct qdf_mac_addr *mac_addr)
3591 {
3592 	enum wlan_crypto_cipher_type cipher;
3593 	struct wlan_crypto_key *crypto_key;
3594 	uint8_t wep_key_idx = 0;
3595 	struct wlan_objmgr_vdev *vdev;
3596 
3597 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, session_id,
3598 						    WLAN_LEGACY_MAC_ID);
3599 	if (!vdev) {
3600 		sme_err("VDEV object not found for session_id %d", session_id);
3601 		return QDF_STATUS_E_INVAL;
3602 	}
3603 	cipher = wlan_crypto_get_cipher(vdev, unicast, key_idx);
3604 	if (IS_WEP_CIPHER(cipher)) {
3605 		wep_key_idx = wlan_crypto_get_default_key_idx(vdev, !unicast);
3606 		crypto_key = wlan_crypto_get_key(vdev, wep_key_idx);
3607 		csr_update_wep_key_peer_macaddr(vdev, crypto_key, unicast,
3608 						mac_addr);
3609 	} else {
3610 		crypto_key = wlan_crypto_get_key(vdev, key_idx);
3611 	}
3612 
3613 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
3614 
3615 	sme_debug("session:%d, cipher:%d, ucast:%d, idx:%d, wep:%d, add:%d",
3616 		  session_id, cipher, unicast, key_idx, wep_key_idx, add_key);
3617 	if (!IS_WEP_CIPHER(cipher) && !add_key)
3618 		return QDF_STATUS_E_INVAL;
3619 
3620 	return ucfg_crypto_set_key_req(vdev, crypto_key, (unicast ?
3621 				       WLAN_CRYPTO_KEY_TYPE_UNICAST :
3622 				       WLAN_CRYPTO_KEY_TYPE_GROUP));
3623 }
3624 
3625 QDF_STATUS
3626 csr_issue_set_context_req_helper(struct mac_context *mac_ctx,
3627 				 uint32_t vdev_id, tSirMacAddr *bssid,
3628 				 bool addkey, bool unicast, uint8_t key_id)
3629 {
3630 	return csr_roam_issue_set_context_req(mac_ctx, vdev_id, addkey,
3631 					      unicast, key_id,
3632 					      (struct qdf_mac_addr *)bssid);
3633 }
3634 
3635 static
3636 bool csr_roam_issue_wm_status_change(struct mac_context *mac, uint32_t sessionId,
3637 				     enum csr_roam_wmstatus_changetypes Type,
3638 				     tSirSmeRsp *pSmeRsp)
3639 {
3640 	bool fCommandQueued = false;
3641 	tSmeCmd *pCommand;
3642 
3643 	do {
3644 		/* Validate the type is ok... */
3645 		if ((eCsrDisassociated != Type)
3646 		    && (eCsrDeauthenticated != Type))
3647 			break;
3648 		pCommand = csr_get_command_buffer(mac);
3649 		if (!pCommand) {
3650 			sme_err(" fail to get command buffer");
3651 			break;
3652 		}
3653 
3654 		pCommand->command = eSmeCommandWmStatusChange;
3655 		pCommand->vdev_id = (uint8_t) sessionId;
3656 		pCommand->u.wmStatusChangeCmd.Type = Type;
3657 		if (eCsrDisassociated == Type) {
3658 			qdf_mem_copy(&pCommand->u.wmStatusChangeCmd.u.
3659 				     DisassocIndMsg, pSmeRsp,
3660 				     sizeof(pCommand->u.wmStatusChangeCmd.u.
3661 					    DisassocIndMsg));
3662 		} else {
3663 			qdf_mem_copy(&pCommand->u.wmStatusChangeCmd.u.
3664 				     DeauthIndMsg, pSmeRsp,
3665 				     sizeof(pCommand->u.wmStatusChangeCmd.u.
3666 					    DeauthIndMsg));
3667 		}
3668 		if (QDF_IS_STATUS_SUCCESS
3669 			    (csr_queue_sme_command(mac, pCommand, false)))
3670 			fCommandQueued = true;
3671 		else
3672 			sme_err("fail to send message");
3673 	} while (0);
3674 	return fCommandQueued;
3675 }
3676 
3677 static void csr_update_snr(struct mac_context *mac, void *pMsg)
3678 {
3679 	tAniGetSnrReq *pGetSnrReq = (tAniGetSnrReq *) pMsg;
3680 
3681 	if (pGetSnrReq) {
3682 		if (QDF_STATUS_SUCCESS != wma_get_snr(pGetSnrReq)) {
3683 			sme_err("Error in wma_get_snr");
3684 			return;
3685 		}
3686 
3687 	} else
3688 		sme_err("pGetSnrReq is NULL");
3689 }
3690 
3691 /**
3692  * csr_translate_akm_type() - Convert ani_akm_type value to equivalent
3693  * enum csr_akm_type
3694  * @akm_type: value of type ani_akm_type
3695  *
3696  * Return: enum csr_akm_type value
3697  */
3698 static enum csr_akm_type csr_translate_akm_type(enum ani_akm_type akm_type)
3699 {
3700 	enum csr_akm_type csr_akm_type;
3701 
3702 	switch (akm_type)
3703 	{
3704 	case ANI_AKM_TYPE_NONE:
3705 		csr_akm_type = eCSR_AUTH_TYPE_NONE;
3706 		break;
3707 #ifdef WLAN_FEATURE_SAE
3708 	case ANI_AKM_TYPE_SAE:
3709 		csr_akm_type = eCSR_AUTH_TYPE_SAE;
3710 		break;
3711 #endif
3712 	case ANI_AKM_TYPE_WPA:
3713 		csr_akm_type = eCSR_AUTH_TYPE_WPA;
3714 		break;
3715 	case ANI_AKM_TYPE_WPA_PSK:
3716 		csr_akm_type = eCSR_AUTH_TYPE_WPA_PSK;
3717 		break;
3718 	case ANI_AKM_TYPE_RSN:
3719 		csr_akm_type = eCSR_AUTH_TYPE_RSN;
3720 		break;
3721 	case ANI_AKM_TYPE_RSN_PSK:
3722 		csr_akm_type = eCSR_AUTH_TYPE_RSN_PSK;
3723 		break;
3724 	case ANI_AKM_TYPE_FT_RSN:
3725 		csr_akm_type = eCSR_AUTH_TYPE_FT_RSN;
3726 		break;
3727 	case ANI_AKM_TYPE_FT_RSN_PSK:
3728 		csr_akm_type = eCSR_AUTH_TYPE_FT_RSN_PSK;
3729 		break;
3730 #ifdef FEATURE_WLAN_ESE
3731 	case ANI_AKM_TYPE_CCKM:
3732 		csr_akm_type = eCSR_AUTH_TYPE_CCKM_RSN;
3733 		break;
3734 #endif
3735 	case ANI_AKM_TYPE_RSN_PSK_SHA256:
3736 		csr_akm_type = eCSR_AUTH_TYPE_RSN_PSK_SHA256;
3737 		break;
3738 	case ANI_AKM_TYPE_RSN_8021X_SHA256:
3739 		csr_akm_type = eCSR_AUTH_TYPE_RSN_8021X_SHA256;
3740 		break;
3741 	case ANI_AKM_TYPE_FILS_SHA256:
3742 		csr_akm_type = eCSR_AUTH_TYPE_FILS_SHA256;
3743 		break;
3744 	case ANI_AKM_TYPE_FILS_SHA384:
3745 		csr_akm_type = eCSR_AUTH_TYPE_FILS_SHA384;
3746 		break;
3747 	case ANI_AKM_TYPE_FT_FILS_SHA256:
3748 		csr_akm_type = eCSR_AUTH_TYPE_FT_FILS_SHA256;
3749 		break;
3750 	case ANI_AKM_TYPE_FT_FILS_SHA384:
3751 		csr_akm_type = eCSR_AUTH_TYPE_FT_FILS_SHA384;
3752 		break;
3753 	case ANI_AKM_TYPE_DPP_RSN:
3754 		csr_akm_type = eCSR_AUTH_TYPE_DPP_RSN;
3755 		break;
3756 	case ANI_AKM_TYPE_OWE:
3757 		csr_akm_type = eCSR_AUTH_TYPE_OWE;
3758 		break;
3759 	case ANI_AKM_TYPE_SUITEB_EAP_SHA256:
3760 		csr_akm_type = eCSR_AUTH_TYPE_SUITEB_EAP_SHA256;
3761 		break;
3762 	case ANI_AKM_TYPE_SUITEB_EAP_SHA384:
3763 		csr_akm_type = eCSR_AUTH_TYPE_SUITEB_EAP_SHA384;
3764 		break;
3765 	case ANI_AKM_TYPE_OSEN:
3766 		csr_akm_type = eCSR_AUTH_TYPE_OSEN;
3767 		break;
3768 	default:
3769 		csr_akm_type = eCSR_AUTH_TYPE_UNKNOWN;
3770 	}
3771 
3772 	return csr_akm_type;
3773 }
3774 
3775 #ifdef WLAN_FEATURE_11BE_MLO
3776 static void
3777 csr_send_assoc_ind_to_upper_layer_mac_copy(tSirSmeAssocIndToUpperLayerCnf *cnf,
3778 					   struct assoc_ind *ind)
3779 {
3780 	qdf_mem_copy(&cnf->peer_mld_addr, &ind->peer_mld_addr,
3781 		     sizeof(cnf->peer_mld_addr));
3782 }
3783 #else /* WLAN_FEATURE_11BE_MLO */
3784 static inline void
3785 csr_send_assoc_ind_to_upper_layer_mac_copy(tSirSmeAssocIndToUpperLayerCnf *cnf,
3786 					   struct assoc_ind *ind)
3787 {
3788 }
3789 #endif /* WLAN_FEATURE_11BE_MLO */
3790 
3791 static QDF_STATUS
3792 csr_send_assoc_ind_to_upper_layer_cnf_msg(struct mac_context *mac,
3793 					  struct assoc_ind *ind,
3794 					  QDF_STATUS status,
3795 					  uint8_t vdev_id)
3796 {
3797 	struct scheduler_msg msg = {0};
3798 	tSirSmeAssocIndToUpperLayerCnf *cnf;
3799 
3800 	cnf = qdf_mem_malloc(sizeof(*cnf));
3801 	if (!cnf)
3802 		return QDF_STATUS_E_NOMEM;
3803 
3804 	cnf->messageType = eWNI_SME_UPPER_LAYER_ASSOC_CNF;
3805 	cnf->length = sizeof(*cnf);
3806 	cnf->sessionId = vdev_id;
3807 
3808 	if (QDF_IS_STATUS_SUCCESS(status))
3809 		cnf->status_code = eSIR_SME_SUCCESS;
3810 	else
3811 		cnf->status_code = eSIR_SME_ASSOC_REFUSED;
3812 	qdf_mem_copy(&cnf->bssId, &ind->bssId, sizeof(cnf->bssId));
3813 	qdf_mem_copy(&cnf->peerMacAddr, &ind->peerMacAddr,
3814 		     sizeof(cnf->peerMacAddr));
3815 	csr_send_assoc_ind_to_upper_layer_mac_copy(cnf, ind);
3816 	cnf->aid = ind->staId;
3817 	cnf->wmmEnabledSta = ind->wmmEnabledSta;
3818 	cnf->rsnIE = ind->rsnIE;
3819 #ifdef FEATURE_WLAN_WAPI
3820 	cnf->wapiIE = ind->wapiIE;
3821 #endif
3822 	cnf->addIE = ind->addIE;
3823 	cnf->reassocReq = ind->reassocReq;
3824 	cnf->timingMeasCap = ind->timingMeasCap;
3825 	cnf->chan_info = ind->chan_info;
3826 	cnf->ampdu = ind->ampdu;
3827 	cnf->sgi_enable = ind->sgi_enable;
3828 	cnf->tx_stbc = ind->tx_stbc;
3829 	cnf->ch_width = ind->ch_width;
3830 	cnf->mode = ind->mode;
3831 	cnf->rx_stbc = ind->rx_stbc;
3832 	cnf->max_supp_idx = ind->max_supp_idx;
3833 	cnf->max_ext_idx = ind->max_ext_idx;
3834 	cnf->max_mcs_idx = ind->max_mcs_idx;
3835 	cnf->max_real_mcs_idx = ind->max_real_mcs_idx;
3836 	cnf->rx_mcs_map = ind->rx_mcs_map;
3837 	cnf->tx_mcs_map = ind->tx_mcs_map;
3838 	cnf->ecsa_capable = ind->ecsa_capable;
3839 	cnf->ext_cap = ind->ext_cap;
3840 	cnf->supported_band = ind->supported_band;
3841 	if (ind->HTCaps.present)
3842 		cnf->ht_caps = ind->HTCaps;
3843 	if (ind->VHTCaps.present)
3844 		cnf->vht_caps = ind->VHTCaps;
3845 	cnf->capability_info = ind->capability_info;
3846 	cnf->he_caps_present = ind->he_caps_present;
3847 	cnf->eht_caps_present = ind->eht_caps_present;
3848 	if (ind->assocReqPtr) {
3849 		if (ind->assocReqLength < MAX_ASSOC_REQ_IE_LEN) {
3850 			cnf->ies = qdf_mem_malloc(ind->assocReqLength);
3851 			if (!cnf->ies) {
3852 				qdf_mem_free(cnf);
3853 				return QDF_STATUS_E_NOMEM;
3854 			}
3855 			cnf->ies_len = ind->assocReqLength;
3856 			qdf_mem_copy(cnf->ies, ind->assocReqPtr,
3857 				     cnf->ies_len);
3858 		} else {
3859 			sme_err("Assoc Ie length is too long");
3860 		}
3861 	}
3862 
3863 	msg.type = eWNI_SME_UPPER_LAYER_ASSOC_CNF;
3864 	msg.bodyptr = cnf;
3865 	sys_process_mmh_msg(mac, &msg);
3866 
3867 	return QDF_STATUS_SUCCESS;
3868 }
3869 
3870 static void
3871 csr_roam_chk_lnk_assoc_ind_upper_layer(
3872 		struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
3873 {
3874 	uint32_t session_id = WLAN_UMAC_VDEV_ID_MAX;
3875 	struct assoc_ind *assoc_ind;
3876 	QDF_STATUS status;
3877 
3878 	assoc_ind = (struct assoc_ind *)msg_ptr;
3879 	status = csr_roam_get_session_id_from_bssid(
3880 			mac_ctx, (struct qdf_mac_addr *)assoc_ind->bssId,
3881 			&session_id);
3882 	if (!QDF_IS_STATUS_SUCCESS(status)) {
3883 		sme_debug("Couldn't find session_id for given BSSID");
3884 		goto free_mem;
3885 	}
3886 	csr_send_assoc_ind_to_upper_layer_cnf_msg(
3887 					mac_ctx, assoc_ind, status, session_id);
3888 	/*in the association response tx compete case,
3889 	 *memory for assoc_ind->assocReqPtr will be malloced
3890 	 *in the lim_assoc_rsp_tx_complete -> lim_fill_sme_assoc_ind_params
3891 	 *and then assoc_ind will pass here, so after using it
3892 	 *in the csr_send_assoc_ind_to_upper_layer_cnf_msg and
3893 	 *then free the memory here.
3894 	 */
3895 free_mem:
3896 	if (assoc_ind->assocReqLength != 0 && assoc_ind->assocReqPtr)
3897 		qdf_mem_free(assoc_ind->assocReqPtr);
3898 }
3899 
3900 static void
3901 csr_roam_chk_lnk_assoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
3902 {
3903 	struct csr_roam_session *session;
3904 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
3905 	QDF_STATUS status;
3906 	struct csr_roam_info *roam_info;
3907 	struct assoc_ind *pAssocInd;
3908 	enum wlan_status_code mac_status_code = STATUS_SUCCESS;
3909 	enum csr_akm_type csr_akm_type;
3910 	enum QDF_OPMODE opmode;
3911 
3912 	sme_debug("Receive WNI_SME_ASSOC_IND from SME");
3913 	pAssocInd = (struct assoc_ind *) msg_ptr;
3914 	sme_debug("Receive WNI_SME_ASSOC_IND from SME vdev id %d",
3915 		  pAssocInd->sessionId);
3916 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
3917 				(struct qdf_mac_addr *) pAssocInd->bssId,
3918 				&sessionId);
3919 	if (!QDF_IS_STATUS_SUCCESS(status)) {
3920 		sme_debug("Couldn't find session_id for given BSSID" QDF_MAC_ADDR_FMT,
3921 			  QDF_MAC_ADDR_REF(pAssocInd->bssId));
3922 		return;
3923 	}
3924 	session = CSR_GET_SESSION(mac_ctx, sessionId);
3925 	if (!session) {
3926 		sme_err("session %d not found", sessionId);
3927 		return;
3928 	}
3929 	csr_akm_type = csr_translate_akm_type(pAssocInd->akm_type);
3930 
3931 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
3932 	if (!roam_info)
3933 		return;
3934 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId);
3935 	/* Required for indicating the frames to upper layer */
3936 	roam_info->assocReqLength = pAssocInd->assocReqLength;
3937 	roam_info->assocReqPtr = pAssocInd->assocReqPtr;
3938 	roam_info->status_code = eSIR_SME_SUCCESS;
3939 	roam_info->staId = (uint8_t)pAssocInd->staId;
3940 	roam_info->rsnIELen = (uint8_t)pAssocInd->rsnIE.length;
3941 	roam_info->prsnIE = pAssocInd->rsnIE.rsnIEdata;
3942 #ifdef FEATURE_WLAN_WAPI
3943 	roam_info->wapiIELen = (uint8_t)pAssocInd->wapiIE.length;
3944 	roam_info->pwapiIE = pAssocInd->wapiIE.wapiIEdata;
3945 #endif
3946 	roam_info->addIELen = (uint8_t)pAssocInd->addIE.length;
3947 	roam_info->paddIE = pAssocInd->addIE.addIEdata;
3948 	roam_info->fReassocReq = pAssocInd->reassocReq;
3949 	qdf_mem_copy(roam_info->peerMac.bytes,
3950 		     pAssocInd->peerMacAddr,
3951 		     sizeof(tSirMacAddr));
3952 	qdf_mem_copy(roam_info->bssid.bytes,
3953 		     pAssocInd->bssId,
3954 		     sizeof(struct qdf_mac_addr));
3955 	roam_info->wmmEnabledSta = pAssocInd->wmmEnabledSta;
3956 	roam_info->timingMeasCap = pAssocInd->timingMeasCap;
3957 	roam_info->ecsa_capable = pAssocInd->ecsa_capable;
3958 	qdf_mem_copy(&roam_info->chan_info,
3959 		     &pAssocInd->chan_info,
3960 		     sizeof(struct oem_channel_info));
3961 
3962 	if (pAssocInd->HTCaps.present)
3963 		qdf_mem_copy(&roam_info->ht_caps,
3964 			     &pAssocInd->HTCaps,
3965 			     sizeof(tDot11fIEHTCaps));
3966 	if (pAssocInd->VHTCaps.present)
3967 		qdf_mem_copy(&roam_info->vht_caps,
3968 			     &pAssocInd->VHTCaps,
3969 			     sizeof(tDot11fIEVHTCaps));
3970 	roam_info->capability_info = pAssocInd->capability_info;
3971 	roam_info->he_caps_present = pAssocInd->he_caps_present;
3972 	roam_info->eht_caps_present = pAssocInd->eht_caps_present;
3973 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
3974 		if (wlan_is_open_wep_cipher(mac_ctx->pdev, sessionId)) {
3975 			csr_issue_set_context_req_helper(mac_ctx, sessionId,
3976 					&roam_info->peerMac.bytes, false, true,
3977 					0);
3978 			roam_info->fAuthRequired = false;
3979 		} else {
3980 			roam_info->fAuthRequired = true;
3981 		}
3982 		sme_debug("Receive AUTH_TYPE of %d", csr_akm_type);
3983 		if (csr_akm_type == eCSR_AUTH_TYPE_OWE) {
3984 			roam_info->owe_pending_assoc_ind = qdf_mem_malloc(
3985 							    sizeof(*pAssocInd));
3986 			if (roam_info->owe_pending_assoc_ind)
3987 				qdf_mem_copy(roam_info->owe_pending_assoc_ind,
3988 					     pAssocInd, sizeof(*pAssocInd));
3989 		} else if (csr_akm_type == eCSR_AUTH_TYPE_FT_RSN_PSK) {
3990 			roam_info->ft_pending_assoc_ind = qdf_mem_malloc(
3991 			    sizeof(*pAssocInd));
3992 			if (roam_info->ft_pending_assoc_ind)
3993 				qdf_mem_copy(roam_info->ft_pending_assoc_ind,
3994 					     pAssocInd, sizeof(*pAssocInd));
3995 		}
3996 		status = csr_roam_call_callback(mac_ctx, sessionId,
3997 					roam_info, eCSR_ROAM_INFRA_IND,
3998 					eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND);
3999 		if (!QDF_IS_STATUS_SUCCESS(status)) {
4000 			/* Refused due to Mac filtering */
4001 			if (roam_info->owe_pending_assoc_ind) {
4002 				qdf_mem_free(roam_info->owe_pending_assoc_ind);
4003 				roam_info->owe_pending_assoc_ind = NULL;
4004 			} else if (roam_info->ft_pending_assoc_ind) {
4005 				qdf_mem_free(roam_info->ft_pending_assoc_ind);
4006 				roam_info->ft_pending_assoc_ind = NULL;
4007 			}
4008 			roam_info->status_code = eSIR_SME_ASSOC_REFUSED;
4009 		}
4010 	}
4011 	sme_debug("csr_akm_type: %d", csr_akm_type);
4012 
4013 	if (csr_akm_type != eCSR_AUTH_TYPE_OWE &&
4014 	    csr_akm_type != eCSR_AUTH_TYPE_FT_RSN_PSK) {
4015 		if ((opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) &&
4016 		    roam_info->status_code != eSIR_SME_ASSOC_REFUSED)
4017 			pAssocInd->need_assoc_rsp_tx_cb = true;
4018 		/* Send Association completion message to PE */
4019 		status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status,
4020 						mac_status_code);
4021 	}
4022 
4023 	qdf_mem_free(roam_info);
4024 }
4025 
4026 /* csr_if_peer_present() - Check whether peer is present or not
4027  * @mac_ctx: Pointer to mac context
4028  * @bssid: Pointer to bssid address
4029  * @peer_macaddr: Pointer to peer mac address
4030  *
4031  * Consider a case
4032  * 1. SAP received south bound disconnect command
4033  * 2. At same time, SAP CSA to DFS channel happened and thus peers are deleted.
4034  * 3. Later same peer got re-added and south bound disconnect command becomes
4035  *    active for same peer.
4036  *
4037  * When SAP receives south bound disconnect command req, driver will post to
4038  * schedular thread and it will wait in SME message queue. When SAP CSA to DFS
4039  * channel happens, driver will post to schedular thread and it will wait in PE
4040  * message queue. Since PE has higher priority than SME message queue, so it
4041  * will process first. As part of CSA, it will delete all peer including sta
4042  * hash entry.
4043  * After CSA, south bound disconnect command got queue to serialization and
4044  * same peer got re-added again. When south bound disconnect command becomes
4045  * active, the states will not be proper because for old peer, disassocTrigger
4046  * is eLIM_PEER_ENTITY_DISASSOC/eLIM_PEER_ENTITY_DEAUTH and when new peer gets
4047  * re-added, disassocTrigger will be eLIM_HOST_DISASSOC/eLIM_HOST_DEAUTH and
4048  * thus response to CSR will not be proper. Due to this south bound disconnect
4049  * command will not remove from active queue which leads to active command
4050  * timeout.
4051  * Validate the peer before sending to serialization to avoid queuing command
4052  * if peer is already deleted.
4053  *
4054  * Return: True if peer is present otherwise return false
4055  */
4056 static bool csr_if_peer_present(struct mac_context *mac_ctx,
4057 				uint8_t *bssid,
4058 				uint8_t *peer_macaddr)
4059 {
4060 	struct wlan_objmgr_peer *peer;
4061 	uint8_t pdev_id;
4062 
4063 	pdev_id = wlan_objmgr_pdev_get_pdev_id(mac_ctx->pdev);
4064 
4065 	peer = wlan_objmgr_get_peer_by_mac_n_vdev(mac_ctx->psoc, pdev_id,
4066 						  bssid, peer_macaddr,
4067 						  WLAN_LEGACY_SME_ID);
4068 
4069 	if (!peer) {
4070 		sme_info("peer not found for mac: " QDF_MAC_ADDR_FMT "and bssid: "
4071 			  QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_macaddr),
4072 			  QDF_MAC_ADDR_REF(bssid));
4073 		return false;
4074 	}
4075 
4076 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_SME_ID);
4077 	return true;
4078 }
4079 
4080 static void
4081 csr_roam_chk_lnk_disassoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4082 {
4083 	struct csr_roam_session *session;
4084 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4085 	struct disassoc_ind *pDisassocInd;
4086 
4087 	/*
4088 	 * Check if AP dis-associated us because of MIC failure. If so,
4089 	 * then we need to take action immediately and not wait till the
4090 	 * the WmStatusChange requests is pushed and processed
4091 	 */
4092 	pDisassocInd = (struct disassoc_ind *)msg_ptr;
4093 	sessionId = pDisassocInd->vdev_id;
4094 	sme_debug("Disassoc Indication from MAC for vdev_id %d bssid " QDF_MAC_ADDR_FMT,
4095 		  pDisassocInd->vdev_id,
4096 		  QDF_MAC_ADDR_REF(pDisassocInd->bssid.bytes));
4097 
4098 	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
4099 		sme_err("vdev:%d Invalid session. BSSID: " QDF_MAC_ADDR_FMT,
4100 			sessionId, QDF_MAC_ADDR_REF(pDisassocInd->bssid.bytes));
4101 
4102 		return;
4103 	}
4104 
4105 	if (!csr_if_peer_present(mac_ctx, &pDisassocInd->bssid.bytes[0],
4106 				 &pDisassocInd->peer_macaddr.bytes[0]))
4107 		return;
4108 
4109 	if (csr_is_deauth_disassoc_already_active(mac_ctx, sessionId,
4110 	    pDisassocInd->peer_macaddr))
4111 		return;
4112 
4113 	sme_nofl_info("disassoc from peer " QDF_MAC_ADDR_FMT
4114 		      "reason: %d status: %d vid %d",
4115 		      QDF_MAC_ADDR_REF(pDisassocInd->peer_macaddr.bytes),
4116 		      pDisassocInd->reasonCode,
4117 		      pDisassocInd->status_code, sessionId);
4118 	session = CSR_GET_SESSION(mac_ctx, sessionId);
4119 	if (!session) {
4120 		sme_err("session: %d not found", sessionId);
4121 		return;
4122 	}
4123 	/* Update the disconnect stats */
4124 	session->disconnect_stats.disconnection_cnt++;
4125 	session->disconnect_stats.disassoc_by_peer++;
4126 
4127 	csr_roam_issue_wm_status_change(mac_ctx, sessionId,
4128 					eCsrDisassociated, msg_ptr);
4129 }
4130 
4131 static void
4132 csr_roam_chk_lnk_deauth_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4133 {
4134 	struct csr_roam_session *session;
4135 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4136 	struct deauth_ind *pDeauthInd;
4137 
4138 	pDeauthInd = (struct deauth_ind *)msg_ptr;
4139 	sme_debug("DEAUTH Indication from MAC for vdev_id %d bssid "QDF_MAC_ADDR_FMT,
4140 		  pDeauthInd->vdev_id,
4141 		  QDF_MAC_ADDR_REF(pDeauthInd->bssid.bytes));
4142 
4143 	sessionId = pDeauthInd->vdev_id;
4144 	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
4145 		sme_err("vdev %d: Invalid session BSSID: " QDF_MAC_ADDR_FMT,
4146 			pDeauthInd->vdev_id,
4147 			QDF_MAC_ADDR_REF(pDeauthInd->bssid.bytes));
4148 		return;
4149 	}
4150 
4151 	if (!csr_if_peer_present(mac_ctx, &pDeauthInd->bssid.bytes[0],
4152 				 &pDeauthInd->peer_macaddr.bytes[0]))
4153 		return;
4154 
4155 	if (csr_is_deauth_disassoc_already_active(mac_ctx, sessionId,
4156 	    pDeauthInd->peer_macaddr))
4157 		return;
4158 	session = CSR_GET_SESSION(mac_ctx, sessionId);
4159 	if (!session) {
4160 		sme_err("session %d not found", sessionId);
4161 		return;
4162 	}
4163 	/* Update the disconnect stats */
4164 	switch (pDeauthInd->reasonCode) {
4165 	case REASON_DISASSOC_DUE_TO_INACTIVITY:
4166 		session->disconnect_stats.disconnection_cnt++;
4167 		session->disconnect_stats.peer_kickout++;
4168 		break;
4169 	case REASON_UNSPEC_FAILURE:
4170 	case REASON_PREV_AUTH_NOT_VALID:
4171 	case REASON_DEAUTH_NETWORK_LEAVING:
4172 	case REASON_CLASS2_FRAME_FROM_NON_AUTH_STA:
4173 	case REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA:
4174 	case REASON_STA_NOT_AUTHENTICATED:
4175 		session->disconnect_stats.disconnection_cnt++;
4176 		session->disconnect_stats.deauth_by_peer++;
4177 		break;
4178 	case REASON_BEACON_MISSED:
4179 		session->disconnect_stats.disconnection_cnt++;
4180 		session->disconnect_stats.bmiss++;
4181 		break;
4182 	default:
4183 		/* Unknown reason code */
4184 		break;
4185 	}
4186 
4187 	csr_roam_issue_wm_status_change(mac_ctx, sessionId,
4188 					eCsrDeauthenticated,
4189 					msg_ptr);
4190 }
4191 
4192 static void
4193 csr_roam_chk_lnk_swt_ch_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4194 {
4195 	struct csr_roam_session *session;
4196 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4197 	QDF_STATUS status;
4198 	struct switch_channel_ind *pSwitchChnInd;
4199 	struct csr_roam_info *roam_info;
4200 
4201 	/* in case of STA, the SWITCH_CHANNEL originates from its AP */
4202 	sme_debug("eWNI_SME_SWITCH_CHL_IND from SME");
4203 	pSwitchChnInd = (struct switch_channel_ind *)msg_ptr;
4204 	/* Update with the new channel id. The channel id is hidden in the
4205 	 * status_code.
4206 	 */
4207 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
4208 			&pSwitchChnInd->bssid, &sessionId);
4209 	if (QDF_IS_STATUS_ERROR(status))
4210 		return;
4211 
4212 	session = CSR_GET_SESSION(mac_ctx, sessionId);
4213 	if (!session) {
4214 		sme_err("session %d not found", sessionId);
4215 		return;
4216 	}
4217 
4218 	if (QDF_IS_STATUS_ERROR(pSwitchChnInd->status)) {
4219 		sme_err("Channel switch failed");
4220 		return;
4221 	}
4222 	/* Update the occupied channel list with the new switched channel */
4223 	wlan_cm_init_occupied_ch_freq_list(mac_ctx->pdev, mac_ctx->psoc,
4224 					   sessionId);
4225 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4226 	if (!roam_info)
4227 		return;
4228 	roam_info->chan_info.mhz = pSwitchChnInd->freq;
4229 	roam_info->chan_info.ch_width = pSwitchChnInd->chan_params.ch_width;
4230 	roam_info->chan_info.sec_ch_offset =
4231 				pSwitchChnInd->chan_params.sec_ch_offset;
4232 	roam_info->chan_info.band_center_freq1 =
4233 				pSwitchChnInd->chan_params.mhz_freq_seg0;
4234 	roam_info->chan_info.band_center_freq2 =
4235 				pSwitchChnInd->chan_params.mhz_freq_seg1;
4236 
4237 	if (IS_WLAN_PHYMODE_HT(pSwitchChnInd->ch_phymode))
4238 		roam_info->mode = SIR_SME_PHY_MODE_HT;
4239 	else if (IS_WLAN_PHYMODE_VHT(pSwitchChnInd->ch_phymode) ||
4240 		 IS_WLAN_PHYMODE_HE(pSwitchChnInd->ch_phymode))
4241 		roam_info->mode = SIR_SME_PHY_MODE_VHT;
4242 #ifdef WLAN_FEATURE_11BE
4243 	else if (IS_WLAN_PHYMODE_EHT(pSwitchChnInd->ch_phymode))
4244 		roam_info->mode = SIR_SME_PHY_MODE_VHT;
4245 #endif
4246 	else
4247 		roam_info->mode = SIR_SME_PHY_MODE_LEGACY;
4248 
4249 	status = csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4250 					eCSR_ROAM_STA_CHANNEL_SWITCH,
4251 					eCSR_ROAM_RESULT_NONE);
4252 	qdf_mem_free(roam_info);
4253 }
4254 
4255 static void
4256 csr_roam_chk_lnk_deauth_rsp(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4257 {
4258 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4259 	QDF_STATUS status;
4260 	struct csr_roam_info *roam_info;
4261 	struct deauth_rsp *pDeauthRsp = (struct deauth_rsp *) msg_ptr;
4262 	enum QDF_OPMODE opmode;
4263 
4264 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4265 	if (!roam_info)
4266 		return;
4267 	sme_debug("eWNI_SME_DEAUTH_RSP from SME");
4268 	sessionId = pDeauthRsp->sessionId;
4269 	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
4270 		qdf_mem_free(roam_info);
4271 		return;
4272 	}
4273 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId);
4274 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
4275 		qdf_copy_macaddr(&roam_info->peerMac,
4276 				 &pDeauthRsp->peer_macaddr);
4277 		roam_info->reasonCode = eCSR_ROAM_RESULT_FORCED;
4278 		roam_info->status_code = pDeauthRsp->status_code;
4279 		status = csr_roam_call_callback(mac_ctx, sessionId,
4280 						roam_info, eCSR_ROAM_LOSTLINK,
4281 						eCSR_ROAM_RESULT_FORCED);
4282 	}
4283 	qdf_mem_free(roam_info);
4284 }
4285 
4286 static void
4287 csr_roam_chk_lnk_disassoc_rsp(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4288 {
4289 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4290 	QDF_STATUS status;
4291 	struct csr_roam_info *roam_info;
4292 	enum QDF_OPMODE opmode;
4293 	/*
4294 	 * session id is invalid here so cant use it to access the array
4295 	 * curSubstate as index
4296 	 */
4297 	struct disassoc_rsp *pDisassocRsp = (struct disassoc_rsp *) msg_ptr;
4298 
4299 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4300 	if (!roam_info)
4301 		return;
4302 	sme_debug("eWNI_SME_DISASSOC_RSP from SME ");
4303 	sessionId = pDisassocRsp->sessionId;
4304 	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
4305 		qdf_mem_free(roam_info);
4306 		return;
4307 	}
4308 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId);
4309 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
4310 		qdf_copy_macaddr(&roam_info->peerMac,
4311 				 &pDisassocRsp->peer_macaddr);
4312 		roam_info->reasonCode = eCSR_ROAM_RESULT_FORCED;
4313 		roam_info->status_code = pDisassocRsp->status_code;
4314 		status = csr_roam_call_callback(mac_ctx, sessionId,
4315 						roam_info,
4316 						eCSR_ROAM_LOSTLINK,
4317 						eCSR_ROAM_RESULT_FORCED);
4318 	}
4319 	qdf_mem_free(roam_info);
4320 }
4321 
4322 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
4323 static void
4324 csr_roam_diag_mic_fail(struct mac_context *mac_ctx, uint32_t sessionId)
4325 {
4326 	WLAN_HOST_DIAG_EVENT_DEF(secEvent,
4327 				 host_event_wlan_security_payload_type);
4328 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, sessionId);
4329 
4330 	if (!session) {
4331 		sme_err("session %d not found", sessionId);
4332 		return;
4333 	}
4334 	qdf_mem_zero(&secEvent, sizeof(host_event_wlan_security_payload_type));
4335 	secEvent.eventId = WLAN_SECURITY_EVENT_MIC_ERROR;
4336 	cm_diag_get_auth_enc_type_vdev_id(mac_ctx->psoc,
4337 					  &secEvent.authMode,
4338 					  &secEvent.encryptionModeUnicast,
4339 					  &secEvent.encryptionModeMulticast,
4340 					  sessionId);
4341 	wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, sessionId,
4342 				    (struct qdf_mac_addr *)&secEvent.bssid);
4343 	WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
4344 }
4345 #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
4346 
4347 static void
4348 csr_roam_chk_lnk_mic_fail_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4349 {
4350 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4351 	QDF_STATUS status;
4352 	struct csr_roam_info *roam_info;
4353 	struct mic_failure_ind *mic_ind = (struct mic_failure_ind *)msg_ptr;
4354 	eCsrRoamResult result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST;
4355 
4356 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4357 	if (!roam_info)
4358 		return;
4359 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
4360 				&mic_ind->bssId, &sessionId);
4361 	if (QDF_IS_STATUS_SUCCESS(status)) {
4362 		roam_info->u.pMICFailureInfo = &mic_ind->info;
4363 		if (mic_ind->info.multicast)
4364 			result = eCSR_ROAM_RESULT_MIC_ERROR_GROUP;
4365 		else
4366 			result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST;
4367 		csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4368 				       eCSR_ROAM_MIC_ERROR_IND, result);
4369 	}
4370 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
4371 	csr_roam_diag_mic_fail(mac_ctx, sessionId);
4372 #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
4373 	qdf_mem_free(roam_info);
4374 }
4375 
4376 static void
4377 csr_roam_chk_lnk_pbs_probe_req_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4378 {
4379 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4380 	QDF_STATUS status;
4381 	struct csr_roam_info *roam_info;
4382 	tpSirSmeProbeReqInd pProbeReqInd = (tpSirSmeProbeReqInd) msg_ptr;
4383 
4384 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4385 	if (!roam_info)
4386 		return;
4387 	sme_debug("WPS PBC Probe request Indication from SME");
4388 
4389 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
4390 			&pProbeReqInd->bssid, &sessionId);
4391 	if (QDF_IS_STATUS_SUCCESS(status)) {
4392 		roam_info->u.pWPSPBCProbeReq = &pProbeReqInd->WPSPBCProbeReq;
4393 		csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4394 				       eCSR_ROAM_WPS_PBC_PROBE_REQ_IND,
4395 				       eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND);
4396 	}
4397 	qdf_mem_free(roam_info);
4398 }
4399 
4400 static void
4401 csr_roam_chk_lnk_max_assoc_exceeded(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4402 {
4403 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4404 	tSmeMaxAssocInd *pSmeMaxAssocInd;
4405 	struct csr_roam_info *roam_info;
4406 
4407 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4408 	if (!roam_info)
4409 		return;
4410 	pSmeMaxAssocInd = (tSmeMaxAssocInd *) msg_ptr;
4411 	sme_debug(
4412 		"max assoc have been reached, new peer cannot be accepted");
4413 	sessionId = pSmeMaxAssocInd->sessionId;
4414 	qdf_copy_macaddr(&roam_info->peerMac, &pSmeMaxAssocInd->peer_mac);
4415 	csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4416 			       eCSR_ROAM_INFRA_IND,
4417 			       eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED);
4418 	qdf_mem_free(roam_info);
4419 }
4420 
4421 void csr_roam_check_for_link_status_change(struct mac_context *mac,
4422 						tSirSmeRsp *pSirMsg)
4423 {
4424 	if (!pSirMsg) {
4425 		sme_err("pSirMsg is NULL");
4426 		return;
4427 	}
4428 	switch (pSirMsg->messageType) {
4429 	case eWNI_SME_ASSOC_IND:
4430 		csr_roam_chk_lnk_assoc_ind(mac, pSirMsg);
4431 		break;
4432 	case eWNI_SME_ASSOC_IND_UPPER_LAYER:
4433 		csr_roam_chk_lnk_assoc_ind_upper_layer(mac, pSirMsg);
4434 		break;
4435 	case eWNI_SME_DISASSOC_IND:
4436 		csr_roam_chk_lnk_disassoc_ind(mac, pSirMsg);
4437 		break;
4438 	case eWNI_SME_DISCONNECT_DONE_IND:
4439 		csr_roam_send_disconnect_done_indication(mac, pSirMsg);
4440 		break;
4441 	case eWNI_SME_DEAUTH_IND:
4442 		csr_roam_chk_lnk_deauth_ind(mac, pSirMsg);
4443 		break;
4444 	case eWNI_SME_SWITCH_CHL_IND:
4445 		csr_roam_chk_lnk_swt_ch_ind(mac, pSirMsg);
4446 		break;
4447 	case eWNI_SME_DEAUTH_RSP:
4448 		csr_roam_chk_lnk_deauth_rsp(mac, pSirMsg);
4449 		break;
4450 	case eWNI_SME_DISASSOC_RSP:
4451 		csr_roam_chk_lnk_disassoc_rsp(mac, pSirMsg);
4452 		break;
4453 	case eWNI_SME_MIC_FAILURE_IND:
4454 		csr_roam_chk_lnk_mic_fail_ind(mac, pSirMsg);
4455 		break;
4456 	case eWNI_SME_WPS_PBC_PROBE_REQ_IND:
4457 		csr_roam_chk_lnk_pbs_probe_req_ind(mac, pSirMsg);
4458 		break;
4459 	case eWNI_SME_SETCONTEXT_RSP:
4460 		csr_roam_chk_lnk_set_ctx_rsp(mac, pSirMsg);
4461 		break;
4462 #ifdef FEATURE_WLAN_ESE
4463 	case eWNI_SME_GET_TSM_STATS_RSP:
4464 		sme_debug("TSM Stats rsp from PE");
4465 		csr_tsm_stats_rsp_processor(mac, pSirMsg);
4466 		break;
4467 #endif /* FEATURE_WLAN_ESE */
4468 	case eWNI_SME_GET_SNR_REQ:
4469 		sme_debug("GetSnrReq from self");
4470 		csr_update_snr(mac, pSirMsg);
4471 		break;
4472 	case eWNI_SME_MAX_ASSOC_EXCEEDED:
4473 		csr_roam_chk_lnk_max_assoc_exceeded(mac, pSirMsg);
4474 		break;
4475 	default:
4476 		break;
4477 	} /* end switch on message type */
4478 }
4479 
4480 void csr_roam_wm_status_change_complete(struct mac_context *mac,
4481 					uint8_t session_id)
4482 {
4483 	tListElem *pEntry;
4484 	tSmeCmd *pCommand;
4485 
4486 	pEntry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK);
4487 	if (pEntry) {
4488 		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
4489 		if (eSmeCommandWmStatusChange == pCommand->command) {
4490 			/* Nothing to process in a Lost Link completion....  It just kicks off a */
4491 			/* roaming sequence. */
4492 			if (csr_nonscan_active_ll_remove_entry(mac, pEntry,
4493 				    LL_ACCESS_LOCK)) {
4494 				csr_release_command(mac, pCommand);
4495 			} else {
4496 				sme_err("Failed to release command");
4497 			}
4498 		} else {
4499 			sme_warn("CSR: LOST LINK command is not ACTIVE ...");
4500 		}
4501 	} else {
4502 		sme_warn("CSR: NO commands are ACTIVE ...");
4503 	}
4504 }
4505 
4506 void csr_roam_process_wm_status_change_command(
4507 		struct mac_context *mac, tSmeCmd *pCommand)
4508 {
4509 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac,
4510 						pCommand->vdev_id);
4511 	struct qdf_mac_addr peer_mac;
4512 
4513 	if (!pSession) {
4514 		sme_err("session %d not found", pCommand->vdev_id);
4515 		csr_roam_wm_status_change_complete(mac, pCommand->vdev_id);
4516 	}
4517 	sme_debug("session:%d, CmdType : %d",
4518 		pCommand->vdev_id, pCommand->u.wmStatusChangeCmd.Type);
4519 
4520 	switch (pCommand->u.wmStatusChangeCmd.Type) {
4521 	case eCsrDisassociated:
4522 		qdf_mem_copy(&peer_mac, &pCommand->u.wmStatusChangeCmd.
4523 					u.DisassocIndMsg.peer_macaddr,
4524 			     QDF_MAC_ADDR_SIZE);
4525 		/*
4526 		 * Get peer stats before peer gets deleted so that these stats
4527 		 * can be given to user space when big data stats are queried.
4528 		 * Once peer stats are retrieved disassoc sta will continue
4529 		 */
4530 		csr_get_peer_stats(mac, pCommand->vdev_id, peer_mac);
4531 		break;
4532 	case eCsrDeauthenticated:
4533 		qdf_mem_copy(&peer_mac, &pCommand->u.wmStatusChangeCmd.
4534 					u.DeauthIndMsg.peer_macaddr,
4535 			     QDF_MAC_ADDR_SIZE);
4536 		/*
4537 		 * Get peer stats before peer gets deleted so that these stats
4538 		 * can be given to user space when big data stats are queried.
4539 		 * Once peer stats are retrieved deauth sta will continue
4540 		 */
4541 		csr_get_peer_stats(mac, pCommand->vdev_id, peer_mac);
4542 		break;
4543 	default:
4544 		sme_warn("gets an unknown command %d",
4545 			pCommand->u.wmStatusChangeCmd.Type);
4546 		csr_roam_wm_status_change_complete(mac, pCommand->vdev_id);
4547 		break;
4548 	}
4549 }
4550 
4551 /**
4552  * csr_compute_mode_and_band() - computes dot11mode
4553  * @mac: mac global context
4554  * @dot11_mode: out param, do11 mode calculated
4555  * @band: out param, band caclculated
4556  * @opr_ch_freq: operating channel freq in MHz
4557  *
4558  * This function finds dot11 mode based on current mode, operating channel and
4559  * fw supported modes.
4560  *
4561  * Return: void
4562  */
4563 static void
4564 csr_compute_mode_and_band(struct mac_context *mac_ctx,
4565 			  enum csr_cfgdot11mode *dot11_mode,
4566 			  enum reg_wifi_band *band,
4567 			  uint32_t opr_ch_freq)
4568 {
4569 	bool vht_24_ghz = mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band;
4570 
4571 	switch (mac_ctx->roam.configParam.uCfgDot11Mode) {
4572 	case eCSR_CFG_DOT11_MODE_11A:
4573 		*dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4574 		*band = REG_BAND_5G;
4575 		break;
4576 	case eCSR_CFG_DOT11_MODE_11B:
4577 		*dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4578 		*band = REG_BAND_2G;
4579 		break;
4580 	case eCSR_CFG_DOT11_MODE_11G:
4581 		*dot11_mode = eCSR_CFG_DOT11_MODE_11G;
4582 		*band = REG_BAND_2G;
4583 		break;
4584 	case eCSR_CFG_DOT11_MODE_11N:
4585 		*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4586 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4587 		break;
4588 	case eCSR_CFG_DOT11_MODE_11AC:
4589 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4590 			/*
4591 			 * If the operating channel is in 2.4 GHz band, check
4592 			 * for INI item to disable VHT operation in 2.4 GHz band
4593 			 */
4594 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4595 			    !vht_24_ghz)
4596 				/* Disable 11AC operation */
4597 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4598 			else
4599 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4600 		} else {
4601 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4602 		}
4603 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4604 		break;
4605 	case eCSR_CFG_DOT11_MODE_11AC_ONLY:
4606 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4607 			/*
4608 			 * If the operating channel is in 2.4 GHz band, check
4609 			 * for INI item to disable VHT operation in 2.4 GHz band
4610 			 */
4611 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4612 			    !vht_24_ghz)
4613 				/* Disable 11AC operation */
4614 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4615 			else
4616 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC_ONLY;
4617 		} else {
4618 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4619 		}
4620 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4621 		break;
4622 	case eCSR_CFG_DOT11_MODE_11AX:
4623 	case eCSR_CFG_DOT11_MODE_11AX_ONLY:
4624 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX)) {
4625 			*dot11_mode = mac_ctx->roam.configParam.uCfgDot11Mode;
4626 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4627 			/*
4628 			 * If the operating channel is in 2.4 GHz band, check
4629 			 * for INI item to disable VHT operation in 2.4 GHz band
4630 			 */
4631 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4632 			    !vht_24_ghz)
4633 				/* Disable 11AC operation */
4634 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4635 			else
4636 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4637 		} else {
4638 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4639 		}
4640 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4641 		break;
4642 #ifdef WLAN_FEATURE_11BE
4643 	case eCSR_CFG_DOT11_MODE_11BE:
4644 	case eCSR_CFG_DOT11_MODE_11BE_ONLY:
4645 		if (IS_FEATURE_11BE_SUPPORTED_BY_FW) {
4646 			*dot11_mode = mac_ctx->roam.configParam.uCfgDot11Mode;
4647 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX)) {
4648 			*dot11_mode = eCSR_CFG_DOT11_MODE_11AX;
4649 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4650 			/*
4651 			 * If the operating channel is in 2.4 GHz band, check
4652 			 * for INI item to disable VHT operation in 2.4 GHz band
4653 			 */
4654 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4655 			    !vht_24_ghz)
4656 				/* Disable 11AC operation */
4657 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4658 			else
4659 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4660 		} else {
4661 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4662 		}
4663 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4664 		break;
4665 #endif
4666 	case eCSR_CFG_DOT11_MODE_AUTO:
4667 #ifdef WLAN_FEATURE_11BE
4668 		if (IS_FEATURE_11BE_SUPPORTED_BY_FW) {
4669 			*dot11_mode = eCSR_CFG_DOT11_MODE_11BE;
4670 		} else
4671 #endif
4672 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX)) {
4673 			*dot11_mode = eCSR_CFG_DOT11_MODE_11AX;
4674 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4675 			/*
4676 			 * If the operating channel is in 2.4 GHz band,
4677 			 * check for INI item to disable VHT operation
4678 			 * in 2.4 GHz band
4679 			 */
4680 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4681 			    !vht_24_ghz)
4682 				/* Disable 11AC operation */
4683 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4684 			else
4685 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4686 		} else {
4687 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4688 		}
4689 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4690 		break;
4691 	default:
4692 		/*
4693 		 * Global dot11 Mode setting is 11a/b/g. use the channel number
4694 		 * to determine the Mode setting.
4695 		 */
4696 		if (eCSR_OPERATING_CHANNEL_AUTO == opr_ch_freq) {
4697 			*band = (mac_ctx->mlme_cfg->gen.band == BAND_2G ?
4698 				REG_BAND_2G : REG_BAND_5G);
4699 			if (REG_BAND_2G == *band) {
4700 				*dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4701 			} else {
4702 				/* prefer 5GHz */
4703 				*band = REG_BAND_5G;
4704 				*dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4705 			}
4706 		} else if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq)) {
4707 			*dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4708 			*band = REG_BAND_2G;
4709 		} else {
4710 			/* else, it's a 5.0GHz channel.  Set mode to 11a. */
4711 			*dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4712 			*band = REG_BAND_5G;
4713 		}
4714 		break;
4715 	} /* switch */
4716 }
4717 
4718 /**
4719  * csr_roam_get_phy_mode_band_for_bss() - This function returns band and mode
4720  * information.
4721  * @mac_ctx:  mac global context
4722  * dot11_cfg: pointer to dot11 config
4723  *
4724  * This function finds dot11 mode based on current mode, operating channel and
4725  * fw supported modes. The only tricky part is that if phyMode is set to 11abg,
4726  * this function may return eCSR_CFG_DOT11_MODE_11B instead of
4727  * eCSR_CFG_DOT11_MODE_11G if everything is set to auto-pick.
4728  *
4729  * Return: dot11mode
4730  */
4731 enum csr_cfgdot11mode
4732 csr_roam_get_phy_mode_band_for_bss(struct mac_context *mac_ctx,
4733 				   struct bss_dot11_config *dot11_cfg)
4734 {
4735 	enum reg_wifi_band band = REG_BAND_2G;
4736 	qdf_freq_t opr_freq = 0;
4737 	bool is_11n_allowed;
4738 	enum csr_cfgdot11mode curr_mode =
4739 		mac_ctx->roam.configParam.uCfgDot11Mode;
4740 	enum csr_cfgdot11mode cfg_dot11_mode;
4741 	enum QDF_OPMODE opmode;
4742 	bool is_ap = false;
4743 	uint8_t privacy;
4744 	uint8_t vdev_id = dot11_cfg->vdev_id;
4745 
4746 	if (dot11_cfg->bss_op_ch_freq)
4747 		opr_freq = dot11_cfg->bss_op_ch_freq;
4748 
4749 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
4750 	is_ap = (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE);
4751 	cfg_dot11_mode =
4752 		csr_get_cfg_dot11_mode_from_csr_phy_mode(is_ap,
4753 							 dot11_cfg->phy_mode);
4754 	privacy = dot11_cfg->privacy;
4755 
4756 	/*
4757 	 * If the global setting for dot11Mode is set to auto/abg, we overwrite
4758 	 * the setting in the profile.
4759 	 */
4760 	if ((!is_ap && ((eCSR_CFG_DOT11_MODE_AUTO == curr_mode) ||
4761 	     (eCSR_CFG_DOT11_MODE_ABG == curr_mode))) ||
4762 	     (eCSR_CFG_DOT11_MODE_AUTO == cfg_dot11_mode) ||
4763 	     (eCSR_CFG_DOT11_MODE_ABG == cfg_dot11_mode)) {
4764 		csr_compute_mode_and_band(mac_ctx, &cfg_dot11_mode,
4765 					  &band, opr_freq);
4766 	} /* if( eCSR_CFG_DOT11_MODE_ABG == cfg_dot11_mode ) */
4767 	else {
4768 		/* dot11 mode is set, lets pick the band */
4769 		if (0 == opr_freq) {
4770 			/* channel is Auto also. */
4771 			if (mac_ctx->mlme_cfg->gen.band == BAND_ALL) {
4772 				/* prefer 5GHz */
4773 				band = REG_BAND_5G;
4774 			}
4775 		} else{
4776 			band = wlan_reg_freq_to_band(opr_freq);
4777 		}
4778 	}
4779 
4780 	dot11_cfg->p_band = band;
4781 	if (opr_freq == 2484 && wlan_reg_is_24ghz_ch_freq(opr_freq)) {
4782 		sme_err("Switching to Dot11B mode");
4783 		cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4784 	}
4785 
4786 	if (wlan_reg_is_24ghz_ch_freq(opr_freq) &&
4787 	    !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band &&
4788 	    (eCSR_CFG_DOT11_MODE_11AC == cfg_dot11_mode ||
4789 	    eCSR_CFG_DOT11_MODE_11AC_ONLY == cfg_dot11_mode))
4790 		cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4791 	/*
4792 	 * Incase of WEP Security encryption type is coming as part of add key.
4793 	 * So while STart BSS dont have information
4794 	 */
4795 	is_11n_allowed = wlan_vdev_id_is_11n_allowed(mac_ctx->pdev, vdev_id);
4796 	if ((!is_11n_allowed || (privacy &&
4797 	    wlan_vdev_id_is_open_cipher(mac_ctx->pdev, vdev_id))) &&
4798 	    ((eCSR_CFG_DOT11_MODE_11N == cfg_dot11_mode) ||
4799 	    (eCSR_CFG_DOT11_MODE_11AC == cfg_dot11_mode) ||
4800 	    (eCSR_CFG_DOT11_MODE_11AX == cfg_dot11_mode) ||
4801 	    CSR_IS_CFG_DOT11_PHY_MODE_11BE(cfg_dot11_mode))) {
4802 		/* We cannot do 11n here */
4803 		if (wlan_reg_is_24ghz_ch_freq(opr_freq))
4804 			cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11G;
4805 		else
4806 			cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4807 	}
4808 	sme_debug("dot11mode: %d phyMode %d is_11n_allowed %d privacy %d chan freq %d fw sup AX %d",
4809 		  cfg_dot11_mode, dot11_cfg->phy_mode, is_11n_allowed,
4810 		  privacy, opr_freq,
4811 		  IS_FEATURE_SUPPORTED_BY_FW(DOT11AX));
4812 
4813 #ifdef WLAN_FEATURE_11BE
4814 	sme_debug("BE :%d", IS_FEATURE_SUPPORTED_BY_FW(DOT11BE));
4815 #endif
4816 	return cfg_dot11_mode;
4817 }
4818 
4819 QDF_STATUS csr_get_cfg_valid_channels(struct mac_context *mac,
4820 				      qdf_freq_t *ch_freq_list,
4821 				      uint32_t *num_ch_freq)
4822 {
4823 	uint8_t num_chan_temp = 0;
4824 	int i;
4825 	uint32_t *valid_ch_freq_list =
4826 				mac->mlme_cfg->reg.valid_channel_freq_list;
4827 
4828 	*num_ch_freq = mac->mlme_cfg->reg.valid_channel_list_num;
4829 
4830 	for (i = 0; i < *num_ch_freq; i++) {
4831 		if (!wlan_reg_is_dsrc_freq(valid_ch_freq_list[i])) {
4832 			ch_freq_list[num_chan_temp] = valid_ch_freq_list[i];
4833 			num_chan_temp++;
4834 		}
4835 	}
4836 
4837 	*num_ch_freq = num_chan_temp;
4838 	return QDF_STATUS_SUCCESS;
4839 }
4840 
4841 /**
4842  * csr_convert_mode_to_nw_type() - convert mode into network type
4843  * @dot11_mode:    dot11_mode
4844  * @band:          2.4 or 5 GHz
4845  *
4846  * Return: tSirNwType
4847  */
4848 tSirNwType
4849 csr_convert_mode_to_nw_type(enum csr_cfgdot11mode dot11_mode,
4850 			    enum reg_wifi_band band)
4851 {
4852 	switch (dot11_mode) {
4853 	case eCSR_CFG_DOT11_MODE_11G:
4854 		return eSIR_11G_NW_TYPE;
4855 	case eCSR_CFG_DOT11_MODE_11B:
4856 		return eSIR_11B_NW_TYPE;
4857 	case eCSR_CFG_DOT11_MODE_11A:
4858 		return eSIR_11A_NW_TYPE;
4859 	case eCSR_CFG_DOT11_MODE_11N:
4860 	default:
4861 		/*
4862 		 * Because LIM only verifies it against 11a, 11b or 11g, set
4863 		 * only 11g or 11a here
4864 		 */
4865 		if (REG_BAND_2G == band)
4866 			return eSIR_11G_NW_TYPE;
4867 		else
4868 			return eSIR_11A_NW_TYPE;
4869 	}
4870 	return eSIR_DONOT_USE_NW_TYPE;
4871 }
4872 
4873 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
4874 #ifdef WLAN_FEATURE_11BE_MLO
4875 static bool csr_pmk_match_mlo_address(struct wlan_objmgr_vdev *vdev,
4876 				      struct wlan_crypto_pmksa *pmksa)
4877 {
4878 	struct qdf_mac_addr bss_peer_mld_mac = {0};
4879 
4880 	wlan_vdev_get_bss_peer_mld_mac(vdev, &bss_peer_mld_mac);
4881 
4882 	return qdf_is_macaddr_equal(&bss_peer_mld_mac, &pmksa->bssid);
4883 }
4884 #else
4885 static inline bool csr_pmk_match_mlo_address(struct wlan_objmgr_vdev *vdev,
4886 					     struct wlan_crypto_pmksa *pmksa)
4887 {
4888 	return false;
4889 }
4890 #endif
4891 
4892 void csr_get_pmk_info(struct mac_context *mac_ctx, uint8_t session_id,
4893 		      struct wlan_crypto_pmksa *pmk_cache)
4894 {
4895 	if (!mac_ctx) {
4896 		sme_err("Mac_ctx is NULL");
4897 		return;
4898 	}
4899 	wlan_cm_get_psk_pmk(mac_ctx->pdev, session_id, pmk_cache->pmk,
4900 			    &pmk_cache->pmk_len);
4901 }
4902 
4903 QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac,
4904 				struct wlan_crypto_pmksa *pmksa,
4905 				uint8_t vdev_id, bool update_to_fw)
4906 {
4907 	struct wlan_objmgr_vdev *vdev;
4908 	struct qdf_mac_addr connected_bssid = {0};
4909 	QDF_STATUS status;
4910 
4911 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
4912 						    WLAN_LEGACY_SME_ID);
4913 	if (!vdev) {
4914 		sme_err("vdev is NULL");
4915 		return QDF_STATUS_E_FAILURE;
4916 	}
4917 
4918 	wlan_mlme_get_bssid_vdev_id(mac->pdev, vdev_id, &connected_bssid);
4919 
4920 	/*
4921 	 * If the set_pmksa is received from the userspace in
4922 	 * connected state and if the connected BSSID is not
4923 	 * same as the PMKSA entry bssid, then reject this
4924 	 * global cache updation.
4925 	 *
4926 	 * Also for FILS connection, the set_pmksa will not have
4927 	 * the BSSID. So avoid this check for FILS connection.
4928 	 */
4929 	if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_UP &&
4930 	    !pmksa->ssid_len &&
4931 	    !qdf_is_macaddr_equal(&connected_bssid, &pmksa->bssid) &&
4932 	    !csr_pmk_match_mlo_address(vdev, pmksa)) {
4933 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
4934 		sme_debug("Set pmksa received for non-connected bss");
4935 		return QDF_STATUS_E_INVAL;
4936 	}
4937 
4938 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
4939 
4940 	wlan_cm_set_psk_pmk(mac->pdev, vdev_id, pmksa->pmk, pmksa->pmk_len);
4941 	if (update_to_fw) {
4942 		status = wlan_roam_update_cfg(mac->psoc, vdev_id,
4943 					      REASON_ROAM_PSK_PMK_CHANGED);
4944 		if (status == QDF_STATUS_E_INVAL)
4945 			wlan_mlme_defer_pmk_set_in_roaming(mac->psoc, vdev_id,
4946 							   true);
4947 	}
4948 
4949 	return QDF_STATUS_SUCCESS;
4950 }
4951 
4952 QDF_STATUS csr_set_pmk_cache_ft(struct mac_context *mac, uint8_t vdev_id,
4953 				struct wlan_crypto_pmksa *pmk_cache)
4954 {
4955 	struct wlan_objmgr_vdev *vdev;
4956 	int32_t akm;
4957 
4958 	if (!CSR_IS_SESSION_VALID(mac, vdev_id)) {
4959 		sme_err("session %d not found", vdev_id);
4960 		return QDF_STATUS_E_INVAL;
4961 	}
4962 
4963 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
4964 						    WLAN_LEGACY_SME_ID);
4965 	if (!vdev) {
4966 		sme_err("vdev is NULL");
4967 		return QDF_STATUS_E_FAILURE;
4968 	}
4969 
4970 	akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
4971 
4972 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
4973 
4974 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) {
4975 		sme_debug("PMK update is not required for ESE");
4976 		return QDF_STATUS_SUCCESS;
4977 	}
4978 
4979 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) ||
4980 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256) ||
4981 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384) ||
4982 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) {
4983 		sme_debug("Auth type: %x update the MDID in cache", akm);
4984 		cm_update_pmk_cache_ft(mac->psoc, vdev_id, pmk_cache);
4985 	} else {
4986 		struct cm_roam_values_copy src_cfg = {};
4987 		struct scan_filter *scan_filter;
4988 		qdf_list_t *list = NULL;
4989 		struct scan_cache_node *first_node = NULL;
4990 		struct rsn_mdie *mdie = NULL;
4991 		qdf_list_node_t *cur_node = NULL;
4992 
4993 		scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
4994 		if (!scan_filter)
4995 			return QDF_STATUS_E_NOMEM;
4996 		scan_filter->num_of_bssid = 1;
4997 		qdf_mem_copy(scan_filter->bssid_list[0].bytes,
4998 			     &pmk_cache->bssid, sizeof(struct qdf_mac_addr));
4999 		list = wlan_scan_get_result(mac->pdev, scan_filter);
5000 		qdf_mem_free(scan_filter);
5001 		if (!list || (list && !qdf_list_size(list))) {
5002 			sme_debug("Scan list is empty");
5003 			goto err;
5004 		}
5005 		qdf_list_peek_front(list, &cur_node);
5006 		first_node = qdf_container_of(cur_node,
5007 					      struct scan_cache_node,
5008 					      node);
5009 		if (first_node && first_node->entry)
5010 			mdie = (struct rsn_mdie *)
5011 					util_scan_entry_mdie(first_node->entry);
5012 		if (mdie) {
5013 			sme_debug("Update MDID in cache from scan_res");
5014 			src_cfg.bool_value = true;
5015 			src_cfg.uint_value =
5016 				(mdie->mobility_domain[0] |
5017 				 (mdie->mobility_domain[1] << 8));
5018 			wlan_cm_roam_cfg_set_value(mac->psoc, vdev_id,
5019 						   MOBILITY_DOMAIN, &src_cfg);
5020 			cm_update_pmk_cache_ft(mac->psoc, vdev_id, pmk_cache);
5021 		}
5022 err:
5023 		if (list)
5024 			wlan_scan_purge_results(list);
5025 	}
5026 	return QDF_STATUS_SUCCESS;
5027 }
5028 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
5029 
5030 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
5031 void csr_clear_sae_single_pmk(struct wlan_objmgr_psoc *psoc,
5032 			      uint8_t vdev_id,
5033 			      struct wlan_crypto_pmksa *pmk_cache)
5034 {
5035 	struct wlan_objmgr_vdev *vdev;
5036 	int32_t keymgmt;
5037 	struct mlme_pmk_info pmk_info;
5038 
5039 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
5040 						    WLAN_LEGACY_SME_ID);
5041 	if (!vdev) {
5042 		sme_err("vdev is NULL");
5043 		return;
5044 	}
5045 
5046 	keymgmt = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
5047 	if (keymgmt < 0) {
5048 		sme_err("Invalid mgmt cipher");
5049 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
5050 		return;
5051 	}
5052 
5053 	if (!(keymgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE))) {
5054 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
5055 		return;
5056 	}
5057 	if (pmk_cache) {
5058 		qdf_mem_copy(&pmk_info.pmk, pmk_cache->pmk, pmk_cache->pmk_len);
5059 		pmk_info.pmk_len = pmk_cache->pmk_len;
5060 		wlan_mlme_clear_sae_single_pmk_info(vdev, &pmk_info);
5061 	} else {
5062 		wlan_mlme_clear_sae_single_pmk_info(vdev, NULL);
5063 	}
5064 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
5065 }
5066 #endif
5067 
5068 #ifdef FEATURE_WLAN_ESE
5069 void csr_update_prev_ap_info(struct csr_roam_session *session,
5070 			     struct wlan_objmgr_vdev *vdev)
5071 {
5072 	struct wlan_ssid ssid;
5073 	QDF_STATUS status;
5074 	enum QDF_OPMODE opmode;
5075 	struct rso_config *rso_cfg;
5076 
5077 	opmode = wlan_vdev_mlme_get_opmode(vdev);
5078 	rso_cfg = wlan_cm_get_rso_config(vdev);
5079 	if (!rso_cfg)
5080 		return;
5081 
5082 	if (!rso_cfg->is_ese_assoc || opmode != QDF_STA_MODE)
5083 		return;
5084 	status = wlan_vdev_mlme_get_ssid(vdev, ssid.ssid, &ssid.length);
5085 	if (QDF_IS_STATUS_ERROR(status)) {
5086 		sme_err(" failed to find SSID for vdev %d", session->vdev_id);
5087 		return;
5088 	}
5089 	session->isPrevApInfoValid = true;
5090 	session->roamTS1 = qdf_mc_timer_get_system_time();
5091 }
5092 #endif
5093 
5094 #ifdef WLAN_FEATURE_FILS_SK
5095 static QDF_STATUS csr_cm_update_fils_info(struct wlan_objmgr_vdev *vdev,
5096 					  struct bss_description *bss_desc,
5097 					  struct wlan_cm_vdev_connect_req *req)
5098 {
5099 	uint8_t cache_id[CACHE_ID_LEN] = {0};
5100 	struct scan_cache_entry *entry;
5101 	struct wlan_crypto_pmksa *fils_ssid_pmksa, *bssid_lookup_pmksa;
5102 
5103 	if (!req->fils_info || !req->fils_info->is_fils_connection) {
5104 		wlan_cm_update_mlme_fils_info(vdev, NULL);
5105 		return QDF_STATUS_SUCCESS;
5106 	}
5107 
5108 	if (bss_desc->fils_info_element.is_cache_id_present) {
5109 		qdf_mem_copy(cache_id, bss_desc->fils_info_element.cache_id,
5110 			     CACHE_ID_LEN);
5111 		sme_debug("FILS_PMKSA: cache_id[0]:%d, cache_id[1]:%d",
5112 			  cache_id[0], cache_id[1]);
5113 	}
5114 	entry = req->bss->entry;
5115 	bssid_lookup_pmksa = wlan_crypto_get_pmksa(vdev, &entry->bssid);
5116 	fils_ssid_pmksa =
5117 			wlan_crypto_get_fils_pmksa(vdev, cache_id,
5118 						   entry->ssid.ssid,
5119 						   entry->ssid.length);
5120 
5121 	if ((!req->fils_info->rrk_len ||
5122 	     !req->fils_info->username_len) &&
5123 	     !bss_desc->fils_info_element.is_cache_id_present &&
5124 	     !bssid_lookup_pmksa && !fils_ssid_pmksa)
5125 		return QDF_STATUS_E_FAILURE;
5126 
5127 	return wlan_cm_update_mlme_fils_info(vdev, req->fils_info);
5128 }
5129 #else
5130 static inline
5131 QDF_STATUS csr_cm_update_fils_info(struct wlan_objmgr_vdev *vdev,
5132 				   struct bss_description *bss_desc,
5133 				   struct wlan_cm_vdev_connect_req *req)
5134 {
5135 }
5136 #endif
5137 
5138 #if defined(WLAN_FEATURE_HOST_ROAM) && defined(FEATURE_WLAN_ESE)
5139 static void csr_update_tspec_info(struct mac_context *mac_ctx,
5140 				  struct wlan_objmgr_vdev *vdev,
5141 				  tDot11fBeaconIEs *ie_struct)
5142 {
5143 	struct mlme_legacy_priv *mlme_priv;
5144 	tESETspecInfo *ese_tspec;
5145 
5146 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
5147 	if (!mlme_priv)
5148 		return;
5149 	if (!cm_is_ese_connection(vdev, ie_struct->ESEVersion.present))
5150 		return;
5151 
5152 	ese_tspec = &mlme_priv->connect_info.ese_tspec_info;
5153 	qdf_mem_zero(ese_tspec, sizeof(tESETspecInfo));
5154 	ese_tspec->numTspecs = sme_qos_ese_retrieve_tspec_info(mac_ctx,
5155 					wlan_vdev_get_id(vdev),
5156 					ese_tspec->tspec);
5157 }
5158 #else
5159 static inline void csr_update_tspec_info(struct mac_context *mac_ctx,
5160 					 struct wlan_objmgr_vdev *vdev,
5161 					 tDot11fBeaconIEs *ie_struct) {}
5162 #endif
5163 
5164 void cm_csr_send_set_ie(struct wlan_objmgr_vdev *vdev)
5165 {
5166 	struct vdev_mlme_obj *vdev_mlme;
5167 
5168 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
5169 	if (!vdev_mlme) {
5170 		sme_err("Failed to get vdev mlme obj!");
5171 		QDF_BUG(0);
5172 		return;
5173 	}
5174 
5175 	csr_send_set_ie(vdev_mlme->mgmt.generic.type,
5176 			vdev_mlme->mgmt.generic.subtype,
5177 			wlan_vdev_get_id(vdev));
5178 }
5179 
5180 QDF_STATUS cm_csr_handle_join_req(struct wlan_objmgr_vdev *vdev,
5181 				  struct wlan_cm_vdev_connect_req *req,
5182 				  struct cm_vdev_join_req *join_req,
5183 				  bool reassoc)
5184 {
5185 	struct mac_context *mac_ctx;
5186 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5187 	QDF_STATUS status;
5188 	tDot11fBeaconIEs *ie_struct;
5189 	struct bss_description *bss_desc;
5190 	uint32_t ie_len, bss_len;
5191 
5192 	/*
5193 	 * This API is to update legacy struct and should be removed once
5194 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5195 	 * vdev/pdev/psoc instead
5196 	 */
5197 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5198 	if (!mac_ctx)
5199 		return QDF_STATUS_E_INVAL;
5200 
5201 	ie_len = util_scan_entry_ie_len(join_req->entry);
5202 	bss_len = (uint16_t)(offsetof(struct bss_description,
5203 			   ieFields[0]) + ie_len);
5204 
5205 	bss_desc = qdf_mem_malloc(sizeof(*bss_desc) + bss_len);
5206 	if (!bss_desc)
5207 		return QDF_STATUS_E_NOMEM;
5208 
5209 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
5210 						    join_req->entry);
5211 	if (QDF_IS_STATUS_ERROR(status)) {
5212 		qdf_mem_free(bss_desc);
5213 		return QDF_STATUS_E_FAILURE;
5214 	}
5215 
5216 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5217 						     &ie_struct);
5218 	if (QDF_IS_STATUS_ERROR(status)) {
5219 		sme_err("IE parsing failed vdev id %d", vdev_id);
5220 		qdf_mem_free(bss_desc);
5221 		return QDF_STATUS_E_FAILURE;
5222 	}
5223 
5224 	if (reassoc) {
5225 		csr_update_tspec_info(mac_ctx, vdev, ie_struct);
5226 	} else {
5227 		status = csr_cm_update_fils_info(vdev, bss_desc, req);
5228 		if (QDF_IS_STATUS_ERROR(status)) {
5229 			sme_err("failed to update fils info vdev id %d",
5230 				vdev_id);
5231 			qdf_mem_free(ie_struct);
5232 			qdf_mem_free(bss_desc);
5233 			return QDF_STATUS_E_FAILURE;
5234 		}
5235 		sme_qos_csr_event_ind(mac_ctx, vdev_id,
5236 				      SME_QOS_CSR_JOIN_REQ, NULL);
5237 	}
5238 
5239 	if ((wlan_reg_11d_enabled_on_host(mac_ctx->psoc)) &&
5240 	     !ie_struct->Country.present)
5241 		csr_apply_channel_power_info_wrapper(mac_ctx);
5242 
5243 	qdf_mem_free(ie_struct);
5244 	qdf_mem_free(bss_desc);
5245 
5246 	cm_csr_set_joining(vdev_id);
5247 
5248 	return QDF_STATUS_SUCCESS;
5249 }
5250 
5251 #ifdef FEATURE_WLAN_ESE
5252 static uint32_t csr_get_tspec_ie_len(struct cm_vdev_join_rsp *rsp)
5253 {
5254 	return rsp->tspec_ie.len;
5255 }
5256 static inline void csr_copy_tspec_ie_len(struct csr_roam_session *session,
5257 					 uint8_t *frame_ptr,
5258 					 struct cm_vdev_join_rsp *rsp)
5259 {
5260 	session->connectedInfo.nTspecIeLength = rsp->tspec_ie.len;
5261 	if (rsp->tspec_ie.len)
5262 		qdf_mem_copy(frame_ptr, rsp->tspec_ie.ptr,
5263 			     rsp->tspec_ie.len);
5264 }
5265 
5266 #else
5267 static inline uint32_t csr_get_tspec_ie_len(struct cm_vdev_join_rsp *rsp)
5268 {
5269 	return 0;
5270 }
5271 static inline void csr_copy_tspec_ie_len(struct csr_roam_session *session,
5272 					 uint8_t *frame_ptr,
5273 					 struct cm_vdev_join_rsp *rsp)
5274 {}
5275 #endif
5276 
5277 static void csr_fill_connected_info(struct mac_context *mac_ctx,
5278 				    struct csr_roam_session *session,
5279 				    struct cm_vdev_join_rsp *rsp)
5280 {
5281 	uint32_t len;
5282 	struct wlan_connect_rsp_ies *connect_ies;
5283 	uint8_t *frame_ptr;
5284 	uint32_t beacon_data_len = 0;
5285 
5286 	connect_ies = &rsp->connect_rsp.connect_ies;
5287 	csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
5288 	if (connect_ies->bcn_probe_rsp.len > sizeof(struct wlan_frame_hdr))
5289 		beacon_data_len = connect_ies->bcn_probe_rsp.len -
5290 						sizeof(struct wlan_frame_hdr);
5291 	len = beacon_data_len + connect_ies->assoc_req.len +
5292 		connect_ies->assoc_rsp.len + rsp->ric_resp_ie.len +
5293 		csr_get_tspec_ie_len(rsp);
5294 	if (!len)
5295 		return;
5296 
5297 	session->connectedInfo.pbFrames = qdf_mem_malloc(len);
5298 	if (!session->connectedInfo.pbFrames)
5299 		return;
5300 
5301 	frame_ptr = session->connectedInfo.pbFrames;
5302 	session->connectedInfo.nBeaconLength = beacon_data_len;
5303 	if (beacon_data_len)
5304 		qdf_mem_copy(frame_ptr,
5305 			     connect_ies->bcn_probe_rsp.ptr +
5306 			     sizeof(struct wlan_frame_hdr),
5307 			     beacon_data_len);
5308 	frame_ptr += beacon_data_len;
5309 
5310 	session->connectedInfo.nAssocReqLength = connect_ies->assoc_req.len;
5311 	if (connect_ies->assoc_req.len)
5312 		qdf_mem_copy(frame_ptr,
5313 			     connect_ies->assoc_req.ptr,
5314 			     connect_ies->assoc_req.len);
5315 	frame_ptr += connect_ies->assoc_req.len;
5316 
5317 	session->connectedInfo.nAssocRspLength = connect_ies->assoc_rsp.len;
5318 	if (connect_ies->assoc_rsp.len)
5319 		qdf_mem_copy(frame_ptr,
5320 			     connect_ies->assoc_rsp.ptr,
5321 			     connect_ies->assoc_rsp.len);
5322 	frame_ptr += connect_ies->assoc_rsp.len;
5323 
5324 	session->connectedInfo.nRICRspLength = rsp->ric_resp_ie.len;
5325 	if (rsp->ric_resp_ie.len)
5326 		qdf_mem_copy(frame_ptr, rsp->ric_resp_ie.ptr,
5327 			     rsp->ric_resp_ie.len);
5328 	frame_ptr += rsp->ric_resp_ie.len;
5329 
5330 	csr_copy_tspec_ie_len(session, frame_ptr, rsp);
5331 }
5332 
5333 #ifndef WLAN_MDM_CODE_REDUCTION_OPT
5334 static inline void csr_qos_send_disconnect_ind(struct mac_context *mac_ctx,
5335 					       uint8_t vdev_id)
5336 {
5337 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_DISCONNECT_IND,
5338 			      NULL);
5339 }
5340 
5341 static inline void csr_qos_send_assoc_ind(struct mac_context *mac_ctx,
5342 					  uint8_t vdev_id,
5343 					  sme_QosAssocInfo *assoc_info)
5344 {
5345 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_ASSOC_COMPLETE,
5346 			      assoc_info);
5347 }
5348 
5349 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
5350 static void
5351 csr_qso_disconnect_complete_ind(struct mac_context *mac_ctx,
5352 				struct wlan_cm_connect_resp *connect_rsp)
5353 {
5354 	if (IS_ROAM_REASON_DISCONNECTION(
5355 		connect_rsp->roaming_info->roam_reason))
5356 		sme_qos_csr_event_ind(mac_ctx, connect_rsp->vdev_id,
5357 				      SME_QOS_CSR_DISCONNECT_ROAM_COMPLETE,
5358 				      NULL);
5359 }
5360 #else
5361 static inline void
5362 csr_qso_disconnect_complete_ind(struct mac_context *mac_ctx,
5363 				struct wlan_cm_connect_resp *connect_rsp) {}
5364 #endif
5365 
5366 static void
5367 csr_qos_send_reassoc_ind(struct mac_context *mac_ctx,
5368 			 uint8_t vdev_id,
5369 			 sme_QosAssocInfo *assoc_info,
5370 			 struct wlan_cm_connect_resp *connect_rsp)
5371 {
5372 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_HANDOFF_ASSOC_REQ,
5373 			      NULL);
5374 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_REASSOC_REQ,
5375 			      NULL);
5376 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_HANDOFF_COMPLETE,
5377 			      NULL);
5378 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_REASSOC_COMPLETE,
5379 			      assoc_info);
5380 
5381 	csr_qso_disconnect_complete_ind(mac_ctx, connect_rsp);
5382 }
5383 #else
5384 static inline void csr_qos_send_disconnect_ind(struct mac_context *mac_ctx,
5385 					       uint8_t vdev_id)
5386 {}
5387 
5388 static inline void csr_qos_send_assoc_ind(struct mac_context *mac_ctx,
5389 					  uint8_t vdev_id,
5390 					  sme_QosAssocInfo *assoc_info)
5391 {}
5392 static inline void
5393 csr_qos_send_reassoc_ind(struct mac_context *mac_ctx,
5394 			 uint8_t vdev_id,
5395 			 sme_QosAssocInfo *assoc_info,
5396 			 struct wlan_cm_connect_resp *connect_rsp)
5397 {}
5398 #endif
5399 
5400 static void
5401 csr_update_beacon_in_connect_rsp(struct scan_cache_entry *entry,
5402 				 struct wlan_connect_rsp_ies *connect_ies)
5403 {
5404 	if (!entry)
5405 		return;
5406 
5407 	/* no need to update if already present */
5408 	if (connect_ies->bcn_probe_rsp.ptr)
5409 		return;
5410 
5411 	/*
5412 	 * In case connection to MBSSID: Non Tx BSS OR host reassoc,
5413 	 * vdev/peer manager doesn't send unicast probe req so fill the
5414 	 * beacon in connect resp IEs here.
5415 	 */
5416 	connect_ies->bcn_probe_rsp.len =
5417 				util_scan_entry_frame_len(entry);
5418 	connect_ies->bcn_probe_rsp.ptr =
5419 		qdf_mem_malloc(connect_ies->bcn_probe_rsp.len);
5420 	if (!connect_ies->bcn_probe_rsp.ptr)
5421 		return;
5422 
5423 	qdf_mem_copy(connect_ies->bcn_probe_rsp.ptr,
5424 		     util_scan_entry_frame_ptr(entry),
5425 		     connect_ies->bcn_probe_rsp.len);
5426 }
5427 
5428 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
5429 static bool csr_is_link_switch_in_progress(struct wlan_objmgr_vdev *vdev)
5430 {
5431 	return mlo_mgr_is_link_switch_in_progress(vdev);
5432 }
5433 #else
5434 static bool csr_is_link_switch_in_progress(struct wlan_objmgr_vdev *vdev)
5435 {
5436 	return false;
5437 }
5438 #endif
5439 
5440 static void csr_fill_connected_profile(struct mac_context *mac_ctx,
5441 				       struct csr_roam_session *session,
5442 				       struct wlan_objmgr_vdev *vdev,
5443 				       struct cm_vdev_join_rsp *rsp)
5444 {
5445 	struct scan_filter *filter;
5446 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5447 	QDF_STATUS status;
5448 	qdf_list_t *list = NULL;
5449 	qdf_list_node_t *cur_lst = NULL;
5450 	struct scan_cache_node *cur_node = NULL;
5451 	uint32_t bss_len, ie_len;
5452 	struct bss_description *bss_desc = NULL;
5453 	tDot11fBeaconIEs *bcn_ies;
5454 	sme_QosAssocInfo assoc_info;
5455 	struct cm_roam_values_copy src_cfg = {};
5456 	bool is_ese = false;
5457 	uint8_t country_code[REG_ALPHA2_LEN + 1];
5458 
5459 	session->modifyProfileFields.uapsd_mask = rsp->uapsd_mask;
5460 	filter = qdf_mem_malloc(sizeof(*filter));
5461 	if (!filter)
5462 		return;
5463 
5464 	filter->num_of_bssid = 1;
5465 	qdf_copy_macaddr(&filter->bssid_list[0], &rsp->connect_rsp.bssid);
5466 	filter->ignore_auth_enc_type = true;
5467 
5468 	status = wlan_vdev_mlme_get_ssid(vdev, filter->ssid_list[0].ssid,
5469 					 &filter->ssid_list[0].length);
5470 	if (QDF_IS_STATUS_SUCCESS(status))
5471 		filter->num_of_ssid = 1;
5472 
5473 	list = wlan_scan_get_result(mac_ctx->pdev, filter);
5474 	qdf_mem_free(filter);
5475 	if (!list || (list && !qdf_list_size(list)))
5476 		goto purge_list;
5477 
5478 
5479 	qdf_list_peek_front(list, &cur_lst);
5480 	if (!cur_lst)
5481 		goto purge_list;
5482 
5483 	cur_node = qdf_container_of(cur_lst, struct scan_cache_node, node);
5484 	ie_len = util_scan_entry_ie_len(cur_node->entry);
5485 	bss_len = (uint16_t)(offsetof(struct bss_description,
5486 				      ieFields[0]) + ie_len);
5487 	bss_desc = qdf_mem_malloc(bss_len);
5488 	if (!bss_desc)
5489 		goto purge_list;
5490 
5491 	wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc, cur_node->entry);
5492 	pe_debug("Dump scan entry frm:");
5493 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
5494 			   cur_node->entry->raw_frame.ptr,
5495 			   cur_node->entry->raw_frame.len);
5496 
5497 	src_cfg.uint_value = bss_desc->mbo_oce_enabled_ap;
5498 	wlan_cm_roam_cfg_set_value(mac_ctx->psoc, vdev_id, MBO_OCE_ENABLED_AP,
5499 				   &src_cfg);
5500 	csr_fill_single_pmk(mac_ctx->psoc, vdev_id, bss_desc);
5501 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5502 						     &bcn_ies);
5503 	if (QDF_IS_STATUS_ERROR(status))
5504 		goto purge_list;
5505 
5506 	if (!bss_desc->beaconInterval)
5507 		sme_err("ERROR: Beacon interval is ZERO");
5508 
5509 	csr_update_beacon_in_connect_rsp(cur_node->entry,
5510 					 &rsp->connect_rsp.connect_ies);
5511 
5512 	assoc_info.bss_desc = bss_desc;
5513 	if (rsp->connect_rsp.is_reassoc) {
5514 		if (cm_is_ese_connection(vdev, bcn_ies->ESEVersion.present))
5515 			is_ese = true;
5516 		wlan_cm_set_ese_assoc(mac_ctx->pdev, vdev_id, is_ese);
5517 		wlan_cm_roam_cfg_get_value(mac_ctx->psoc, vdev_id, UAPSD_MASK,
5518 					   &src_cfg);
5519 		assoc_info.uapsd_mask = src_cfg.uint_value;
5520 		csr_qos_send_reassoc_ind(mac_ctx, vdev_id, &assoc_info,
5521 					 &rsp->connect_rsp);
5522 		if (src_cfg.uint_value)
5523 			sme_ps_start_uapsd(MAC_HANDLE(mac_ctx), vdev_id);
5524 	} else {
5525 		assoc_info.uapsd_mask = rsp->uapsd_mask;
5526 		csr_qos_send_assoc_ind(mac_ctx, vdev_id, &assoc_info);
5527 	}
5528 
5529 	if (rsp->connect_rsp.is_reassoc ||
5530 	    csr_is_link_switch_in_progress(vdev))
5531 		mlme_set_mbssid_info(vdev, &cur_node->entry->mbssid_info);
5532 
5533 	if (bcn_ies->Country.present)
5534 		qdf_mem_copy(country_code, bcn_ies->Country.country,
5535 			     REG_ALPHA2_LEN + 1);
5536 	else
5537 		qdf_mem_zero(country_code, REG_ALPHA2_LEN + 1);
5538 	wlan_cm_set_country_code(mac_ctx->pdev, vdev_id, country_code);
5539 
5540 	qdf_mem_free(bcn_ies);
5541 
5542 purge_list:
5543 	if (bss_desc)
5544 		qdf_mem_free(bss_desc);
5545 	if (list)
5546 		wlan_scan_purge_results(list);
5547 
5548 }
5549 
5550 QDF_STATUS cm_csr_connect_rsp(struct wlan_objmgr_vdev *vdev,
5551 			      struct cm_vdev_join_rsp *rsp)
5552 {
5553 	struct mac_context *mac_ctx;
5554 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5555 	struct csr_roam_session *session;
5556 	struct cm_roam_values_copy src_config = {};
5557 
5558 	/*
5559 	 * This API is to update legacy struct and should be removed once
5560 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5561 	 * vdev/pdev/psoc instead
5562 	 */
5563 	if (QDF_IS_STATUS_ERROR(rsp->connect_rsp.connect_status))
5564 		return QDF_STATUS_SUCCESS;
5565 
5566 	/* handle below only in case of success */
5567 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5568 	if (!mac_ctx)
5569 		return QDF_STATUS_E_INVAL;
5570 
5571 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
5572 	if (!session || !CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
5573 		sme_err("session not found for vdev_id %d", vdev_id);
5574 		return QDF_STATUS_E_INVAL;
5575 	}
5576 
5577 	if (!rsp->connect_rsp.is_reassoc) {
5578 		if (rsp->uapsd_mask)
5579 			sme_ps_start_uapsd(MAC_HANDLE(mac_ctx), vdev_id);
5580 		src_config.uint_value = rsp->uapsd_mask;
5581 		wlan_cm_roam_cfg_set_value(mac_ctx->psoc, vdev_id, UAPSD_MASK,
5582 					   &src_config);
5583 	}
5584 	session->nss = rsp->nss;
5585 	csr_fill_connected_info(mac_ctx, session, rsp);
5586 	csr_fill_connected_profile(mac_ctx, session, vdev, rsp);
5587 
5588 	return QDF_STATUS_SUCCESS;
5589 }
5590 
5591 static void
5592 cm_update_rsn_ocv_cap(int32_t *rsn_cap,
5593 		      struct wlan_cm_connect_resp *rsp)
5594 {
5595 	struct wlan_crypto_params crypto_params;
5596 	uint8_t *ie_ptr;
5597 	uint32_t ie_len;
5598 	QDF_STATUS status;
5599 
5600 	/* no need to do anything if OCV is not set */
5601 	if (!(*rsn_cap & WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED))
5602 		return;
5603 
5604 	if (!rsp->connect_ies.bcn_probe_rsp.ptr ||
5605 	    !rsp->connect_ies.bcn_probe_rsp.len ||
5606 	    (rsp->connect_ies.bcn_probe_rsp.len <
5607 		(sizeof(struct wlan_frame_hdr) +
5608 		offsetof(struct wlan_bcn_frame, ie)))) {
5609 		sme_err("invalid beacon probe rsp len %d",
5610 			rsp->connect_ies.bcn_probe_rsp.len);
5611 		return;
5612 	}
5613 
5614 	ie_len = (rsp->connect_ies.bcn_probe_rsp.len -
5615 			sizeof(struct wlan_frame_hdr) -
5616 			offsetof(struct wlan_bcn_frame, ie));
5617 	ie_ptr = (uint8_t *)(rsp->connect_ies.bcn_probe_rsp.ptr +
5618 			     sizeof(struct wlan_frame_hdr) +
5619 			     offsetof(struct wlan_bcn_frame, ie));
5620 
5621 	status = wlan_get_crypto_params_from_rsn_ie(&crypto_params, ie_ptr,
5622 						    ie_len);
5623 	if (QDF_IS_STATUS_ERROR(status))
5624 		return;
5625 
5626 	if (!(crypto_params.rsn_caps & WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED))
5627 		*rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED;
5628 }
5629 
5630 QDF_STATUS
5631 cm_csr_connect_done_ind(struct wlan_objmgr_vdev *vdev,
5632 			struct wlan_cm_connect_resp *rsp)
5633 {
5634 	mac_handle_t mac_handle;
5635 	struct mac_context *mac_ctx;
5636 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5637 	int32_t count;
5638 	struct set_context_rsp install_key_rsp;
5639 	int32_t rsn_cap, set_value;
5640 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
5641 	struct dual_sta_policy *dual_sta_policy;
5642 	bool enable_mcc_adaptive_sch = false;
5643 	struct qdf_mac_addr bc_mac = QDF_MAC_ADDR_BCAST_INIT;
5644 
5645 	/*
5646 	 * This API is to update legacy struct and should be removed once
5647 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5648 	 * vdev/pdev/psoc instead
5649 	 */
5650 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
5651 
5652 	mac_ctx = MAC_CONTEXT(mac_handle);
5653 	if (!mac_ctx)
5654 		return QDF_STATUS_E_INVAL;
5655 
5656 	mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc);
5657 	if (!mlme_obj)
5658 		return QDF_STATUS_E_INVAL;
5659 
5660 	if (QDF_IS_STATUS_ERROR(rsp->connect_status)) {
5661 		cm_csr_set_idle(vdev_id);
5662 		sme_qos_update_hand_off(vdev_id, false);
5663 		sme_qos_csr_event_ind(mac_ctx, vdev_id,
5664 				      SME_QOS_CSR_DISCONNECT_IND, NULL);
5665 		/* Fill legacy structures from resp for failure */
5666 
5667 		return QDF_STATUS_SUCCESS;
5668 	}
5669 
5670 	dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy;
5671 	count = policy_mgr_mode_specific_connection_count(mac_ctx->psoc,
5672 							  PM_STA_MODE, NULL);
5673 	/*
5674 	 * send duty cycle percentage to FW only if STA + STA
5675 	 * concurrency is in MCC.
5676 	 */
5677 	sme_debug("Current iface vdev_id:%d, Primary vdev_id:%d, Dual sta policy:%d, count:%d",
5678 		  vdev_id, dual_sta_policy->primary_vdev_id,
5679 		  dual_sta_policy->concurrent_sta_policy, count);
5680 
5681 	if (dual_sta_policy->primary_vdev_id != WLAN_UMAC_VDEV_ID_MAX &&
5682 	    dual_sta_policy->concurrent_sta_policy ==
5683 	    QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY && count == 2 &&
5684 	    policy_mgr_current_concurrency_is_mcc(mac_ctx->psoc)) {
5685 		policy_mgr_get_mcc_adaptive_sch(mac_ctx->psoc,
5686 						&enable_mcc_adaptive_sch);
5687 		if (enable_mcc_adaptive_sch) {
5688 			sme_debug("Disable mcc_adaptive_scheduler");
5689 			policy_mgr_set_dynamic_mcc_adaptive_sch(
5690 							mac_ctx->psoc, false);
5691 			if (QDF_STATUS_SUCCESS != sme_set_mas(false)) {
5692 				sme_err("Failed to disable mcc_adaptive_sched");
5693 				return -EAGAIN;
5694 			}
5695 		}
5696 		set_value =
5697 			wlan_mlme_get_mcc_duty_cycle_percentage(mac_ctx->pdev);
5698 		sme_cli_set_command(vdev_id, WMA_VDEV_MCC_SET_TIME_QUOTA,
5699 				    set_value, VDEV_CMD);
5700 	  } else if (dual_sta_policy->concurrent_sta_policy ==
5701 		     QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED && count == 2 &&
5702 		     policy_mgr_current_concurrency_is_mcc(mac_ctx->psoc)) {
5703 		policy_mgr_get_mcc_adaptive_sch(mac_ctx->psoc,
5704 						&enable_mcc_adaptive_sch);
5705 		if (enable_mcc_adaptive_sch) {
5706 			sme_debug("Enable mcc_adaptive_scheduler");
5707 			policy_mgr_set_dynamic_mcc_adaptive_sch(
5708 						  mac_ctx->psoc, true);
5709 			if (QDF_STATUS_SUCCESS != sme_set_mas(true)) {
5710 				sme_err("Failed to enable mcc_adaptive_sched");
5711 				return -EAGAIN;
5712 			}
5713 		}
5714 	} else {
5715 		QDF_STATUS status = QDF_STATUS_SUCCESS;
5716 		uint32_t quota_val;
5717 
5718 		quota_val =
5719 			ucfg_mlme_get_user_mcc_quota_percentage(mac_ctx->psoc);
5720 
5721 		if (quota_val) {
5722 			if (enable_mcc_adaptive_sch) {
5723 				policy_mgr_set_dynamic_mcc_adaptive_sch(
5724 							mac_ctx->psoc, false);
5725 				status = sme_set_mas(false);
5726 			}
5727 			if (status == QDF_STATUS_SUCCESS)
5728 				sme_cli_set_command(wlan_vdev_get_id(vdev),
5729 						    WMA_VDEV_MCC_SET_TIME_QUOTA,
5730 						    quota_val, VDEV_CMD);
5731 		} else {
5732 			sme_debug("no applicable user mcc/quota");
5733 		}
5734 	}
5735 
5736 	/*
5737 	 * For open mode authentication, send dummy install key response to
5738 	 * send OBSS scan and QOS event.
5739 	 */
5740 	if (!rsp->is_wps_connection && cm_is_open_mode(vdev)) {
5741 		install_key_rsp.length = sizeof(install_key_rsp);
5742 		install_key_rsp.status_code = eSIR_SME_SUCCESS;
5743 		install_key_rsp.sessionId = vdev_id;
5744 		/* use BC mac to enable OBSS scan */
5745 		qdf_copy_macaddr(&install_key_rsp.peer_macaddr, &bc_mac);
5746 		csr_roam_chk_lnk_set_ctx_rsp(mac_ctx,
5747 					     (tSirSmeRsp *)&install_key_rsp);
5748 	}
5749 
5750 	rsn_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP);
5751 	if (rsn_cap >= 0) {
5752 		cm_update_rsn_ocv_cap(&rsn_cap, rsp);
5753 		if (wma_cli_set2_command(vdev_id, wmi_vdev_param_rsn_capability,
5754 					 rsn_cap, 0, VDEV_CMD))
5755 			sme_err("Failed to update wmi_vdev_param_rsn_capability for vdev id %d",
5756 				vdev_id);
5757 	}
5758 
5759 	/*
5760 	 * Update the IEs after connection to reconfigure
5761 	 * any capability that changed during connection.
5762 	 */
5763 	if (mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g)
5764 		sme_set_vdev_ies_per_band(mac_handle, vdev_id,
5765 					  wlan_vdev_mlme_get_opmode(vdev));
5766 
5767 	return QDF_STATUS_SUCCESS;
5768 }
5769 
5770 QDF_STATUS cm_csr_handle_diconnect_req(struct wlan_objmgr_vdev *vdev,
5771 				       struct wlan_cm_vdev_discon_req *req)
5772 {
5773 	struct mac_context *mac_ctx;
5774 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5775 	struct csr_roam_session *session;
5776 
5777 	/*
5778 	 * This API is to update legacy struct and should be removed once
5779 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5780 	 * vdev/pdev/psoc instead
5781 	 */
5782 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5783 	if (!mac_ctx)
5784 		return QDF_STATUS_E_INVAL;
5785 
5786 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
5787 	if (!session || !CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
5788 		sme_err("session not found for vdev_id %d", vdev_id);
5789 		return QDF_STATUS_E_INVAL;
5790 	}
5791 
5792 	cm_csr_set_joining(vdev_id);
5793 
5794 	/* Update the disconnect stats */
5795 	session->disconnect_stats.disconnection_cnt++;
5796 	if (req->req.source == CM_PEER_DISCONNECT) {
5797 		session->disconnect_stats.disassoc_by_peer++;
5798 	} else if (req->req.source == CM_SB_DISCONNECT) {
5799 		switch (req->req.reason_code) {
5800 		case REASON_DISASSOC_DUE_TO_INACTIVITY:
5801 			session->disconnect_stats.peer_kickout++;
5802 			break;
5803 		case REASON_BEACON_MISSED:
5804 			session->disconnect_stats.bmiss++;
5805 			break;
5806 		default:
5807 			/* Unknown reason code */
5808 			break;
5809 		}
5810 	} else if (req->req.source == CM_MLO_LINK_SWITCH_DISCONNECT) {
5811 		/* Do not update any stats as session is going to be deleted*/
5812 	} else {
5813 		session->disconnect_stats.disconnection_by_app++;
5814 	}
5815 
5816 	csr_update_prev_ap_info(session, vdev);
5817 	csr_qos_send_disconnect_ind(mac_ctx, vdev_id);
5818 
5819 	return QDF_STATUS_SUCCESS;
5820 }
5821 
5822 QDF_STATUS
5823 cm_csr_disconnect_done_ind(struct wlan_objmgr_vdev *vdev,
5824 			   struct wlan_cm_discon_rsp *rsp)
5825 {
5826 	mac_handle_t mac_handle;
5827 	struct mac_context *mac_ctx;
5828 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5829 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
5830 
5831 	/*
5832 	 * This API is to update legacy struct and should be removed once
5833 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5834 	 * vdev/pdev/psoc instead
5835 	 */
5836 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
5837 
5838 	mac_ctx = MAC_CONTEXT(mac_handle);
5839 	if (!mac_ctx)
5840 		return QDF_STATUS_E_INVAL;
5841 
5842 	mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc);
5843 	if (!mlme_obj)
5844 		return QDF_STATUS_E_INVAL;
5845 
5846 	cm_csr_set_idle(vdev_id);
5847 	if (cm_is_vdev_roaming(vdev))
5848 		sme_qos_update_hand_off(vdev_id, false);
5849 	csr_set_default_dot11_mode(mac_ctx);
5850 
5851 	/*
5852 	 * Update the IEs after disconnection to remove
5853 	 * any connection specific capability change and
5854 	 * to reset back to self cap
5855 	 */
5856 	if (mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g) {
5857 		wlan_cm_set_force_20mhz_in_24ghz(vdev, true);
5858 		sme_set_vdev_ies_per_band(mac_handle, vdev_id,
5859 					  wlan_vdev_mlme_get_opmode(vdev));
5860 	}
5861 
5862 	return QDF_STATUS_SUCCESS;
5863 }
5864 
5865 #ifdef WLAN_FEATURE_HOST_ROAM
5866 void cm_csr_preauth_done(struct wlan_objmgr_vdev *vdev)
5867 {
5868 	struct mac_context *mac_ctx;
5869 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5870 	struct cm_roam_values_copy config;
5871 	bool is_11r;
5872 
5873 	/*
5874 	 * This API is to update legacy struct and should be removed once
5875 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5876 	 * vdev/pdev/psoc instead
5877 	 */
5878 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5879 	if (!mac_ctx) {
5880 		sme_err("mac_ctx is NULL");
5881 		return;
5882 	}
5883 
5884 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, vdev_id, IS_11R_CONNECTION,
5885 				   &config);
5886 	is_11r = config.bool_value;
5887 	if (is_11r || wlan_cm_get_ese_assoc(mac_ctx->pdev, vdev_id))
5888 		sme_qos_csr_event_ind(mac_ctx, vdev_id,
5889 				      SME_QOS_CSR_PREAUTH_SUCCESS_IND, NULL);
5890 }
5891 #endif
5892 
5893 /* */
5894 QDF_STATUS csr_send_mb_disassoc_req_msg(struct mac_context *mac,
5895 					uint32_t sessionId,
5896 					tSirMacAddr bssId, uint16_t reasonCode)
5897 {
5898 	struct disassoc_req *pMsg;
5899 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
5900 
5901 	if (!CSR_IS_SESSION_VALID(mac, sessionId))
5902 		return QDF_STATUS_E_FAILURE;
5903 
5904 	pMsg = qdf_mem_malloc(sizeof(*pMsg));
5905 	if (!pMsg)
5906 		return QDF_STATUS_E_NOMEM;
5907 
5908 	pMsg->messageType = eWNI_SME_DISASSOC_REQ;
5909 	pMsg->length = sizeof(*pMsg);
5910 	pMsg->sessionId = sessionId;
5911 
5912 	wlan_mlme_get_mac_vdev_id(mac->pdev, sessionId, &pMsg->bssid);
5913 	qdf_mem_copy(&pMsg->peer_macaddr.bytes, bssId, QDF_MAC_ADDR_SIZE);
5914 	pMsg->reasonCode = reasonCode;
5915 
5916 	/* Update the disconnect stats */
5917 	pSession->disconnect_stats.disconnection_cnt++;
5918 	pSession->disconnect_stats.disconnection_by_app++;
5919 
5920 	return umac_send_mb_message_to_mac(pMsg);
5921 }
5922 
5923 QDF_STATUS csr_send_chng_mcc_beacon_interval(struct mac_context *mac,
5924 						uint32_t sessionId)
5925 {
5926 	struct wlan_change_bi *pMsg;
5927 	uint16_t len = 0;
5928 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5929 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
5930 
5931 	if (!pSession) {
5932 		sme_err("session %d not found", sessionId);
5933 		return QDF_STATUS_E_FAILURE;
5934 	}
5935 	/* NO need to update the Beacon Params if update beacon parameter flag
5936 	 * is not set
5937 	 */
5938 	if (!mac->roam.roamSession[sessionId].update_bcn_int)
5939 		return QDF_STATUS_SUCCESS;
5940 
5941 	mac->roam.roamSession[sessionId].update_bcn_int =
5942 		false;
5943 
5944 	/* Create the message and send to lim */
5945 	len = sizeof(*pMsg);
5946 	pMsg = qdf_mem_malloc(len);
5947 	if (!pMsg)
5948 		status = QDF_STATUS_E_NOMEM;
5949 	else
5950 		status = QDF_STATUS_SUCCESS;
5951 	if (QDF_IS_STATUS_SUCCESS(status)) {
5952 		pMsg->message_type = eWNI_SME_CHNG_MCC_BEACON_INTERVAL;
5953 		pMsg->length = len;
5954 
5955 		wlan_mlme_get_mac_vdev_id(mac->pdev, sessionId,
5956 					  &pMsg->bssid);
5957 		sme_debug("CSR Attempting to change BI for Bssid= "
5958 			  QDF_MAC_ADDR_FMT,
5959 			  QDF_MAC_ADDR_REF(pMsg->bssid.bytes));
5960 		pMsg->session_id = sessionId;
5961 		sme_debug("session %d BeaconInterval %d",
5962 			sessionId,
5963 			mac->roam.roamSession[sessionId].bcn_int);
5964 		pMsg->beacon_interval =
5965 			mac->roam.roamSession[sessionId].bcn_int;
5966 		status = umac_send_mb_message_to_mac(pMsg);
5967 	}
5968 	return status;
5969 }
5970 
5971 #ifdef QCA_HT_2040_COEX
5972 QDF_STATUS csr_set_ht2040_mode(struct mac_context *mac, uint32_t sessionId,
5973 			       ePhyChanBondState cbMode, bool obssEnabled)
5974 {
5975 	struct set_ht2040_mode *pMsg;
5976 	uint16_t len = 0;
5977 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5978 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
5979 
5980 	if (!pSession) {
5981 		sme_err("session %d not found", sessionId);
5982 		return QDF_STATUS_E_FAILURE;
5983 	}
5984 
5985 	/* Create the message and send to lim */
5986 	len = sizeof(struct set_ht2040_mode);
5987 	pMsg = qdf_mem_malloc(len);
5988 	if (!pMsg)
5989 		status = QDF_STATUS_E_NOMEM;
5990 	else
5991 		status = QDF_STATUS_SUCCESS;
5992 	if (QDF_IS_STATUS_SUCCESS(status)) {
5993 		qdf_mem_zero(pMsg, sizeof(struct set_ht2040_mode));
5994 		pMsg->messageType = eWNI_SME_SET_HT_2040_MODE;
5995 		pMsg->length = len;
5996 
5997 		wlan_mlme_get_mac_vdev_id(mac->pdev, sessionId, &pMsg->bssid);
5998 		sme_debug(
5999 			"CSR Attempting to set HT20/40 mode for Bssid= "
6000 			 QDF_MAC_ADDR_FMT,
6001 			 QDF_MAC_ADDR_REF(pMsg->bssid.bytes));
6002 		pMsg->sessionId = sessionId;
6003 		sme_debug("  session %d HT20/40 mode %d",
6004 			sessionId, cbMode);
6005 		pMsg->cbMode = cbMode;
6006 		pMsg->obssEnabled = obssEnabled;
6007 		status = umac_send_mb_message_to_mac(pMsg);
6008 	}
6009 	return status;
6010 }
6011 #endif
6012 
6013 QDF_STATUS csr_send_mb_deauth_req_msg(struct mac_context *mac,
6014 				      uint32_t vdev_id,
6015 				      tSirMacAddr bssId, uint16_t reasonCode)
6016 {
6017 	struct deauth_req *pMsg;
6018 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, vdev_id);
6019 
6020 	if (!CSR_IS_SESSION_VALID(mac, vdev_id))
6021 		return QDF_STATUS_E_FAILURE;
6022 
6023 	pMsg = qdf_mem_malloc(sizeof(*pMsg));
6024 	if (!pMsg)
6025 		return QDF_STATUS_E_NOMEM;
6026 
6027 	pMsg->messageType = eWNI_SME_DEAUTH_REQ;
6028 	pMsg->length = sizeof(*pMsg);
6029 	pMsg->vdev_id = vdev_id;
6030 
6031 	wlan_mlme_get_mac_vdev_id(mac->pdev, vdev_id, &pMsg->bssid);
6032 	/* Set the peer MAC address before sending the message to LIM */
6033 	qdf_mem_copy(&pMsg->peer_macaddr.bytes, bssId, QDF_MAC_ADDR_SIZE);
6034 	pMsg->reasonCode = reasonCode;
6035 
6036 	/* Update the disconnect stats */
6037 	pSession->disconnect_stats.disconnection_cnt++;
6038 	pSession->disconnect_stats.disconnection_by_app++;
6039 
6040 	return umac_send_mb_message_to_mac(pMsg);
6041 }
6042 
6043 QDF_STATUS csr_send_mb_disassoc_cnf_msg(struct mac_context *mac,
6044 					struct disassoc_ind *pDisassocInd)
6045 {
6046 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6047 	struct disassoc_cnf *pMsg;
6048 
6049 	do {
6050 		pMsg = qdf_mem_malloc(sizeof(*pMsg));
6051 		if (!pMsg)
6052 			status = QDF_STATUS_E_NOMEM;
6053 		else
6054 			status = QDF_STATUS_SUCCESS;
6055 		if (!QDF_IS_STATUS_SUCCESS(status))
6056 			break;
6057 		pMsg->messageType = eWNI_SME_DISASSOC_CNF;
6058 		pMsg->status_code = eSIR_SME_SUCCESS;
6059 		pMsg->length = sizeof(*pMsg);
6060 		pMsg->vdev_id = pDisassocInd->vdev_id;
6061 		qdf_copy_macaddr(&pMsg->peer_macaddr,
6062 				 &pDisassocInd->peer_macaddr);
6063 		status = QDF_STATUS_SUCCESS;
6064 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6065 			qdf_mem_free(pMsg);
6066 			break;
6067 		}
6068 
6069 		qdf_copy_macaddr(&pMsg->bssid, &pDisassocInd->bssid);
6070 		status = QDF_STATUS_SUCCESS;
6071 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6072 			qdf_mem_free(pMsg);
6073 			break;
6074 		}
6075 
6076 		status = umac_send_mb_message_to_mac(pMsg);
6077 	} while (0);
6078 	return status;
6079 }
6080 
6081 QDF_STATUS csr_send_mb_deauth_cnf_msg(struct mac_context *mac,
6082 				      struct deauth_ind *pDeauthInd)
6083 {
6084 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6085 	struct deauth_cnf *pMsg;
6086 
6087 	do {
6088 		pMsg = qdf_mem_malloc(sizeof(*pMsg));
6089 		if (!pMsg)
6090 			status = QDF_STATUS_E_NOMEM;
6091 		else
6092 			status = QDF_STATUS_SUCCESS;
6093 		if (!QDF_IS_STATUS_SUCCESS(status))
6094 			break;
6095 		pMsg->messageType = eWNI_SME_DEAUTH_CNF;
6096 		pMsg->status_code = eSIR_SME_SUCCESS;
6097 		pMsg->length = sizeof(*pMsg);
6098 		pMsg->vdev_id = pDeauthInd->vdev_id;
6099 		qdf_copy_macaddr(&pMsg->bssid, &pDeauthInd->bssid);
6100 		status = QDF_STATUS_SUCCESS;
6101 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6102 			qdf_mem_free(pMsg);
6103 			break;
6104 		}
6105 		qdf_copy_macaddr(&pMsg->peer_macaddr,
6106 				 &pDeauthInd->peer_macaddr);
6107 		status = QDF_STATUS_SUCCESS;
6108 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6109 			qdf_mem_free(pMsg);
6110 			break;
6111 		}
6112 		status = umac_send_mb_message_to_mac(pMsg);
6113 	} while (0);
6114 	return status;
6115 }
6116 
6117 QDF_STATUS csr_send_assoc_cnf_msg(struct mac_context *mac,
6118 				  struct assoc_ind *pAssocInd,
6119 				  QDF_STATUS Halstatus,
6120 				  enum wlan_status_code mac_status_code)
6121 {
6122 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6123 	struct assoc_cnf *pMsg;
6124 	struct scheduler_msg msg = { 0 };
6125 
6126 	sme_debug("HalStatus: %d, mac_status_code %d",
6127 		  Halstatus, mac_status_code);
6128 	do {
6129 		pMsg = qdf_mem_malloc(sizeof(*pMsg));
6130 		if (!pMsg)
6131 			return QDF_STATUS_E_NOMEM;
6132 		pMsg->messageType = eWNI_SME_ASSOC_CNF;
6133 		pMsg->length = sizeof(*pMsg);
6134 		if (QDF_IS_STATUS_SUCCESS(Halstatus)) {
6135 			pMsg->status_code = eSIR_SME_SUCCESS;
6136 		} else {
6137 			pMsg->status_code = eSIR_SME_ASSOC_REFUSED;
6138 			pMsg->mac_status_code = mac_status_code;
6139 		}
6140 		/* bssId */
6141 		qdf_mem_copy(pMsg->bssid.bytes, pAssocInd->bssId,
6142 			     QDF_MAC_ADDR_SIZE);
6143 		/* peerMacAddr */
6144 		qdf_mem_copy(pMsg->peer_macaddr.bytes, pAssocInd->peerMacAddr,
6145 			     QDF_MAC_ADDR_SIZE);
6146 		/* aid */
6147 		pMsg->aid = pAssocInd->aid;
6148 		/* OWE IE */
6149 		if (pAssocInd->owe_ie_len) {
6150 			pMsg->owe_ie = qdf_mem_malloc(pAssocInd->owe_ie_len);
6151 			if (!pMsg->owe_ie)
6152 				return QDF_STATUS_E_NOMEM;
6153 			qdf_mem_copy(pMsg->owe_ie, pAssocInd->owe_ie,
6154 				     pAssocInd->owe_ie_len);
6155 			pMsg->owe_ie_len = pAssocInd->owe_ie_len;
6156 		}
6157 
6158 		if (pAssocInd->ft_ie_len) {
6159 			pMsg->ft_ie = qdf_mem_malloc(pAssocInd->ft_ie_len);
6160 			if (!pMsg->ft_ie)
6161 				return QDF_STATUS_E_NOMEM;
6162 			qdf_mem_copy(pMsg->ft_ie, pAssocInd->ft_ie,
6163 				     pAssocInd->ft_ie_len);
6164 			pMsg->ft_ie_len = pAssocInd->ft_ie_len;
6165 		}
6166 		pMsg->need_assoc_rsp_tx_cb = pAssocInd->need_assoc_rsp_tx_cb;
6167 
6168 		msg.type = pMsg->messageType;
6169 		msg.bodyval = 0;
6170 		msg.bodyptr = pMsg;
6171 		/* pMsg is freed by umac_send_mb_message_to_mac in anycase*/
6172 		status = scheduler_post_msg_by_priority(QDF_MODULE_ID_PE, &msg,
6173 							true);
6174 	} while (0);
6175 	return status;
6176 }
6177 
6178 /**
6179  * csr_store_oce_cfg_flags_in_vdev() - fill OCE flags from ini
6180  * @mac: mac_context.
6181  * @vdev: Pointer to pdev obj
6182  * @vdev_id: vdev_id
6183  *
6184  * This API will store the oce flags in vdev mlme priv object
6185  *
6186  * Return: none
6187  */
6188 static void csr_store_oce_cfg_flags_in_vdev(struct mac_context *mac,
6189 					    struct wlan_objmgr_pdev *pdev,
6190 					    uint8_t vdev_id)
6191 {
6192 	uint8_t *vdev_dynamic_oce;
6193 	struct wlan_objmgr_vdev *vdev =
6194 	wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, WLAN_LEGACY_MAC_ID);
6195 
6196 	if (!vdev)
6197 		return;
6198 
6199 	vdev_dynamic_oce = mlme_get_dynamic_oce_flags(vdev);
6200 	if (vdev_dynamic_oce)
6201 		*vdev_dynamic_oce = mac->mlme_cfg->oce.feature_bitmap;
6202 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
6203 }
6204 
6205 void csr_send_set_ie(uint8_t type, uint8_t sub_type,
6206 		     uint8_t vdev_id)
6207 {
6208 	struct send_extcap_ie *msg;
6209 	QDF_STATUS status;
6210 
6211 	sme_debug("send SET IE msg to PE");
6212 
6213 	if (!(type == WLAN_VDEV_MLME_TYPE_STA ||
6214 	      (type == WLAN_VDEV_MLME_TYPE_AP &&
6215 	      sub_type == WLAN_VDEV_MLME_SUBTYPE_P2P_DEVICE))) {
6216 		sme_debug("Failed to send set IE req for vdev_%d", vdev_id);
6217 		return;
6218 	}
6219 
6220 	msg = qdf_mem_malloc(sizeof(*msg));
6221 	if (!msg)
6222 		return;
6223 
6224 	msg->msg_type = eWNI_SME_SET_IE_REQ;
6225 	msg->session_id = vdev_id;
6226 	msg->length = sizeof(*msg);
6227 	status = umac_send_mb_message_to_mac(msg);
6228 	if (!QDF_IS_STATUS_SUCCESS(status))
6229 		sme_debug("Failed to send set IE req for vdev_%d", vdev_id);
6230 }
6231 
6232 void csr_get_vdev_type_nss(enum QDF_OPMODE dev_mode, uint8_t *nss_2g,
6233 			   uint8_t *nss_5g)
6234 {
6235 	struct mac_context *mac_ctx = sme_get_mac_context();
6236 
6237 	if (!mac_ctx) {
6238 		sme_err("Invalid MAC context");
6239 		return;
6240 	}
6241 
6242 	switch (dev_mode) {
6243 	case QDF_STA_MODE:
6244 		*nss_2g = mac_ctx->vdev_type_nss_2g.sta;
6245 		*nss_5g = mac_ctx->vdev_type_nss_5g.sta;
6246 		break;
6247 	case QDF_SAP_MODE:
6248 		*nss_2g = mac_ctx->vdev_type_nss_2g.sap;
6249 		*nss_5g = mac_ctx->vdev_type_nss_5g.sap;
6250 		break;
6251 	case QDF_P2P_CLIENT_MODE:
6252 		*nss_2g = mac_ctx->vdev_type_nss_2g.p2p_cli;
6253 		*nss_5g = mac_ctx->vdev_type_nss_5g.p2p_cli;
6254 		break;
6255 	case QDF_P2P_GO_MODE:
6256 		*nss_2g = mac_ctx->vdev_type_nss_2g.p2p_go;
6257 		*nss_5g = mac_ctx->vdev_type_nss_5g.p2p_go;
6258 		break;
6259 	case QDF_P2P_DEVICE_MODE:
6260 		*nss_2g = mac_ctx->vdev_type_nss_2g.p2p_dev;
6261 		*nss_5g = mac_ctx->vdev_type_nss_5g.p2p_dev;
6262 		break;
6263 	case QDF_IBSS_MODE:
6264 		*nss_2g = mac_ctx->vdev_type_nss_2g.ibss;
6265 		*nss_5g = mac_ctx->vdev_type_nss_5g.ibss;
6266 		break;
6267 	case QDF_OCB_MODE:
6268 		*nss_2g = mac_ctx->vdev_type_nss_2g.ocb;
6269 		*nss_5g = mac_ctx->vdev_type_nss_5g.ocb;
6270 		break;
6271 	case QDF_NAN_DISC_MODE:
6272 		*nss_2g = mac_ctx->vdev_type_nss_2g.nan;
6273 		*nss_5g = mac_ctx->vdev_type_nss_5g.nan;
6274 		break;
6275 	case QDF_NDI_MODE:
6276 		*nss_2g = mac_ctx->vdev_type_nss_2g.ndi;
6277 		*nss_5g = mac_ctx->vdev_type_nss_5g.ndi;
6278 		break;
6279 	default:
6280 		*nss_2g = 1;
6281 		*nss_5g = 1;
6282 		sme_err("Unknown device mode: %d", dev_mode);
6283 		break;
6284 	}
6285 	sme_debug("mode - %d: nss_2g - %d, 5g - %d",
6286 		  dev_mode, *nss_2g, *nss_5g);
6287 }
6288 
6289 QDF_STATUS csr_setup_vdev_session(struct vdev_mlme_obj *vdev_mlme)
6290 {
6291 	QDF_STATUS status;
6292 	uint32_t existing_session_id;
6293 	struct csr_roam_session *session;
6294 	struct mlme_vht_capabilities_info *vht_cap_info;
6295 	u8 vdev_id;
6296 	struct qdf_mac_addr *mac_addr;
6297 	mac_handle_t mac_handle;
6298 	struct mac_context *mac_ctx;
6299 	struct wlan_objmgr_vdev *vdev;
6300 	struct wlan_vht_config vht_config;
6301 	struct wlan_ht_config ht_cap;
6302 
6303 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
6304 	mac_ctx = MAC_CONTEXT(mac_handle);
6305 	if (!mac_ctx) {
6306 		QDF_ASSERT(0);
6307 		return QDF_STATUS_E_INVAL;
6308 	}
6309 
6310 	if (!(mac_ctx->mlme_cfg)) {
6311 		sme_err("invalid mlme cfg");
6312 		return QDF_STATUS_E_FAILURE;
6313 	}
6314 	vht_cap_info = &mac_ctx->mlme_cfg->vht_caps.vht_cap_info;
6315 
6316 	vdev = vdev_mlme->vdev;
6317 
6318 	vdev_id = wlan_vdev_get_id(vdev);
6319 	mac_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_macaddr(vdev);
6320 	/* check to see if the mac address already belongs to a session */
6321 	status = csr_roam_get_session_id_from_bssid(mac_ctx, mac_addr,
6322 						    &existing_session_id);
6323 	if (QDF_IS_STATUS_SUCCESS(status)) {
6324 		sme_err("Session %d exists with mac address "QDF_MAC_ADDR_FMT,
6325 			existing_session_id,
6326 			QDF_MAC_ADDR_REF(mac_addr->bytes));
6327 		return QDF_STATUS_E_FAILURE;
6328 	}
6329 
6330 	/* attempt to retrieve session for Id */
6331 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
6332 	if (!session) {
6333 		sme_err("Session does not exist for interface %d", vdev_id);
6334 		return QDF_STATUS_E_FAILURE;
6335 	}
6336 
6337 	/* check to see if the session is already active */
6338 	if (session->sessionActive) {
6339 		sme_err("Cannot re-open active session with Id %d", vdev_id);
6340 		return QDF_STATUS_E_FAILURE;
6341 	}
6342 
6343 	session->sessionActive = true;
6344 	session->vdev_id = vdev_id;
6345 
6346 	ht_cap.caps = 0;
6347 	vht_config.caps = 0;
6348 	ht_cap.ht_caps = mac_ctx->mlme_cfg->ht_caps.ht_cap_info;
6349 	vdev_mlme->proto.ht_info.ht_caps = ht_cap.caps;
6350 
6351 	vht_config.max_mpdu_len = vht_cap_info->ampdu_len;
6352 	vht_config.supported_channel_widthset =
6353 			vht_cap_info->supp_chan_width;
6354 	vht_config.ldpc_coding = vht_cap_info->ldpc_coding_cap;
6355 	vht_config.shortgi80 = vht_cap_info->short_gi_80mhz;
6356 	vht_config.shortgi160and80plus80 =
6357 			vht_cap_info->short_gi_160mhz;
6358 	vht_config.tx_stbc = vht_cap_info->tx_stbc;
6359 	vht_config.rx_stbc = vht_cap_info->rx_stbc;
6360 	vht_config.su_beam_former = vht_cap_info->su_bformer;
6361 	vht_config.su_beam_formee = vht_cap_info->su_bformee;
6362 	vht_config.csnof_beamformer_antSup =
6363 			vht_cap_info->tx_bfee_ant_supp;
6364 	vht_config.num_soundingdim = vht_cap_info->num_soundingdim;
6365 	vht_config.mu_beam_former = vht_cap_info->mu_bformer;
6366 	vht_config.mu_beam_formee = vht_cap_info->enable_mu_bformee;
6367 	vht_config.vht_txops = vht_cap_info->txop_ps;
6368 	vht_config.htc_vhtcap = vht_cap_info->htc_vhtc;
6369 	vht_config.rx_antpattern = vht_cap_info->rx_antpattern;
6370 	vht_config.tx_antpattern = vht_cap_info->tx_antpattern;
6371 
6372 	vht_config.max_ampdu_lenexp =
6373 			vht_cap_info->ampdu_len_exponent;
6374 	vdev_mlme->proto.vht_info.caps = vht_config.caps;
6375 	csr_update_session_he_cap(mac_ctx, session);
6376 	csr_update_session_eht_cap(mac_ctx, session);
6377 
6378 	csr_send_set_ie(vdev_mlme->mgmt.generic.type,
6379 			vdev_mlme->mgmt.generic.subtype,
6380 			wlan_vdev_get_id(vdev));
6381 
6382 	if (vdev_mlme->mgmt.generic.type == WLAN_VDEV_MLME_TYPE_STA) {
6383 		csr_store_oce_cfg_flags_in_vdev(mac_ctx, mac_ctx->pdev,
6384 						wlan_vdev_get_id(vdev));
6385 		wlan_mlme_update_oce_flags(mac_ctx->pdev);
6386 	}
6387 
6388 	return QDF_STATUS_SUCCESS;
6389 }
6390 
6391 void csr_cleanup_vdev_session(struct mac_context *mac, uint8_t vdev_id)
6392 {
6393 	if (CSR_IS_SESSION_VALID(mac, vdev_id)) {
6394 		struct csr_roam_session *pSession = CSR_GET_SESSION(mac,
6395 								vdev_id);
6396 
6397 		csr_flush_roam_scan_chan_lists(mac, vdev_id);
6398 		csr_roam_free_connected_info(mac, &pSession->connectedInfo);
6399 		csr_init_session(mac, vdev_id);
6400 	}
6401 }
6402 
6403 QDF_STATUS csr_prepare_vdev_delete(struct mac_context *mac_ctx,
6404 				   struct wlan_objmgr_vdev *vdev)
6405 {
6406 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6407 	struct csr_roam_session *session;
6408 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
6409 
6410 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
6411 	if (!session)
6412 		return QDF_STATUS_E_INVAL;
6413 
6414 	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id))
6415 		return QDF_STATUS_E_INVAL;
6416 
6417 	if (CSR_IS_WAIT_FOR_KEY(mac_ctx, vdev_id)) {
6418 		sme_debug("Stop Wait for key timer and change substate to eCSR_ROAM_SUBSTATE_NONE");
6419 		cm_stop_wait_for_key_timer(mac_ctx->psoc, vdev_id);
6420 		csr_roam_substate_change(mac_ctx, eCSR_ROAM_SUBSTATE_NONE,
6421 					 vdev_id);
6422 	}
6423 
6424 	wlan_ser_vdev_queue_disable(vdev);
6425 	/* Flush all the commands for vdev */
6426 	wlan_serialization_purge_all_cmd_by_vdev_id(mac_ctx->pdev, vdev_id);
6427 	if (!mac_ctx->session_close_cb) {
6428 		sme_err("no close session callback registered");
6429 		return QDF_STATUS_E_FAILURE;
6430 	}
6431 
6432 	return status;
6433 }
6434 
6435 static void csr_init_session(struct mac_context *mac, uint32_t sessionId)
6436 {
6437 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
6438 
6439 	if (!pSession)
6440 		return;
6441 
6442 	pSession->sessionActive = false;
6443 	pSession->vdev_id = WLAN_UMAC_VDEV_ID_MAX;
6444 	pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
6445 	csr_roam_free_connected_info(mac, &pSession->connectedInfo);
6446 }
6447 
6448 static void csr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev,
6449 				       void *object, void *arg)
6450 {
6451 	struct bssid_search_arg *bssid_arg = arg;
6452 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
6453 	struct wlan_objmgr_peer *peer;
6454 
6455 	if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS)
6456 		return;
6457 
6458 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_LEGACY_SME_ID);
6459 	if (!peer)
6460 		return;
6461 
6462 	if (WLAN_ADDR_EQ(bssid_arg->peer_addr.bytes,
6463 			 wlan_peer_get_macaddr(peer)) == QDF_STATUS_SUCCESS)
6464 		bssid_arg->vdev_id = wlan_vdev_get_id(vdev);
6465 
6466 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_SME_ID);
6467 }
6468 
6469 QDF_STATUS csr_roam_get_session_id_from_bssid(struct mac_context *mac,
6470 					      struct qdf_mac_addr *bssid,
6471 					      uint32_t *pSessionId)
6472 {
6473 	struct bssid_search_arg bssid_arg;
6474 
6475 	qdf_copy_macaddr(&bssid_arg.peer_addr, bssid);
6476 	bssid_arg.vdev_id = WLAN_MAX_VDEVS;
6477 	wlan_objmgr_pdev_iterate_obj_list(mac->pdev, WLAN_VDEV_OP,
6478 					  csr_get_vdev_id_from_bssid,
6479 					  &bssid_arg, 0,
6480 					  WLAN_LEGACY_SME_ID);
6481 	if (bssid_arg.vdev_id >= WLAN_MAX_VDEVS) {
6482 		*pSessionId = 0;
6483 		return QDF_STATUS_E_FAILURE;
6484 	}
6485 
6486 	*pSessionId = bssid_arg.vdev_id;
6487 
6488 	return QDF_STATUS_SUCCESS;
6489 }
6490 
6491 QDF_STATUS csr_get_snr(struct mac_context *mac,
6492 		       tCsrSnrCallback callback,
6493 		       struct qdf_mac_addr bssId, void *pContext)
6494 {
6495 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6496 	struct scheduler_msg msg = {0};
6497 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
6498 	tAniGetSnrReq *pMsg;
6499 
6500 	pMsg = qdf_mem_malloc(sizeof(tAniGetSnrReq));
6501 	if (!pMsg)
6502 		return QDF_STATUS_E_NOMEM;
6503 
6504 	status = csr_roam_get_session_id_from_bssid(mac, &bssId, &sessionId);
6505 	if (!QDF_IS_STATUS_SUCCESS(status)) {
6506 		qdf_mem_free(pMsg);
6507 		sme_err("Couldn't find session_id for given BSSID");
6508 		return status;
6509 	}
6510 
6511 	pMsg->msgType = eWNI_SME_GET_SNR_REQ;
6512 	pMsg->msgLen = (uint16_t) sizeof(tAniGetSnrReq);
6513 	pMsg->sessionId = sessionId;
6514 	pMsg->snrCallback = callback;
6515 	pMsg->pDevContext = pContext;
6516 	msg.type = eWNI_SME_GET_SNR_REQ;
6517 	msg.bodyptr = pMsg;
6518 	msg.reserved = 0;
6519 
6520 	if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME,
6521 							 QDF_MODULE_ID_SME,
6522 							 QDF_MODULE_ID_SME,
6523 							 &msg)) {
6524 		qdf_mem_free((void *)pMsg);
6525 		status = QDF_STATUS_E_FAILURE;
6526 	}
6527 
6528 	return status;
6529 }
6530 
6531 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
6532 QDF_STATUS csr_invoke_neighbor_report_request(
6533 				uint8_t session_id,
6534 				struct sRrmNeighborReq *neighbor_report_req,
6535 				bool send_resp_to_host)
6536 {
6537 	struct wmi_invoke_neighbor_report_params *invoke_params;
6538 	struct scheduler_msg msg = {0};
6539 
6540 	if (!neighbor_report_req) {
6541 		sme_err("Invalid params");
6542 		return QDF_STATUS_E_INVAL;
6543 	}
6544 
6545 	invoke_params = qdf_mem_malloc(sizeof(*invoke_params));
6546 	if (!invoke_params)
6547 		return QDF_STATUS_E_NOMEM;
6548 
6549 	invoke_params->vdev_id = session_id;
6550 	invoke_params->send_resp_to_host = send_resp_to_host;
6551 
6552 	if (!neighbor_report_req->no_ssid) {
6553 		invoke_params->ssid.length = neighbor_report_req->ssid.length;
6554 		qdf_mem_copy(invoke_params->ssid.ssid,
6555 			     neighbor_report_req->ssid.ssId,
6556 			     neighbor_report_req->ssid.length);
6557 	} else {
6558 		invoke_params->ssid.length = 0;
6559 	}
6560 
6561 	sme_debug("Sending SIR_HAL_INVOKE_NEIGHBOR_REPORT");
6562 
6563 	msg.type = SIR_HAL_INVOKE_NEIGHBOR_REPORT;
6564 	msg.reserved = 0;
6565 	msg.bodyptr = invoke_params;
6566 
6567 	if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME,
6568 							 QDF_MODULE_ID_WMA,
6569 							 QDF_MODULE_ID_WMA,
6570 							 &msg)) {
6571 		sme_err("Not able to post message to WMA");
6572 		qdf_mem_free(invoke_params);
6573 		return QDF_STATUS_E_FAILURE;
6574 	}
6575 
6576 	return QDF_STATUS_SUCCESS;
6577 }
6578 
6579 #ifdef FEATURE_WLAN_ESE
6580 void wlan_cm_ese_populate_additional_ies(struct wlan_objmgr_pdev *pdev,
6581 			struct wlan_mlme_psoc_ext_obj *mlme_obj,
6582 			uint8_t vdev_id,
6583 			struct wlan_roam_scan_offload_params *rso_mode_cfg)
6584 {
6585 	uint8_t tspec_ie_hdr[SIR_MAC_OUI_WME_HDR_MIN]
6586 			= { 0x00, 0x50, 0xf2, 0x02, 0x02, 0x01 };
6587 	uint8_t tspec_ie_buf[DOT11F_IE_WMMTSPEC_MAX_LEN], j;
6588 	ese_wmm_tspec_ie *tspec_ie;
6589 	tESETspecInfo ese_tspec;
6590 	struct mac_context *mac_ctx;
6591 	struct csr_roam_session *session;
6592 
6593 	mac_ctx = sme_get_mac_context();
6594 	if (!mac_ctx) {
6595 		sme_err("mac_ctx is NULL");
6596 		return;
6597 	}
6598 
6599 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
6600 	if (!session) {
6601 		sme_err("session is null %d", vdev_id);
6602 		return;
6603 	}
6604 
6605 	tspec_ie = (ese_wmm_tspec_ie *)(tspec_ie_buf + SIR_MAC_OUI_WME_HDR_MIN);
6606 	if (csr_is_wmm_supported(mac_ctx) &&
6607 	    mlme_obj->cfg.lfr.ese_enabled &&
6608 	    wlan_cm_get_ese_assoc(pdev, session->vdev_id)) {
6609 		ese_tspec.numTspecs = sme_qos_ese_retrieve_tspec_info(
6610 					mac_ctx, session->vdev_id,
6611 					(tTspecInfo *)&ese_tspec.tspec[0]);
6612 		qdf_mem_copy(tspec_ie_buf, tspec_ie_hdr,
6613 			     SIR_MAC_OUI_WME_HDR_MIN);
6614 		for (j = 0; j < ese_tspec.numTspecs; j++) {
6615 			/* Populate the tspec_ie */
6616 			ese_populate_wmm_tspec(&ese_tspec.tspec[j].tspec,
6617 					       tspec_ie);
6618 			wlan_cm_append_assoc_ies(rso_mode_cfg,
6619 						 WLAN_ELEMID_VENDOR,
6620 						  DOT11F_IE_WMMTSPEC_MAX_LEN,
6621 						 tspec_ie_buf);
6622 		}
6623 	}
6624 }
6625 #endif
6626 
6627 uint8_t *wlan_cm_get_rrm_cap_ie_data(void)
6628 {
6629 	struct mac_context *mac_ctx;
6630 
6631 	mac_ctx = sme_get_mac_context();
6632 	if (!mac_ctx) {
6633 		sme_err("mac_ctx is NULL");
6634 		return NULL;
6635 	}
6636 
6637 	return (uint8_t *)&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps;
6638 }
6639 #endif
6640 
6641 tSmeCmd *csr_get_command_buffer(struct mac_context *mac)
6642 {
6643 	tSmeCmd *pCmd = sme_get_command_buffer(mac);
6644 
6645 	if (pCmd)
6646 		mac->roam.sPendingCommands++;
6647 
6648 	return pCmd;
6649 }
6650 
6651 static void csr_free_cmd_memory(struct mac_context *mac, tSmeCmd *pCommand)
6652 {
6653 	if (!pCommand) {
6654 		sme_err("pCommand is NULL");
6655 		return;
6656 	}
6657 	switch (pCommand->command) {
6658 	case eSmeCommandRoam:
6659 		csr_release_command_roam(mac, pCommand);
6660 		break;
6661 	case eSmeCommandWmStatusChange:
6662 		csr_release_command_wm_status_change(mac, pCommand);
6663 		break;
6664 	default:
6665 		break;
6666 	}
6667 }
6668 
6669 void csr_release_command_buffer(struct mac_context *mac, tSmeCmd *pCommand)
6670 {
6671 	if (mac->roam.sPendingCommands > 0) {
6672 		/*
6673 		 * All command allocated through csr_get_command_buffer
6674 		 * need to decrement the pending count when releasing
6675 		 */
6676 		mac->roam.sPendingCommands--;
6677 		csr_free_cmd_memory(mac, pCommand);
6678 		sme_release_command(mac, pCommand);
6679 	} else {
6680 		sme_err("no pending commands");
6681 		QDF_ASSERT(0);
6682 	}
6683 }
6684 
6685 void csr_release_command(struct mac_context *mac_ctx, tSmeCmd *sme_cmd)
6686 {
6687 	struct wlan_serialization_queued_cmd_info cmd_info;
6688 	struct wlan_serialization_command cmd;
6689 	struct wlan_objmgr_vdev *vdev;
6690 
6691 	if (!sme_cmd) {
6692 		sme_err("sme_cmd is NULL");
6693 		return;
6694 	}
6695 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
6696 			sme_cmd->vdev_id, WLAN_LEGACY_SME_ID);
6697 	if (!vdev) {
6698 		sme_err("Invalid vdev");
6699 		return;
6700 	}
6701 	qdf_mem_zero(&cmd_info,
6702 			sizeof(struct wlan_serialization_queued_cmd_info));
6703 	cmd_info.cmd_id = sme_cmd->cmd_id;
6704 	cmd_info.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD;
6705 	cmd_info.cmd_type = csr_get_cmd_type(sme_cmd);
6706 	cmd_info.vdev = vdev;
6707 	qdf_mem_zero(&cmd, sizeof(struct wlan_serialization_command));
6708 	cmd.cmd_id = cmd_info.cmd_id;
6709 	cmd.cmd_type = cmd_info.cmd_type;
6710 	cmd.vdev = cmd_info.vdev;
6711 	if (wlan_serialization_is_cmd_present_in_active_queue(
6712 				mac_ctx->psoc, &cmd)) {
6713 		cmd_info.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
6714 		wlan_serialization_remove_cmd(&cmd_info);
6715 	} else if (wlan_serialization_is_cmd_present_in_pending_queue(
6716 				mac_ctx->psoc, &cmd)) {
6717 		cmd_info.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
6718 		wlan_serialization_cancel_request(&cmd_info);
6719 	} else {
6720 		sme_debug("can't find cmd_id %d cmd_type %d", cmd_info.cmd_id,
6721 			  cmd_info.cmd_type);
6722 	}
6723 	if (cmd_info.vdev)
6724 		wlan_objmgr_vdev_release_ref(cmd_info.vdev, WLAN_LEGACY_SME_ID);
6725 }
6726 
6727 
6728 static enum wlan_serialization_cmd_type csr_get_roam_cmd_type(
6729 		tSmeCmd *sme_cmd)
6730 {
6731 	enum wlan_serialization_cmd_type cmd_type = WLAN_SER_CMD_MAX;
6732 
6733 	switch (sme_cmd->u.roamCmd.roamReason) {
6734 	case eCsrForcedDisassocSta:
6735 		cmd_type = WLAN_SER_CMD_FORCE_DISASSOC_STA;
6736 		break;
6737 	case eCsrForcedDeauthSta:
6738 		cmd_type = WLAN_SER_CMD_FORCE_DEAUTH_STA;
6739 		break;
6740 	default:
6741 		break;
6742 	}
6743 
6744 	return cmd_type;
6745 }
6746 
6747 enum wlan_serialization_cmd_type csr_get_cmd_type(tSmeCmd *sme_cmd)
6748 {
6749 	enum wlan_serialization_cmd_type cmd_type = WLAN_SER_CMD_MAX;
6750 
6751 	switch (sme_cmd->command) {
6752 	case eSmeCommandRoam:
6753 		cmd_type = csr_get_roam_cmd_type(sme_cmd);
6754 		break;
6755 	case eSmeCommandWmStatusChange:
6756 		cmd_type = WLAN_SER_CMD_WM_STATUS_CHANGE;
6757 		break;
6758 	case eSmeCommandAddTs:
6759 		cmd_type = WLAN_SER_CMD_ADDTS;
6760 		break;
6761 	case eSmeCommandDelTs:
6762 		cmd_type = WLAN_SER_CMD_DELTS;
6763 		break;
6764 	case e_sme_command_set_hw_mode:
6765 		cmd_type = WLAN_SER_CMD_SET_HW_MODE;
6766 		break;
6767 	case e_sme_command_nss_update:
6768 		cmd_type = WLAN_SER_CMD_NSS_UPDATE;
6769 		break;
6770 	case e_sme_command_set_dual_mac_config:
6771 		cmd_type = WLAN_SER_CMD_SET_DUAL_MAC_CONFIG;
6772 		break;
6773 	case e_sme_command_set_antenna_mode:
6774 		cmd_type = WLAN_SER_CMD_SET_ANTENNA_MODE;
6775 		break;
6776 	case e_sme_command_sap_ch_width_update:
6777 		cmd_type = WLAN_SER_CMD_SAP_BW_UPDATE;
6778 		break;
6779 	default:
6780 		break;
6781 	}
6782 
6783 	return cmd_type;
6784 }
6785 
6786 static uint32_t csr_get_monotonous_number(struct mac_context *mac_ctx)
6787 {
6788 	uint32_t cmd_id;
6789 	uint32_t mask = 0x00FFFFFF, prefix = 0x0D000000;
6790 
6791 	cmd_id = qdf_atomic_inc_return(&mac_ctx->global_cmd_id);
6792 	cmd_id = (cmd_id & mask);
6793 	cmd_id = (cmd_id | prefix);
6794 
6795 	return cmd_id;
6796 }
6797 
6798 static void csr_fill_cmd_timeout(struct wlan_serialization_command *cmd)
6799 {
6800 	switch (cmd->cmd_type) {
6801 	case WLAN_SER_CMD_WM_STATUS_CHANGE:
6802 		cmd->cmd_timeout_duration = SME_CMD_PEER_DISCONNECT_TIMEOUT;
6803 		break;
6804 	case WLAN_SER_CMD_VDEV_START_BSS:
6805 		cmd->cmd_timeout_duration = SME_CMD_VDEV_START_BSS_TIMEOUT;
6806 		break;
6807 	case WLAN_SER_CMD_VDEV_STOP_BSS:
6808 		cmd->cmd_timeout_duration = SME_CMD_STOP_BSS_CMD_TIMEOUT;
6809 		break;
6810 	case WLAN_SER_CMD_FORCE_DISASSOC_STA:
6811 	case WLAN_SER_CMD_FORCE_DEAUTH_STA:
6812 		cmd->cmd_timeout_duration = SME_CMD_PEER_DISCONNECT_TIMEOUT;
6813 		break;
6814 
6815 	case WLAN_SER_CMD_ADDTS:
6816 	case WLAN_SER_CMD_DELTS:
6817 		cmd->cmd_timeout_duration = SME_CMD_ADD_DEL_TS_TIMEOUT;
6818 		break;
6819 	case WLAN_SER_CMD_SET_HW_MODE:
6820 	case WLAN_SER_CMD_NSS_UPDATE:
6821 	case WLAN_SER_CMD_SET_DUAL_MAC_CONFIG:
6822 	case WLAN_SER_CMD_SET_ANTENNA_MODE:
6823 	case WLAN_SER_CMD_SAP_BW_UPDATE:
6824 		cmd->cmd_timeout_duration = SME_CMD_POLICY_MGR_CMD_TIMEOUT;
6825 		break;
6826 	default:
6827 		cmd->cmd_timeout_duration = SME_ACTIVE_LIST_CMD_TIMEOUT_VALUE;
6828 		break;
6829 	}
6830 }
6831 
6832 QDF_STATUS csr_set_serialization_params_to_cmd(struct mac_context *mac_ctx,
6833 		tSmeCmd *sme_cmd, struct wlan_serialization_command *cmd,
6834 		uint8_t high_priority)
6835 {
6836 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
6837 
6838 	if (!sme_cmd) {
6839 		sme_err("Invalid sme_cmd");
6840 		return status;
6841 	}
6842 	if (!cmd) {
6843 		sme_err("Invalid serialization_cmd");
6844 		return status;
6845 	}
6846 
6847 	/*
6848 	 * no need to fill command id for non-scan as they will be
6849 	 * zero always
6850 	 */
6851 	sme_cmd->cmd_id = csr_get_monotonous_number(mac_ctx);
6852 	cmd->cmd_id = sme_cmd->cmd_id;
6853 
6854 	cmd->cmd_type = csr_get_cmd_type(sme_cmd);
6855 	if (cmd->cmd_type == WLAN_SER_CMD_MAX) {
6856 		sme_err("serialization enum not found for sme_cmd type %d",
6857 			sme_cmd->command);
6858 		return status;
6859 	}
6860 	cmd->vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
6861 				sme_cmd->vdev_id, WLAN_LEGACY_SME_ID);
6862 	if (!cmd->vdev) {
6863 		sme_err("vdev is NULL for vdev_id:%d", sme_cmd->vdev_id);
6864 		return status;
6865 	}
6866 	cmd->umac_cmd = sme_cmd;
6867 
6868 	csr_fill_cmd_timeout(cmd);
6869 
6870 	cmd->source = WLAN_UMAC_COMP_MLME;
6871 	cmd->cmd_cb = sme_ser_cmd_callback;
6872 	cmd->is_high_priority = high_priority;
6873 	cmd->is_blocking = true;
6874 
6875 	return QDF_STATUS_SUCCESS;
6876 }
6877 
6878 QDF_STATUS csr_queue_sme_command(struct mac_context *mac_ctx, tSmeCmd *sme_cmd,
6879 				 bool high_priority)
6880 {
6881 	struct wlan_serialization_command cmd;
6882 	struct wlan_objmgr_vdev *vdev = NULL;
6883 	enum wlan_serialization_status ser_cmd_status;
6884 	QDF_STATUS status;
6885 
6886 	if (!SME_IS_START(mac_ctx)) {
6887 		sme_err("Sme in stop state");
6888 		QDF_ASSERT(0);
6889 		goto error;
6890 	}
6891 
6892 	qdf_mem_zero(&cmd, sizeof(struct wlan_serialization_command));
6893 	status = csr_set_serialization_params_to_cmd(mac_ctx, sme_cmd,
6894 					&cmd, high_priority);
6895 	if (QDF_IS_STATUS_ERROR(status)) {
6896 		sme_err("failed to set ser params");
6897 		goto error;
6898 	}
6899 
6900 	vdev = cmd.vdev;
6901 	ser_cmd_status = wlan_serialization_request(&cmd);
6902 
6903 	switch (ser_cmd_status) {
6904 	case WLAN_SER_CMD_PENDING:
6905 	case WLAN_SER_CMD_ACTIVE:
6906 		/* Command posted to active/pending list */
6907 		status = QDF_STATUS_SUCCESS;
6908 		break;
6909 	default:
6910 		sme_err("Failed to queue command %d with status:%d",
6911 			  sme_cmd->command, ser_cmd_status);
6912 		status = QDF_STATUS_E_FAILURE;
6913 		goto error;
6914 	}
6915 
6916 	return status;
6917 
6918 error:
6919 	if (vdev)
6920 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
6921 
6922 	csr_release_command_buffer(mac_ctx, sme_cmd);
6923 
6924 	return QDF_STATUS_E_FAILURE;
6925 }
6926 
6927 QDF_STATUS csr_roam_update_config(struct mac_context *mac_ctx, uint8_t session_id,
6928 				  uint16_t capab, uint32_t value)
6929 {
6930 	struct update_config *msg;
6931 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6932 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, session_id);
6933 
6934 	sme_debug("update HT config requested");
6935 	if (!session) {
6936 		sme_err("Session does not exist for session id %d", session_id);
6937 		return QDF_STATUS_E_FAILURE;
6938 	}
6939 
6940 	msg = qdf_mem_malloc(sizeof(*msg));
6941 	if (!msg)
6942 		return QDF_STATUS_E_NOMEM;
6943 
6944 	msg->messageType = eWNI_SME_UPDATE_CONFIG;
6945 	msg->vdev_id = session_id;
6946 	msg->capab = capab;
6947 	msg->value = value;
6948 	msg->length = sizeof(*msg);
6949 	status = umac_send_mb_message_to_mac(msg);
6950 
6951 	return status;
6952 }
6953 
6954 QDF_STATUS csr_send_channel_change_req(struct mac_context *mac,
6955 				      struct channel_change_req *req)
6956 {
6957 	struct scheduler_msg msg = {0};
6958 	struct channel_change_req *ch_change_req;
6959 	QDF_STATUS status;
6960 
6961 	ch_change_req = qdf_mem_malloc(sizeof(*ch_change_req));
6962 	if (!ch_change_req)
6963 		return QDF_STATUS_E_NOMEM;
6964 
6965 	qdf_mem_copy(ch_change_req, req, sizeof(*ch_change_req));
6966 	msg.type = eWNI_SME_CHANNEL_CHANGE_REQ;
6967 	msg.bodyptr = ch_change_req;
6968 	msg.reserved = 0;
6969 
6970 	status = scheduler_post_message(QDF_MODULE_ID_SME,
6971 					QDF_MODULE_ID_PE,
6972 					QDF_MODULE_ID_PE,
6973 					&msg);
6974 	if (QDF_IS_STATUS_ERROR(status)) {
6975 		sme_err("Failed to send channel change request with status : %d",
6976 			status);
6977 		qdf_mem_free(ch_change_req);
6978 	}
6979 
6980 	return status;
6981 }
6982 /*
6983  * Post Beacon Tx Start request to LIM
6984  * immediately after SAP CAC WAIT is
6985  * completed without any RADAR indications.
6986  */
6987 QDF_STATUS csr_roam_start_beacon_req(struct mac_context *mac,
6988 				     struct qdf_mac_addr bssid,
6989 				     uint8_t dfsCacWaitStatus)
6990 {
6991 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6992 	tSirStartBeaconIndication *pMsg;
6993 
6994 	pMsg = qdf_mem_malloc(sizeof(tSirStartBeaconIndication));
6995 	if (!pMsg)
6996 		return QDF_STATUS_E_NOMEM;
6997 
6998 	pMsg->messageType = eWNI_SME_START_BEACON_REQ;
6999 	pMsg->messageLen = sizeof(tSirStartBeaconIndication);
7000 	pMsg->beaconStartStatus = dfsCacWaitStatus;
7001 	qdf_mem_copy(pMsg->bssid, bssid.bytes, QDF_MAC_ADDR_SIZE);
7002 
7003 	status = umac_send_mb_message_to_mac(pMsg);
7004 
7005 	return status;
7006 }
7007 
7008 /*
7009  * csr_roam_modify_add_ies -
7010  * This function sends msg to modify the additional IE buffers in PE
7011  *
7012  * @mac: mac global structure
7013  * @pModifyIE: pointer to tSirModifyIE structure
7014  * @updateType: Type of buffer
7015  *
7016  *
7017  * Return: QDF_STATUS -  Success or failure
7018  */
7019 QDF_STATUS
7020 csr_roam_modify_add_ies(struct mac_context *mac,
7021 			 tSirModifyIE *pModifyIE, eUpdateIEsType updateType)
7022 {
7023 	tpSirModifyIEsInd pModifyAddIEInd = NULL;
7024 	uint8_t *pLocalBuffer = NULL;
7025 	QDF_STATUS status;
7026 
7027 	/* following buffer will be freed by consumer (PE) */
7028 	pLocalBuffer = qdf_mem_malloc(pModifyIE->ieBufferlength);
7029 	if (!pLocalBuffer)
7030 		return QDF_STATUS_E_NOMEM;
7031 
7032 	pModifyAddIEInd = qdf_mem_malloc(sizeof(tSirModifyIEsInd));
7033 	if (!pModifyAddIEInd) {
7034 		qdf_mem_free(pLocalBuffer);
7035 		return QDF_STATUS_E_NOMEM;
7036 	}
7037 
7038 	/*copy the IE buffer */
7039 	qdf_mem_copy(pLocalBuffer, pModifyIE->pIEBuffer,
7040 		     pModifyIE->ieBufferlength);
7041 	qdf_mem_zero(pModifyAddIEInd, sizeof(tSirModifyIEsInd));
7042 
7043 	pModifyAddIEInd->msgType = eWNI_SME_MODIFY_ADDITIONAL_IES;
7044 	pModifyAddIEInd->msgLen = sizeof(tSirModifyIEsInd);
7045 
7046 	qdf_copy_macaddr(&pModifyAddIEInd->modifyIE.bssid, &pModifyIE->bssid);
7047 
7048 	pModifyAddIEInd->modifyIE.vdev_id = pModifyIE->vdev_id;
7049 	pModifyAddIEInd->modifyIE.notify = pModifyIE->notify;
7050 	pModifyAddIEInd->modifyIE.ieID = pModifyIE->ieID;
7051 	pModifyAddIEInd->modifyIE.ieIDLen = pModifyIE->ieIDLen;
7052 	pModifyAddIEInd->modifyIE.pIEBuffer = pLocalBuffer;
7053 	pModifyAddIEInd->modifyIE.ieBufferlength = pModifyIE->ieBufferlength;
7054 	pModifyAddIEInd->modifyIE.oui_length = pModifyIE->oui_length;
7055 
7056 	pModifyAddIEInd->updateType = updateType;
7057 
7058 	status = umac_send_mb_message_to_mac(pModifyAddIEInd);
7059 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7060 		sme_err("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg status %d",
7061 			status);
7062 		qdf_mem_free(pLocalBuffer);
7063 	}
7064 	return status;
7065 }
7066 
7067 /*
7068  * csr_roam_update_add_ies -
7069  * This function sends msg to updates the additional IE buffers in PE
7070  *
7071  * @mac: mac global structure
7072  * @sessionId: SME session id
7073  * @bssid: BSSID
7074  * @additionIEBuffer: buffer containing addition IE from hostapd
7075  * @length: length of buffer
7076  * @updateType: Type of buffer
7077  * @append: append or replace completely
7078  *
7079  *
7080  * Return: QDF_STATUS -  Success or failure
7081  */
7082 QDF_STATUS
7083 csr_roam_update_add_ies(struct mac_context *mac,
7084 			 tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType)
7085 {
7086 	tpSirUpdateIEsInd pUpdateAddIEs = NULL;
7087 	uint8_t *pLocalBuffer = NULL;
7088 	QDF_STATUS status;
7089 
7090 	if (pUpdateIE->ieBufferlength != 0) {
7091 		/* Following buffer will be freed by consumer (PE) */
7092 		pLocalBuffer = qdf_mem_malloc(pUpdateIE->ieBufferlength);
7093 		if (!pLocalBuffer) {
7094 			return QDF_STATUS_E_NOMEM;
7095 		}
7096 		qdf_mem_copy(pLocalBuffer, pUpdateIE->pAdditionIEBuffer,
7097 			     pUpdateIE->ieBufferlength);
7098 	}
7099 
7100 	pUpdateAddIEs = qdf_mem_malloc(sizeof(tSirUpdateIEsInd));
7101 	if (!pUpdateAddIEs) {
7102 		qdf_mem_free(pLocalBuffer);
7103 		return QDF_STATUS_E_NOMEM;
7104 	}
7105 
7106 	pUpdateAddIEs->msgType = eWNI_SME_UPDATE_ADDITIONAL_IES;
7107 	pUpdateAddIEs->msgLen = sizeof(tSirUpdateIEsInd);
7108 
7109 	qdf_copy_macaddr(&pUpdateAddIEs->updateIE.bssid, &pUpdateIE->bssid);
7110 
7111 	pUpdateAddIEs->updateIE.vdev_id = pUpdateIE->vdev_id;
7112 	pUpdateAddIEs->updateIE.append = pUpdateIE->append;
7113 	pUpdateAddIEs->updateIE.notify = pUpdateIE->notify;
7114 	pUpdateAddIEs->updateIE.ieBufferlength = pUpdateIE->ieBufferlength;
7115 	pUpdateAddIEs->updateIE.pAdditionIEBuffer = pLocalBuffer;
7116 
7117 	pUpdateAddIEs->updateType = updateType;
7118 
7119 	status = umac_send_mb_message_to_mac(pUpdateAddIEs);
7120 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7121 		sme_err("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg status %d",
7122 			status);
7123 		qdf_mem_free(pLocalBuffer);
7124 	}
7125 	return status;
7126 }
7127 
7128 /**
7129  * csr_send_ext_change_freq()- function to post send ECSA
7130  * action frame to lim.
7131  * @mac_ctx: pointer to global mac structure
7132  * @ch_freq: new channel freq to switch
7133  * @session_id: senssion it should be sent on.
7134  *
7135  * This function is called to post ECSA frame to lim.
7136  *
7137  * Return: success if msg posted to LIM else return failure
7138  */
7139 QDF_STATUS csr_send_ext_change_freq(struct mac_context *mac_ctx,
7140 				    qdf_freq_t ch_freq, uint8_t session_id)
7141 {
7142 	QDF_STATUS status = QDF_STATUS_SUCCESS;
7143 	struct sir_sme_ext_cng_chan_req *msg;
7144 
7145 	msg = qdf_mem_malloc(sizeof(*msg));
7146 	if (!msg)
7147 		return QDF_STATUS_E_NOMEM;
7148 
7149 	msg->message_type = eWNI_SME_EXT_CHANGE_CHANNEL;
7150 	msg->length = sizeof(*msg);
7151 	msg->new_ch_freq = ch_freq;
7152 	msg->vdev_id = session_id;
7153 	status = umac_send_mb_message_to_mac(msg);
7154 	return status;
7155 }
7156 
7157 QDF_STATUS csr_csa_restart(struct mac_context *mac_ctx, uint8_t vdev_id)
7158 {
7159 	QDF_STATUS status;
7160 	struct wlan_objmgr_vdev *vdev;
7161 	struct scheduler_msg message = {0};
7162 
7163 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
7164 						    WLAN_LEGACY_MAC_ID);
7165 	if (!vdev) {
7166 		sme_err("VDEV not found for vdev id: %d", vdev_id);
7167 		return QDF_STATUS_E_FAILURE;
7168 	}
7169 
7170 	if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_AP_CSA_START, NULL);
7171 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
7172 
7173 	/* Serialize the req through MC thread */
7174 	message.bodyval = vdev_id;
7175 	message.type    = eWNI_SME_CSA_RESTART_REQ;
7176 	status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_PE,
7177 					QDF_MODULE_ID_PE, &message);
7178 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7179 		sme_err("scheduler_post_msg failed!(err=%d)", status);
7180 		status = QDF_STATUS_E_FAILURE;
7181 	}
7182 
7183 	return status;
7184 }
7185 
7186 QDF_STATUS csr_roam_send_chan_sw_ie_request(struct mac_context *mac_ctx,
7187 					    struct qdf_mac_addr bssid,
7188 					    uint32_t target_chan_freq,
7189 					    uint8_t csa_ie_reqd,
7190 					    struct ch_params *ch_params,
7191 					    uint32_t new_cac_ms)
7192 {
7193 	QDF_STATUS status = QDF_STATUS_SUCCESS;
7194 	tSirDfsCsaIeRequest *msg;
7195 
7196 	msg = qdf_mem_malloc(sizeof(tSirDfsCsaIeRequest));
7197 	if (!msg)
7198 		return QDF_STATUS_E_NOMEM;
7199 
7200 	msg->msgType = eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ;
7201 	msg->msgLen = sizeof(tSirDfsCsaIeRequest);
7202 
7203 	msg->target_chan_freq = target_chan_freq;
7204 	msg->csaIeRequired = csa_ie_reqd;
7205 	msg->ch_switch_beacon_cnt =
7206 		 mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt;
7207 	if (mac_ctx->sap.one_time_csa_count) {
7208 		msg->ch_switch_beacon_cnt = mac_ctx->sap.one_time_csa_count;
7209 		mac_ctx->sap.one_time_csa_count = 0;
7210 	}
7211 	msg->ch_switch_mode = mac_ctx->sap.SapDfsInfo.sap_ch_switch_mode;
7212 	msg->dfs_ch_switch_disable =
7213 		mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch;
7214 	msg->new_chan_cac_ms = new_cac_ms;
7215 	qdf_mem_copy(msg->bssid, bssid.bytes, QDF_MAC_ADDR_SIZE);
7216 	qdf_mem_copy(&msg->ch_params, ch_params, sizeof(struct ch_params));
7217 
7218 	status = umac_send_mb_message_to_mac(msg);
7219 
7220 	return status;
7221 }
7222 
7223 QDF_STATUS csr_sta_continue_csa(struct mac_context *mac_ctx, uint8_t vdev_id)
7224 {
7225 	QDF_STATUS status;
7226 	struct scheduler_msg message = {0};
7227 
7228 	/* Serialize the req through MC thread */
7229 	message.bodyval = vdev_id;
7230 	message.type    = eWNI_SME_STA_CSA_CONTINUE_REQ;
7231 	status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_PE,
7232 					QDF_MODULE_ID_PE, &message);
7233 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7234 		sme_err("eWNI_SME_STA_CSA_CONTINUE_REQ failed!(err=%d)",
7235 			status);
7236 		status = QDF_STATUS_E_FAILURE;
7237 	}
7238 
7239 	return status;
7240 }
7241 
7242 /**
7243  * csr_update_op_class_array() - update op class for each band
7244  * @mac_ctx:          mac global context
7245  * @op_classes:       out param, operating class array to update
7246  * @channel_info:     channel info
7247  * @ch_name:          channel band name to display in debug messages
7248  * @i:                out param, stores number of operating classes
7249  *
7250  * Return: void
7251  */
7252 static void
7253 csr_update_op_class_array(struct mac_context *mac_ctx,
7254 			  uint8_t *op_classes,
7255 			  struct csr_channel *channel_info,
7256 			  char *ch_name,
7257 			  uint8_t *i)
7258 {
7259 	uint8_t j = 0, idx = 0, class = 0;
7260 	bool found = false;
7261 	uint8_t num_channels = channel_info->numChannels;
7262 	uint8_t ch_num;
7263 
7264 	sme_debug("Num %s channels,  %d", ch_name, num_channels);
7265 
7266 	for (idx = 0; idx < num_channels &&
7267 		*i < (REG_MAX_SUPP_OPER_CLASSES - 1); idx++) {
7268 		wlan_reg_freq_to_chan_op_class(
7269 			mac_ctx->pdev, channel_info->channel_freq_list[idx],
7270 			true, BIT(BEHAV_NONE), &class, &ch_num);
7271 
7272 		found = false;
7273 		for (j = 0; j < REG_MAX_SUPP_OPER_CLASSES - 1; j++) {
7274 			if (op_classes[j] == class) {
7275 				found = true;
7276 				break;
7277 			}
7278 		}
7279 
7280 		if (!found) {
7281 			op_classes[*i] = class;
7282 			*i = *i + 1;
7283 		}
7284 	}
7285 }
7286 
7287 /**
7288  * csr_init_operating_classes() - update op class for all bands
7289  * @mac: pointer to mac context.
7290  *
7291  * Return: void
7292  */
7293 static void csr_init_operating_classes(struct mac_context *mac)
7294 {
7295 	uint8_t i = 0;
7296 	uint8_t j = 0;
7297 	uint8_t swap = 0;
7298 	uint8_t numClasses = 0;
7299 	uint8_t opClasses[REG_MAX_SUPP_OPER_CLASSES] = {0,};
7300 	uint8_t reg_cc[REG_ALPHA2_LEN + 1];
7301 
7302 	wlan_reg_read_current_country(mac->psoc, reg_cc);
7303 	sme_debug("Current Country = %s", reg_cc);
7304 
7305 	csr_update_op_class_array(mac, opClasses,
7306 				  &mac->scan.base_channels, "20MHz", &i);
7307 	numClasses = i;
7308 
7309 	/* As per spec the operating classes should be in ascending order.
7310 	 * Bubble sort is fine since we don't have many classes
7311 	 */
7312 	for (i = 0; i < (numClasses - 1); i++) {
7313 		for (j = 0; j < (numClasses - i - 1); j++) {
7314 			/* For decreasing order use < */
7315 			if (opClasses[j] > opClasses[j + 1]) {
7316 				swap = opClasses[j];
7317 				opClasses[j] = opClasses[j + 1];
7318 				opClasses[j + 1] = swap;
7319 			}
7320 		}
7321 	}
7322 
7323 	/* Set the ordered list of op classes in regdomain
7324 	 * for use by other modules
7325 	 */
7326 	wlan_reg_dmn_set_curr_opclasses(numClasses, &opClasses[0]);
7327 }
7328 
7329 /**
7330  * csr_process_set_hw_mode() - Set HW mode command to PE
7331  * @mac: Globacl MAC pointer
7332  * @command: Command received from SME
7333  *
7334  * Posts the set HW mode command to PE. This message passing
7335  * through PE is required for PE's internal management
7336  *
7337  * Return: None
7338  */
7339 void csr_process_set_hw_mode(struct mac_context *mac, tSmeCmd *command)
7340 {
7341 	uint32_t len;
7342 	struct s_sir_set_hw_mode *cmd = NULL;
7343 	QDF_STATUS status;
7344 	struct scheduler_msg msg = {0};
7345 	struct sir_set_hw_mode_resp *param;
7346 	enum policy_mgr_hw_mode_change hw_mode;
7347 	enum policy_mgr_conc_next_action action;
7348 	enum set_hw_mode_status hw_mode_change_status =
7349 						SET_HW_MODE_STATUS_ECANCELED;
7350 
7351 	/* Setting HW mode is for the entire system.
7352 	 * So, no need to check session
7353 	 */
7354 
7355 	if (!command) {
7356 		sme_err("Set HW mode param is NULL");
7357 		goto fail;
7358 	}
7359 
7360 	len = sizeof(*cmd);
7361 	cmd = qdf_mem_malloc(len);
7362 	if (!cmd)
7363 		/* Probably the fail response will also fail during malloc.
7364 		 * Still proceeding to send response!
7365 		 */
7366 		goto fail;
7367 
7368 	action = command->u.set_hw_mode_cmd.action;
7369 
7370 	status = policy_mgr_validate_dbs_switch(mac->psoc, action);
7371 
7372 	if (QDF_IS_STATUS_ERROR(status)) {
7373 		sme_debug("Hw mode change not sent to FW status = %d", status);
7374 		if (status == QDF_STATUS_E_ALREADY)
7375 			hw_mode_change_status = SET_HW_MODE_STATUS_ALREADY;
7376 		goto fail;
7377 	}
7378 
7379 	hw_mode = policy_mgr_get_hw_mode_change_from_hw_mode_index(
7380 			mac->psoc, command->u.set_hw_mode_cmd.hw_mode_index);
7381 
7382 	if (POLICY_MGR_HW_MODE_NOT_IN_PROGRESS == hw_mode) {
7383 		sme_err("hw_mode %d, failing", hw_mode);
7384 		goto fail;
7385 	}
7386 
7387 	policy_mgr_set_hw_mode_change_in_progress(mac->psoc, hw_mode);
7388 	policy_mgr_reset_connection_update(mac->psoc);
7389 
7390 	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
7391 	     command->u.set_hw_mode_cmd.reason) &&
7392 	    (true == mac->sme.get_connection_info_cb(NULL, NULL))) {
7393 		sme_err("Set HW mode refused: conn in progress");
7394 		policy_mgr_restart_opportunistic_timer(mac->psoc, false);
7395 		goto reset_state;
7396 	}
7397 
7398 	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
7399 	     command->u.set_hw_mode_cmd.reason) &&
7400 	    (!command->u.set_hw_mode_cmd.hw_mode_index &&
7401 	     !policy_mgr_need_opportunistic_upgrade(mac->psoc, NULL))) {
7402 		sme_err("Set HW mode to SMM not needed anymore");
7403 		goto reset_state;
7404 	}
7405 
7406 	cmd->messageType = eWNI_SME_SET_HW_MODE_REQ;
7407 	cmd->length = len;
7408 	cmd->set_hw.hw_mode_index = command->u.set_hw_mode_cmd.hw_mode_index;
7409 	cmd->set_hw.reason = command->u.set_hw_mode_cmd.reason;
7410 	/*
7411 	 * Below callback and context info are not needed for PE as of now.
7412 	 * Storing the passed value in the same s_sir_set_hw_mode format.
7413 	 */
7414 	cmd->set_hw.set_hw_mode_cb = command->u.set_hw_mode_cmd.set_hw_mode_cb;
7415 
7416 	sme_debug(
7417 		"Posting set hw mode req to PE session:%d reason:%d",
7418 		command->u.set_hw_mode_cmd.session_id,
7419 		command->u.set_hw_mode_cmd.reason);
7420 
7421 	status = umac_send_mb_message_to_mac(cmd);
7422 	if (QDF_STATUS_SUCCESS != status) {
7423 		sme_err("Posting to PE failed");
7424 		cmd = NULL;
7425 		goto reset_state;
7426 	}
7427 	return;
7428 
7429 reset_state:
7430 	policy_mgr_set_hw_mode_change_in_progress(mac->psoc,
7431 			POLICY_MGR_HW_MODE_NOT_IN_PROGRESS);
7432 fail:
7433 	if (cmd)
7434 		qdf_mem_free(cmd);
7435 	param = qdf_mem_malloc(sizeof(*param));
7436 	if (!param)
7437 		return;
7438 
7439 	sme_debug("Sending set HW fail response to SME");
7440 	param->status = hw_mode_change_status;
7441 	param->cfgd_hw_mode_index = 0;
7442 	param->num_vdev_mac_entries = 0;
7443 	msg.type = eWNI_SME_SET_HW_MODE_RESP;
7444 	msg.bodyptr = param;
7445 	msg.bodyval = 0;
7446 	sys_process_mmh_msg(mac, &msg);
7447 }
7448 
7449 /**
7450  * csr_process_set_dual_mac_config() - Set HW mode command to PE
7451  * @mac: Global MAC pointer
7452  * @command: Command received from SME
7453  *
7454  * Posts the set dual mac config command to PE.
7455  *
7456  * Return: None
7457  */
7458 void csr_process_set_dual_mac_config(struct mac_context *mac, tSmeCmd *command)
7459 {
7460 	uint32_t len;
7461 	struct sir_set_dual_mac_cfg *cmd;
7462 	QDF_STATUS status;
7463 	struct scheduler_msg msg = {0};
7464 	struct sir_dual_mac_config_resp *param;
7465 
7466 	/* Setting MAC configuration is for the entire system.
7467 	 * So, no need to check session
7468 	 */
7469 
7470 	if (!command) {
7471 		sme_err("Set HW mode param is NULL");
7472 		goto fail;
7473 	}
7474 
7475 	len = sizeof(*cmd);
7476 	cmd = qdf_mem_malloc(len);
7477 	if (!cmd)
7478 		/* Probably the fail response will also fail during malloc.
7479 		 * Still proceeding to send response!
7480 		 */
7481 		goto fail;
7482 
7483 	cmd->message_type = eWNI_SME_SET_DUAL_MAC_CFG_REQ;
7484 	cmd->length = len;
7485 	cmd->set_dual_mac.scan_config = command->u.set_dual_mac_cmd.scan_config;
7486 	cmd->set_dual_mac.fw_mode_config =
7487 		command->u.set_dual_mac_cmd.fw_mode_config;
7488 	/*
7489 	 * Below callback and context info are not needed for PE as of now.
7490 	 * Storing the passed value in the same sir_set_dual_mac_cfg format.
7491 	 */
7492 	cmd->set_dual_mac.set_dual_mac_cb =
7493 		command->u.set_dual_mac_cmd.set_dual_mac_cb;
7494 
7495 	sme_debug("Posting eWNI_SME_SET_DUAL_MAC_CFG_REQ to PE: %x %x",
7496 		  cmd->set_dual_mac.scan_config,
7497 		  cmd->set_dual_mac.fw_mode_config);
7498 
7499 	status = umac_send_mb_message_to_mac(cmd);
7500 	if (QDF_IS_STATUS_ERROR(status)) {
7501 		sme_err("Posting to PE failed");
7502 		goto fail;
7503 	}
7504 	return;
7505 fail:
7506 	param = qdf_mem_malloc(sizeof(*param));
7507 	if (!param)
7508 		return;
7509 
7510 	sme_err("Sending set dual mac fail response to SME");
7511 	param->status = SET_HW_MODE_STATUS_ECANCELED;
7512 	msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP;
7513 	msg.bodyptr = param;
7514 	msg.bodyval = 0;
7515 	sys_process_mmh_msg(mac, &msg);
7516 }
7517 
7518 /**
7519  * csr_process_set_antenna_mode() - Set antenna mode command to
7520  * PE
7521  * @mac: Global MAC pointer
7522  * @command: Command received from SME
7523  *
7524  * Posts the set dual mac config command to PE.
7525  *
7526  * Return: None
7527  */
7528 void csr_process_set_antenna_mode(struct mac_context *mac, tSmeCmd *command)
7529 {
7530 	uint32_t len;
7531 	struct sir_set_antenna_mode *cmd;
7532 	QDF_STATUS status;
7533 	struct scheduler_msg msg = {0};
7534 	struct sir_antenna_mode_resp *param;
7535 
7536 	/* Setting MAC configuration is for the entire system.
7537 	 * So, no need to check session
7538 	 */
7539 
7540 	if (!command) {
7541 		sme_err("Set antenna mode param is NULL");
7542 		goto fail;
7543 	}
7544 
7545 	len = sizeof(*cmd);
7546 	cmd = qdf_mem_malloc(len);
7547 	if (!cmd)
7548 		goto fail;
7549 
7550 	cmd->message_type = eWNI_SME_SET_ANTENNA_MODE_REQ;
7551 	cmd->length = len;
7552 	cmd->set_antenna_mode = command->u.set_antenna_mode_cmd;
7553 
7554 	sme_debug(
7555 		"Posting eWNI_SME_SET_ANTENNA_MODE_REQ to PE: %d %d",
7556 		cmd->set_antenna_mode.num_rx_chains,
7557 		cmd->set_antenna_mode.num_tx_chains);
7558 
7559 	status = umac_send_mb_message_to_mac(cmd);
7560 	if (QDF_STATUS_SUCCESS != status) {
7561 		sme_err("Posting to PE failed");
7562 		/*
7563 		 * umac_send_mb_message_to_mac would've released the mem
7564 		 * allocated by cmd.
7565 		 */
7566 		goto fail;
7567 	}
7568 
7569 	return;
7570 fail:
7571 	param = qdf_mem_malloc(sizeof(*param));
7572 	if (!param)
7573 		return;
7574 
7575 	sme_err("Sending set dual mac fail response to SME");
7576 	param->status = SET_ANTENNA_MODE_STATUS_ECANCELED;
7577 	msg.type = eWNI_SME_SET_ANTENNA_MODE_RESP;
7578 	msg.bodyptr = param;
7579 	msg.bodyval = 0;
7580 	sys_process_mmh_msg(mac, &msg);
7581 }
7582 
7583 /**
7584  * csr_process_nss_update_req() - Update nss command to PE
7585  * @mac: Globacl MAC pointer
7586  * @command: Command received from SME
7587  *
7588  * Posts the nss update command to PE. This message passing
7589  * through PE is required for PE's internal management
7590  *
7591  * Return: None
7592  */
7593 void csr_process_nss_update_req(struct mac_context *mac, tSmeCmd *command)
7594 {
7595 	uint32_t len;
7596 	struct sir_nss_update_request *msg;
7597 	QDF_STATUS status;
7598 	struct scheduler_msg msg_return = {0};
7599 	struct sir_bcn_update_rsp *param;
7600 	struct csr_roam_session *session;
7601 
7602 
7603 	if (!CSR_IS_SESSION_VALID(mac, command->vdev_id)) {
7604 		sme_err("Invalid session id %d", command->vdev_id);
7605 		goto fail;
7606 	}
7607 	session = CSR_GET_SESSION(mac, command->vdev_id);
7608 
7609 	len = sizeof(*msg);
7610 	msg = qdf_mem_malloc(len);
7611 	if (!msg)
7612 		/* Probably the fail response is also fail during malloc.
7613 		 * Still proceeding to send response!
7614 		 */
7615 		goto fail;
7616 
7617 	msg->msgType = eWNI_SME_NSS_UPDATE_REQ;
7618 	msg->msgLen = sizeof(*msg);
7619 
7620 	msg->new_nss = command->u.nss_update_cmd.new_nss;
7621 	msg->ch_width = command->u.nss_update_cmd.ch_width;
7622 	msg->vdev_id = command->u.nss_update_cmd.session_id;
7623 
7624 	sme_debug("Posting eWNI_SME_NSS_UPDATE_REQ to PE");
7625 
7626 	status = umac_send_mb_message_to_mac(msg);
7627 	if (QDF_IS_STATUS_SUCCESS(status))
7628 		return;
7629 
7630 	sme_err("Posting to PE failed");
7631 fail:
7632 	param = qdf_mem_malloc(sizeof(*param));
7633 	if (!param)
7634 		return;
7635 
7636 	sme_err("Sending nss update fail response to SME");
7637 	param->status = QDF_STATUS_E_FAILURE;
7638 	param->vdev_id = command->u.nss_update_cmd.session_id;
7639 	param->reason = REASON_NSS_UPDATE;
7640 	msg_return.type = eWNI_SME_NSS_UPDATE_RSP;
7641 	msg_return.bodyptr = param;
7642 	msg_return.bodyval = 0;
7643 	sys_process_mmh_msg(mac, &msg_return);
7644 }
7645 
7646 /**
7647  * csr_process_sap_ch_width_update() - Update ch_width command to PE
7648  * @mac: Globacl MAC pointer
7649  * @command: Command received from SME
7650  *
7651  * Posts the ch_width update command to PE. This message passing
7652  * through PE is required for PE's internal management
7653  *
7654  * Return: None
7655  */
7656 void csr_process_sap_ch_width_update(struct mac_context *mac, tSmeCmd *command)
7657 {
7658 	uint32_t len;
7659 	struct sir_sap_ch_width_update *msg;
7660 	QDF_STATUS status;
7661 	struct scheduler_msg msg_return = {0};
7662 	struct sir_bcn_update_rsp *param;
7663 	enum policy_mgr_conn_update_reason reason =
7664 				command->u.bw_update_cmd.reason;
7665 
7666 	if (!CSR_IS_SESSION_VALID(mac, command->vdev_id)) {
7667 		sme_err("Invalid session id %d", command->vdev_id);
7668 		goto fail;
7669 	}
7670 
7671 	if ((reason == POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC) &&
7672 	    (mac->sme.get_connection_info_cb(NULL, NULL))) {
7673 		policy_mgr_restart_opportunistic_timer(mac->psoc, false);
7674 		sme_info("Vdev %d : Avoid set BW as conn in progress",
7675 			 command->vdev_id);
7676 		goto fail;
7677 	}
7678 
7679 	if ((reason == POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC) &&
7680 	    (!policy_mgr_need_opportunistic_upgrade(mac->psoc, &reason))) {
7681 		sme_info("Vdev %d: BW update not needed anymore",
7682 			 command->vdev_id);
7683 		goto fail;
7684 	}
7685 
7686 	len = sizeof(*msg);
7687 	msg = qdf_mem_malloc(len);
7688 	if (!msg)
7689 		/* Probably the fail response is also fail during malloc.
7690 		 * Still proceeding to send response!
7691 		 */
7692 		goto fail;
7693 
7694 	msg->msgType = eWNI_SME_SAP_CH_WIDTH_UPDATE_REQ;
7695 	msg->msgLen = sizeof(*msg);
7696 
7697 	msg->ch_width = command->u.bw_update_cmd.ch_width;
7698 	msg->vdev_id = command->u.bw_update_cmd.vdev_id;
7699 
7700 	sme_debug("Posting eWNI_SME_SAP_CH_WIDTH_UPDATE_REQ to PE");
7701 
7702 	status = umac_send_mb_message_to_mac(msg);
7703 	if (QDF_IS_STATUS_SUCCESS(status))
7704 		return;
7705 
7706 	sme_err("Posting to PE failed");
7707 fail:
7708 	param = qdf_mem_malloc(sizeof(*param));
7709 	if (param) {
7710 		param->status = QDF_STATUS_E_FAILURE;
7711 		param->vdev_id = command->u.bw_update_cmd.vdev_id;
7712 		param->reason = REASON_CH_WIDTH_UPDATE;
7713 	}
7714 	msg_return.type = eWNI_SME_SAP_CH_WIDTH_UPDATE_RSP;
7715 	msg_return.bodyptr = param;
7716 	msg_return.bodyval = 0;
7717 	sys_process_mmh_msg(mac, &msg_return);
7718 }
7719 
7720 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
7721 #ifdef WLAN_FEATURE_SAE
7722 /**
7723  * csr_process_roam_auth_sae_callback() - API to trigger the
7724  * WPA3 pre-auth event for candidate AP received from firmware.
7725  * @mac_ctx: Global mac context pointer
7726  * @vdev_id: vdev id
7727  * @roam_bssid: Candidate BSSID to roam
7728  * @akm: Candidate AKM
7729  *
7730  * This function calls the hdd_sme_roam_callback with reason
7731  * eCSR_ROAM_SAE_COMPUTE to trigger SAE auth to supplicant.
7732  */
7733 static QDF_STATUS
7734 csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
7735 				   uint8_t vdev_id,
7736 				   struct qdf_mac_addr roam_bssid,
7737 				   uint32_t akm)
7738 {
7739 	struct csr_roam_info *roam_info;
7740 	struct sir_sae_info sae_info;
7741 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id);
7742 
7743 	if (!session) {
7744 		sme_err("WPA3 Preauth event with invalid session id:%d",
7745 			vdev_id);
7746 		return QDF_STATUS_E_FAILURE;
7747 	}
7748 
7749 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
7750 	if (!roam_info)
7751 		return QDF_STATUS_E_FAILURE;
7752 
7753 	sae_info.msg_len = sizeof(sae_info);
7754 	sae_info.vdev_id = vdev_id;
7755 	sae_info.akm = akm;
7756 	wlan_cm_get_roam_offload_ssid(mac_ctx->psoc, vdev_id,
7757 				      sae_info.ssid.ssId,
7758 				      &sae_info.ssid.length);
7759 	qdf_mem_copy(sae_info.peer_mac_addr.bytes,
7760 		     roam_bssid.bytes, QDF_MAC_ADDR_SIZE);
7761 
7762 	roam_info->sae_info = &sae_info;
7763 
7764 	csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
7765 			       eCSR_ROAM_SAE_COMPUTE, eCSR_ROAM_RESULT_NONE);
7766 
7767 	qdf_mem_free(roam_info);
7768 
7769 	return QDF_STATUS_SUCCESS;
7770 }
7771 #else
7772 static inline QDF_STATUS
7773 csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
7774 				   uint8_t vdev_id,
7775 				   struct qdf_mac_addr roam_bssid,
7776 				   uint32_t akm)
7777 {
7778 	return QDF_STATUS_E_NOSUPPORT;
7779 }
7780 #endif
7781 
7782 QDF_STATUS
7783 csr_roam_auth_offload_callback(struct mac_context *mac_ctx, uint8_t vdev_id,
7784 			       struct qdf_mac_addr bssid, uint32_t akm)
7785 {
7786 	QDF_STATUS status;
7787 
7788 	status = sme_acquire_global_lock(&mac_ctx->sme);
7789 	if (!QDF_IS_STATUS_SUCCESS(status))
7790 		return status;
7791 
7792 	status = csr_process_roam_auth_sae_callback(mac_ctx, vdev_id,
7793 						    bssid, akm);
7794 
7795 	sme_release_global_lock(&mac_ctx->sme);
7796 
7797 	return status;
7798 
7799 }
7800 #endif
7801 
7802 QDF_STATUS csr_update_owe_info(struct mac_context *mac,
7803 			       struct assoc_ind *assoc_ind)
7804 {
7805 	uint32_t session_id = WLAN_UMAC_VDEV_ID_MAX;
7806 	QDF_STATUS status;
7807 
7808 	status = csr_roam_get_session_id_from_bssid(mac,
7809 					(struct qdf_mac_addr *)assoc_ind->bssId,
7810 					&session_id);
7811 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7812 		sme_debug("Couldn't find session_id for given BSSID");
7813 		return QDF_STATUS_E_FAILURE;
7814 	}
7815 
7816 	/* Send Association completion message to PE */
7817 	if (assoc_ind->owe_status)
7818 		status = QDF_STATUS_E_INVAL;
7819 	status = csr_send_assoc_cnf_msg(mac, assoc_ind, status,
7820 					assoc_ind->owe_status);
7821 	/*
7822 	 * send a message to CSR itself just to avoid the EAPOL frames
7823 	 * going OTA before association response
7824 	 */
7825 	if (assoc_ind->owe_status == 0)
7826 		status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac,
7827 								   assoc_ind,
7828 								   status,
7829 								   session_id);
7830 
7831 	return status;
7832 }
7833 
7834 QDF_STATUS csr_update_ft_info(struct mac_context *mac,
7835 			      struct assoc_ind *assoc_ind)
7836 {
7837 	QDF_STATUS status;
7838 
7839 	/* Send Association completion message to PE */
7840 	status = assoc_ind->ft_status ? QDF_STATUS_E_INVAL : QDF_STATUS_SUCCESS;
7841 	assoc_ind->need_assoc_rsp_tx_cb = true;
7842 	status = csr_send_assoc_cnf_msg(mac, assoc_ind, status,
7843 					assoc_ind->ft_status);
7844 	return status;
7845 }
7846 
7847 /**
7848  * csr_set_sap_ser_params() - API to fill serialization parameters for
7849  * SAP requests
7850  * @cmd : Serialization command
7851  * @cmd_type: Type of serialization command
7852  *
7853  * Return: Void
7854  */
7855 static void csr_set_sap_ser_params(struct wlan_serialization_command *cmd,
7856 				   enum wlan_serialization_cmd_type cmd_type)
7857 {
7858 	cmd->cmd_type = cmd_type;
7859 	cmd->source = WLAN_UMAC_COMP_MLME;
7860 	cmd->cmd_cb = sme_sap_ser_callback;
7861 	cmd->is_high_priority =  false;
7862 	cmd->is_blocking = true;
7863 	return;
7864 }
7865 
7866 QDF_STATUS csr_bss_start(struct mac_context *mac, uint32_t vdev_id,
7867 			 struct start_bss_config *bss_config)
7868 {
7869 	struct wlan_serialization_command cmd = {0};
7870 	struct wlan_objmgr_vdev *vdev;
7871 	struct start_bss_config *start_bss_cfg = NULL;
7872 	enum QDF_OPMODE persona;
7873 	enum wlan_serialization_status status;
7874 	struct csr_roam_session *session;
7875 	struct validate_bss_data candidate;
7876 
7877 	session = CSR_GET_SESSION(mac, vdev_id);
7878 	if (!session)
7879 		return QDF_STATUS_E_FAILURE;
7880 
7881 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac->pdev, vdev_id,
7882 						    WLAN_LEGACY_MAC_ID);
7883 	if (!vdev) {
7884 		sme_err("VDEV not found for vdev id : %d", vdev_id);
7885 		return QDF_STATUS_E_FAILURE;
7886 	}
7887 
7888 	persona = wlan_vdev_mlme_get_opmode(vdev);
7889 	if (persona != QDF_SAP_MODE && persona != QDF_NDI_MODE &&
7890 	    persona != QDF_P2P_GO_MODE) {
7891 		sme_err("Start BSS request for invalid mode %d", persona);
7892 		goto error;
7893 	}
7894 
7895 	start_bss_cfg = qdf_mem_malloc(sizeof(struct start_bss_config));
7896 	if (!start_bss_cfg) {
7897 		sme_err("SAP BSS config allocation failed");
7898 		goto error;
7899 	}
7900 
7901 	qdf_mem_copy(start_bss_cfg, bss_config,
7902 		     sizeof(struct start_bss_config));
7903 	start_bss_cfg->cmd_id = csr_get_monotonous_number(mac);
7904 
7905 	session->cb_mode = start_bss_cfg->sec_ch_offset;
7906 	session->bcn_int = bss_config->beaconInterval;
7907 	candidate.beacon_interval = session->bcn_int;
7908 	candidate.chan_freq = bss_config->oper_ch_freq;
7909 	if_mgr_is_beacon_interval_valid(mac->pdev, vdev_id,
7910 					&candidate);
7911 	bss_config->beaconInterval = candidate.beacon_interval;
7912 	session->bcn_int = candidate.beacon_interval;
7913 
7914 	cmd.cmd_id = start_bss_cfg->cmd_id;
7915 	csr_set_sap_ser_params(&cmd, WLAN_SER_CMD_VDEV_START_BSS);
7916 	cmd.umac_cmd = start_bss_cfg;
7917 	cmd.vdev = vdev;
7918 	csr_fill_cmd_timeout(&cmd);
7919 
7920 	status = wlan_vdev_mlme_ser_start_bss(&cmd);
7921 	switch (status) {
7922 	case WLAN_SER_CMD_PENDING:
7923 	case WLAN_SER_CMD_ACTIVE:
7924 		break;
7925 	default:
7926 		sme_err("ser cmd status %d", status);
7927 		goto error;
7928 	}
7929 
7930 	return QDF_STATUS_SUCCESS;
7931 error:
7932 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
7933 	if (start_bss_cfg)
7934 		qdf_mem_free(start_bss_cfg);
7935 
7936 	return QDF_STATUS_E_FAILURE;
7937 }
7938 
7939 QDF_STATUS csr_roam_issue_stop_bss_cmd(struct mac_context *mac,
7940 				       uint8_t vdev_id,
7941 				       eCsrRoamBssType bss_type)
7942 {
7943 	struct wlan_objmgr_vdev *vdev;
7944 	struct wlan_serialization_command cmd = {0};
7945 	enum wlan_serialization_status status;
7946 	struct stop_bss_req *stop_bss_req;
7947 
7948 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac->pdev, vdev_id,
7949 						    WLAN_LEGACY_MAC_ID);
7950 	if (!vdev) {
7951 		sme_err("VDEV not found for vdev id : %d", vdev_id);
7952 		return QDF_STATUS_E_FAILURE;
7953 	}
7954 
7955 	/* Change the substate in case it is wait-for-key */
7956 	if (CSR_IS_WAIT_FOR_KEY(mac, vdev_id)) {
7957 		cm_stop_wait_for_key_timer(mac->psoc, vdev_id);
7958 		csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_NONE,
7959 					 vdev_id);
7960 	}
7961 
7962 	sme_debug("Stop BSS vdev_id: %d bss_type %d", vdev_id, bss_type);
7963 	stop_bss_req = qdf_mem_malloc(sizeof(*stop_bss_req));
7964 	if (!stop_bss_req)
7965 		goto error;
7966 
7967 	stop_bss_req->vdev_id = vdev_id;
7968 	stop_bss_req->cmd_id = csr_get_monotonous_number(mac);
7969 
7970 	cmd.cmd_id = stop_bss_req->cmd_id;
7971 	csr_set_sap_ser_params(&cmd, WLAN_SER_CMD_VDEV_STOP_BSS);
7972 	cmd.umac_cmd = stop_bss_req;
7973 	cmd.vdev = vdev;
7974 	csr_fill_cmd_timeout(&cmd);
7975 
7976 	status = wlan_vdev_mlme_ser_stop_bss(&cmd);
7977 	switch (status) {
7978 	case WLAN_SER_CMD_PENDING:
7979 	case WLAN_SER_CMD_ACTIVE:
7980 		break;
7981 	default:
7982 		sme_err("ser cmd status %d", status);
7983 		goto error;
7984 	}
7985 	return QDF_STATUS_SUCCESS;
7986 
7987 error:
7988 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
7989 	qdf_mem_free(stop_bss_req);
7990 	return QDF_STATUS_E_FAILURE;
7991 }
7992 
7993 static void csr_process_stop_bss_response(struct mac_context *mac_ctx,
7994 					  uint32_t vdev_id)
7995 {
7996 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id);
7997 
7998 	if (CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac_ctx, vdev_id)) {
7999 		csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
8000 		csr_set_default_dot11_mode(mac_ctx);
8001 	}
8002 
8003 	csr_roam_call_callback(mac_ctx, vdev_id, NULL, eCSR_ROAM_INFRA_IND,
8004 			       eCSR_ROAM_RESULT_INFRA_STOPPED);
8005 	return;
8006 }
8007 
8008 /**
8009  * csr_process_sap_results() - API to process the LIM response for
8010  * the messages posted by SAP module
8011  * @mac_ctx: mac context
8012  * @req: Serialization command posted by SAP
8013  * @rsp: Response from LIM
8014  * @result: Result from LIM
8015  * @vdev_id : vdev id
8016  *
8017  * Return: void
8018  */
8019 static bool csr_process_sap_results(struct mac_context *mac_ctx,
8020 				    void *rsp,
8021 				    enum csr_sap_response_type result,
8022 				    uint8_t vdev_id)
8023 {
8024 	struct csr_roam_info *roam_info;
8025 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id);
8026 	eRoamCmdStatus roam_status = eCSR_ROAM_INFRA_IND;
8027 	eCsrRoamResult roam_result = eCSR_ROAM_RESULT_INFRA_START_FAILED;
8028 	enum QDF_OPMODE opmode;
8029 
8030 	if (!session) {
8031 		sme_err("session %d not found ", vdev_id);
8032 		return false;
8033 	}
8034 
8035 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
8036 	if (!roam_info)
8037 		return false;
8038 
8039 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
8040 	sme_debug("SAP result : %d", result);
8041 
8042 	switch (result) {
8043 	case CSR_SAP_START_BSS_SUCCESS:
8044 		csr_roam_process_start_bss_success(mac_ctx, roam_info,
8045 						   rsp, vdev_id);
8046 		break;
8047 	case CSR_SAP_START_BSS_FAILURE:
8048 		if (opmode == QDF_NDI_MODE) {
8049 			csr_roam_update_ndp_return_params(mac_ctx,
8050 							  CSR_SAP_START_BSS_FAILURE,
8051 							  &roam_status,
8052 							  &roam_result,
8053 							  roam_info);
8054 		}
8055 		csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
8056 				       roam_status, roam_result);
8057 		csr_set_default_dot11_mode(mac_ctx);
8058 		break;
8059 	case CSR_SAP_STOP_BSS_SUCCESS:
8060 	case CSR_SAP_STOP_BSS_FAILURE:
8061 		if (opmode == QDF_NDI_MODE) {
8062 			qdf_mem_zero(roam_info, sizeof(*roam_info));
8063 			csr_roam_update_ndp_return_params(mac_ctx, result,
8064 							  &roam_status,
8065 							  &roam_result,
8066 							  roam_info);
8067 			csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
8068 					       roam_status, roam_result);
8069 		} else {
8070 			csr_process_stop_bss_response(mac_ctx, vdev_id);
8071 		}
8072 		break;
8073 	default:
8074 		sme_err("Invalid response");
8075 		break;
8076 	}
8077 	qdf_mem_free(roam_info);
8078 	return true;
8079 }
8080 
8081 static enum wlan_serialization_cmd_type
8082 get_cmd_type_from_result(enum csr_sap_response_type result)
8083 {
8084 	switch (result) {
8085 	case CSR_SAP_START_BSS_SUCCESS:
8086 	case CSR_SAP_START_BSS_FAILURE:
8087 		return WLAN_SER_CMD_VDEV_START_BSS;
8088 	case CSR_SAP_STOP_BSS_SUCCESS:
8089 	case CSR_SAP_STOP_BSS_FAILURE:
8090 		return WLAN_SER_CMD_VDEV_STOP_BSS;
8091 	default:
8092 		return WLAN_SER_CMD_MAX;
8093 	}
8094 }
8095 
8096 static inline
8097 uint32_t get_cmd_id_from_cmd_type(void *cmd,
8098 				  enum wlan_serialization_cmd_type cmd_type)
8099 {
8100 	switch (cmd_type) {
8101 	case WLAN_SER_CMD_VDEV_START_BSS:
8102 		return ((struct start_bss_config *)cmd)->cmd_id;
8103 	case WLAN_SER_CMD_VDEV_STOP_BSS:
8104 		return ((struct stop_bss_req *)cmd)->cmd_id;
8105 	default:
8106 		sme_err("Invalid cmd_type %d to be dequeued", cmd_type);
8107 		return 0;
8108 	}
8109 }
8110 
8111 void csr_process_sap_response(struct mac_context *mac_ctx,
8112 			      enum csr_sap_response_type result,
8113 			      void *rsp, uint8_t vdev_id)
8114 {
8115 	struct wlan_objmgr_vdev *vdev;
8116 	void *req;
8117 	uint32_t cmd_id;
8118 	enum wlan_serialization_cmd_type cmd_type =
8119 				get_cmd_type_from_result(result);
8120 
8121 	if (cmd_type >= WLAN_SER_CMD_MAX) {
8122 		sme_err("Invalid command to be dequeued %d", cmd_type);
8123 		return;
8124 	}
8125 
8126 	req = wlan_serialization_get_active_cmd(mac_ctx->psoc,
8127 						vdev_id, cmd_type);
8128 	if (!req) {
8129 		sme_err("No active command for response from LIM for cmd: %d vdev: %d",
8130 			cmd_type, vdev_id);
8131 		csr_process_sap_results(mac_ctx, rsp, result, vdev_id);
8132 		return;
8133 	}
8134 
8135 	csr_process_sap_results(mac_ctx, rsp, result, vdev_id);
8136 
8137 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
8138 						    WLAN_LEGACY_MAC_ID);
8139 	if (!vdev) {
8140 		sme_err("vdev not found for vdev id: %d", vdev_id);
8141 		return;
8142 	}
8143 
8144 	cmd_id = get_cmd_id_from_cmd_type(req, cmd_type);
8145 	sme_debug("Dequeue cmd id : %d type : %d", cmd_id, cmd_type);
8146 
8147 	wlan_vdev_mlme_ser_remove_request(vdev, cmd_id, cmd_type);
8148 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
8149 }
8150 
8151 void csr_set_vdev_ies_per_band(mac_handle_t mac_handle, uint8_t vdev_id,
8152 			       enum QDF_OPMODE device_mode)
8153 {
8154 	struct sir_set_vdev_ies_per_band *p_msg;
8155 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
8156 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
8157 	enum csr_cfgdot11mode curr_dot11_mode =
8158 			mac_ctx->roam.configParam.uCfgDot11Mode;
8159 
8160 	p_msg = qdf_mem_malloc(sizeof(*p_msg));
8161 	if (!p_msg)
8162 		return;
8163 
8164 	p_msg->vdev_id = vdev_id;
8165 	p_msg->device_mode = device_mode;
8166 	p_msg->dot11_mode = csr_get_vdev_dot11_mode(mac_ctx, vdev_id,
8167 						    curr_dot11_mode);
8168 	p_msg->msg_type = eWNI_SME_SET_VDEV_IES_PER_BAND;
8169 	p_msg->len = sizeof(*p_msg);
8170 	sme_debug("SET_VDEV_IES_PER_BAND: vdev_id %d dot11mode %d dev_mode %d",
8171 		  vdev_id, p_msg->dot11_mode, device_mode);
8172 	status = umac_send_mb_message_to_mac(p_msg);
8173 	if (QDF_STATUS_SUCCESS != status)
8174 		sme_err("Send eWNI_SME_SET_VDEV_IES_PER_BAND fail");
8175 }
8176