1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * 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  */
csr_sae_callback(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)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
csr_sae_callback(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)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 */
csr_roam_init_globals(struct mac_context * mac)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 */
csr_roam_free_globals(void)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 */
csr_roam_init_globals(struct mac_context * mac)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 
csr_roam_free_globals(void)214 static inline void csr_roam_free_globals(void)
215 {
216 }
217 #endif /* WLAN_ALLOCATE_GLOBAL_BUFFERS_DYNAMICALLY */
218 
csr_roam_de_init_globals(struct mac_context * mac)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
csr_roam_lost_link(struct mac_context * mac,uint32_t session_id,uint32_t type,tSirSmeRsp * sir_msg)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  */
csr_process_deauth_disassoc_cmd(struct mac_context * mac,tSmeCmd * sme_cmd)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  */
csr_process_wmm_status_change_cmd(struct mac_context * mac,tSmeCmd * sme_cmd)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  */
csr_get_active_peer_disconnect_command(struct mac_context * mac,uint8_t vdev_id)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
csr_continue_peer_disconnect_after_get_stats(struct mac_context * mac)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  */
csr_disconnect_stats_timer_cb(void * user_data)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  */
csr_init_disconnect_stats_timer(struct mac_context * mac)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  */
csr_deinit_disconnect_stats_timer(struct mac_context * mac)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 
csr_open(struct mac_context * mac)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 
csr_init_chan_list(struct mac_context * mac)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 
csr_set_channels(struct mac_context * mac,struct csr_config_params * pParam)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 
csr_close(struct mac_context * mac)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
csr_find_channel_pwr(struct channel_power * pdefaultPowerTable,uint32_t chan_freq)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  */
csr_roam_arrange_ch_list(struct mac_context * mac_ctx,tSirUpdateChanParam * chan_list,uint8_t num_channel)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  */
csr_roam_sort_channel_for_early_stop(struct mac_context * mac_ctx,tSirUpdateChanList * chan_list,uint8_t num_channel)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 
csr_emu_chan_req(uint32_t channel)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
csr_emu_chan_req(uint32_t channel_num)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
csr_add_len_of_social_channels(struct mac_context * mac,uint8_t * num_chan)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 
csr_add_social_channels(struct mac_context * mac,tSirUpdateChanList * chan_list,struct csr_scanstruct * pScan,uint8_t * num_chan)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
csr_add_len_of_social_channels(struct mac_context * mac,uint8_t * num_chan)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 }
csr_add_social_channels(struct mac_context * mac,tSirUpdateChanList * chan_list,struct csr_scanstruct * pScan,uint8_t * num_chan)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  */
csr_scan_event_handler(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)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  */
csr_update_roam_pcl_per_connected_sta_vdev(struct wlan_objmgr_psoc * psoc)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 
csr_update_channel_list(struct mac_context * mac)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 
csr_start(struct mac_context * mac)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 
csr_stop(struct mac_context * mac)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 
csr_ready(struct mac_context * mac)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 
csr_set_default_dot11_mode(struct mac_context * mac)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 
csr_set_global_cfgs(struct mac_context * mac)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  */
csr_packetdump_timer_handler(void * pv)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 
csr_packetdump_timer_start(void)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 
csr_packetdump_timer_stop(void)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 
csr_packetdump_timer_init(struct mac_context * mac)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 
csr_packetdump_timer_deinit(struct mac_context * mac)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
csr_packetdump_timer_init(struct mac_context * mac)1380 static inline QDF_STATUS csr_packetdump_timer_init(struct mac_context *mac)
1381 {
1382 	return QDF_STATUS_SUCCESS;
1383 }
1384 
csr_packetdump_timer_deinit(struct mac_context * mac)1385 static inline void csr_packetdump_timer_deinit(struct mac_context *mac) {}
1386 #endif
1387 
csr_roam_open(struct mac_context * mac)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 
csr_roam_close(struct mac_context * mac)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 
csr_roam_free_connected_info(struct mac_context * mac,struct csr_roam_connectedinfo * pConnectedInfo)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 
csr_release_command_roam(struct mac_context * mac,tSmeCmd * pCommand)1442 void csr_release_command_roam(struct mac_context *mac, tSmeCmd *pCommand)
1443 {
1444 	csr_reinit_roam_cmd(mac, pCommand);
1445 }
1446 
csr_release_command_wm_status_change(struct mac_context * mac,tSmeCmd * pCommand)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 
csr_roam_substate_change(struct mac_context * mac,enum csr_roam_substate NewSubstate,uint32_t sessionId)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 
csr_roam_state_change(struct mac_context * mac,enum csr_roam_state NewRoamState,uint8_t sessionId)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 
init_config_param(struct mac_context * mac)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
csr_flush_roam_scan_chan_lists(struct mac_context * mac,uint8_t vdev_id)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  */
csr_roam_is_ese_assoc(struct mac_context * mac_ctx,uint32_t session_id)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  */
csr_tsm_stats_rsp_processor(struct mac_context * mac,void * pMsg)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  */
csr_send_ese_adjacent_ap_rep_ind(struct mac_context * mac,struct csr_roam_session * pSession)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  */
csr_get_tsm_stats(struct mac_context * mac,tCsrTsmStatsCallback callback,struct qdf_mac_addr bssId,void * pContext,uint8_t tid)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  */
csr_convert_cb_ini_value_to_phy_cb_state(uint32_t cbIniValue)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
csr_convert_phy_cb_state_to_ini_value(ePhyChanBondState phyCbState)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
csr_update_session_eht_cap(struct mac_context * mac_ctx,struct csr_roam_session * session)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
csr_update_session_he_cap(struct mac_context * mac_ctx,struct csr_roam_session * session)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 
csr_change_default_config_param(struct mac_context * mac,struct csr_config_params * pParam)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 
csr_get_config_param(struct mac_context * mac,struct csr_config_params * pParam)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  */
csr_prune_ch_list(struct csr_channel * ch_lst,bool is_24_GHz)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  */
csr_prune_channel_list_for_mode(struct mac_context * mac_ctx,struct csr_channel * ch_lst)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 
csr_get_channel_and_power_list(struct mac_context * mac)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 
csr_apply_channel_and_power_list(struct mac_context * mac)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 
csr_init11d_info(struct mac_context * mac,tCsr11dinfo * ps11dinfo)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 */
csr_init_channel_power_list(struct mac_context * mac,tCsr11dinfo * ps11dinfo)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
csr_cm_get_sta_cxn_info(struct mac_context * mac_ctx,uint8_t vdev_id,char * buf,uint32_t buf_sz)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 
csr_roam_call_callback(struct mac_context * mac,uint32_t sessionId,struct csr_roam_info * roam_info,eRoamCmdStatus u1,eCsrRoamResult u2)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 
csr_peer_mac_match_cmd(tSmeCmd * sme_cmd,struct qdf_mac_addr * peer_macaddr,struct qdf_mac_addr * peer_mld_addr,uint8_t vdev_id)2313 static bool csr_peer_mac_match_cmd(tSmeCmd *sme_cmd,
2314 				   struct qdf_mac_addr *peer_macaddr,
2315 				   struct qdf_mac_addr *peer_mld_addr,
2316 				   uint8_t vdev_id)
2317 {
2318 	if (sme_cmd->command == eSmeCommandRoam &&
2319 	    (sme_cmd->u.roamCmd.roamReason == eCsrForcedDisassocSta ||
2320 	     sme_cmd->u.roamCmd.roamReason == eCsrForcedDeauthSta) &&
2321 	     (qdf_is_macaddr_equal(
2322 			peer_macaddr,
2323 			(struct qdf_mac_addr *)sme_cmd->u.roamCmd.peerMac) ||
2324 	      (!qdf_is_macaddr_zero(peer_mld_addr) &&
2325 	       qdf_is_macaddr_equal(peer_mld_addr,
2326 				    &sme_cmd->u.roamCmd.peer_mld_addr))))
2327 		return true;
2328 
2329 	if (sme_cmd->command == eSmeCommandWmStatusChange) {
2330 		struct wmstatus_changecmd *wms_cmd;
2331 
2332 		wms_cmd = &sme_cmd->u.wmStatusChangeCmd;
2333 		if (wms_cmd->Type == eCsrDisassociated &&
2334 		    (qdf_is_macaddr_equal(
2335 				peer_macaddr,
2336 				&wms_cmd->u.DisassocIndMsg.peer_macaddr) ||
2337 		     (!qdf_is_macaddr_zero(peer_mld_addr) &&
2338 		      qdf_is_macaddr_equal(
2339 				peer_mld_addr,
2340 				&wms_cmd->u.DisassocIndMsg.peer_mld_addr))))
2341 			return true;
2342 
2343 		if (wms_cmd->Type == eCsrDeauthenticated &&
2344 		    (qdf_is_macaddr_equal(
2345 				peer_macaddr,
2346 				&wms_cmd->u.DeauthIndMsg.peer_macaddr) ||
2347 		     (!qdf_is_macaddr_zero(peer_mld_addr) &&
2348 		      qdf_is_macaddr_equal(
2349 				peer_mld_addr,
2350 				&wms_cmd->u.DeauthIndMsg.peer_mld_addr))))
2351 			return true;
2352 	}
2353 
2354 	return false;
2355 }
2356 
2357 static bool
csr_is_deauth_disassoc_in_pending_q(struct mac_context * mac_ctx,uint8_t vdev_id,struct qdf_mac_addr * peer_macaddr,struct qdf_mac_addr * peer_mld_addr)2358 csr_is_deauth_disassoc_in_pending_q(struct mac_context *mac_ctx,
2359 				    uint8_t vdev_id,
2360 				    struct qdf_mac_addr *peer_macaddr,
2361 				    struct qdf_mac_addr *peer_mld_addr)
2362 {
2363 	tListElem *entry = NULL;
2364 	tSmeCmd *sme_cmd;
2365 
2366 	entry = csr_nonscan_pending_ll_peek_head(mac_ctx, LL_ACCESS_NOLOCK);
2367 	while (entry) {
2368 		sme_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
2369 		if ((sme_cmd->vdev_id == vdev_id) &&
2370 		    csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
2371 					   peer_mld_addr, vdev_id))
2372 			return true;
2373 		entry = csr_nonscan_pending_ll_next(mac_ctx, entry,
2374 						    LL_ACCESS_NOLOCK);
2375 	}
2376 
2377 	return false;
2378 }
2379 
2380 static bool
csr_is_deauth_disassoc_in_active_q(struct mac_context * mac_ctx,uint8_t vdev_id,struct qdf_mac_addr * peer_macaddr,struct qdf_mac_addr * peer_mld_addr)2381 csr_is_deauth_disassoc_in_active_q(struct mac_context *mac_ctx,
2382 				   uint8_t vdev_id,
2383 				   struct qdf_mac_addr *peer_macaddr,
2384 				   struct qdf_mac_addr *peer_mld_addr)
2385 {
2386 	tSmeCmd *sme_cmd;
2387 
2388 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
2389 						WLAN_SER_CMD_FORCE_DEAUTH_STA);
2390 
2391 	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
2392 					      peer_mld_addr, vdev_id))
2393 		return true;
2394 
2395 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
2396 					WLAN_SER_CMD_FORCE_DISASSOC_STA);
2397 
2398 	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
2399 					      peer_mld_addr, vdev_id))
2400 		return true;
2401 
2402 	/*
2403 	 * WLAN_SER_CMD_WM_STATUS_CHANGE is of two type, the handling
2404 	 * should take care of both the types.
2405 	 */
2406 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
2407 						WLAN_SER_CMD_WM_STATUS_CHANGE);
2408 	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
2409 					      peer_mld_addr, vdev_id))
2410 		return true;
2411 
2412 	return false;
2413 }
2414 
2415 /*
2416  * csr_is_deauth_disassoc_already_active() - Function to check if deauth or
2417  *  disassoc is already in progress.
2418  * @mac_ctx: Global MAC context
2419  * @vdev_id: vdev id
2420  * @peer_macaddr: Peer MAC address to check
2421  * @peer_mld_addr: peer MLD address to check
2422  *
2423  * Return: True if deauth/disassoc indication can be dropped
2424  *  else false
2425  */
2426 static bool
csr_is_deauth_disassoc_already_active(struct mac_context * mac_ctx,uint8_t vdev_id,struct qdf_mac_addr * peer_macaddr,struct qdf_mac_addr * peer_mld_addr)2427 csr_is_deauth_disassoc_already_active(struct mac_context *mac_ctx,
2428 				      uint8_t vdev_id,
2429 				      struct qdf_mac_addr *peer_macaddr,
2430 				      struct qdf_mac_addr *peer_mld_addr)
2431 {
2432 	char mld_log_str[MAC_ADDR_DUMP_LEN] = {0};
2433 
2434 	bool ret = csr_is_deauth_disassoc_in_pending_q(
2435 					mac_ctx, vdev_id, peer_macaddr,
2436 					peer_mld_addr);
2437 	if (!ret)
2438 		/**
2439 		 * commands are not found in pending queue, check in active
2440 		 * queue as well
2441 		 */
2442 		ret = csr_is_deauth_disassoc_in_active_q(
2443 					mac_ctx, vdev_id,
2444 					peer_macaddr, peer_mld_addr);
2445 
2446 	if (ret) {
2447 		if (!qdf_is_macaddr_zero((struct qdf_mac_addr *)&peer_mld_addr))
2448 			qdf_scnprintf(mld_log_str, MAC_ADDR_DUMP_LEN,
2449 				      " mld: " QDF_MAC_ADDR_FMT,
2450 				      QDF_MAC_ADDR_REF(peer_mld_addr->bytes));
2451 		sme_debug("Deauth/Disassoc already in progress for " QDF_MAC_ADDR_FMT "%s",
2452 			  QDF_MAC_ADDR_REF(peer_macaddr->bytes), mld_log_str);
2453 	}
2454 
2455 	return ret;
2456 }
2457 
2458 /*
2459  * csr_is_deauth_disassoc_cmd_active() - Function to check if deauth or
2460  *  disassoc is already in progress.
2461  * @mac_ctx: Global MAC context
2462  * @vdev_id: vdev ID
2463  * @macaddr: mac address provided (mld/link/mac for the peer to check)
2464  * @peer_mac: found peer mac
2465  * @peer_mld_mac: found peer mld if ML connection
2466  *
2467  * Return: True if deauth/disassoc indication can be dropped else false
2468  */
2469 static bool
csr_is_deauth_disassoc_cmd_active(struct mac_context * mac_ctx,uint8_t vdev_id,struct qdf_mac_addr macaddr,struct qdf_mac_addr * peer_mac,struct qdf_mac_addr * peer_mld_mac)2470 csr_is_deauth_disassoc_cmd_active(struct mac_context *mac_ctx,
2471 				  uint8_t vdev_id, struct qdf_mac_addr macaddr,
2472 				  struct qdf_mac_addr *peer_mac,
2473 				  struct qdf_mac_addr *peer_mld_mac)
2474 {
2475 	struct peer_mac_addresses peer_mac_info;
2476 
2477 	qdf_mem_zero(&peer_mac_info, sizeof(struct peer_mac_addresses));
2478 	qdf_copy_macaddr(&peer_mac_info.mac, &macaddr);
2479 	wlan_find_peer_and_get_mac_and_mld_addr(mac_ctx->psoc, &peer_mac_info);
2480 	if (csr_is_deauth_disassoc_already_active(mac_ctx, vdev_id,
2481 						  &peer_mac_info.peer_mac,
2482 						  &peer_mac_info.peer_mld))
2483 		return true;
2484 
2485 	if (peer_mac && peer_mld_mac) {
2486 		if (!qdf_is_macaddr_equal(&macaddr, &peer_mac_info.peer_mac))
2487 			sme_debug("Vdev %d, given mac " QDF_MAC_ADDR_FMT " found peer mac " QDF_MAC_ADDR_FMT,
2488 				  vdev_id, QDF_MAC_ADDR_REF(macaddr.bytes),
2489 				  QDF_MAC_ADDR_REF(peer_mac_info.peer_mac.bytes));
2490 		qdf_copy_macaddr(peer_mac, &peer_mac_info.peer_mac);
2491 		qdf_copy_macaddr(peer_mld_mac, &peer_mac_info.peer_mld);
2492 	}
2493 
2494 	return false;
2495 }
2496 
2497 static QDF_STATUS
csr_roam_issue_discon_sta_roam_cmd(struct mac_context * mac,uint8_t vdev_id,enum csr_roam_reason discon_reason,struct csr_del_sta_params * del_sta_params)2498 csr_roam_issue_discon_sta_roam_cmd(struct mac_context *mac,
2499 				   uint8_t vdev_id,
2500 				   enum csr_roam_reason discon_reason,
2501 				   struct csr_del_sta_params *del_sta_params)
2502 {
2503 	tSmeCmd *cmd;
2504 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2505 	struct qdf_mac_addr peer_mac = QDF_MAC_ADDR_ZERO_INIT;
2506 	struct qdf_mac_addr peer_mld_mac = QDF_MAC_ADDR_ZERO_INIT;
2507 
2508 	if (csr_is_deauth_disassoc_cmd_active(mac, vdev_id,
2509 					      del_sta_params->peerMacAddr,
2510 					      &peer_mac, &peer_mld_mac))
2511 		return status;
2512 
2513 	cmd = csr_get_command_buffer(mac);
2514 	if (!cmd) {
2515 		sme_err("Vdev %d " QDF_MAC_ADDR_FMT " fails to get command buffer for reason %d",
2516 			vdev_id,
2517 			QDF_MAC_ADDR_REF(del_sta_params->peerMacAddr.bytes),
2518 			discon_reason);
2519 		return QDF_STATUS_E_RESOURCES;
2520 	}
2521 
2522 	cmd->command = eSmeCommandRoam;
2523 	cmd->vdev_id = vdev_id;
2524 	cmd->u.roamCmd.roamReason = discon_reason;
2525 	qdf_copy_macaddr((struct qdf_mac_addr *)&cmd->u.roamCmd.peerMac,
2526 			 &peer_mac);
2527 	qdf_copy_macaddr(&cmd->u.roamCmd.peer_mld_addr, &peer_mld_mac);
2528 	cmd->u.roamCmd.reason = del_sta_params->reason_code;
2529 
2530 	status = csr_queue_sme_command(mac, cmd, false);
2531 	if (QDF_IS_STATUS_ERROR(status))
2532 		sme_err("Vdev %d " QDF_MAC_ADDR_FMT " fails to get send message status: %d",
2533 			vdev_id,
2534 			QDF_MAC_ADDR_REF(del_sta_params->peerMacAddr.bytes),
2535 			status);
2536 
2537 	return status;
2538 }
2539 
2540 QDF_STATUS
csr_roam_issue_disassociate_sta_cmd(struct mac_context * mac,uint8_t vdev_id,struct csr_del_sta_params * del_sta_params)2541 csr_roam_issue_disassociate_sta_cmd(struct mac_context *mac,
2542 				    uint8_t vdev_id,
2543 				    struct csr_del_sta_params *del_sta_params)
2544 
2545 {
2546 	return csr_roam_issue_discon_sta_roam_cmd(mac, vdev_id,
2547 						  eCsrForcedDisassocSta,
2548 						  del_sta_params);
2549 }
2550 
2551 QDF_STATUS
csr_roam_issue_deauth_sta_cmd(struct mac_context * mac,uint8_t vdev_id,struct csr_del_sta_params * del_sta_params)2552 csr_roam_issue_deauth_sta_cmd(struct mac_context *mac,
2553 			      uint8_t vdev_id,
2554 			      struct csr_del_sta_params *del_sta_params)
2555 {
2556 	return csr_roam_issue_discon_sta_roam_cmd(mac, vdev_id,
2557 						  eCsrForcedDeauthSta,
2558 						  del_sta_params);
2559 }
2560 
2561 /**
2562  * csr_get_peer_stats_cb - Peer stats callback
2563  * @ev: stats event
2564  * @cookie: Void pointer to mac contaxt
2565  *
2566  * Return: None
2567  */
csr_get_peer_stats_cb(struct stats_event * ev,void * cookie)2568 static void csr_get_peer_stats_cb(struct stats_event *ev, void *cookie)
2569 {
2570 	struct mac_context *mac = (struct mac_context *)cookie;
2571 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2572 
2573 	if (!mac) {
2574 		sme_err("Invalid mac ctx");
2575 		return;
2576 	}
2577 
2578 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
2579 	if (!mlme_obj) {
2580 		sme_err("NULL mlme psoc object");
2581 		return;
2582 	}
2583 
2584 	qdf_mc_timer_stop(
2585 		&mlme_obj->disconnect_stats_param.disconn_stats_timer);
2586 
2587 	if (!ev->peer_stats) {
2588 		sme_debug("no peer stats");
2589 		goto disconnect_stats_complete;
2590 	}
2591 
2592 	mac->peer_rssi = ev->peer_stats->peer_rssi;
2593 	mac->peer_txrate = ev->peer_stats->tx_rate;
2594 	mac->peer_rxrate = ev->peer_stats->rx_rate;
2595 	if (!ev->peer_extended_stats) {
2596 		sme_debug("no peer extended stats");
2597 		goto disconnect_stats_complete;
2598 	}
2599 	mac->rx_mc_bc_cnt = ev->peer_extended_stats->rx_mc_bc_cnt;
2600 
2601 disconnect_stats_complete:
2602 	sme_debug("peer rssi %d tx_rate %d rx_rate %d rx_mc_bc_cnt %d",
2603 		  mac->peer_rssi, mac->peer_txrate, mac->peer_rxrate,
2604 		  mac->rx_mc_bc_cnt);
2605 	csr_continue_peer_disconnect_after_get_stats(mac);
2606 }
2607 
2608 /**
2609  * csr_get_peer_stats - Get Peer stats
2610  * @mac: MAC contaxt
2611  * @session_id: Current session id
2612  * @peer_mac: Peer mac address
2613  *
2614  * Return: None
2615  */
csr_get_peer_stats(struct mac_context * mac,uint32_t session_id,struct qdf_mac_addr peer_mac)2616 static void csr_get_peer_stats(struct mac_context *mac, uint32_t session_id,
2617 			       struct qdf_mac_addr peer_mac)
2618 {
2619 	struct wlan_objmgr_vdev *vdev;
2620 	struct request_info info = {0};
2621 	QDF_STATUS status;
2622 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2623 
2624 	mlme_obj = mlme_get_psoc_ext_obj(mac->psoc);
2625 	if (!mlme_obj) {
2626 		sme_err("NULL mlme psoc object");
2627 		return;
2628 	}
2629 	/* Reset is_disconn_stats_completed before error handing. */
2630 	qdf_atomic_set(
2631 		&mlme_obj->disconnect_stats_param.is_disconn_stats_completed,
2632 		0);
2633 
2634 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, session_id,
2635 						    WLAN_LEGACY_SME_ID);
2636 
2637 	if (!vdev) {
2638 		csr_continue_peer_disconnect_after_get_stats(mac);
2639 		return;
2640 	}
2641 
2642 	info.cookie = mac;
2643 	info.u.get_peer_rssi_cb = csr_get_peer_stats_cb;
2644 	info.vdev_id = wlan_vdev_get_id(vdev);
2645 	info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
2646 	qdf_mem_copy(info.peer_mac_addr, &peer_mac, QDF_MAC_ADDR_SIZE);
2647 	sme_debug("peer_mac" QDF_MAC_ADDR_FMT,
2648 		  QDF_MAC_ADDR_REF(peer_mac.bytes));
2649 	mlme_obj->disconnect_stats_param.vdev_id = info.vdev_id;
2650 	status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_PEER_STATS,
2651 						     &info);
2652 	if (QDF_IS_STATUS_ERROR(status)) {
2653 		sme_err("stats req failed: %d", status);
2654 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
2655 		csr_continue_peer_disconnect_after_get_stats(mac);
2656 		return;
2657 	}
2658 
2659 	qdf_mc_timer_start(
2660 		&mlme_obj->disconnect_stats_param.disconn_stats_timer,
2661 		SME_CMD_GET_DISCONNECT_STATS_TIMEOUT);
2662 
2663 	wma_get_rx_retry_cnt(mac, session_id, info.peer_mac_addr);
2664 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
2665 }
2666 
csr_roam_process_command(struct mac_context * mac,tSmeCmd * pCommand)2667 QDF_STATUS csr_roam_process_command(struct mac_context *mac, tSmeCmd *pCommand)
2668 {
2669 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2670 	uint32_t sessionId = pCommand->vdev_id;
2671 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
2672 	struct qdf_mac_addr peer_mac;
2673 
2674 	if (!pSession) {
2675 		sme_err("session %d not found", sessionId);
2676 		return QDF_STATUS_E_FAILURE;
2677 	}
2678 	sme_debug("Roam Reason: %d sessionId: %d",
2679 		pCommand->u.roamCmd.roamReason, sessionId);
2680 
2681 	switch (pCommand->u.roamCmd.roamReason) {
2682 	case eCsrForcedDisassocSta:
2683 	case eCsrForcedDeauthSta:
2684 		csr_roam_state_change(mac, eCSR_ROAMING_STATE_JOINING,
2685 				      sessionId);
2686 		if (pCommand->u.roamCmd.roamReason == eCsrForcedDeauthSta)
2687 			csr_roam_substate_change(mac,
2688 						 eCSR_ROAM_SUBSTATE_DEAUTH_REQ,
2689 						 sessionId);
2690 		else
2691 			csr_roam_substate_change(
2692 						mac,
2693 						eCSR_ROAM_SUBSTATE_DISASSOC_REQ,
2694 						sessionId);
2695 
2696 		qdf_mem_copy(&peer_mac, &pCommand->u.roamCmd.peerMac,
2697 			     QDF_MAC_ADDR_SIZE);
2698 		/*
2699 		 * Get peer stats before peer gets deleted so that these stats
2700 		 * can be given to user space when big data stats are queried.
2701 		 * Once peer stats are retrieved deauth sta will continue
2702 		 */
2703 		csr_get_peer_stats(mac, sessionId, peer_mac);
2704 		break;
2705 	}
2706 	return status;
2707 }
2708 
csr_reinit_roam_cmd(struct mac_context * mac,tSmeCmd * pCommand)2709 void csr_reinit_roam_cmd(struct mac_context *mac, tSmeCmd *pCommand)
2710 {
2711 	/* Because u.roamCmd is union and share with scanCmd and StatusChange */
2712 	qdf_mem_zero(&pCommand->u.roamCmd, sizeof(struct roam_cmd));
2713 }
2714 
csr_reinit_wm_status_change_cmd(struct mac_context * mac,tSmeCmd * pCommand)2715 void csr_reinit_wm_status_change_cmd(struct mac_context *mac,
2716 			tSmeCmd *pCommand)
2717 {
2718 	qdf_mem_zero(&pCommand->u.wmStatusChangeCmd,
2719 			sizeof(struct wmstatus_changecmd));
2720 }
2721 
csr_roam_complete(struct mac_context * mac_ctx,uint8_t session_id)2722 void csr_roam_complete(struct mac_context *mac_ctx, uint8_t session_id)
2723 {
2724 	tSmeCmd *sme_cmd;
2725 	struct wlan_serialization_command *cmd;
2726 
2727 	cmd = wlan_serialization_peek_head_active_cmd_using_psoc(
2728 				mac_ctx->psoc, false);
2729 	if (!cmd) {
2730 		sme_err("Roam completion called but cmd is not active");
2731 		return;
2732 	}
2733 	sme_cmd = cmd->umac_cmd;
2734 	if (!sme_cmd) {
2735 		sme_err("sme_cmd is NULL");
2736 		return;
2737 	}
2738 	if (eSmeCommandRoam == sme_cmd->command) {
2739 		csr_roam_process_results_default(mac_ctx, sme_cmd);
2740 		csr_release_command(mac_ctx, sme_cmd);
2741 	}
2742 }
2743 
2744 /* Returns whether the current association is a 11r assoc or not */
csr_roam_is11r_assoc(struct mac_context * mac,uint8_t sessionId)2745 bool csr_roam_is11r_assoc(struct mac_context *mac, uint8_t sessionId)
2746 {
2747 	struct cm_roam_values_copy config;
2748 
2749 	wlan_cm_roam_cfg_get_value(mac->psoc, sessionId, IS_11R_CONNECTION,
2750 				   &config);
2751 
2752 	return config.bool_value;
2753 }
2754 
csr_roam_process_results_default(struct mac_context * mac_ctx,tSmeCmd * cmd)2755 void csr_roam_process_results_default(struct mac_context *mac_ctx,
2756 				      tSmeCmd *cmd)
2757 {
2758 	uint32_t session_id = cmd->vdev_id;
2759 	struct csr_roam_session *session;
2760 	struct csr_roam_info *roam_info;
2761 	QDF_STATUS status;
2762 	enum QDF_OPMODE opmode;
2763 
2764 	if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
2765 		sme_err("Invalid session id %d", session_id);
2766 		return;
2767 	}
2768 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, session_id);
2769 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
2770 	if (!roam_info)
2771 		return;
2772 	session = CSR_GET_SESSION(mac_ctx, session_id);
2773 	if (CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac_ctx, session_id)) {
2774 		/*
2775 		 * do not free for the other profiles as we need
2776 		 * to send down stop BSS later
2777 		 */
2778 		csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
2779 		csr_set_default_dot11_mode(mac_ctx);
2780 	}
2781 
2782 	switch (cmd->u.roamCmd.roamReason) {
2783 	case eCsrForcedDisassocSta:
2784 	case eCsrForcedDeauthSta:
2785 		roam_info->rssi = mac_ctx->peer_rssi;
2786 		roam_info->tx_rate = mac_ctx->peer_txrate;
2787 		roam_info->rx_rate = mac_ctx->peer_rxrate;
2788 		roam_info->rx_mc_bc_cnt = mac_ctx->rx_mc_bc_cnt;
2789 		roam_info->rx_retry_cnt = mac_ctx->rx_retry_cnt;
2790 
2791 		csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED,
2792 				      session_id);
2793 		if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
2794 			qdf_mem_copy(roam_info->peerMac.bytes,
2795 				     cmd->u.roamCmd.peerMac,
2796 				     sizeof(tSirMacAddr));
2797 			roam_info->reasonCode = eCSR_ROAM_RESULT_FORCED;
2798 			/* Update the MAC reason code */
2799 			roam_info->disassoc_reason = cmd->u.roamCmd.reason;
2800 			roam_info->status_code = eSIR_SME_SUCCESS;
2801 			status = csr_roam_call_callback(mac_ctx, session_id,
2802 							roam_info,
2803 							eCSR_ROAM_LOSTLINK,
2804 							eCSR_ROAM_RESULT_FORCED);
2805 		}
2806 		break;
2807 	default:
2808 		csr_roam_state_change(mac_ctx,
2809 			eCSR_ROAMING_STATE_IDLE, session_id);
2810 		break;
2811 	}
2812 	qdf_mem_free(roam_info);
2813 }
2814 
2815 /**
2816  * csr_roam_process_start_bss_success() - Process the result for start bss
2817  * @mac_ctx:   Global MAC Context
2818  * @context:   Additional data in context of the cmd
2819  * @vdev_id:   vdev id
2820  *
2821  * Return: None
2822  */
csr_roam_process_start_bss_success(struct mac_context * mac_ctx,struct csr_roam_info * roam_info,void * context,uint8_t vdev_id)2823 static void csr_roam_process_start_bss_success(struct mac_context *mac_ctx,
2824 					       struct csr_roam_info *roam_info,
2825 					       void *context, uint8_t vdev_id)
2826 {
2827 	struct csr_roam_session *session;
2828 	struct start_bss_rsp *start_bss_rsp = NULL;
2829 	eRoamCmdStatus roam_status = eCSR_ROAM_INFRA_IND;
2830 	eCsrRoamResult roam_result = eCSR_ROAM_RESULT_INFRA_STARTED;
2831 	tSirMacAddr bcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2832 	QDF_STATUS status;
2833 	enum QDF_OPMODE opmode;
2834 	uint8_t wmm_mode = 0, value = 0;
2835 
2836 	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
2837 		sme_err("Invalid session id %d", vdev_id);
2838 		return;
2839 	}
2840 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
2841 
2842 	sme_debug("Start BSS success");
2843 	start_bss_rsp = (struct start_bss_rsp *)context;
2844 
2845 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
2846 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE)
2847 		session->connectState =
2848 				eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED;
2849 	else if (opmode == QDF_NDI_MODE)
2850 		session->connectState = eCSR_CONNECT_STATE_TYPE_NDI_STARTED;
2851 	else
2852 		session->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED;
2853 
2854 	if (opmode == QDF_NDI_MODE) {
2855 		status = ucfg_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode);
2856 		if (!QDF_IS_STATUS_SUCCESS(status))
2857 			return;
2858 		if (wmm_mode == WMM_USER_MODE_NO_QOS) {
2859 			session->modifyProfileFields.uapsd_mask = 0;
2860 		} else {
2861 			status =
2862 			   ucfg_mlme_get_wmm_uapsd_mask(mac_ctx->psoc, &value);
2863 			if (!QDF_IS_STATUS_SUCCESS(status))
2864 				return;
2865 			session->modifyProfileFields.uapsd_mask = value;
2866 		}
2867 	}
2868 	csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, vdev_id);
2869 	csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
2870 	wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, vdev_id, &roam_info->bssid);
2871 
2872 	/* We are done with the IEs so free it */
2873 	/*
2874 	 * Only set context for non-WDS_STA. We don't even need it for
2875 	 * WDS_AP. But since the encryption.
2876 	 * is WPA2-PSK so it won't matter.
2877 	 */
2878 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
2879 		if (wlan_is_open_wep_cipher(mac_ctx->pdev, vdev_id)) {
2880 			csr_issue_set_context_req_helper(mac_ctx, vdev_id,
2881 							 &bcast_mac, false,
2882 							 false, 0);
2883 		}
2884 	}
2885 
2886 	/*
2887 	 * Only tell upper layer is we start the BSS because Vista doesn't like
2888 	 * multiple connection indications. If we don't start the BSS ourself,
2889 	 * handler of eSIR_SME_JOINED_NEW_BSS will trigger the connection start
2890 	 * indication in Vista
2891 	 */
2892 	roam_info->staId = (uint8_t)start_bss_rsp->staId;
2893 	if (opmode == QDF_NDI_MODE) {
2894 		csr_roam_update_ndp_return_params(mac_ctx,
2895 						  CSR_SAP_START_BSS_SUCCESS,
2896 						   &roam_status,
2897 						   &roam_result,
2898 						    roam_info);
2899 	}
2900 	/*
2901 	 * Only tell upper layer is we start the BSS because Vista
2902 	 * doesn't like multiple connection indications. If we don't
2903 	 * start the BSS ourself, handler of eSIR_SME_JOINED_NEW_BSS
2904 	 * will trigger the connection start indication in Vista
2905 	 */
2906 	roam_info->status_code = eSIR_SME_SUCCESS;
2907 	csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
2908 			       roam_status, roam_result);
2909 }
2910 
csr_flush_pending_start_bss_cmd(struct mac_context * mac_ctx,uint8_t vdev_id)2911 static void csr_flush_pending_start_bss_cmd(struct mac_context *mac_ctx,
2912 					     uint8_t vdev_id)
2913 {
2914 	struct wlan_serialization_queued_cmd_info cmd = {0};
2915 	struct wlan_objmgr_vdev *vdev;
2916 
2917 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
2918 						    WLAN_LEGACY_SME_ID);
2919 	if (!vdev) {
2920 		sme_err("vdev not found for id %d", vdev_id);
2921 		return;
2922 	}
2923 
2924 	/* Flush any pending vdev start command */
2925 	cmd.vdev = vdev;
2926 	cmd.cmd_type = WLAN_SER_CMD_VDEV_START_BSS;
2927 	cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE;
2928 	cmd.requestor = WLAN_UMAC_COMP_MLME;
2929 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
2930 
2931 	wlan_serialization_cancel_request(&cmd);
2932 
2933 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
2934 }
2935 
cm_csr_is_ss_wait_for_key(uint8_t vdev_id)2936 bool cm_csr_is_ss_wait_for_key(uint8_t vdev_id)
2937 {
2938 	struct mac_context *mac;
2939 	bool is_wait_for_key = false;
2940 
2941 	mac = sme_get_mac_context();
2942 	if (!mac) {
2943 		sme_err("mac_ctx is NULL");
2944 		return is_wait_for_key;
2945 	}
2946 
2947 	spin_lock(&mac->roam.roam_state_lock);
2948 	if (CSR_IS_WAIT_FOR_KEY(mac, vdev_id))
2949 		is_wait_for_key = true;
2950 	spin_unlock(&mac->roam.roam_state_lock);
2951 
2952 	return is_wait_for_key;
2953 }
2954 
cm_csr_set_ss_wait_for_key(uint8_t vdev_id)2955 void cm_csr_set_ss_wait_for_key(uint8_t vdev_id)
2956 {
2957 	struct mac_context *mac;
2958 
2959 	mac = sme_get_mac_context();
2960 	if (!mac) {
2961 		sme_err("mac_ctx is NULL");
2962 		return;
2963 	}
2964 
2965 	csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY,
2966 				 vdev_id);
2967 }
2968 
cm_csr_set_joining(uint8_t vdev_id)2969 void cm_csr_set_joining(uint8_t vdev_id)
2970 {
2971 	struct mac_context *mac;
2972 
2973 	mac = sme_get_mac_context();
2974 	if (!mac) {
2975 		sme_err("mac_ctx is NULL");
2976 		return;
2977 	}
2978 
2979 	csr_roam_state_change(mac, eCSR_ROAMING_STATE_JOINING, vdev_id);
2980 }
2981 
cm_csr_set_joined(uint8_t vdev_id)2982 void cm_csr_set_joined(uint8_t vdev_id)
2983 {
2984 	struct mac_context *mac;
2985 
2986 	mac = sme_get_mac_context();
2987 	if (!mac) {
2988 		sme_err("mac_ctx is NULL");
2989 		return;
2990 	}
2991 
2992 	csr_roam_state_change(mac, eCSR_ROAMING_STATE_JOINED, vdev_id);
2993 }
2994 
cm_csr_set_idle(uint8_t vdev_id)2995 void cm_csr_set_idle(uint8_t vdev_id)
2996 {
2997 	struct mac_context *mac;
2998 
2999 	mac = sme_get_mac_context();
3000 	if (!mac) {
3001 		sme_err("mac_ctx is NULL");
3002 		return;
3003 	}
3004 
3005 	csr_roam_state_change(mac, eCSR_ROAMING_STATE_IDLE, vdev_id);
3006 }
3007 
cm_csr_set_ss_none(uint8_t vdev_id)3008 void cm_csr_set_ss_none(uint8_t vdev_id)
3009 {
3010 	struct mac_context *mac;
3011 
3012 	mac = sme_get_mac_context();
3013 	if (!mac) {
3014 		sme_err("mac_ctx is NULL");
3015 		return;
3016 	}
3017 
3018 	csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_NONE,
3019 				 vdev_id);
3020 }
3021 
csr_roam_ndi_stop(struct mac_context * mac_ctx,uint8_t vdev_id)3022 QDF_STATUS csr_roam_ndi_stop(struct mac_context *mac_ctx, uint8_t vdev_id)
3023 {
3024 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
3025 	bool is_vdev_up;
3026 	bool is_start_bss_in_active_q = false;
3027 
3028 	csr_flush_pending_start_bss_cmd(mac_ctx, vdev_id);
3029 
3030 	is_vdev_up = wlan_is_vdev_id_up(mac_ctx->pdev, vdev_id);
3031 	if (wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
3032 					      WLAN_SER_CMD_VDEV_START_BSS))
3033 		is_start_bss_in_active_q = true;
3034 
3035 	sme_debug("vdev_id: %d is_vdev_up %d is_start_bss_in_active_q %d",
3036 		  vdev_id, is_vdev_up, is_start_bss_in_active_q);
3037 
3038 	if (is_vdev_up || is_start_bss_in_active_q)
3039 		status = csr_roam_issue_stop_bss_cmd(mac_ctx, vdev_id,
3040 						     eCSR_BSS_TYPE_NDI);
3041 	return status;
3042 }
3043 
3044 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
csr_fill_single_pmk(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct bss_description * bss_desc)3045 static void csr_fill_single_pmk(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
3046 				struct bss_description *bss_desc)
3047 {
3048 	struct cm_roam_values_copy src_cfg = {};
3049 
3050 	src_cfg.bool_value = bss_desc->is_single_pmk;
3051 	wlan_cm_roam_cfg_set_value(psoc, vdev_id,
3052 				   IS_SINGLE_PMK, &src_cfg);
3053 }
3054 #else
3055 static inline void
csr_fill_single_pmk(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct bss_description * bss_desc)3056 csr_fill_single_pmk(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
3057 		    struct bss_description *bss_desc)
3058 {}
3059 #endif
3060 
csr_roam_roaming_state_stop_bss_rsp_processor(struct mac_context * mac,void * msg)3061 void csr_roam_roaming_state_stop_bss_rsp_processor(struct mac_context *mac,
3062 						   void *msg)
3063 {
3064 	struct stop_bss_rsp *stop_bss_rsp = (struct stop_bss_rsp *)msg;
3065 	uint8_t vdev_id = stop_bss_rsp->vdev_id;
3066 	enum csr_sap_response_type result_code = CSR_SAP_STOP_BSS_SUCCESS;
3067 
3068 	sme_debug("Received stop bss rsp on vdev: %d", vdev_id);
3069 	mac->roam.roamSession[vdev_id].connectState =
3070 					eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
3071 	if (CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac, vdev_id)) {
3072 		if (stop_bss_rsp->status_code != eSIR_SME_SUCCESS)
3073 			result_code = CSR_SAP_STOP_BSS_FAILURE;
3074 		csr_process_sap_response(mac, result_code, NULL, vdev_id);
3075 	}
3076 }
3077 
3078 static
csr_roam_roaming_state_disassoc_rsp_processor(struct mac_context * mac,struct disassoc_rsp * rsp)3079 void csr_roam_roaming_state_disassoc_rsp_processor(struct mac_context *mac,
3080 						   struct disassoc_rsp *rsp)
3081 {
3082 	struct csr_roam_session *pSession;
3083 
3084 	sme_debug("Received disassoc response for vdev : %d status : %d",
3085 		  rsp->sessionId, rsp->status_code);
3086 
3087 	pSession = CSR_GET_SESSION(mac, rsp->sessionId);
3088 	if (!pSession) {
3089 		sme_err("session not found");
3090 		return;
3091 	}
3092 
3093 	csr_roam_complete(mac, rsp->sessionId);
3094 }
3095 
csr_roam_roaming_state_deauth_rsp_processor(struct mac_context * mac,struct deauth_rsp * rsp)3096 static void csr_roam_roaming_state_deauth_rsp_processor(struct mac_context *mac,
3097 						struct deauth_rsp *rsp)
3098 {
3099 	csr_roam_complete(mac, rsp->sessionId);
3100 }
3101 
3102 void
csr_roam_roaming_state_start_bss_rsp_processor(struct mac_context * mac,void * msg)3103 csr_roam_roaming_state_start_bss_rsp_processor(struct mac_context *mac,
3104 					       void *msg)
3105 {
3106 	enum csr_sap_response_type result;
3107 	struct start_bss_rsp *start_bss_rsp = (struct start_bss_rsp *)msg;
3108 
3109 	if (!CSR_IS_ROAM_SUBSTATE_START_BSS_REQ(mac, start_bss_rsp->vdev_id)) {
3110 		sme_err(" Start bss received in invalid state");
3111 		return;
3112 	}
3113 
3114 	sme_debug("Start Bss response status : %d",
3115 		  start_bss_rsp->status_code);
3116 	if (start_bss_rsp->status_code == eSIR_SME_SUCCESS)
3117 		result = CSR_SAP_START_BSS_SUCCESS;
3118 	else
3119 		result = CSR_SAP_START_BSS_FAILURE;
3120 
3121 	csr_process_sap_response(mac, result, start_bss_rsp,
3122 				 start_bss_rsp->vdev_id);
3123 }
3124 
3125 
3126 /**
3127  * csr_roam_send_disconnect_done_indication() - Send disconnect ind to HDD.
3128  *
3129  * @mac_ctx: mac global context
3130  * @msg_ptr: incoming message
3131  *
3132  * This function gives final disconnect event to HDD after all cleanup in
3133  * lower layers is done.
3134  *
3135  * Return: None
3136  */
3137 static void
csr_roam_send_disconnect_done_indication(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)3138 csr_roam_send_disconnect_done_indication(struct mac_context *mac_ctx,
3139 					 tSirSmeRsp *msg_ptr)
3140 {
3141 	struct sir_sme_discon_done_ind *discon_ind =
3142 				(struct sir_sme_discon_done_ind *)(msg_ptr);
3143 	struct csr_roam_info *roam_info;
3144 	uint8_t vdev_id;
3145 
3146 	vdev_id = discon_ind->session_id;
3147 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
3148 	if (!roam_info)
3149 		return;
3150 
3151 	sme_debug("DISCONNECT_DONE_IND RC:%d", discon_ind->reason_code);
3152 
3153 	if (CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
3154 		roam_info->reasonCode = discon_ind->reason_code;
3155 		roam_info->status_code = eSIR_SME_STA_NOT_ASSOCIATED;
3156 		qdf_mem_copy(roam_info->peerMac.bytes, discon_ind->peer_mac,
3157 			     ETH_ALEN);
3158 
3159 		roam_info->rssi = mac_ctx->peer_rssi;
3160 		roam_info->tx_rate = mac_ctx->peer_txrate;
3161 		roam_info->rx_rate = mac_ctx->peer_rxrate;
3162 		roam_info->disassoc_reason = discon_ind->reason_code;
3163 		roam_info->rx_mc_bc_cnt = mac_ctx->rx_mc_bc_cnt;
3164 		roam_info->rx_retry_cnt = mac_ctx->rx_retry_cnt;
3165 		csr_roam_call_callback(mac_ctx, vdev_id,
3166 				       roam_info, eCSR_ROAM_LOSTLINK,
3167 				       eCSR_ROAM_RESULT_DISASSOC_IND);
3168 	} else {
3169 		sme_err("Inactive vdev_id %d", vdev_id);
3170 	}
3171 
3172 	/*
3173 	 * Release WM status change command as eWNI_SME_DISCONNECT_DONE_IND
3174 	 * has been sent to HDD and there is nothing else left to do.
3175 	 */
3176 	csr_roam_wm_status_change_complete(mac_ctx, vdev_id);
3177 	qdf_mem_free(roam_info);
3178 }
3179 
3180 /**
3181  * csr_roaming_state_msg_processor() - process roaming messages
3182  * @mac:       mac global context
3183  * @msg_buf:    message buffer
3184  *
3185  * We need to be careful on whether to cast msg_buf (pSmeRsp) to other type of
3186  * structures. It depends on how the message is constructed. If the message is
3187  * sent by lim_send_sme_rsp, the msg_buf is only a generic response and can only
3188  * be used as pointer to tSirSmeRsp. For the messages where sender allocates
3189  * memory for specific structures, then it can be cast accordingly.
3190  *
3191  * Return: status of operation
3192  */
csr_roaming_state_msg_processor(struct mac_context * mac,void * msg_buf)3193 void csr_roaming_state_msg_processor(struct mac_context *mac, void *msg_buf)
3194 {
3195 	tSirSmeRsp *pSmeRsp;
3196 
3197 	pSmeRsp = (tSirSmeRsp *)msg_buf;
3198 
3199 	switch (pSmeRsp->messageType) {
3200 	case eWNI_SME_DISASSOC_RSP:
3201 		/* or the Disassociate response message... */
3202 		if (CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ(mac, pSmeRsp->vdev_id)) {
3203 			sme_debug("eWNI_SME_DISASSOC_RSP subState = %s",
3204 				  mac_trace_getcsr_roam_sub_state(
3205 				  mac->roam.curSubState[pSmeRsp->vdev_id]));
3206 			csr_roam_roaming_state_disassoc_rsp_processor(mac,
3207 						(struct disassoc_rsp *) pSmeRsp);
3208 		}
3209 		break;
3210 	case eWNI_SME_DEAUTH_RSP:
3211 		/* or the Deauthentication response message... */
3212 		if (CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ(mac, pSmeRsp->vdev_id))
3213 			csr_roam_roaming_state_deauth_rsp_processor(mac,
3214 						(struct deauth_rsp *) pSmeRsp);
3215 		break;
3216 	/* In case CSR issues STOP_BSS, we need to tell HDD about peer departed
3217 	 * because PE is removing them
3218 	 */
3219 	case eWNI_SME_TRIGGER_SAE:
3220 		sme_debug("Invoke SAE callback");
3221 		csr_sae_callback(mac, pSmeRsp);
3222 		break;
3223 
3224 	case eWNI_SME_SETCONTEXT_RSP:
3225 		csr_roam_check_for_link_status_change(mac, pSmeRsp);
3226 		break;
3227 
3228 	case eWNI_SME_DISCONNECT_DONE_IND:
3229 		csr_roam_send_disconnect_done_indication(mac, pSmeRsp);
3230 		break;
3231 
3232 	case eWNI_SME_UPPER_LAYER_ASSOC_CNF:
3233 		csr_roam_joined_state_msg_processor(mac, pSmeRsp);
3234 		break;
3235 	default:
3236 		sme_debug("Unexpected message type: %d[0x%X] received in substate %s",
3237 			pSmeRsp->messageType, pSmeRsp->messageType,
3238 			mac_trace_getcsr_roam_sub_state(
3239 				mac->roam.curSubState[pSmeRsp->vdev_id]));
3240 		/* If we are connected, check the link status change */
3241 		if (!csr_is_conn_state_disconnected(mac, pSmeRsp->vdev_id))
3242 			csr_roam_check_for_link_status_change(mac, pSmeRsp);
3243 		break;
3244 	}
3245 }
3246 
3247 #ifdef WLAN_FEATURE_11BE_MLO
3248 static void
csr_roam_assoc_cnf_mld_copy(struct csr_roam_info * roam_info,tSirSmeAssocIndToUpperLayerCnf * pUpperLayerAssocCnf,uint32_t num_bytes)3249 csr_roam_assoc_cnf_mld_copy(struct csr_roam_info *roam_info,
3250 			    tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf,
3251 			    uint32_t num_bytes)
3252 {
3253 	qdf_mem_copy(roam_info->peer_mld.bytes,
3254 		     pUpperLayerAssocCnf->peer_mld_addr,
3255 		     num_bytes);
3256 }
3257 #else /* WLAN_FEATURE_11BE_MLO */
3258 static inline void
csr_roam_assoc_cnf_mld_copy(struct csr_roam_info * roam_info,tSirSmeAssocIndToUpperLayerCnf * pUpperLayerAssocCnf,uint32_t num_bytes)3259 csr_roam_assoc_cnf_mld_copy(struct csr_roam_info *roam_info,
3260 			    tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf,
3261 			    uint32_t num_bytes)
3262 {
3263 }
3264 #endif /* WLAN_FEATURE_11BE_MLO */
3265 
csr_roam_joined_state_msg_processor(struct mac_context * mac,void * msg_buf)3266 void csr_roam_joined_state_msg_processor(struct mac_context *mac, void *msg_buf)
3267 {
3268 	tSirSmeRsp *pSirMsg = (tSirSmeRsp *)msg_buf;
3269 
3270 	switch (pSirMsg->messageType) {
3271 	case eWNI_SME_UPPER_LAYER_ASSOC_CNF:
3272 	{
3273 		struct csr_roam_session *pSession;
3274 		tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf;
3275 		struct csr_roam_info *roam_info;
3276 		uint32_t sessionId;
3277 		QDF_STATUS status;
3278 		enum QDF_OPMODE opmode;
3279 
3280 		sme_debug("ASSOCIATION confirmation can be given to upper layer ");
3281 		pUpperLayerAssocCnf =
3282 			(tSirSmeAssocIndToUpperLayerCnf *)msg_buf;
3283 		status = csr_roam_get_session_id_from_bssid(mac,
3284 							(struct qdf_mac_addr *)
3285 							   pUpperLayerAssocCnf->
3286 							   bssId, &sessionId);
3287 		pSession = CSR_GET_SESSION(mac, sessionId);
3288 
3289 		if (!pSession) {
3290 			sme_err("session %d not found", sessionId);
3291 			if (pUpperLayerAssocCnf->ies)
3292 				qdf_mem_free(pUpperLayerAssocCnf->ies);
3293 			return;
3294 		}
3295 
3296 		roam_info = qdf_mem_malloc(sizeof(*roam_info));
3297 		if (!roam_info) {
3298 			if (pUpperLayerAssocCnf->ies)
3299 				qdf_mem_free(pUpperLayerAssocCnf->ies);
3300 			return;
3301 		}
3302 		opmode = wlan_get_opmode_from_vdev_id(mac->pdev, sessionId);
3303 		/* send the status code as Success */
3304 		roam_info->status_code = eSIR_SME_SUCCESS;
3305 		roam_info->staId = (uint8_t) pUpperLayerAssocCnf->aid;
3306 		roam_info->rsnIELen =
3307 			(uint8_t) pUpperLayerAssocCnf->rsnIE.length;
3308 		roam_info->prsnIE =
3309 			pUpperLayerAssocCnf->rsnIE.rsnIEdata;
3310 #ifdef FEATURE_WLAN_WAPI
3311 		roam_info->wapiIELen =
3312 			(uint8_t) pUpperLayerAssocCnf->wapiIE.length;
3313 		roam_info->pwapiIE =
3314 			pUpperLayerAssocCnf->wapiIE.wapiIEdata;
3315 #endif
3316 		roam_info->addIELen =
3317 			(uint8_t) pUpperLayerAssocCnf->addIE.length;
3318 		roam_info->paddIE =
3319 			pUpperLayerAssocCnf->addIE.addIEdata;
3320 		qdf_mem_copy(roam_info->peerMac.bytes,
3321 			     pUpperLayerAssocCnf->peerMacAddr,
3322 			     sizeof(tSirMacAddr));
3323 		csr_roam_assoc_cnf_mld_copy(roam_info,
3324 					    pUpperLayerAssocCnf,
3325 					    sizeof(tSirMacAddr));
3326 		qdf_mem_copy(&roam_info->bssid,
3327 			     pUpperLayerAssocCnf->bssId,
3328 			     sizeof(struct qdf_mac_addr));
3329 		roam_info->wmmEnabledSta =
3330 			pUpperLayerAssocCnf->wmmEnabledSta;
3331 		roam_info->timingMeasCap =
3332 			pUpperLayerAssocCnf->timingMeasCap;
3333 		qdf_mem_copy(&roam_info->chan_info,
3334 			     &pUpperLayerAssocCnf->chan_info,
3335 			     sizeof(struct oem_channel_info));
3336 
3337 		roam_info->ampdu = pUpperLayerAssocCnf->ampdu;
3338 		roam_info->sgi_enable = pUpperLayerAssocCnf->sgi_enable;
3339 		roam_info->tx_stbc = pUpperLayerAssocCnf->tx_stbc;
3340 		roam_info->rx_stbc = pUpperLayerAssocCnf->rx_stbc;
3341 		roam_info->ch_width = pUpperLayerAssocCnf->ch_width;
3342 		roam_info->mode = pUpperLayerAssocCnf->mode;
3343 		roam_info->max_supp_idx = pUpperLayerAssocCnf->max_supp_idx;
3344 		roam_info->max_ext_idx = pUpperLayerAssocCnf->max_ext_idx;
3345 		roam_info->max_mcs_idx = pUpperLayerAssocCnf->max_mcs_idx;
3346 		roam_info->max_real_mcs_idx =
3347 					pUpperLayerAssocCnf->max_real_mcs_idx;
3348 		roam_info->rx_mcs_map = pUpperLayerAssocCnf->rx_mcs_map;
3349 		roam_info->tx_mcs_map = pUpperLayerAssocCnf->tx_mcs_map;
3350 		roam_info->ecsa_capable = pUpperLayerAssocCnf->ecsa_capable;
3351 		roam_info->ext_cap = pUpperLayerAssocCnf->ext_cap;
3352 		roam_info->supported_band =
3353 					pUpperLayerAssocCnf->supported_band;
3354 		if (pUpperLayerAssocCnf->ht_caps.present)
3355 			roam_info->ht_caps = pUpperLayerAssocCnf->ht_caps;
3356 		if (pUpperLayerAssocCnf->vht_caps.present)
3357 			roam_info->vht_caps = pUpperLayerAssocCnf->vht_caps;
3358 		roam_info->capability_info =
3359 					pUpperLayerAssocCnf->capability_info;
3360 		roam_info->he_caps_present =
3361 					pUpperLayerAssocCnf->he_caps_present;
3362 		roam_info->eht_caps_present =
3363 			pUpperLayerAssocCnf->eht_caps_present;
3364 		if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
3365 			if (pUpperLayerAssocCnf->ies_len > 0) {
3366 				roam_info->assocReqLength =
3367 						pUpperLayerAssocCnf->ies_len;
3368 				roam_info->assocReqPtr =
3369 						pUpperLayerAssocCnf->ies;
3370 			}
3371 
3372 			mac->roam.roamSession[sessionId].connectState =
3373 				eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED;
3374 			roam_info->fReassocReq =
3375 				pUpperLayerAssocCnf->reassocReq;
3376 			status = csr_roam_call_callback(mac, sessionId,
3377 						       roam_info,
3378 						       eCSR_ROAM_INFRA_IND,
3379 					eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF);
3380 		}
3381 		if (pUpperLayerAssocCnf->ies)
3382 			qdf_mem_free(pUpperLayerAssocCnf->ies);
3383 		qdf_mem_free(roam_info);
3384 	}
3385 	break;
3386 	default:
3387 		csr_roam_check_for_link_status_change(mac, pSirMsg);
3388 		break;
3389 	}
3390 }
3391 
3392 /**
3393  * csr_update_wep_key_peer_macaddr() - Update wep key peer mac addr
3394  * @vdev: vdev object
3395  * @crypto_key: crypto key info
3396  * @unicast: uncast or broadcast
3397  * @mac_addr: peer mac address
3398  *
3399  * Update peer mac address to key context before set wep key to target.
3400  *
3401  * Return void
3402  */
3403 static void
csr_update_wep_key_peer_macaddr(struct wlan_objmgr_vdev * vdev,struct wlan_crypto_key * crypto_key,bool unicast,struct qdf_mac_addr * mac_addr)3404 csr_update_wep_key_peer_macaddr(struct wlan_objmgr_vdev *vdev,
3405 				struct wlan_crypto_key *crypto_key,
3406 				bool unicast,
3407 				struct qdf_mac_addr *mac_addr)
3408 {
3409 	if (!crypto_key || !vdev) {
3410 		sme_err("vdev or crytpo_key null");
3411 		return;
3412 	}
3413 
3414 	if (unicast) {
3415 		qdf_mem_copy(&crypto_key->macaddr, mac_addr,
3416 			     QDF_MAC_ADDR_SIZE);
3417 	} else {
3418 		if (vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE ||
3419 		    vdev->vdev_mlme.vdev_opmode == QDF_P2P_CLIENT_MODE)
3420 			qdf_mem_copy(&crypto_key->macaddr, mac_addr,
3421 				     QDF_MAC_ADDR_SIZE);
3422 		else
3423 			qdf_mem_copy(&crypto_key->macaddr,
3424 				     vdev->vdev_mlme.macaddr,
3425 				     QDF_MAC_ADDR_SIZE);
3426 	}
3427 }
3428 
3429 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3430 static void
csr_roam_diag_set_ctx_rsp(struct mac_context * mac_ctx,struct csr_roam_session * session,struct set_context_rsp * pRsp)3431 csr_roam_diag_set_ctx_rsp(struct mac_context *mac_ctx,
3432 			  struct csr_roam_session *session,
3433 			  struct set_context_rsp *pRsp)
3434 {
3435 	WLAN_HOST_DIAG_EVENT_DEF(setKeyEvent,
3436 				 host_event_wlan_security_payload_type);
3437 	struct wlan_objmgr_vdev *vdev;
3438 
3439 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev,
3440 						    session->vdev_id,
3441 						    WLAN_LEGACY_SME_ID);
3442 	if (!vdev)
3443 		return;
3444 	if (cm_is_open_mode(vdev)) {
3445 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
3446 		return;
3447 	}
3448 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
3449 
3450 	qdf_mem_zero(&setKeyEvent,
3451 		     sizeof(host_event_wlan_security_payload_type));
3452 	if (qdf_is_macaddr_group(&pRsp->peer_macaddr))
3453 		setKeyEvent.eventId =
3454 			WLAN_SECURITY_EVENT_SET_BCAST_RSP;
3455 	else
3456 		setKeyEvent.eventId =
3457 			WLAN_SECURITY_EVENT_SET_UNICAST_RSP;
3458 	cm_diag_get_auth_enc_type_vdev_id(mac_ctx->psoc,
3459 					  &setKeyEvent.authMode,
3460 					  &setKeyEvent.encryptionModeUnicast,
3461 					  &setKeyEvent.encryptionModeMulticast,
3462 					  session->vdev_id);
3463 	wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, session->vdev_id,
3464 				    (struct qdf_mac_addr *)&setKeyEvent.bssid);
3465 	if (eSIR_SME_SUCCESS != pRsp->status_code)
3466 		setKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE;
3467 	WLAN_HOST_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY);
3468 }
3469 #else /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3470 static void
csr_roam_diag_set_ctx_rsp(struct mac_context * mac_ctx,struct csr_roam_session * session,struct set_context_rsp * pRsp)3471 csr_roam_diag_set_ctx_rsp(struct mac_context *mac_ctx,
3472 			  struct csr_roam_session *session,
3473 			  struct set_context_rsp *pRsp)
3474 {
3475 }
3476 #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3477 
3478 #ifdef WLAN_FEATURE_11BE_MLO
3479 static QDF_STATUS
csr_roam_send_rso_enable(struct mac_context * mac_ctx,uint8_t vdev_id)3480 csr_roam_send_rso_enable(struct mac_context *mac_ctx, uint8_t vdev_id)
3481 {
3482 	struct wlan_objmgr_vdev *vdev = NULL;
3483 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
3484 
3485 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
3486 						    vdev_id,
3487 						    WLAN_MLME_OBJMGR_ID);
3488 	if (!vdev) {
3489 		sme_err("vdev object is NULL for vdev %d", vdev_id);
3490 		return QDF_STATUS_E_FAILURE;
3491 	}
3492 
3493 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
3494 	    mlo_check_if_all_links_up(vdev)) {
3495 		assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev);
3496 		if (!assoc_vdev) {
3497 			sme_err("Assoc vdev is null");
3498 			wlan_objmgr_vdev_release_ref(vdev,
3499 						     WLAN_MLME_OBJMGR_ID);
3500 			return QDF_STATUS_E_FAILURE;
3501 		}
3502 		cm_roam_start_init_on_connect(mac_ctx->pdev,
3503 					      wlan_vdev_get_id(assoc_vdev));
3504 	} else if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
3505 		cm_roam_start_init_on_connect(mac_ctx->pdev, vdev_id);
3506 	}
3507 	wlan_objmgr_vdev_release_ref(vdev,
3508 				     WLAN_MLME_OBJMGR_ID);
3509 	return QDF_STATUS_SUCCESS;
3510 }
3511 #else
3512 static QDF_STATUS
csr_roam_send_rso_enable(struct mac_context * mac_ctx,uint8_t vdev_id)3513 csr_roam_send_rso_enable(struct mac_context *mac_ctx, uint8_t vdev_id)
3514 {
3515 	cm_roam_start_init_on_connect(mac_ctx->pdev, vdev_id);
3516 	return QDF_STATUS_SUCCESS;
3517 }
3518 #endif
3519 
3520 static void
csr_roam_chk_lnk_set_ctx_rsp(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)3521 csr_roam_chk_lnk_set_ctx_rsp(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
3522 {
3523 	struct csr_roam_session *session;
3524 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
3525 	QDF_STATUS status;
3526 	qdf_freq_t chan_freq;
3527 	struct csr_roam_info *roam_info;
3528 	eCsrRoamResult result = eCSR_ROAM_RESULT_NONE;
3529 	struct set_context_rsp *pRsp = (struct set_context_rsp *)msg_ptr;
3530 	struct qdf_mac_addr connected_bssid;
3531 
3532 	if (!pRsp) {
3533 		sme_err("set key response is NULL");
3534 		return;
3535 	}
3536 
3537 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
3538 	if (!roam_info)
3539 		return;
3540 	sessionId = pRsp->sessionId;
3541 	session = CSR_GET_SESSION(mac_ctx, sessionId);
3542 	if (!session) {
3543 		sme_err("session %d not found", sessionId);
3544 		qdf_mem_free(roam_info);
3545 		return;
3546 	}
3547 
3548 	csr_roam_diag_set_ctx_rsp(mac_ctx, session, pRsp);
3549 	chan_freq = wlan_get_operation_chan_freq_vdev_id(mac_ctx->pdev,
3550 							 sessionId);
3551 	wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, sessionId,
3552 				    &connected_bssid);
3553 	sme_debug("vdev %d, Status %d, peer_macaddr "QDF_MAC_ADDR_FMT " obss offload %d freq %d opmode %d",
3554 		  pRsp->sessionId, pRsp->status_code,
3555 		  QDF_MAC_ADDR_REF(pRsp->peer_macaddr.bytes),
3556 		  mac_ctx->obss_scan_offload, chan_freq,
3557 		  wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId));
3558 
3559 	if (CSR_IS_WAIT_FOR_KEY(mac_ctx, sessionId)) {
3560 		/* We are done with authentication, whethere succeed or not */
3561 		csr_roam_substate_change(mac_ctx, eCSR_ROAM_SUBSTATE_NONE,
3562 					 sessionId);
3563 		cm_stop_wait_for_key_timer(mac_ctx->psoc, sessionId);
3564 		if (QDF_IS_STATUS_ERROR(csr_roam_send_rso_enable(mac_ctx,
3565 								 sessionId))) {
3566 			qdf_mem_free(roam_info);
3567 			return;
3568 		}
3569 	}
3570 	if (eSIR_SME_SUCCESS == pRsp->status_code) {
3571 		qdf_copy_macaddr(&roam_info->peerMac, &pRsp->peer_macaddr);
3572 		/* Make sure we install the GTK before indicating to HDD as
3573 		 * authenticated. This is to prevent broadcast packets go out
3574 		 * after PTK and before GTK.
3575 		 */
3576 		if (qdf_is_macaddr_broadcast(&pRsp->peer_macaddr)) {
3577 			/*
3578 			 * OBSS SCAN Indication will be sent to Firmware
3579 			 * to start OBSS Scan
3580 			 */
3581 			if (mac_ctx->obss_scan_offload &&
3582 			    wlan_reg_is_24ghz_ch_freq(chan_freq) &&
3583 			    cm_is_vdevid_connected(mac_ctx->pdev, sessionId)) {
3584 				struct sme_obss_ht40_scanind_msg *msg;
3585 
3586 				msg = qdf_mem_malloc(sizeof(
3587 					struct sme_obss_ht40_scanind_msg));
3588 				if (!msg) {
3589 					qdf_mem_free(roam_info);
3590 					return;
3591 				}
3592 
3593 				msg->msg_type = eWNI_SME_HT40_OBSS_SCAN_IND;
3594 				msg->length =
3595 				      sizeof(struct sme_obss_ht40_scanind_msg);
3596 				qdf_copy_macaddr(&msg->mac_addr,
3597 					&connected_bssid);
3598 				status = umac_send_mb_message_to_mac(msg);
3599 			}
3600 			result = eCSR_ROAM_RESULT_AUTHENTICATED;
3601 		} else {
3602 			result = eCSR_ROAM_RESULT_NONE;
3603 		}
3604 	} else {
3605 		result = eCSR_ROAM_RESULT_FAILURE;
3606 		sme_err(
3607 			"CSR: setkey command failed(err=%d) PeerMac "
3608 			QDF_MAC_ADDR_FMT,
3609 			pRsp->status_code,
3610 			QDF_MAC_ADDR_REF(pRsp->peer_macaddr.bytes));
3611 	}
3612 	csr_roam_call_callback(mac_ctx, sessionId, roam_info,
3613 			       eCSR_ROAM_SET_KEY_COMPLETE, result);
3614 	/* Indicate SME_QOS that the SET_KEY is completed, so that SME_QOS
3615 	 * can go ahead and initiate the TSPEC if any are pending
3616 	 */
3617 	sme_qos_csr_event_ind(mac_ctx, (uint8_t)sessionId,
3618 			      SME_QOS_CSR_SET_KEY_SUCCESS_IND, NULL);
3619 #ifdef FEATURE_WLAN_ESE
3620 	/* Send Adjacent AP repot to new AP. */
3621 	if (result == eCSR_ROAM_RESULT_AUTHENTICATED &&
3622 	    session->isPrevApInfoValid &&
3623 	    wlan_cm_get_ese_assoc(mac_ctx->pdev, sessionId)) {
3624 		csr_send_ese_adjacent_ap_rep_ind(mac_ctx, session);
3625 		session->isPrevApInfoValid = false;
3626 	}
3627 #endif
3628 	qdf_mem_free(roam_info);
3629 }
3630 
csr_roam_issue_set_context_req(struct mac_context * mac_ctx,uint32_t session_id,bool add_key,bool unicast,uint8_t key_idx,struct qdf_mac_addr * mac_addr)3631 static QDF_STATUS csr_roam_issue_set_context_req(struct mac_context *mac_ctx,
3632 						 uint32_t session_id,
3633 						 bool add_key, bool unicast,
3634 						 uint8_t key_idx,
3635 						 struct qdf_mac_addr *mac_addr)
3636 {
3637 	enum wlan_crypto_cipher_type cipher;
3638 	struct wlan_crypto_key *crypto_key;
3639 	uint8_t wep_key_idx = 0;
3640 	struct wlan_objmgr_vdev *vdev;
3641 
3642 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, session_id,
3643 						    WLAN_LEGACY_MAC_ID);
3644 	if (!vdev) {
3645 		sme_err("VDEV object not found for session_id %d", session_id);
3646 		return QDF_STATUS_E_INVAL;
3647 	}
3648 	cipher = wlan_crypto_get_cipher(vdev, unicast, key_idx);
3649 	if (IS_WEP_CIPHER(cipher)) {
3650 		wep_key_idx = wlan_crypto_get_default_key_idx(vdev, !unicast);
3651 		crypto_key = wlan_crypto_get_key(vdev, wep_key_idx);
3652 		csr_update_wep_key_peer_macaddr(vdev, crypto_key, unicast,
3653 						mac_addr);
3654 	} else {
3655 		crypto_key = wlan_crypto_get_key(vdev, key_idx);
3656 	}
3657 
3658 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
3659 
3660 	sme_debug("session:%d, cipher:%d, ucast:%d, idx:%d, wep:%d, add:%d",
3661 		  session_id, cipher, unicast, key_idx, wep_key_idx, add_key);
3662 	if (!IS_WEP_CIPHER(cipher) && !add_key)
3663 		return QDF_STATUS_E_INVAL;
3664 
3665 	return ucfg_crypto_set_key_req(vdev, crypto_key, (unicast ?
3666 				       WLAN_CRYPTO_KEY_TYPE_UNICAST :
3667 				       WLAN_CRYPTO_KEY_TYPE_GROUP));
3668 }
3669 
3670 QDF_STATUS
csr_issue_set_context_req_helper(struct mac_context * mac_ctx,uint32_t vdev_id,tSirMacAddr * bssid,bool addkey,bool unicast,uint8_t key_id)3671 csr_issue_set_context_req_helper(struct mac_context *mac_ctx,
3672 				 uint32_t vdev_id, tSirMacAddr *bssid,
3673 				 bool addkey, bool unicast, uint8_t key_id)
3674 {
3675 	return csr_roam_issue_set_context_req(mac_ctx, vdev_id, addkey,
3676 					      unicast, key_id,
3677 					      (struct qdf_mac_addr *)bssid);
3678 }
3679 
3680 static
csr_roam_issue_wm_status_change(struct mac_context * mac,uint32_t sessionId,enum csr_roam_wmstatus_changetypes Type,tSirSmeRsp * pSmeRsp)3681 bool csr_roam_issue_wm_status_change(struct mac_context *mac, uint32_t sessionId,
3682 				     enum csr_roam_wmstatus_changetypes Type,
3683 				     tSirSmeRsp *pSmeRsp)
3684 {
3685 	bool fCommandQueued = false;
3686 	tSmeCmd *pCommand;
3687 
3688 	do {
3689 		/* Validate the type is ok... */
3690 		if ((eCsrDisassociated != Type)
3691 		    && (eCsrDeauthenticated != Type))
3692 			break;
3693 		pCommand = csr_get_command_buffer(mac);
3694 		if (!pCommand) {
3695 			sme_err(" fail to get command buffer");
3696 			break;
3697 		}
3698 
3699 		pCommand->command = eSmeCommandWmStatusChange;
3700 		pCommand->vdev_id = (uint8_t) sessionId;
3701 		pCommand->u.wmStatusChangeCmd.Type = Type;
3702 		if (eCsrDisassociated == Type) {
3703 			qdf_mem_copy(&pCommand->u.wmStatusChangeCmd.u.
3704 				     DisassocIndMsg, pSmeRsp,
3705 				     sizeof(pCommand->u.wmStatusChangeCmd.u.
3706 					    DisassocIndMsg));
3707 		} else {
3708 			qdf_mem_copy(&pCommand->u.wmStatusChangeCmd.u.
3709 				     DeauthIndMsg, pSmeRsp,
3710 				     sizeof(pCommand->u.wmStatusChangeCmd.u.
3711 					    DeauthIndMsg));
3712 		}
3713 		if (QDF_IS_STATUS_SUCCESS
3714 			    (csr_queue_sme_command(mac, pCommand, false)))
3715 			fCommandQueued = true;
3716 		else
3717 			sme_err("fail to send message");
3718 	} while (0);
3719 	return fCommandQueued;
3720 }
3721 
csr_update_snr(struct mac_context * mac,void * pMsg)3722 static void csr_update_snr(struct mac_context *mac, void *pMsg)
3723 {
3724 	tAniGetSnrReq *pGetSnrReq = (tAniGetSnrReq *) pMsg;
3725 
3726 	if (pGetSnrReq) {
3727 		if (QDF_STATUS_SUCCESS != wma_get_snr(pGetSnrReq)) {
3728 			sme_err("Error in wma_get_snr");
3729 			return;
3730 		}
3731 
3732 	} else
3733 		sme_err("pGetSnrReq is NULL");
3734 }
3735 
3736 /**
3737  * csr_translate_akm_type() - Convert ani_akm_type value to equivalent
3738  * enum csr_akm_type
3739  * @akm_type: value of type ani_akm_type
3740  *
3741  * Return: enum csr_akm_type value
3742  */
csr_translate_akm_type(enum ani_akm_type akm_type)3743 static enum csr_akm_type csr_translate_akm_type(enum ani_akm_type akm_type)
3744 {
3745 	enum csr_akm_type csr_akm_type;
3746 
3747 	switch (akm_type)
3748 	{
3749 	case ANI_AKM_TYPE_NONE:
3750 		csr_akm_type = eCSR_AUTH_TYPE_NONE;
3751 		break;
3752 #ifdef WLAN_FEATURE_SAE
3753 	case ANI_AKM_TYPE_SAE:
3754 		csr_akm_type = eCSR_AUTH_TYPE_SAE;
3755 		break;
3756 #endif
3757 	case ANI_AKM_TYPE_WPA:
3758 		csr_akm_type = eCSR_AUTH_TYPE_WPA;
3759 		break;
3760 	case ANI_AKM_TYPE_WPA_PSK:
3761 		csr_akm_type = eCSR_AUTH_TYPE_WPA_PSK;
3762 		break;
3763 	case ANI_AKM_TYPE_RSN:
3764 		csr_akm_type = eCSR_AUTH_TYPE_RSN;
3765 		break;
3766 	case ANI_AKM_TYPE_RSN_PSK:
3767 		csr_akm_type = eCSR_AUTH_TYPE_RSN_PSK;
3768 		break;
3769 	case ANI_AKM_TYPE_FT_RSN:
3770 		csr_akm_type = eCSR_AUTH_TYPE_FT_RSN;
3771 		break;
3772 	case ANI_AKM_TYPE_FT_RSN_PSK:
3773 		csr_akm_type = eCSR_AUTH_TYPE_FT_RSN_PSK;
3774 		break;
3775 #ifdef FEATURE_WLAN_ESE
3776 	case ANI_AKM_TYPE_CCKM:
3777 		csr_akm_type = eCSR_AUTH_TYPE_CCKM_RSN;
3778 		break;
3779 #endif
3780 	case ANI_AKM_TYPE_RSN_PSK_SHA256:
3781 		csr_akm_type = eCSR_AUTH_TYPE_RSN_PSK_SHA256;
3782 		break;
3783 	case ANI_AKM_TYPE_RSN_8021X_SHA256:
3784 		csr_akm_type = eCSR_AUTH_TYPE_RSN_8021X_SHA256;
3785 		break;
3786 	case ANI_AKM_TYPE_FILS_SHA256:
3787 		csr_akm_type = eCSR_AUTH_TYPE_FILS_SHA256;
3788 		break;
3789 	case ANI_AKM_TYPE_FILS_SHA384:
3790 		csr_akm_type = eCSR_AUTH_TYPE_FILS_SHA384;
3791 		break;
3792 	case ANI_AKM_TYPE_FT_FILS_SHA256:
3793 		csr_akm_type = eCSR_AUTH_TYPE_FT_FILS_SHA256;
3794 		break;
3795 	case ANI_AKM_TYPE_FT_FILS_SHA384:
3796 		csr_akm_type = eCSR_AUTH_TYPE_FT_FILS_SHA384;
3797 		break;
3798 	case ANI_AKM_TYPE_DPP_RSN:
3799 		csr_akm_type = eCSR_AUTH_TYPE_DPP_RSN;
3800 		break;
3801 	case ANI_AKM_TYPE_OWE:
3802 		csr_akm_type = eCSR_AUTH_TYPE_OWE;
3803 		break;
3804 	case ANI_AKM_TYPE_SUITEB_EAP_SHA256:
3805 		csr_akm_type = eCSR_AUTH_TYPE_SUITEB_EAP_SHA256;
3806 		break;
3807 	case ANI_AKM_TYPE_SUITEB_EAP_SHA384:
3808 		csr_akm_type = eCSR_AUTH_TYPE_SUITEB_EAP_SHA384;
3809 		break;
3810 	case ANI_AKM_TYPE_OSEN:
3811 		csr_akm_type = eCSR_AUTH_TYPE_OSEN;
3812 		break;
3813 	default:
3814 		csr_akm_type = eCSR_AUTH_TYPE_UNKNOWN;
3815 	}
3816 
3817 	return csr_akm_type;
3818 }
3819 
3820 #ifdef WLAN_FEATURE_11BE_MLO
3821 static void
csr_send_assoc_ind_to_upper_layer_mac_copy(tSirSmeAssocIndToUpperLayerCnf * cnf,struct assoc_ind * ind)3822 csr_send_assoc_ind_to_upper_layer_mac_copy(tSirSmeAssocIndToUpperLayerCnf *cnf,
3823 					   struct assoc_ind *ind)
3824 {
3825 	qdf_mem_copy(&cnf->peer_mld_addr, &ind->peer_mld_addr,
3826 		     sizeof(cnf->peer_mld_addr));
3827 }
3828 #else /* WLAN_FEATURE_11BE_MLO */
3829 static inline void
csr_send_assoc_ind_to_upper_layer_mac_copy(tSirSmeAssocIndToUpperLayerCnf * cnf,struct assoc_ind * ind)3830 csr_send_assoc_ind_to_upper_layer_mac_copy(tSirSmeAssocIndToUpperLayerCnf *cnf,
3831 					   struct assoc_ind *ind)
3832 {
3833 }
3834 #endif /* WLAN_FEATURE_11BE_MLO */
3835 
3836 static QDF_STATUS
csr_send_assoc_ind_to_upper_layer_cnf_msg(struct mac_context * mac,struct assoc_ind * ind,QDF_STATUS status,uint8_t vdev_id)3837 csr_send_assoc_ind_to_upper_layer_cnf_msg(struct mac_context *mac,
3838 					  struct assoc_ind *ind,
3839 					  QDF_STATUS status,
3840 					  uint8_t vdev_id)
3841 {
3842 	struct scheduler_msg msg = {0};
3843 	tSirSmeAssocIndToUpperLayerCnf *cnf;
3844 
3845 	cnf = qdf_mem_malloc(sizeof(*cnf));
3846 	if (!cnf)
3847 		return QDF_STATUS_E_NOMEM;
3848 
3849 	cnf->messageType = eWNI_SME_UPPER_LAYER_ASSOC_CNF;
3850 	cnf->length = sizeof(*cnf);
3851 	cnf->sessionId = vdev_id;
3852 
3853 	if (QDF_IS_STATUS_SUCCESS(status))
3854 		cnf->status_code = eSIR_SME_SUCCESS;
3855 	else
3856 		cnf->status_code = eSIR_SME_ASSOC_REFUSED;
3857 	qdf_mem_copy(&cnf->bssId, &ind->bssId, sizeof(cnf->bssId));
3858 	qdf_mem_copy(&cnf->peerMacAddr, &ind->peerMacAddr,
3859 		     sizeof(cnf->peerMacAddr));
3860 	csr_send_assoc_ind_to_upper_layer_mac_copy(cnf, ind);
3861 	cnf->aid = ind->staId;
3862 	cnf->wmmEnabledSta = ind->wmmEnabledSta;
3863 	cnf->rsnIE = ind->rsnIE;
3864 #ifdef FEATURE_WLAN_WAPI
3865 	cnf->wapiIE = ind->wapiIE;
3866 #endif
3867 	cnf->addIE = ind->addIE;
3868 	cnf->reassocReq = ind->reassocReq;
3869 	cnf->timingMeasCap = ind->timingMeasCap;
3870 	cnf->chan_info = ind->chan_info;
3871 	cnf->ampdu = ind->ampdu;
3872 	cnf->sgi_enable = ind->sgi_enable;
3873 	cnf->tx_stbc = ind->tx_stbc;
3874 	cnf->ch_width = ind->ch_width;
3875 	cnf->mode = ind->mode;
3876 	cnf->rx_stbc = ind->rx_stbc;
3877 	cnf->max_supp_idx = ind->max_supp_idx;
3878 	cnf->max_ext_idx = ind->max_ext_idx;
3879 	cnf->max_mcs_idx = ind->max_mcs_idx;
3880 	cnf->max_real_mcs_idx = ind->max_real_mcs_idx;
3881 	cnf->rx_mcs_map = ind->rx_mcs_map;
3882 	cnf->tx_mcs_map = ind->tx_mcs_map;
3883 	cnf->ecsa_capable = ind->ecsa_capable;
3884 	cnf->ext_cap = ind->ext_cap;
3885 	cnf->supported_band = ind->supported_band;
3886 	if (ind->HTCaps.present)
3887 		cnf->ht_caps = ind->HTCaps;
3888 	if (ind->VHTCaps.present)
3889 		cnf->vht_caps = ind->VHTCaps;
3890 	cnf->capability_info = ind->capability_info;
3891 	cnf->he_caps_present = ind->he_caps_present;
3892 	cnf->eht_caps_present = ind->eht_caps_present;
3893 	if (ind->assocReqPtr) {
3894 		if (ind->assocReqLength < MAX_ASSOC_REQ_IE_LEN) {
3895 			cnf->ies = qdf_mem_malloc(ind->assocReqLength);
3896 			if (!cnf->ies) {
3897 				qdf_mem_free(cnf);
3898 				return QDF_STATUS_E_NOMEM;
3899 			}
3900 			cnf->ies_len = ind->assocReqLength;
3901 			qdf_mem_copy(cnf->ies, ind->assocReqPtr,
3902 				     cnf->ies_len);
3903 		} else {
3904 			sme_err("Assoc Ie length is too long");
3905 		}
3906 	}
3907 
3908 	msg.type = eWNI_SME_UPPER_LAYER_ASSOC_CNF;
3909 	msg.bodyptr = cnf;
3910 	sys_process_mmh_msg(mac, &msg);
3911 
3912 	return QDF_STATUS_SUCCESS;
3913 }
3914 
3915 static void
csr_roam_chk_lnk_assoc_ind_upper_layer(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)3916 csr_roam_chk_lnk_assoc_ind_upper_layer(
3917 		struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
3918 {
3919 	uint32_t session_id = WLAN_UMAC_VDEV_ID_MAX;
3920 	struct assoc_ind *assoc_ind;
3921 	QDF_STATUS status;
3922 
3923 	assoc_ind = (struct assoc_ind *)msg_ptr;
3924 	status = csr_roam_get_session_id_from_bssid(
3925 			mac_ctx, (struct qdf_mac_addr *)assoc_ind->bssId,
3926 			&session_id);
3927 	if (!QDF_IS_STATUS_SUCCESS(status)) {
3928 		sme_debug("Couldn't find session_id for given BSSID");
3929 		goto free_mem;
3930 	}
3931 	csr_send_assoc_ind_to_upper_layer_cnf_msg(
3932 					mac_ctx, assoc_ind, status, session_id);
3933 	/*in the association response tx compete case,
3934 	 *memory for assoc_ind->assocReqPtr will be malloced
3935 	 *in the lim_assoc_rsp_tx_complete -> lim_fill_sme_assoc_ind_params
3936 	 *and then assoc_ind will pass here, so after using it
3937 	 *in the csr_send_assoc_ind_to_upper_layer_cnf_msg and
3938 	 *then free the memory here.
3939 	 */
3940 free_mem:
3941 	if (assoc_ind->assocReqLength != 0 && assoc_ind->assocReqPtr)
3942 		qdf_mem_free(assoc_ind->assocReqPtr);
3943 }
3944 
3945 static void
csr_roam_chk_lnk_assoc_ind(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)3946 csr_roam_chk_lnk_assoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
3947 {
3948 	struct csr_roam_session *session;
3949 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
3950 	QDF_STATUS status;
3951 	struct csr_roam_info *roam_info;
3952 	struct assoc_ind *pAssocInd;
3953 	enum wlan_status_code mac_status_code = STATUS_SUCCESS;
3954 	enum csr_akm_type csr_akm_type;
3955 	enum QDF_OPMODE opmode;
3956 
3957 	sme_debug("Receive WNI_SME_ASSOC_IND from SME");
3958 	pAssocInd = (struct assoc_ind *) msg_ptr;
3959 	sme_debug("Receive WNI_SME_ASSOC_IND from SME vdev id %d",
3960 		  pAssocInd->sessionId);
3961 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
3962 				(struct qdf_mac_addr *) pAssocInd->bssId,
3963 				&sessionId);
3964 	if (!QDF_IS_STATUS_SUCCESS(status)) {
3965 		sme_debug("Couldn't find session_id for given BSSID" QDF_MAC_ADDR_FMT,
3966 			  QDF_MAC_ADDR_REF(pAssocInd->bssId));
3967 		return;
3968 	}
3969 	session = CSR_GET_SESSION(mac_ctx, sessionId);
3970 	if (!session) {
3971 		sme_err("session %d not found", sessionId);
3972 		return;
3973 	}
3974 	csr_akm_type = csr_translate_akm_type(pAssocInd->akm_type);
3975 
3976 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
3977 	if (!roam_info)
3978 		return;
3979 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId);
3980 	/* Required for indicating the frames to upper layer */
3981 	roam_info->assocReqLength = pAssocInd->assocReqLength;
3982 	roam_info->assocReqPtr = pAssocInd->assocReqPtr;
3983 	roam_info->status_code = eSIR_SME_SUCCESS;
3984 	roam_info->staId = (uint8_t)pAssocInd->staId;
3985 	roam_info->rsnIELen = (uint8_t)pAssocInd->rsnIE.length;
3986 	roam_info->prsnIE = pAssocInd->rsnIE.rsnIEdata;
3987 #ifdef FEATURE_WLAN_WAPI
3988 	roam_info->wapiIELen = (uint8_t)pAssocInd->wapiIE.length;
3989 	roam_info->pwapiIE = pAssocInd->wapiIE.wapiIEdata;
3990 #endif
3991 	roam_info->addIELen = (uint8_t)pAssocInd->addIE.length;
3992 	roam_info->paddIE = pAssocInd->addIE.addIEdata;
3993 	roam_info->fReassocReq = pAssocInd->reassocReq;
3994 	qdf_mem_copy(roam_info->peerMac.bytes,
3995 		     pAssocInd->peerMacAddr,
3996 		     sizeof(tSirMacAddr));
3997 	qdf_mem_copy(roam_info->bssid.bytes,
3998 		     pAssocInd->bssId,
3999 		     sizeof(struct qdf_mac_addr));
4000 	roam_info->wmmEnabledSta = pAssocInd->wmmEnabledSta;
4001 	roam_info->timingMeasCap = pAssocInd->timingMeasCap;
4002 	roam_info->ecsa_capable = pAssocInd->ecsa_capable;
4003 	qdf_mem_copy(&roam_info->chan_info,
4004 		     &pAssocInd->chan_info,
4005 		     sizeof(struct oem_channel_info));
4006 
4007 	if (pAssocInd->HTCaps.present)
4008 		qdf_mem_copy(&roam_info->ht_caps,
4009 			     &pAssocInd->HTCaps,
4010 			     sizeof(tDot11fIEHTCaps));
4011 	if (pAssocInd->VHTCaps.present)
4012 		qdf_mem_copy(&roam_info->vht_caps,
4013 			     &pAssocInd->VHTCaps,
4014 			     sizeof(tDot11fIEVHTCaps));
4015 	roam_info->capability_info = pAssocInd->capability_info;
4016 	roam_info->he_caps_present = pAssocInd->he_caps_present;
4017 	roam_info->eht_caps_present = pAssocInd->eht_caps_present;
4018 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
4019 		if (wlan_is_open_wep_cipher(mac_ctx->pdev, sessionId)) {
4020 			csr_issue_set_context_req_helper(mac_ctx, sessionId,
4021 					&roam_info->peerMac.bytes, false, true,
4022 					0);
4023 			roam_info->fAuthRequired = false;
4024 		} else {
4025 			roam_info->fAuthRequired = true;
4026 		}
4027 		sme_debug("Receive AUTH_TYPE of %d", csr_akm_type);
4028 		if (csr_akm_type == eCSR_AUTH_TYPE_OWE) {
4029 			roam_info->owe_pending_assoc_ind = qdf_mem_malloc(
4030 							    sizeof(*pAssocInd));
4031 			if (roam_info->owe_pending_assoc_ind)
4032 				qdf_mem_copy(roam_info->owe_pending_assoc_ind,
4033 					     pAssocInd, sizeof(*pAssocInd));
4034 		} else if (csr_akm_type == eCSR_AUTH_TYPE_FT_RSN_PSK) {
4035 			roam_info->ft_pending_assoc_ind = qdf_mem_malloc(
4036 			    sizeof(*pAssocInd));
4037 			if (roam_info->ft_pending_assoc_ind)
4038 				qdf_mem_copy(roam_info->ft_pending_assoc_ind,
4039 					     pAssocInd, sizeof(*pAssocInd));
4040 		}
4041 		status = csr_roam_call_callback(mac_ctx, sessionId,
4042 					roam_info, eCSR_ROAM_INFRA_IND,
4043 					eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND);
4044 		if (!QDF_IS_STATUS_SUCCESS(status)) {
4045 			/* Refused due to Mac filtering */
4046 			if (roam_info->owe_pending_assoc_ind) {
4047 				qdf_mem_free(roam_info->owe_pending_assoc_ind);
4048 				roam_info->owe_pending_assoc_ind = NULL;
4049 			} else if (roam_info->ft_pending_assoc_ind) {
4050 				qdf_mem_free(roam_info->ft_pending_assoc_ind);
4051 				roam_info->ft_pending_assoc_ind = NULL;
4052 			}
4053 			roam_info->status_code = eSIR_SME_ASSOC_REFUSED;
4054 		}
4055 	}
4056 	sme_debug("csr_akm_type: %d", csr_akm_type);
4057 
4058 	if (csr_akm_type != eCSR_AUTH_TYPE_OWE &&
4059 	    csr_akm_type != eCSR_AUTH_TYPE_FT_RSN_PSK) {
4060 		if ((opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) &&
4061 		    roam_info->status_code != eSIR_SME_ASSOC_REFUSED)
4062 			pAssocInd->need_assoc_rsp_tx_cb = true;
4063 		/* Send Association completion message to PE */
4064 		status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status,
4065 						mac_status_code);
4066 	}
4067 
4068 	qdf_mem_free(roam_info);
4069 }
4070 
4071 /* csr_if_peer_present() - Check whether peer is present or not
4072  * @mac_ctx: Pointer to mac context
4073  * @bssid: Pointer to bssid address
4074  * @peer_macaddr: Pointer to peer mac address
4075  *
4076  * Consider a case
4077  * 1. SAP received south bound disconnect command
4078  * 2. At same time, SAP CSA to DFS channel happened and thus peers are deleted.
4079  * 3. Later same peer got re-added and south bound disconnect command becomes
4080  *    active for same peer.
4081  *
4082  * When SAP receives south bound disconnect command req, driver will post to
4083  * schedular thread and it will wait in SME message queue. When SAP CSA to DFS
4084  * channel happens, driver will post to schedular thread and it will wait in PE
4085  * message queue. Since PE has higher priority than SME message queue, so it
4086  * will process first. As part of CSA, it will delete all peer including sta
4087  * hash entry.
4088  * After CSA, south bound disconnect command got queue to serialization and
4089  * same peer got re-added again. When south bound disconnect command becomes
4090  * active, the states will not be proper because for old peer, disassocTrigger
4091  * is eLIM_PEER_ENTITY_DISASSOC/eLIM_PEER_ENTITY_DEAUTH and when new peer gets
4092  * re-added, disassocTrigger will be eLIM_HOST_DISASSOC/eLIM_HOST_DEAUTH and
4093  * thus response to CSR will not be proper. Due to this south bound disconnect
4094  * command will not remove from active queue which leads to active command
4095  * timeout.
4096  * Validate the peer before sending to serialization to avoid queuing command
4097  * if peer is already deleted.
4098  *
4099  * Return: True if peer is present otherwise return false
4100  */
csr_if_peer_present(struct mac_context * mac_ctx,uint8_t * bssid,uint8_t * peer_macaddr)4101 static bool csr_if_peer_present(struct mac_context *mac_ctx,
4102 				uint8_t *bssid,
4103 				uint8_t *peer_macaddr)
4104 {
4105 	struct wlan_objmgr_peer *peer;
4106 	uint8_t pdev_id;
4107 
4108 	pdev_id = wlan_objmgr_pdev_get_pdev_id(mac_ctx->pdev);
4109 
4110 	peer = wlan_objmgr_get_peer_by_mac_n_vdev(mac_ctx->psoc, pdev_id,
4111 						  bssid, peer_macaddr,
4112 						  WLAN_LEGACY_SME_ID);
4113 
4114 	if (!peer) {
4115 		sme_info("peer not found for mac: " QDF_MAC_ADDR_FMT "and bssid: "
4116 			  QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_macaddr),
4117 			  QDF_MAC_ADDR_REF(bssid));
4118 		return false;
4119 	}
4120 
4121 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_SME_ID);
4122 	return true;
4123 }
4124 
4125 static void
csr_roam_chk_lnk_disassoc_ind(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4126 csr_roam_chk_lnk_disassoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4127 {
4128 	struct csr_roam_session *session;
4129 	uint8_t vdev_id = WLAN_UMAC_VDEV_ID_MAX;
4130 	struct disassoc_ind *disassoc_ind;
4131 
4132 	/*
4133 	 * Check if AP dis-associated us because of MIC failure. If so,
4134 	 * then we need to take action immediately and not wait till the
4135 	 * the WmStatusChange requests is pushed and processed
4136 	 */
4137 	disassoc_ind = (struct disassoc_ind *)msg_ptr;
4138 	vdev_id = disassoc_ind->vdev_id;
4139 
4140 	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
4141 		sme_err("vdev:%d Invalid session. BSSID: " QDF_MAC_ADDR_FMT,
4142 			vdev_id, QDF_MAC_ADDR_REF(disassoc_ind->bssid.bytes));
4143 
4144 		return;
4145 	}
4146 
4147 	if (!csr_if_peer_present(mac_ctx, &disassoc_ind->bssid.bytes[0],
4148 				 &disassoc_ind->peer_macaddr.bytes[0]))
4149 		return;
4150 
4151 	if (csr_is_deauth_disassoc_cmd_active(mac_ctx, vdev_id,
4152 					      disassoc_ind->peer_macaddr,
4153 					      &disassoc_ind->peer_macaddr,
4154 					      &disassoc_ind->peer_mld_addr))
4155 		return;
4156 
4157 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
4158 	if (!session) {
4159 		sme_err("vdev %d session not found", vdev_id);
4160 		return;
4161 	}
4162 	sme_debug("Vdev %d, peer " QDF_MAC_ADDR_FMT " reason: %d status: %d",
4163 		  vdev_id, QDF_MAC_ADDR_REF(disassoc_ind->peer_macaddr.bytes),
4164 		  disassoc_ind->reasonCode, disassoc_ind->status_code);
4165 	/* Update the disconnect stats */
4166 	session->disconnect_stats.disconnection_cnt++;
4167 	session->disconnect_stats.disassoc_by_peer++;
4168 
4169 	csr_roam_issue_wm_status_change(mac_ctx, vdev_id,
4170 					eCsrDisassociated, msg_ptr);
4171 }
4172 
4173 static void
csr_roam_chk_lnk_deauth_ind(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4174 csr_roam_chk_lnk_deauth_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4175 {
4176 	struct csr_roam_session *session;
4177 	uint8_t vdev_id = WLAN_UMAC_VDEV_ID_MAX;
4178 	struct deauth_ind *deauth_ind;
4179 
4180 	deauth_ind = (struct deauth_ind *)msg_ptr;
4181 
4182 	vdev_id = deauth_ind->vdev_id;
4183 	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
4184 		sme_err("vdev %d: Invalid session BSSID: " QDF_MAC_ADDR_FMT,
4185 			deauth_ind->vdev_id,
4186 			QDF_MAC_ADDR_REF(deauth_ind->bssid.bytes));
4187 		return;
4188 	}
4189 
4190 	if (!csr_if_peer_present(mac_ctx, &deauth_ind->bssid.bytes[0],
4191 				 &deauth_ind->peer_macaddr.bytes[0]))
4192 		return;
4193 
4194 	if (csr_is_deauth_disassoc_cmd_active(mac_ctx, vdev_id,
4195 					      deauth_ind->peer_macaddr,
4196 					      &deauth_ind->peer_macaddr,
4197 					      &deauth_ind->peer_mld_addr))
4198 		return;
4199 
4200 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
4201 	if (!session) {
4202 		sme_err("vdev %d session not found", vdev_id);
4203 		return;
4204 	}
4205 	sme_debug("vdev %d bssid " QDF_MAC_ADDR_FMT " reason: %d status: %d",
4206 		  deauth_ind->vdev_id,
4207 		  QDF_MAC_ADDR_REF(deauth_ind->bssid.bytes),
4208 		  deauth_ind->reasonCode, deauth_ind->status_code);
4209 	/* Update the disconnect stats */
4210 	switch (deauth_ind->reasonCode) {
4211 	case REASON_DISASSOC_DUE_TO_INACTIVITY:
4212 		session->disconnect_stats.disconnection_cnt++;
4213 		session->disconnect_stats.peer_kickout++;
4214 		break;
4215 	case REASON_UNSPEC_FAILURE:
4216 	case REASON_PREV_AUTH_NOT_VALID:
4217 	case REASON_DEAUTH_NETWORK_LEAVING:
4218 	case REASON_CLASS2_FRAME_FROM_NON_AUTH_STA:
4219 	case REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA:
4220 	case REASON_STA_NOT_AUTHENTICATED:
4221 		session->disconnect_stats.disconnection_cnt++;
4222 		session->disconnect_stats.deauth_by_peer++;
4223 		break;
4224 	case REASON_BEACON_MISSED:
4225 		session->disconnect_stats.disconnection_cnt++;
4226 		session->disconnect_stats.bmiss++;
4227 		break;
4228 	default:
4229 		/* Unknown reason code */
4230 		break;
4231 	}
4232 
4233 	csr_roam_issue_wm_status_change(mac_ctx, vdev_id,
4234 					eCsrDeauthenticated,
4235 					msg_ptr);
4236 }
4237 
4238 static void
csr_roam_chk_lnk_swt_ch_ind(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4239 csr_roam_chk_lnk_swt_ch_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4240 {
4241 	struct csr_roam_session *session;
4242 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4243 	QDF_STATUS status;
4244 	struct switch_channel_ind *pSwitchChnInd;
4245 	struct csr_roam_info *roam_info;
4246 
4247 	/* in case of STA, the SWITCH_CHANNEL originates from its AP */
4248 	sme_debug("eWNI_SME_SWITCH_CHL_IND from SME");
4249 	pSwitchChnInd = (struct switch_channel_ind *)msg_ptr;
4250 	/* Update with the new channel id. The channel id is hidden in the
4251 	 * status_code.
4252 	 */
4253 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
4254 			&pSwitchChnInd->bssid, &sessionId);
4255 	if (QDF_IS_STATUS_ERROR(status))
4256 		return;
4257 
4258 	session = CSR_GET_SESSION(mac_ctx, sessionId);
4259 	if (!session) {
4260 		sme_err("session %d not found", sessionId);
4261 		return;
4262 	}
4263 
4264 	if (QDF_IS_STATUS_ERROR(pSwitchChnInd->status)) {
4265 		sme_err("Channel switch failed");
4266 		return;
4267 	}
4268 	/* Update the occupied channel list with the new switched channel */
4269 	wlan_cm_init_occupied_ch_freq_list(mac_ctx->pdev, mac_ctx->psoc,
4270 					   sessionId);
4271 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4272 	if (!roam_info)
4273 		return;
4274 	roam_info->chan_info.mhz = pSwitchChnInd->freq;
4275 	roam_info->chan_info.ch_width = pSwitchChnInd->chan_params.ch_width;
4276 	roam_info->chan_info.sec_ch_offset =
4277 				pSwitchChnInd->chan_params.sec_ch_offset;
4278 	roam_info->chan_info.band_center_freq1 =
4279 				pSwitchChnInd->chan_params.mhz_freq_seg0;
4280 	roam_info->chan_info.band_center_freq2 =
4281 				pSwitchChnInd->chan_params.mhz_freq_seg1;
4282 
4283 	if (IS_WLAN_PHYMODE_HT(pSwitchChnInd->ch_phymode))
4284 		roam_info->mode = SIR_SME_PHY_MODE_HT;
4285 	else if (IS_WLAN_PHYMODE_VHT(pSwitchChnInd->ch_phymode) ||
4286 		 IS_WLAN_PHYMODE_HE(pSwitchChnInd->ch_phymode))
4287 		roam_info->mode = SIR_SME_PHY_MODE_VHT;
4288 #ifdef WLAN_FEATURE_11BE
4289 	else if (IS_WLAN_PHYMODE_EHT(pSwitchChnInd->ch_phymode))
4290 		roam_info->mode = SIR_SME_PHY_MODE_VHT;
4291 #endif
4292 	else
4293 		roam_info->mode = SIR_SME_PHY_MODE_LEGACY;
4294 
4295 	status = csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4296 					eCSR_ROAM_STA_CHANNEL_SWITCH,
4297 					eCSR_ROAM_RESULT_NONE);
4298 	qdf_mem_free(roam_info);
4299 }
4300 
4301 static void
csr_roam_chk_lnk_deauth_rsp(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4302 csr_roam_chk_lnk_deauth_rsp(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4303 {
4304 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4305 	QDF_STATUS status;
4306 	struct csr_roam_info *roam_info;
4307 	struct deauth_rsp *pDeauthRsp = (struct deauth_rsp *) msg_ptr;
4308 	enum QDF_OPMODE opmode;
4309 
4310 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4311 	if (!roam_info)
4312 		return;
4313 	sme_debug("eWNI_SME_DEAUTH_RSP from SME");
4314 	sessionId = pDeauthRsp->sessionId;
4315 	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
4316 		qdf_mem_free(roam_info);
4317 		return;
4318 	}
4319 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId);
4320 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
4321 		qdf_copy_macaddr(&roam_info->peerMac,
4322 				 &pDeauthRsp->peer_macaddr);
4323 		roam_info->reasonCode = eCSR_ROAM_RESULT_FORCED;
4324 		roam_info->status_code = pDeauthRsp->status_code;
4325 		status = csr_roam_call_callback(mac_ctx, sessionId,
4326 						roam_info, eCSR_ROAM_LOSTLINK,
4327 						eCSR_ROAM_RESULT_FORCED);
4328 	}
4329 	qdf_mem_free(roam_info);
4330 }
4331 
4332 static void
csr_roam_chk_lnk_disassoc_rsp(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4333 csr_roam_chk_lnk_disassoc_rsp(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4334 {
4335 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4336 	QDF_STATUS status;
4337 	struct csr_roam_info *roam_info;
4338 	enum QDF_OPMODE opmode;
4339 	/*
4340 	 * session id is invalid here so cant use it to access the array
4341 	 * curSubstate as index
4342 	 */
4343 	struct disassoc_rsp *pDisassocRsp = (struct disassoc_rsp *) msg_ptr;
4344 
4345 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4346 	if (!roam_info)
4347 		return;
4348 	sme_debug("eWNI_SME_DISASSOC_RSP from SME ");
4349 	sessionId = pDisassocRsp->sessionId;
4350 	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
4351 		qdf_mem_free(roam_info);
4352 		return;
4353 	}
4354 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, sessionId);
4355 	if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) {
4356 		qdf_copy_macaddr(&roam_info->peerMac,
4357 				 &pDisassocRsp->peer_macaddr);
4358 		roam_info->reasonCode = eCSR_ROAM_RESULT_FORCED;
4359 		roam_info->status_code = pDisassocRsp->status_code;
4360 		status = csr_roam_call_callback(mac_ctx, sessionId,
4361 						roam_info,
4362 						eCSR_ROAM_LOSTLINK,
4363 						eCSR_ROAM_RESULT_FORCED);
4364 	}
4365 	qdf_mem_free(roam_info);
4366 }
4367 
4368 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
4369 static void
csr_roam_diag_mic_fail(struct mac_context * mac_ctx,uint32_t sessionId)4370 csr_roam_diag_mic_fail(struct mac_context *mac_ctx, uint32_t sessionId)
4371 {
4372 	WLAN_HOST_DIAG_EVENT_DEF(secEvent,
4373 				 host_event_wlan_security_payload_type);
4374 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, sessionId);
4375 
4376 	if (!session) {
4377 		sme_err("session %d not found", sessionId);
4378 		return;
4379 	}
4380 	qdf_mem_zero(&secEvent, sizeof(host_event_wlan_security_payload_type));
4381 	secEvent.eventId = WLAN_SECURITY_EVENT_MIC_ERROR;
4382 	cm_diag_get_auth_enc_type_vdev_id(mac_ctx->psoc,
4383 					  &secEvent.authMode,
4384 					  &secEvent.encryptionModeUnicast,
4385 					  &secEvent.encryptionModeMulticast,
4386 					  sessionId);
4387 	wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, sessionId,
4388 				    (struct qdf_mac_addr *)&secEvent.bssid);
4389 	WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
4390 }
4391 #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
4392 
4393 static void
csr_roam_chk_lnk_mic_fail_ind(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4394 csr_roam_chk_lnk_mic_fail_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4395 {
4396 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4397 	QDF_STATUS status;
4398 	struct csr_roam_info *roam_info;
4399 	struct mic_failure_ind *mic_ind = (struct mic_failure_ind *)msg_ptr;
4400 	eCsrRoamResult result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST;
4401 
4402 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4403 	if (!roam_info)
4404 		return;
4405 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
4406 				&mic_ind->bssId, &sessionId);
4407 	if (QDF_IS_STATUS_SUCCESS(status)) {
4408 		roam_info->u.pMICFailureInfo = &mic_ind->info;
4409 		if (mic_ind->info.multicast)
4410 			result = eCSR_ROAM_RESULT_MIC_ERROR_GROUP;
4411 		else
4412 			result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST;
4413 		csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4414 				       eCSR_ROAM_MIC_ERROR_IND, result);
4415 	}
4416 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
4417 	csr_roam_diag_mic_fail(mac_ctx, sessionId);
4418 #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
4419 	qdf_mem_free(roam_info);
4420 }
4421 
4422 static void
csr_roam_chk_lnk_pbs_probe_req_ind(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4423 csr_roam_chk_lnk_pbs_probe_req_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4424 {
4425 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4426 	QDF_STATUS status;
4427 	struct csr_roam_info *roam_info;
4428 	tpSirSmeProbeReqInd pProbeReqInd = (tpSirSmeProbeReqInd) msg_ptr;
4429 
4430 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4431 	if (!roam_info)
4432 		return;
4433 	sme_debug("WPS PBC Probe request Indication from SME");
4434 
4435 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
4436 			&pProbeReqInd->bssid, &sessionId);
4437 	if (QDF_IS_STATUS_SUCCESS(status)) {
4438 		roam_info->u.pWPSPBCProbeReq = &pProbeReqInd->WPSPBCProbeReq;
4439 		csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4440 				       eCSR_ROAM_WPS_PBC_PROBE_REQ_IND,
4441 				       eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND);
4442 	}
4443 	qdf_mem_free(roam_info);
4444 }
4445 
4446 static void
csr_roam_chk_lnk_max_assoc_exceeded(struct mac_context * mac_ctx,tSirSmeRsp * msg_ptr)4447 csr_roam_chk_lnk_max_assoc_exceeded(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
4448 {
4449 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
4450 	tSmeMaxAssocInd *pSmeMaxAssocInd;
4451 	struct csr_roam_info *roam_info;
4452 
4453 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
4454 	if (!roam_info)
4455 		return;
4456 	pSmeMaxAssocInd = (tSmeMaxAssocInd *) msg_ptr;
4457 	sme_debug(
4458 		"max assoc have been reached, new peer cannot be accepted");
4459 	sessionId = pSmeMaxAssocInd->sessionId;
4460 	qdf_copy_macaddr(&roam_info->peerMac, &pSmeMaxAssocInd->peer_mac);
4461 	csr_roam_call_callback(mac_ctx, sessionId, roam_info,
4462 			       eCSR_ROAM_INFRA_IND,
4463 			       eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED);
4464 	qdf_mem_free(roam_info);
4465 }
4466 
csr_roam_check_for_link_status_change(struct mac_context * mac,tSirSmeRsp * pSirMsg)4467 void csr_roam_check_for_link_status_change(struct mac_context *mac,
4468 						tSirSmeRsp *pSirMsg)
4469 {
4470 	if (!pSirMsg) {
4471 		sme_err("pSirMsg is NULL");
4472 		return;
4473 	}
4474 	switch (pSirMsg->messageType) {
4475 	case eWNI_SME_ASSOC_IND:
4476 		csr_roam_chk_lnk_assoc_ind(mac, pSirMsg);
4477 		break;
4478 	case eWNI_SME_ASSOC_IND_UPPER_LAYER:
4479 		csr_roam_chk_lnk_assoc_ind_upper_layer(mac, pSirMsg);
4480 		break;
4481 	case eWNI_SME_DISASSOC_IND:
4482 		csr_roam_chk_lnk_disassoc_ind(mac, pSirMsg);
4483 		break;
4484 	case eWNI_SME_DISCONNECT_DONE_IND:
4485 		csr_roam_send_disconnect_done_indication(mac, pSirMsg);
4486 		break;
4487 	case eWNI_SME_DEAUTH_IND:
4488 		csr_roam_chk_lnk_deauth_ind(mac, pSirMsg);
4489 		break;
4490 	case eWNI_SME_SWITCH_CHL_IND:
4491 		csr_roam_chk_lnk_swt_ch_ind(mac, pSirMsg);
4492 		break;
4493 	case eWNI_SME_DEAUTH_RSP:
4494 		csr_roam_chk_lnk_deauth_rsp(mac, pSirMsg);
4495 		break;
4496 	case eWNI_SME_DISASSOC_RSP:
4497 		csr_roam_chk_lnk_disassoc_rsp(mac, pSirMsg);
4498 		break;
4499 	case eWNI_SME_MIC_FAILURE_IND:
4500 		csr_roam_chk_lnk_mic_fail_ind(mac, pSirMsg);
4501 		break;
4502 	case eWNI_SME_WPS_PBC_PROBE_REQ_IND:
4503 		csr_roam_chk_lnk_pbs_probe_req_ind(mac, pSirMsg);
4504 		break;
4505 	case eWNI_SME_SETCONTEXT_RSP:
4506 		csr_roam_chk_lnk_set_ctx_rsp(mac, pSirMsg);
4507 		break;
4508 #ifdef FEATURE_WLAN_ESE
4509 	case eWNI_SME_GET_TSM_STATS_RSP:
4510 		sme_debug("TSM Stats rsp from PE");
4511 		csr_tsm_stats_rsp_processor(mac, pSirMsg);
4512 		break;
4513 #endif /* FEATURE_WLAN_ESE */
4514 	case eWNI_SME_GET_SNR_REQ:
4515 		sme_debug("GetSnrReq from self");
4516 		csr_update_snr(mac, pSirMsg);
4517 		break;
4518 	case eWNI_SME_MAX_ASSOC_EXCEEDED:
4519 		csr_roam_chk_lnk_max_assoc_exceeded(mac, pSirMsg);
4520 		break;
4521 	default:
4522 		break;
4523 	} /* end switch on message type */
4524 }
4525 
csr_roam_wm_status_change_complete(struct mac_context * mac,uint8_t session_id)4526 void csr_roam_wm_status_change_complete(struct mac_context *mac,
4527 					uint8_t session_id)
4528 {
4529 	tListElem *pEntry;
4530 	tSmeCmd *pCommand;
4531 
4532 	pEntry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK);
4533 	if (pEntry) {
4534 		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
4535 		if (eSmeCommandWmStatusChange == pCommand->command) {
4536 			/* Nothing to process in a Lost Link completion....  It just kicks off a */
4537 			/* roaming sequence. */
4538 			if (csr_nonscan_active_ll_remove_entry(mac, pEntry,
4539 				    LL_ACCESS_LOCK)) {
4540 				csr_release_command(mac, pCommand);
4541 			} else {
4542 				sme_err("Failed to release command");
4543 			}
4544 		} else {
4545 			sme_warn("CSR: LOST LINK command is not ACTIVE ...");
4546 		}
4547 	} else {
4548 		sme_warn("CSR: NO commands are ACTIVE ...");
4549 	}
4550 }
4551 
csr_roam_process_wm_status_change_command(struct mac_context * mac,tSmeCmd * pCommand)4552 void csr_roam_process_wm_status_change_command(
4553 		struct mac_context *mac, tSmeCmd *pCommand)
4554 {
4555 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac,
4556 						pCommand->vdev_id);
4557 	struct qdf_mac_addr peer_mac;
4558 
4559 	if (!pSession) {
4560 		sme_err("session %d not found", pCommand->vdev_id);
4561 		csr_roam_wm_status_change_complete(mac, pCommand->vdev_id);
4562 	}
4563 	sme_debug("session:%d, CmdType : %d",
4564 		pCommand->vdev_id, pCommand->u.wmStatusChangeCmd.Type);
4565 
4566 	switch (pCommand->u.wmStatusChangeCmd.Type) {
4567 	case eCsrDisassociated:
4568 		qdf_mem_copy(&peer_mac, &pCommand->u.wmStatusChangeCmd.
4569 					u.DisassocIndMsg.peer_macaddr,
4570 			     QDF_MAC_ADDR_SIZE);
4571 		/*
4572 		 * Get peer stats before peer gets deleted so that these stats
4573 		 * can be given to user space when big data stats are queried.
4574 		 * Once peer stats are retrieved disassoc sta will continue
4575 		 */
4576 		csr_get_peer_stats(mac, pCommand->vdev_id, peer_mac);
4577 		break;
4578 	case eCsrDeauthenticated:
4579 		qdf_mem_copy(&peer_mac, &pCommand->u.wmStatusChangeCmd.
4580 					u.DeauthIndMsg.peer_macaddr,
4581 			     QDF_MAC_ADDR_SIZE);
4582 		/*
4583 		 * Get peer stats before peer gets deleted so that these stats
4584 		 * can be given to user space when big data stats are queried.
4585 		 * Once peer stats are retrieved deauth sta will continue
4586 		 */
4587 		csr_get_peer_stats(mac, pCommand->vdev_id, peer_mac);
4588 		break;
4589 	default:
4590 		sme_warn("gets an unknown command %d",
4591 			pCommand->u.wmStatusChangeCmd.Type);
4592 		csr_roam_wm_status_change_complete(mac, pCommand->vdev_id);
4593 		break;
4594 	}
4595 }
4596 
4597 /**
4598  * csr_compute_mode_and_band() - computes dot11mode
4599  * @mac: mac global context
4600  * @dot11_mode: out param, do11 mode calculated
4601  * @band: out param, band caclculated
4602  * @opr_ch_freq: operating channel freq in MHz
4603  *
4604  * This function finds dot11 mode based on current mode, operating channel and
4605  * fw supported modes.
4606  *
4607  * Return: void
4608  */
4609 static void
csr_compute_mode_and_band(struct mac_context * mac_ctx,enum csr_cfgdot11mode * dot11_mode,enum reg_wifi_band * band,uint32_t opr_ch_freq)4610 csr_compute_mode_and_band(struct mac_context *mac_ctx,
4611 			  enum csr_cfgdot11mode *dot11_mode,
4612 			  enum reg_wifi_band *band,
4613 			  uint32_t opr_ch_freq)
4614 {
4615 	bool vht_24_ghz = mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band;
4616 
4617 	switch (mac_ctx->roam.configParam.uCfgDot11Mode) {
4618 	case eCSR_CFG_DOT11_MODE_11A:
4619 		*dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4620 		*band = REG_BAND_5G;
4621 		break;
4622 	case eCSR_CFG_DOT11_MODE_11B:
4623 		*dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4624 		*band = REG_BAND_2G;
4625 		break;
4626 	case eCSR_CFG_DOT11_MODE_11G:
4627 		*dot11_mode = eCSR_CFG_DOT11_MODE_11G;
4628 		*band = REG_BAND_2G;
4629 		break;
4630 	case eCSR_CFG_DOT11_MODE_11N:
4631 		*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4632 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4633 		break;
4634 	case eCSR_CFG_DOT11_MODE_11AC:
4635 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4636 			/*
4637 			 * If the operating channel is in 2.4 GHz band, check
4638 			 * for INI item to disable VHT operation in 2.4 GHz band
4639 			 */
4640 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4641 			    !vht_24_ghz)
4642 				/* Disable 11AC operation */
4643 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4644 			else
4645 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4646 		} else {
4647 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4648 		}
4649 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4650 		break;
4651 	case eCSR_CFG_DOT11_MODE_11AC_ONLY:
4652 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4653 			/*
4654 			 * If the operating channel is in 2.4 GHz band, check
4655 			 * for INI item to disable VHT operation in 2.4 GHz band
4656 			 */
4657 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4658 			    !vht_24_ghz)
4659 				/* Disable 11AC operation */
4660 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4661 			else
4662 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC_ONLY;
4663 		} else {
4664 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4665 		}
4666 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4667 		break;
4668 	case eCSR_CFG_DOT11_MODE_11AX:
4669 	case eCSR_CFG_DOT11_MODE_11AX_ONLY:
4670 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX)) {
4671 			*dot11_mode = mac_ctx->roam.configParam.uCfgDot11Mode;
4672 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4673 			/*
4674 			 * If the operating channel is in 2.4 GHz band, check
4675 			 * for INI item to disable VHT operation in 2.4 GHz band
4676 			 */
4677 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4678 			    !vht_24_ghz)
4679 				/* Disable 11AC operation */
4680 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4681 			else
4682 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4683 		} else {
4684 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4685 		}
4686 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4687 		break;
4688 #ifdef WLAN_FEATURE_11BE
4689 	case eCSR_CFG_DOT11_MODE_11BE:
4690 	case eCSR_CFG_DOT11_MODE_11BE_ONLY:
4691 		if (IS_FEATURE_11BE_SUPPORTED_BY_FW) {
4692 			*dot11_mode = mac_ctx->roam.configParam.uCfgDot11Mode;
4693 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX)) {
4694 			*dot11_mode = eCSR_CFG_DOT11_MODE_11AX;
4695 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4696 			/*
4697 			 * If the operating channel is in 2.4 GHz band, check
4698 			 * for INI item to disable VHT operation in 2.4 GHz band
4699 			 */
4700 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4701 			    !vht_24_ghz)
4702 				/* Disable 11AC operation */
4703 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4704 			else
4705 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4706 		} else {
4707 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4708 		}
4709 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4710 		break;
4711 #endif
4712 	case eCSR_CFG_DOT11_MODE_AUTO:
4713 #ifdef WLAN_FEATURE_11BE
4714 		if (IS_FEATURE_11BE_SUPPORTED_BY_FW) {
4715 			*dot11_mode = eCSR_CFG_DOT11_MODE_11BE;
4716 		} else
4717 #endif
4718 		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX)) {
4719 			*dot11_mode = eCSR_CFG_DOT11_MODE_11AX;
4720 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
4721 			/*
4722 			 * If the operating channel is in 2.4 GHz band,
4723 			 * check for INI item to disable VHT operation
4724 			 * in 2.4 GHz band
4725 			 */
4726 			if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq) &&
4727 			    !vht_24_ghz)
4728 				/* Disable 11AC operation */
4729 				*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4730 			else
4731 				*dot11_mode = eCSR_CFG_DOT11_MODE_11AC;
4732 		} else {
4733 			*dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4734 		}
4735 		*band = wlan_reg_freq_to_band(opr_ch_freq);
4736 		break;
4737 	default:
4738 		/*
4739 		 * Global dot11 Mode setting is 11a/b/g. use the channel number
4740 		 * to determine the Mode setting.
4741 		 */
4742 		if (eCSR_OPERATING_CHANNEL_AUTO == opr_ch_freq) {
4743 			*band = (mac_ctx->mlme_cfg->gen.band == BAND_2G ?
4744 				REG_BAND_2G : REG_BAND_5G);
4745 			if (REG_BAND_2G == *band) {
4746 				*dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4747 			} else {
4748 				/* prefer 5GHz */
4749 				*band = REG_BAND_5G;
4750 				*dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4751 			}
4752 		} else if (WLAN_REG_IS_24GHZ_CH_FREQ(opr_ch_freq)) {
4753 			*dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4754 			*band = REG_BAND_2G;
4755 		} else {
4756 			/* else, it's a 5.0GHz channel.  Set mode to 11a. */
4757 			*dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4758 			*band = REG_BAND_5G;
4759 		}
4760 		break;
4761 	} /* switch */
4762 }
4763 
4764 /**
4765  * csr_roam_get_phy_mode_band_for_bss() - This function returns band and mode
4766  * information.
4767  * @mac_ctx:  mac global context
4768  * dot11_cfg: pointer to dot11 config
4769  *
4770  * This function finds dot11 mode based on current mode, operating channel and
4771  * fw supported modes. The only tricky part is that if phyMode is set to 11abg,
4772  * this function may return eCSR_CFG_DOT11_MODE_11B instead of
4773  * eCSR_CFG_DOT11_MODE_11G if everything is set to auto-pick.
4774  *
4775  * Return: dot11mode
4776  */
4777 enum csr_cfgdot11mode
csr_roam_get_phy_mode_band_for_bss(struct mac_context * mac_ctx,struct bss_dot11_config * dot11_cfg)4778 csr_roam_get_phy_mode_band_for_bss(struct mac_context *mac_ctx,
4779 				   struct bss_dot11_config *dot11_cfg)
4780 {
4781 	enum reg_wifi_band band = REG_BAND_2G;
4782 	qdf_freq_t opr_freq = 0;
4783 	bool is_11n_allowed;
4784 	enum csr_cfgdot11mode curr_mode =
4785 		mac_ctx->roam.configParam.uCfgDot11Mode;
4786 	enum csr_cfgdot11mode cfg_dot11_mode;
4787 	enum QDF_OPMODE opmode;
4788 	bool is_ap = false;
4789 	uint8_t privacy;
4790 	uint8_t vdev_id = dot11_cfg->vdev_id;
4791 
4792 	if (dot11_cfg->bss_op_ch_freq)
4793 		opr_freq = dot11_cfg->bss_op_ch_freq;
4794 
4795 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
4796 	is_ap = (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE);
4797 	cfg_dot11_mode =
4798 		csr_get_cfg_dot11_mode_from_csr_phy_mode(is_ap,
4799 							 dot11_cfg->phy_mode);
4800 	privacy = dot11_cfg->privacy;
4801 
4802 	/*
4803 	 * If the global setting for dot11Mode is set to auto/abg, we overwrite
4804 	 * the setting in the profile.
4805 	 */
4806 	if ((!is_ap && ((eCSR_CFG_DOT11_MODE_AUTO == curr_mode) ||
4807 	     (eCSR_CFG_DOT11_MODE_ABG == curr_mode))) ||
4808 	     (eCSR_CFG_DOT11_MODE_AUTO == cfg_dot11_mode) ||
4809 	     (eCSR_CFG_DOT11_MODE_ABG == cfg_dot11_mode)) {
4810 		csr_compute_mode_and_band(mac_ctx, &cfg_dot11_mode,
4811 					  &band, opr_freq);
4812 	} /* if( eCSR_CFG_DOT11_MODE_ABG == cfg_dot11_mode ) */
4813 	else {
4814 		/* dot11 mode is set, lets pick the band */
4815 		if (0 == opr_freq) {
4816 			/* channel is Auto also. */
4817 			if (mac_ctx->mlme_cfg->gen.band == BAND_ALL) {
4818 				/* prefer 5GHz */
4819 				band = REG_BAND_5G;
4820 			}
4821 		} else{
4822 			band = wlan_reg_freq_to_band(opr_freq);
4823 		}
4824 	}
4825 
4826 	dot11_cfg->p_band = band;
4827 	if (opr_freq == 2484 && wlan_reg_is_24ghz_ch_freq(opr_freq)) {
4828 		sme_err("Switching to Dot11B mode");
4829 		cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11B;
4830 	}
4831 
4832 	if (wlan_reg_is_24ghz_ch_freq(opr_freq) &&
4833 	    !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band &&
4834 	    (eCSR_CFG_DOT11_MODE_11AC == cfg_dot11_mode ||
4835 	    eCSR_CFG_DOT11_MODE_11AC_ONLY == cfg_dot11_mode))
4836 		cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11N;
4837 	/*
4838 	 * Incase of WEP Security encryption type is coming as part of add key.
4839 	 * So while STart BSS dont have information
4840 	 */
4841 	is_11n_allowed = wlan_vdev_id_is_11n_allowed(mac_ctx->pdev, vdev_id);
4842 	if ((!is_11n_allowed || (privacy &&
4843 	    wlan_vdev_id_is_open_cipher(mac_ctx->pdev, vdev_id))) &&
4844 	    ((eCSR_CFG_DOT11_MODE_11N == cfg_dot11_mode) ||
4845 	    (eCSR_CFG_DOT11_MODE_11AC == cfg_dot11_mode) ||
4846 	    (eCSR_CFG_DOT11_MODE_11AX == cfg_dot11_mode) ||
4847 	    CSR_IS_CFG_DOT11_PHY_MODE_11BE(cfg_dot11_mode))) {
4848 		/* We cannot do 11n here */
4849 		if (wlan_reg_is_24ghz_ch_freq(opr_freq))
4850 			cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11G;
4851 		else
4852 			cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11A;
4853 	}
4854 	sme_debug("dot11mode: %d phyMode %d is_11n_allowed %d privacy %d chan freq %d fw sup AX %d",
4855 		  cfg_dot11_mode, dot11_cfg->phy_mode, is_11n_allowed,
4856 		  privacy, opr_freq,
4857 		  IS_FEATURE_SUPPORTED_BY_FW(DOT11AX));
4858 
4859 #ifdef WLAN_FEATURE_11BE
4860 	sme_debug("BE :%d", IS_FEATURE_SUPPORTED_BY_FW(DOT11BE));
4861 #endif
4862 	return cfg_dot11_mode;
4863 }
4864 
csr_get_cfg_valid_channels(struct mac_context * mac,qdf_freq_t * ch_freq_list,uint32_t * num_ch_freq)4865 QDF_STATUS csr_get_cfg_valid_channels(struct mac_context *mac,
4866 				      qdf_freq_t *ch_freq_list,
4867 				      uint32_t *num_ch_freq)
4868 {
4869 	uint8_t num_chan_temp = 0;
4870 	int i;
4871 	uint32_t *valid_ch_freq_list =
4872 				mac->mlme_cfg->reg.valid_channel_freq_list;
4873 
4874 	*num_ch_freq = mac->mlme_cfg->reg.valid_channel_list_num;
4875 
4876 	for (i = 0; i < *num_ch_freq; i++) {
4877 		if (!wlan_reg_is_dsrc_freq(valid_ch_freq_list[i])) {
4878 			ch_freq_list[num_chan_temp] = valid_ch_freq_list[i];
4879 			num_chan_temp++;
4880 		}
4881 	}
4882 
4883 	*num_ch_freq = num_chan_temp;
4884 	return QDF_STATUS_SUCCESS;
4885 }
4886 
4887 /**
4888  * csr_convert_mode_to_nw_type() - convert mode into network type
4889  * @dot11_mode:    dot11_mode
4890  * @band:          2.4 or 5 GHz
4891  *
4892  * Return: tSirNwType
4893  */
4894 tSirNwType
csr_convert_mode_to_nw_type(enum csr_cfgdot11mode dot11_mode,enum reg_wifi_band band)4895 csr_convert_mode_to_nw_type(enum csr_cfgdot11mode dot11_mode,
4896 			    enum reg_wifi_band band)
4897 {
4898 	switch (dot11_mode) {
4899 	case eCSR_CFG_DOT11_MODE_11G:
4900 		return eSIR_11G_NW_TYPE;
4901 	case eCSR_CFG_DOT11_MODE_11B:
4902 		return eSIR_11B_NW_TYPE;
4903 	case eCSR_CFG_DOT11_MODE_11A:
4904 		return eSIR_11A_NW_TYPE;
4905 	case eCSR_CFG_DOT11_MODE_11N:
4906 	default:
4907 		/*
4908 		 * Because LIM only verifies it against 11a, 11b or 11g, set
4909 		 * only 11g or 11a here
4910 		 */
4911 		if (REG_BAND_2G == band)
4912 			return eSIR_11G_NW_TYPE;
4913 		else
4914 			return eSIR_11A_NW_TYPE;
4915 	}
4916 	return eSIR_DONOT_USE_NW_TYPE;
4917 }
4918 
4919 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
4920 #ifdef WLAN_FEATURE_11BE_MLO
csr_pmk_match_mlo_address(struct wlan_objmgr_vdev * vdev,struct wlan_crypto_pmksa * pmksa)4921 static bool csr_pmk_match_mlo_address(struct wlan_objmgr_vdev *vdev,
4922 				      struct wlan_crypto_pmksa *pmksa)
4923 {
4924 	struct qdf_mac_addr bss_peer_mld_mac = {0};
4925 
4926 	wlan_vdev_get_bss_peer_mld_mac(vdev, &bss_peer_mld_mac);
4927 
4928 	return qdf_is_macaddr_equal(&bss_peer_mld_mac, &pmksa->bssid);
4929 }
4930 #else
csr_pmk_match_mlo_address(struct wlan_objmgr_vdev * vdev,struct wlan_crypto_pmksa * pmksa)4931 static inline bool csr_pmk_match_mlo_address(struct wlan_objmgr_vdev *vdev,
4932 					     struct wlan_crypto_pmksa *pmksa)
4933 {
4934 	return false;
4935 }
4936 #endif
4937 
csr_get_pmk_info(struct mac_context * mac_ctx,uint8_t session_id,struct wlan_crypto_pmksa * pmk_cache)4938 void csr_get_pmk_info(struct mac_context *mac_ctx, uint8_t session_id,
4939 		      struct wlan_crypto_pmksa *pmk_cache)
4940 {
4941 	if (!mac_ctx) {
4942 		sme_err("Mac_ctx is NULL");
4943 		return;
4944 	}
4945 	wlan_cm_get_psk_pmk(mac_ctx->pdev, session_id, pmk_cache->pmk,
4946 			    &pmk_cache->pmk_len);
4947 }
4948 
csr_roam_set_psk_pmk(struct mac_context * mac,struct wlan_crypto_pmksa * pmksa,uint8_t vdev_id,bool update_to_fw)4949 QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac,
4950 				struct wlan_crypto_pmksa *pmksa,
4951 				uint8_t vdev_id, bool update_to_fw)
4952 {
4953 	struct wlan_objmgr_vdev *vdev;
4954 	struct qdf_mac_addr connected_bssid = {0};
4955 	QDF_STATUS status;
4956 
4957 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
4958 						    WLAN_LEGACY_SME_ID);
4959 	if (!vdev) {
4960 		sme_err("vdev is NULL");
4961 		return QDF_STATUS_E_FAILURE;
4962 	}
4963 
4964 	wlan_mlme_get_bssid_vdev_id(mac->pdev, vdev_id, &connected_bssid);
4965 
4966 	/*
4967 	 * If the set_pmksa is received from the userspace in
4968 	 * connected state and if the connected BSSID is not
4969 	 * same as the PMKSA entry bssid, then reject this
4970 	 * global cache updation.
4971 	 *
4972 	 * Also for FILS connection, the set_pmksa will not have
4973 	 * the BSSID. So avoid this check for FILS connection.
4974 	 */
4975 	if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_UP &&
4976 	    !pmksa->ssid_len &&
4977 	    !qdf_is_macaddr_equal(&connected_bssid, &pmksa->bssid) &&
4978 	    !csr_pmk_match_mlo_address(vdev, pmksa)) {
4979 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
4980 		sme_debug("Set pmksa received for non-connected bss");
4981 		return QDF_STATUS_E_INVAL;
4982 	}
4983 
4984 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
4985 
4986 	wlan_cm_set_psk_pmk(mac->pdev, vdev_id, pmksa->pmk, pmksa->pmk_len);
4987 	if (update_to_fw) {
4988 		status = wlan_roam_update_cfg(mac->psoc, vdev_id,
4989 					      REASON_ROAM_PSK_PMK_CHANGED);
4990 		if (status == QDF_STATUS_E_INVAL)
4991 			wlan_mlme_defer_pmk_set_in_roaming(mac->psoc, vdev_id,
4992 							   true);
4993 	}
4994 
4995 	return QDF_STATUS_SUCCESS;
4996 }
4997 
csr_set_pmk_cache_ft(struct mac_context * mac,uint8_t vdev_id,struct wlan_crypto_pmksa * pmk_cache)4998 QDF_STATUS csr_set_pmk_cache_ft(struct mac_context *mac, uint8_t vdev_id,
4999 				struct wlan_crypto_pmksa *pmk_cache)
5000 {
5001 	struct wlan_objmgr_vdev *vdev;
5002 	int32_t akm;
5003 
5004 	if (!CSR_IS_SESSION_VALID(mac, vdev_id)) {
5005 		sme_err("session %d not found", vdev_id);
5006 		return QDF_STATUS_E_INVAL;
5007 	}
5008 
5009 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
5010 						    WLAN_LEGACY_SME_ID);
5011 	if (!vdev) {
5012 		sme_err("vdev is NULL");
5013 		return QDF_STATUS_E_FAILURE;
5014 	}
5015 
5016 	akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
5017 
5018 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
5019 
5020 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) {
5021 		sme_debug("PMK update is not required for ESE");
5022 		return QDF_STATUS_SUCCESS;
5023 	}
5024 
5025 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) ||
5026 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256) ||
5027 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384) ||
5028 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) {
5029 		sme_debug("Auth type: %x update the MDID in cache", akm);
5030 		cm_update_pmk_cache_ft(mac->psoc, vdev_id, pmk_cache);
5031 	} else {
5032 		struct cm_roam_values_copy src_cfg = {};
5033 		struct scan_filter *scan_filter;
5034 		qdf_list_t *list = NULL;
5035 		struct scan_cache_node *first_node = NULL;
5036 		struct rsn_mdie *mdie = NULL;
5037 		qdf_list_node_t *cur_node = NULL;
5038 
5039 		scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
5040 		if (!scan_filter)
5041 			return QDF_STATUS_E_NOMEM;
5042 		scan_filter->num_of_bssid = 1;
5043 		qdf_mem_copy(scan_filter->bssid_list[0].bytes,
5044 			     &pmk_cache->bssid, sizeof(struct qdf_mac_addr));
5045 		list = wlan_scan_get_result(mac->pdev, scan_filter);
5046 		qdf_mem_free(scan_filter);
5047 		if (!list || (list && !qdf_list_size(list))) {
5048 			sme_debug("Scan list is empty");
5049 			goto err;
5050 		}
5051 		qdf_list_peek_front(list, &cur_node);
5052 		first_node = qdf_container_of(cur_node,
5053 					      struct scan_cache_node,
5054 					      node);
5055 		if (first_node && first_node->entry)
5056 			mdie = (struct rsn_mdie *)
5057 					util_scan_entry_mdie(first_node->entry);
5058 		if (mdie) {
5059 			sme_debug("Update MDID in cache from scan_res");
5060 			src_cfg.bool_value = true;
5061 			src_cfg.uint_value =
5062 				(mdie->mobility_domain[0] |
5063 				 (mdie->mobility_domain[1] << 8));
5064 			wlan_cm_roam_cfg_set_value(mac->psoc, vdev_id,
5065 						   MOBILITY_DOMAIN, &src_cfg);
5066 			cm_update_pmk_cache_ft(mac->psoc, vdev_id, pmk_cache);
5067 		}
5068 err:
5069 		if (list)
5070 			wlan_scan_purge_results(list);
5071 	}
5072 	return QDF_STATUS_SUCCESS;
5073 }
5074 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
5075 
5076 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
csr_clear_sae_single_pmk(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct wlan_crypto_pmksa * pmk_cache)5077 void csr_clear_sae_single_pmk(struct wlan_objmgr_psoc *psoc,
5078 			      uint8_t vdev_id,
5079 			      struct wlan_crypto_pmksa *pmk_cache)
5080 {
5081 	struct wlan_objmgr_vdev *vdev;
5082 	int32_t keymgmt;
5083 	struct mlme_pmk_info pmk_info;
5084 
5085 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
5086 						    WLAN_LEGACY_SME_ID);
5087 	if (!vdev) {
5088 		sme_err("vdev is NULL");
5089 		return;
5090 	}
5091 
5092 	keymgmt = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
5093 	if (keymgmt < 0) {
5094 		sme_err("Invalid mgmt cipher");
5095 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
5096 		return;
5097 	}
5098 
5099 	if (!(QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE) ||
5100 	      QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))) {
5101 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
5102 		return;
5103 	}
5104 	if (pmk_cache) {
5105 		qdf_mem_copy(&pmk_info.pmk, pmk_cache->pmk, pmk_cache->pmk_len);
5106 		pmk_info.pmk_len = pmk_cache->pmk_len;
5107 		wlan_mlme_clear_sae_single_pmk_info(vdev, &pmk_info);
5108 	} else {
5109 		wlan_mlme_clear_sae_single_pmk_info(vdev, NULL);
5110 	}
5111 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
5112 }
5113 #endif
5114 
5115 #ifdef FEATURE_WLAN_ESE
csr_update_prev_ap_info(struct csr_roam_session * session,struct wlan_objmgr_vdev * vdev)5116 void csr_update_prev_ap_info(struct csr_roam_session *session,
5117 			     struct wlan_objmgr_vdev *vdev)
5118 {
5119 	struct wlan_ssid ssid;
5120 	QDF_STATUS status;
5121 	enum QDF_OPMODE opmode;
5122 	struct rso_config *rso_cfg;
5123 
5124 	opmode = wlan_vdev_mlme_get_opmode(vdev);
5125 	rso_cfg = wlan_cm_get_rso_config(vdev);
5126 	if (!rso_cfg)
5127 		return;
5128 
5129 	if (!rso_cfg->is_ese_assoc || opmode != QDF_STA_MODE)
5130 		return;
5131 	status = wlan_vdev_mlme_get_ssid(vdev, ssid.ssid, &ssid.length);
5132 	if (QDF_IS_STATUS_ERROR(status)) {
5133 		sme_err(" failed to find SSID for vdev %d", session->vdev_id);
5134 		return;
5135 	}
5136 	session->isPrevApInfoValid = true;
5137 	session->roamTS1 = qdf_mc_timer_get_system_time();
5138 }
5139 #endif
5140 
5141 #ifdef WLAN_FEATURE_FILS_SK
csr_cm_update_fils_info(struct wlan_objmgr_vdev * vdev,struct bss_description * bss_desc,struct wlan_cm_vdev_connect_req * req)5142 static QDF_STATUS csr_cm_update_fils_info(struct wlan_objmgr_vdev *vdev,
5143 					  struct bss_description *bss_desc,
5144 					  struct wlan_cm_vdev_connect_req *req)
5145 {
5146 	uint8_t cache_id[CACHE_ID_LEN] = {0};
5147 	struct scan_cache_entry *entry;
5148 	struct wlan_crypto_pmksa *fils_ssid_pmksa, *bssid_lookup_pmksa;
5149 
5150 	if (!req->fils_info || !req->fils_info->is_fils_connection) {
5151 		wlan_cm_update_mlme_fils_info(vdev, NULL);
5152 		return QDF_STATUS_SUCCESS;
5153 	}
5154 
5155 	if (bss_desc->fils_info_element.is_cache_id_present) {
5156 		qdf_mem_copy(cache_id, bss_desc->fils_info_element.cache_id,
5157 			     CACHE_ID_LEN);
5158 		sme_debug("FILS_PMKSA: cache_id[0]:%d, cache_id[1]:%d",
5159 			  cache_id[0], cache_id[1]);
5160 	}
5161 	entry = req->bss->entry;
5162 	bssid_lookup_pmksa = wlan_crypto_get_pmksa(vdev, &entry->bssid);
5163 	fils_ssid_pmksa =
5164 			wlan_crypto_get_fils_pmksa(vdev, cache_id,
5165 						   entry->ssid.ssid,
5166 						   entry->ssid.length);
5167 
5168 	if ((!req->fils_info->rrk_len ||
5169 	     !req->fils_info->username_len) &&
5170 	     !bss_desc->fils_info_element.is_cache_id_present &&
5171 	     !bssid_lookup_pmksa && !fils_ssid_pmksa)
5172 		return QDF_STATUS_E_FAILURE;
5173 
5174 	return wlan_cm_update_mlme_fils_info(vdev, req->fils_info);
5175 }
5176 #else
5177 static inline
csr_cm_update_fils_info(struct wlan_objmgr_vdev * vdev,struct bss_description * bss_desc,struct wlan_cm_vdev_connect_req * req)5178 QDF_STATUS csr_cm_update_fils_info(struct wlan_objmgr_vdev *vdev,
5179 				   struct bss_description *bss_desc,
5180 				   struct wlan_cm_vdev_connect_req *req)
5181 {
5182 }
5183 #endif
5184 
5185 #if defined(WLAN_FEATURE_HOST_ROAM) && defined(FEATURE_WLAN_ESE)
csr_update_tspec_info(struct mac_context * mac_ctx,struct wlan_objmgr_vdev * vdev,tDot11fBeaconIEs * ie_struct)5186 static void csr_update_tspec_info(struct mac_context *mac_ctx,
5187 				  struct wlan_objmgr_vdev *vdev,
5188 				  tDot11fBeaconIEs *ie_struct)
5189 {
5190 	struct mlme_legacy_priv *mlme_priv;
5191 	tESETspecInfo *ese_tspec;
5192 
5193 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
5194 	if (!mlme_priv)
5195 		return;
5196 	if (!cm_is_ese_connection(vdev, ie_struct->ESEVersion.present))
5197 		return;
5198 
5199 	ese_tspec = &mlme_priv->connect_info.ese_tspec_info;
5200 	qdf_mem_zero(ese_tspec, sizeof(tESETspecInfo));
5201 	ese_tspec->numTspecs = sme_qos_ese_retrieve_tspec_info(mac_ctx,
5202 					wlan_vdev_get_id(vdev),
5203 					ese_tspec->tspec);
5204 }
5205 #else
csr_update_tspec_info(struct mac_context * mac_ctx,struct wlan_objmgr_vdev * vdev,tDot11fBeaconIEs * ie_struct)5206 static inline void csr_update_tspec_info(struct mac_context *mac_ctx,
5207 					 struct wlan_objmgr_vdev *vdev,
5208 					 tDot11fBeaconIEs *ie_struct) {}
5209 #endif
5210 
cm_csr_send_set_ie(struct wlan_objmgr_vdev * vdev)5211 void cm_csr_send_set_ie(struct wlan_objmgr_vdev *vdev)
5212 {
5213 	struct vdev_mlme_obj *vdev_mlme;
5214 
5215 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
5216 	if (!vdev_mlme) {
5217 		sme_err("Failed to get vdev mlme obj!");
5218 		QDF_BUG(0);
5219 		return;
5220 	}
5221 
5222 	csr_send_set_ie(vdev_mlme->mgmt.generic.type,
5223 			vdev_mlme->mgmt.generic.subtype,
5224 			wlan_vdev_get_id(vdev));
5225 }
5226 
cm_csr_handle_join_req(struct wlan_objmgr_vdev * vdev,struct wlan_cm_vdev_connect_req * req,struct cm_vdev_join_req * join_req,bool reassoc)5227 QDF_STATUS cm_csr_handle_join_req(struct wlan_objmgr_vdev *vdev,
5228 				  struct wlan_cm_vdev_connect_req *req,
5229 				  struct cm_vdev_join_req *join_req,
5230 				  bool reassoc)
5231 {
5232 	struct mac_context *mac_ctx;
5233 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5234 	QDF_STATUS status;
5235 	tDot11fBeaconIEs *ie_struct;
5236 	struct bss_description *bss_desc;
5237 	uint32_t ie_len, bss_len;
5238 
5239 	/*
5240 	 * This API is to update legacy struct and should be removed once
5241 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5242 	 * vdev/pdev/psoc instead
5243 	 */
5244 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5245 	if (!mac_ctx)
5246 		return QDF_STATUS_E_INVAL;
5247 
5248 	ie_len = util_scan_entry_ie_len(join_req->entry);
5249 	bss_len = (uint16_t)(offsetof(struct bss_description,
5250 			   ieFields[0]) + ie_len);
5251 
5252 	bss_desc = qdf_mem_malloc(sizeof(*bss_desc) + bss_len);
5253 	if (!bss_desc)
5254 		return QDF_STATUS_E_NOMEM;
5255 
5256 	status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc,
5257 						    join_req->entry);
5258 	if (QDF_IS_STATUS_ERROR(status)) {
5259 		qdf_mem_free(bss_desc);
5260 		return QDF_STATUS_E_FAILURE;
5261 	}
5262 
5263 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5264 						     &ie_struct);
5265 	if (QDF_IS_STATUS_ERROR(status)) {
5266 		sme_err("IE parsing failed vdev id %d", vdev_id);
5267 		qdf_mem_free(bss_desc);
5268 		return QDF_STATUS_E_FAILURE;
5269 	}
5270 
5271 	if (reassoc) {
5272 		csr_update_tspec_info(mac_ctx, vdev, ie_struct);
5273 	} else {
5274 		status = csr_cm_update_fils_info(vdev, bss_desc, req);
5275 		if (QDF_IS_STATUS_ERROR(status)) {
5276 			sme_err("failed to update fils info vdev id %d",
5277 				vdev_id);
5278 			qdf_mem_free(ie_struct);
5279 			qdf_mem_free(bss_desc);
5280 			return QDF_STATUS_E_FAILURE;
5281 		}
5282 		sme_qos_csr_event_ind(mac_ctx, vdev_id,
5283 				      SME_QOS_CSR_JOIN_REQ, NULL);
5284 	}
5285 
5286 	if ((wlan_reg_11d_enabled_on_host(mac_ctx->psoc)) &&
5287 	     !ie_struct->Country.present)
5288 		csr_apply_channel_power_info_wrapper(mac_ctx);
5289 
5290 	qdf_mem_free(ie_struct);
5291 	qdf_mem_free(bss_desc);
5292 
5293 	cm_csr_set_joining(vdev_id);
5294 
5295 	return QDF_STATUS_SUCCESS;
5296 }
5297 
5298 #ifdef FEATURE_WLAN_ESE
csr_get_tspec_ie_len(struct cm_vdev_join_rsp * rsp)5299 static uint32_t csr_get_tspec_ie_len(struct cm_vdev_join_rsp *rsp)
5300 {
5301 	return rsp->tspec_ie.len;
5302 }
csr_copy_tspec_ie_len(struct csr_roam_session * session,uint8_t * frame_ptr,struct cm_vdev_join_rsp * rsp)5303 static inline void csr_copy_tspec_ie_len(struct csr_roam_session *session,
5304 					 uint8_t *frame_ptr,
5305 					 struct cm_vdev_join_rsp *rsp)
5306 {
5307 	session->connectedInfo.nTspecIeLength = rsp->tspec_ie.len;
5308 	if (rsp->tspec_ie.len)
5309 		qdf_mem_copy(frame_ptr, rsp->tspec_ie.ptr,
5310 			     rsp->tspec_ie.len);
5311 }
5312 
5313 #else
csr_get_tspec_ie_len(struct cm_vdev_join_rsp * rsp)5314 static inline uint32_t csr_get_tspec_ie_len(struct cm_vdev_join_rsp *rsp)
5315 {
5316 	return 0;
5317 }
csr_copy_tspec_ie_len(struct csr_roam_session * session,uint8_t * frame_ptr,struct cm_vdev_join_rsp * rsp)5318 static inline void csr_copy_tspec_ie_len(struct csr_roam_session *session,
5319 					 uint8_t *frame_ptr,
5320 					 struct cm_vdev_join_rsp *rsp)
5321 {}
5322 #endif
5323 
csr_fill_connected_info(struct mac_context * mac_ctx,struct csr_roam_session * session,struct cm_vdev_join_rsp * rsp)5324 static void csr_fill_connected_info(struct mac_context *mac_ctx,
5325 				    struct csr_roam_session *session,
5326 				    struct cm_vdev_join_rsp *rsp)
5327 {
5328 	uint32_t len;
5329 	struct wlan_connect_rsp_ies *connect_ies;
5330 	uint8_t *frame_ptr;
5331 	uint32_t beacon_data_len = 0;
5332 
5333 	connect_ies = &rsp->connect_rsp.connect_ies;
5334 	csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
5335 	if (connect_ies->bcn_probe_rsp.len > sizeof(struct wlan_frame_hdr))
5336 		beacon_data_len = connect_ies->bcn_probe_rsp.len -
5337 						sizeof(struct wlan_frame_hdr);
5338 	len = beacon_data_len + connect_ies->assoc_req.len +
5339 		connect_ies->assoc_rsp.len + rsp->ric_resp_ie.len +
5340 		csr_get_tspec_ie_len(rsp);
5341 	if (!len)
5342 		return;
5343 
5344 	session->connectedInfo.pbFrames = qdf_mem_malloc(len);
5345 	if (!session->connectedInfo.pbFrames)
5346 		return;
5347 
5348 	frame_ptr = session->connectedInfo.pbFrames;
5349 	session->connectedInfo.nBeaconLength = beacon_data_len;
5350 	if (beacon_data_len)
5351 		qdf_mem_copy(frame_ptr,
5352 			     connect_ies->bcn_probe_rsp.ptr +
5353 			     sizeof(struct wlan_frame_hdr),
5354 			     beacon_data_len);
5355 	frame_ptr += beacon_data_len;
5356 
5357 	session->connectedInfo.nAssocReqLength = connect_ies->assoc_req.len;
5358 	if (connect_ies->assoc_req.len)
5359 		qdf_mem_copy(frame_ptr,
5360 			     connect_ies->assoc_req.ptr,
5361 			     connect_ies->assoc_req.len);
5362 	frame_ptr += connect_ies->assoc_req.len;
5363 
5364 	session->connectedInfo.nAssocRspLength = connect_ies->assoc_rsp.len;
5365 	if (connect_ies->assoc_rsp.len)
5366 		qdf_mem_copy(frame_ptr,
5367 			     connect_ies->assoc_rsp.ptr,
5368 			     connect_ies->assoc_rsp.len);
5369 	frame_ptr += connect_ies->assoc_rsp.len;
5370 
5371 	session->connectedInfo.nRICRspLength = rsp->ric_resp_ie.len;
5372 	if (rsp->ric_resp_ie.len)
5373 		qdf_mem_copy(frame_ptr, rsp->ric_resp_ie.ptr,
5374 			     rsp->ric_resp_ie.len);
5375 	frame_ptr += rsp->ric_resp_ie.len;
5376 
5377 	csr_copy_tspec_ie_len(session, frame_ptr, rsp);
5378 }
5379 
5380 #ifndef WLAN_MDM_CODE_REDUCTION_OPT
csr_qos_send_disconnect_ind(struct mac_context * mac_ctx,uint8_t vdev_id)5381 static inline void csr_qos_send_disconnect_ind(struct mac_context *mac_ctx,
5382 					       uint8_t vdev_id)
5383 {
5384 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_DISCONNECT_IND,
5385 			      NULL);
5386 }
5387 
csr_qos_send_assoc_ind(struct mac_context * mac_ctx,uint8_t vdev_id,sme_QosAssocInfo * assoc_info)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 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_ASSOC_COMPLETE,
5393 			      assoc_info);
5394 }
5395 
5396 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
5397 static void
csr_qso_disconnect_complete_ind(struct mac_context * mac_ctx,struct wlan_cm_connect_resp * connect_rsp)5398 csr_qso_disconnect_complete_ind(struct mac_context *mac_ctx,
5399 				struct wlan_cm_connect_resp *connect_rsp)
5400 {
5401 	if (IS_ROAM_REASON_DISCONNECTION(
5402 		connect_rsp->roaming_info->roam_reason))
5403 		sme_qos_csr_event_ind(mac_ctx, connect_rsp->vdev_id,
5404 				      SME_QOS_CSR_DISCONNECT_ROAM_COMPLETE,
5405 				      NULL);
5406 }
5407 #else
5408 static inline void
csr_qso_disconnect_complete_ind(struct mac_context * mac_ctx,struct wlan_cm_connect_resp * connect_rsp)5409 csr_qso_disconnect_complete_ind(struct mac_context *mac_ctx,
5410 				struct wlan_cm_connect_resp *connect_rsp) {}
5411 #endif
5412 
5413 static void
csr_qos_send_reassoc_ind(struct mac_context * mac_ctx,uint8_t vdev_id,sme_QosAssocInfo * assoc_info,struct wlan_cm_connect_resp * connect_rsp)5414 csr_qos_send_reassoc_ind(struct mac_context *mac_ctx,
5415 			 uint8_t vdev_id,
5416 			 sme_QosAssocInfo *assoc_info,
5417 			 struct wlan_cm_connect_resp *connect_rsp)
5418 {
5419 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_HANDOFF_ASSOC_REQ,
5420 			      NULL);
5421 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_REASSOC_REQ,
5422 			      NULL);
5423 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_HANDOFF_COMPLETE,
5424 			      NULL);
5425 	sme_qos_csr_event_ind(mac_ctx, vdev_id, SME_QOS_CSR_REASSOC_COMPLETE,
5426 			      assoc_info);
5427 
5428 	csr_qso_disconnect_complete_ind(mac_ctx, connect_rsp);
5429 }
5430 #else
csr_qos_send_disconnect_ind(struct mac_context * mac_ctx,uint8_t vdev_id)5431 static inline void csr_qos_send_disconnect_ind(struct mac_context *mac_ctx,
5432 					       uint8_t vdev_id)
5433 {}
5434 
csr_qos_send_assoc_ind(struct mac_context * mac_ctx,uint8_t vdev_id,sme_QosAssocInfo * assoc_info)5435 static inline void csr_qos_send_assoc_ind(struct mac_context *mac_ctx,
5436 					  uint8_t vdev_id,
5437 					  sme_QosAssocInfo *assoc_info)
5438 {}
5439 static inline void
csr_qos_send_reassoc_ind(struct mac_context * mac_ctx,uint8_t vdev_id,sme_QosAssocInfo * assoc_info,struct wlan_cm_connect_resp * connect_rsp)5440 csr_qos_send_reassoc_ind(struct mac_context *mac_ctx,
5441 			 uint8_t vdev_id,
5442 			 sme_QosAssocInfo *assoc_info,
5443 			 struct wlan_cm_connect_resp *connect_rsp)
5444 {}
5445 #endif
5446 
5447 static void
csr_update_beacon_in_connect_rsp(struct scan_cache_entry * entry,struct wlan_connect_rsp_ies * connect_ies)5448 csr_update_beacon_in_connect_rsp(struct scan_cache_entry *entry,
5449 				 struct wlan_connect_rsp_ies *connect_ies)
5450 {
5451 	if (!entry)
5452 		return;
5453 
5454 	/* no need to update if already present */
5455 	if (connect_ies->bcn_probe_rsp.ptr)
5456 		return;
5457 
5458 	/*
5459 	 * In case connection to MBSSID: Non Tx BSS OR host reassoc,
5460 	 * vdev/peer manager doesn't send unicast probe req so fill the
5461 	 * beacon in connect resp IEs here.
5462 	 */
5463 	connect_ies->bcn_probe_rsp.len =
5464 				util_scan_entry_frame_len(entry);
5465 	connect_ies->bcn_probe_rsp.ptr =
5466 		qdf_mem_malloc(connect_ies->bcn_probe_rsp.len);
5467 	if (!connect_ies->bcn_probe_rsp.ptr)
5468 		return;
5469 
5470 	qdf_mem_copy(connect_ies->bcn_probe_rsp.ptr,
5471 		     util_scan_entry_frame_ptr(entry),
5472 		     connect_ies->bcn_probe_rsp.len);
5473 }
5474 
5475 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
csr_is_link_switch_in_progress(struct wlan_objmgr_vdev * vdev)5476 static bool csr_is_link_switch_in_progress(struct wlan_objmgr_vdev *vdev)
5477 {
5478 	return mlo_mgr_is_link_switch_in_progress(vdev);
5479 }
5480 #else
csr_is_link_switch_in_progress(struct wlan_objmgr_vdev * vdev)5481 static bool csr_is_link_switch_in_progress(struct wlan_objmgr_vdev *vdev)
5482 {
5483 	return false;
5484 }
5485 #endif
5486 
csr_fill_connected_profile(struct mac_context * mac_ctx,struct csr_roam_session * session,struct wlan_objmgr_vdev * vdev,struct cm_vdev_join_rsp * rsp)5487 static void csr_fill_connected_profile(struct mac_context *mac_ctx,
5488 				       struct csr_roam_session *session,
5489 				       struct wlan_objmgr_vdev *vdev,
5490 				       struct cm_vdev_join_rsp *rsp)
5491 {
5492 	struct scan_filter *filter;
5493 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5494 	QDF_STATUS status;
5495 	qdf_list_t *list = NULL;
5496 	qdf_list_node_t *cur_lst = NULL;
5497 	struct scan_cache_node *cur_node = NULL;
5498 	uint32_t bss_len, ie_len;
5499 	struct bss_description *bss_desc = NULL;
5500 	tDot11fBeaconIEs *bcn_ies;
5501 	sme_QosAssocInfo assoc_info;
5502 	struct cm_roam_values_copy src_cfg = {};
5503 	bool is_ese = false;
5504 	uint8_t country_code[REG_ALPHA2_LEN + 1];
5505 
5506 	session->modifyProfileFields.uapsd_mask = rsp->uapsd_mask;
5507 	filter = qdf_mem_malloc(sizeof(*filter));
5508 	if (!filter)
5509 		return;
5510 
5511 	filter->num_of_bssid = 1;
5512 	qdf_copy_macaddr(&filter->bssid_list[0], &rsp->connect_rsp.bssid);
5513 	filter->ignore_auth_enc_type = true;
5514 
5515 	status = wlan_vdev_mlme_get_ssid(vdev, filter->ssid_list[0].ssid,
5516 					 &filter->ssid_list[0].length);
5517 	if (QDF_IS_STATUS_SUCCESS(status))
5518 		filter->num_of_ssid = 1;
5519 
5520 	list = wlan_scan_get_result(mac_ctx->pdev, filter);
5521 	qdf_mem_free(filter);
5522 	if (!list || (list && !qdf_list_size(list)))
5523 		goto purge_list;
5524 
5525 
5526 	qdf_list_peek_front(list, &cur_lst);
5527 	if (!cur_lst)
5528 		goto purge_list;
5529 
5530 	cur_node = qdf_container_of(cur_lst, struct scan_cache_node, node);
5531 	ie_len = util_scan_entry_ie_len(cur_node->entry);
5532 	bss_len = (uint16_t)(offsetof(struct bss_description,
5533 				      ieFields[0]) + ie_len);
5534 	bss_desc = qdf_mem_malloc(bss_len);
5535 	if (!bss_desc)
5536 		goto purge_list;
5537 
5538 	wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc, cur_node->entry);
5539 	src_cfg.uint_value = bss_desc->mbo_oce_enabled_ap;
5540 	wlan_cm_roam_cfg_set_value(mac_ctx->psoc, vdev_id, MBO_OCE_ENABLED_AP,
5541 				   &src_cfg);
5542 	csr_fill_single_pmk(mac_ctx->psoc, vdev_id, bss_desc);
5543 	status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc,
5544 						     &bcn_ies);
5545 	if (QDF_IS_STATUS_ERROR(status))
5546 		goto purge_list;
5547 
5548 	if (!bss_desc->beaconInterval)
5549 		sme_err("ERROR: Beacon interval is ZERO");
5550 
5551 	csr_update_beacon_in_connect_rsp(cur_node->entry,
5552 					 &rsp->connect_rsp.connect_ies);
5553 
5554 	assoc_info.bss_desc = bss_desc;
5555 	if (rsp->connect_rsp.is_reassoc) {
5556 		if (cm_is_ese_connection(vdev, bcn_ies->ESEVersion.present))
5557 			is_ese = true;
5558 		wlan_cm_set_ese_assoc(mac_ctx->pdev, vdev_id, is_ese);
5559 		wlan_cm_roam_cfg_get_value(mac_ctx->psoc, vdev_id, UAPSD_MASK,
5560 					   &src_cfg);
5561 		assoc_info.uapsd_mask = src_cfg.uint_value;
5562 		csr_qos_send_reassoc_ind(mac_ctx, vdev_id, &assoc_info,
5563 					 &rsp->connect_rsp);
5564 		if (src_cfg.uint_value)
5565 			sme_ps_start_uapsd(MAC_HANDLE(mac_ctx), vdev_id);
5566 	} else {
5567 		assoc_info.uapsd_mask = rsp->uapsd_mask;
5568 		csr_qos_send_assoc_ind(mac_ctx, vdev_id, &assoc_info);
5569 	}
5570 
5571 	if (rsp->connect_rsp.is_reassoc ||
5572 	    csr_is_link_switch_in_progress(vdev))
5573 		mlme_set_mbssid_info(vdev, &cur_node->entry->mbssid_info,
5574 				     bss_desc->chan_freq);
5575 
5576 	if (bcn_ies->Country.present)
5577 		qdf_mem_copy(country_code, bcn_ies->Country.country,
5578 			     REG_ALPHA2_LEN + 1);
5579 	else
5580 		qdf_mem_zero(country_code, REG_ALPHA2_LEN + 1);
5581 	wlan_cm_set_country_code(mac_ctx->pdev, vdev_id, country_code);
5582 
5583 	qdf_mem_free(bcn_ies);
5584 
5585 purge_list:
5586 	if (bss_desc)
5587 		qdf_mem_free(bss_desc);
5588 	if (list)
5589 		wlan_scan_purge_results(list);
5590 
5591 }
5592 
cm_csr_connect_rsp(struct wlan_objmgr_vdev * vdev,struct cm_vdev_join_rsp * rsp)5593 QDF_STATUS cm_csr_connect_rsp(struct wlan_objmgr_vdev *vdev,
5594 			      struct cm_vdev_join_rsp *rsp)
5595 {
5596 	struct mac_context *mac_ctx;
5597 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5598 	struct csr_roam_session *session;
5599 	struct cm_roam_values_copy src_config = {};
5600 
5601 	/*
5602 	 * This API is to update legacy struct and should be removed once
5603 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5604 	 * vdev/pdev/psoc instead
5605 	 */
5606 	if (QDF_IS_STATUS_ERROR(rsp->connect_rsp.connect_status))
5607 		return QDF_STATUS_SUCCESS;
5608 
5609 	/* handle below only in case of success */
5610 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5611 	if (!mac_ctx)
5612 		return QDF_STATUS_E_INVAL;
5613 
5614 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
5615 	if (!session || !CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
5616 		sme_err("session not found for vdev_id %d", vdev_id);
5617 		return QDF_STATUS_E_INVAL;
5618 	}
5619 
5620 	if (!rsp->connect_rsp.is_reassoc) {
5621 		if (rsp->uapsd_mask)
5622 			sme_ps_start_uapsd(MAC_HANDLE(mac_ctx), vdev_id);
5623 		src_config.uint_value = rsp->uapsd_mask;
5624 		wlan_cm_roam_cfg_set_value(mac_ctx->psoc, vdev_id, UAPSD_MASK,
5625 					   &src_config);
5626 	}
5627 	session->nss = rsp->nss;
5628 	csr_fill_connected_info(mac_ctx, session, rsp);
5629 	csr_fill_connected_profile(mac_ctx, session, vdev, rsp);
5630 
5631 	return QDF_STATUS_SUCCESS;
5632 }
5633 
5634 static void
cm_update_rsn_ocv_cap(int32_t * rsn_cap,struct wlan_cm_connect_resp * rsp)5635 cm_update_rsn_ocv_cap(int32_t *rsn_cap,
5636 		      struct wlan_cm_connect_resp *rsp)
5637 {
5638 	struct wlan_crypto_params crypto_params;
5639 	uint8_t *ie_ptr;
5640 	uint32_t ie_len;
5641 	QDF_STATUS status;
5642 
5643 	/* no need to do anything if OCV is not set */
5644 	if (!(*rsn_cap & WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED))
5645 		return;
5646 
5647 	if (!rsp->connect_ies.bcn_probe_rsp.ptr ||
5648 	    !rsp->connect_ies.bcn_probe_rsp.len ||
5649 	    (rsp->connect_ies.bcn_probe_rsp.len <
5650 		(sizeof(struct wlan_frame_hdr) +
5651 		offsetof(struct wlan_bcn_frame, ie)))) {
5652 		sme_err("invalid beacon probe rsp len %d",
5653 			rsp->connect_ies.bcn_probe_rsp.len);
5654 		return;
5655 	}
5656 
5657 	ie_len = (rsp->connect_ies.bcn_probe_rsp.len -
5658 			sizeof(struct wlan_frame_hdr) -
5659 			offsetof(struct wlan_bcn_frame, ie));
5660 	ie_ptr = (uint8_t *)(rsp->connect_ies.bcn_probe_rsp.ptr +
5661 			     sizeof(struct wlan_frame_hdr) +
5662 			     offsetof(struct wlan_bcn_frame, ie));
5663 
5664 	status = wlan_get_crypto_params_from_rsn_ie(&crypto_params, ie_ptr,
5665 						    ie_len);
5666 	if (QDF_IS_STATUS_ERROR(status))
5667 		return;
5668 
5669 	if (!(crypto_params.rsn_caps & WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED))
5670 		*rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED;
5671 }
5672 
5673 QDF_STATUS
cm_csr_connect_done_ind(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)5674 cm_csr_connect_done_ind(struct wlan_objmgr_vdev *vdev,
5675 			struct wlan_cm_connect_resp *rsp)
5676 {
5677 	mac_handle_t mac_handle;
5678 	struct mac_context *mac_ctx;
5679 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5680 	int32_t count;
5681 	struct set_context_rsp install_key_rsp;
5682 	int32_t rsn_cap, set_value;
5683 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
5684 	struct dual_sta_policy *dual_sta_policy;
5685 	bool enable_mcc_adaptive_sch = false;
5686 	struct qdf_mac_addr bc_mac = QDF_MAC_ADDR_BCAST_INIT;
5687 
5688 	/*
5689 	 * This API is to update legacy struct and should be removed once
5690 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5691 	 * vdev/pdev/psoc instead
5692 	 */
5693 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
5694 
5695 	mac_ctx = MAC_CONTEXT(mac_handle);
5696 	if (!mac_ctx)
5697 		return QDF_STATUS_E_INVAL;
5698 
5699 	mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc);
5700 	if (!mlme_obj)
5701 		return QDF_STATUS_E_INVAL;
5702 
5703 	if (QDF_IS_STATUS_ERROR(rsp->connect_status)) {
5704 		cm_csr_set_idle(vdev_id);
5705 		sme_qos_update_hand_off(vdev_id, false);
5706 		sme_qos_csr_event_ind(mac_ctx, vdev_id,
5707 				      SME_QOS_CSR_DISCONNECT_IND, NULL);
5708 		/* Fill legacy structures from resp for failure */
5709 
5710 		return QDF_STATUS_SUCCESS;
5711 	}
5712 
5713 	dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy;
5714 	count = policy_mgr_mode_specific_connection_count(mac_ctx->psoc,
5715 							  PM_STA_MODE, NULL);
5716 	/*
5717 	 * send duty cycle percentage to FW only if STA + STA
5718 	 * concurrency is in MCC.
5719 	 */
5720 	sme_debug("Current iface vdev_id:%d, Primary vdev_id:%d, Dual sta policy:%d, count:%d",
5721 		  vdev_id, dual_sta_policy->primary_vdev_id,
5722 		  dual_sta_policy->concurrent_sta_policy, count);
5723 
5724 	if (dual_sta_policy->primary_vdev_id != WLAN_UMAC_VDEV_ID_MAX &&
5725 	    dual_sta_policy->concurrent_sta_policy ==
5726 	    QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY && count == 2 &&
5727 	    policy_mgr_current_concurrency_is_mcc(mac_ctx->psoc)) {
5728 		policy_mgr_get_mcc_adaptive_sch(mac_ctx->psoc,
5729 						&enable_mcc_adaptive_sch);
5730 		if (enable_mcc_adaptive_sch) {
5731 			sme_debug("Disable mcc_adaptive_scheduler");
5732 			policy_mgr_set_dynamic_mcc_adaptive_sch(
5733 							mac_ctx->psoc, false);
5734 			if (QDF_STATUS_SUCCESS != sme_set_mas(false)) {
5735 				sme_err("Failed to disable mcc_adaptive_sched");
5736 				return -EAGAIN;
5737 			}
5738 		}
5739 		set_value =
5740 			wlan_mlme_get_mcc_duty_cycle_percentage(mac_ctx->pdev);
5741 		sme_cli_set_command(vdev_id, WMA_VDEV_MCC_SET_TIME_QUOTA,
5742 				    set_value, VDEV_CMD);
5743 	  } else if (dual_sta_policy->concurrent_sta_policy ==
5744 		     QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED && count == 2 &&
5745 		     policy_mgr_current_concurrency_is_mcc(mac_ctx->psoc)) {
5746 		policy_mgr_get_mcc_adaptive_sch(mac_ctx->psoc,
5747 						&enable_mcc_adaptive_sch);
5748 		if (enable_mcc_adaptive_sch) {
5749 			sme_debug("Enable mcc_adaptive_scheduler");
5750 			policy_mgr_set_dynamic_mcc_adaptive_sch(
5751 						  mac_ctx->psoc, true);
5752 			if (QDF_STATUS_SUCCESS != sme_set_mas(true)) {
5753 				sme_err("Failed to enable mcc_adaptive_sched");
5754 				return -EAGAIN;
5755 			}
5756 		}
5757 	} else {
5758 		QDF_STATUS status = QDF_STATUS_SUCCESS;
5759 		uint32_t quota_val;
5760 
5761 		quota_val =
5762 			ucfg_mlme_get_user_mcc_quota_percentage(mac_ctx->psoc);
5763 
5764 		if (quota_val) {
5765 			if (enable_mcc_adaptive_sch) {
5766 				policy_mgr_set_dynamic_mcc_adaptive_sch(
5767 							mac_ctx->psoc, false);
5768 				status = sme_set_mas(false);
5769 			}
5770 			if (status == QDF_STATUS_SUCCESS)
5771 				sme_cli_set_command(wlan_vdev_get_id(vdev),
5772 						    WMA_VDEV_MCC_SET_TIME_QUOTA,
5773 						    quota_val, VDEV_CMD);
5774 		} else {
5775 			sme_debug("no applicable user mcc/quota");
5776 		}
5777 	}
5778 
5779 	/*
5780 	 * For open mode authentication, send dummy install key response to
5781 	 * send OBSS scan and QOS event.
5782 	 */
5783 	if (!rsp->is_wps_connection && cm_is_open_mode(vdev)) {
5784 		install_key_rsp.length = sizeof(install_key_rsp);
5785 		install_key_rsp.status_code = eSIR_SME_SUCCESS;
5786 		install_key_rsp.sessionId = vdev_id;
5787 		/* use BC mac to enable OBSS scan */
5788 		qdf_copy_macaddr(&install_key_rsp.peer_macaddr, &bc_mac);
5789 		csr_roam_chk_lnk_set_ctx_rsp(mac_ctx,
5790 					     (tSirSmeRsp *)&install_key_rsp);
5791 	}
5792 
5793 	rsn_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP);
5794 	if (rsn_cap >= 0) {
5795 		cm_update_rsn_ocv_cap(&rsn_cap, rsp);
5796 		if (wma_cli_set2_command(vdev_id, wmi_vdev_param_rsn_capability,
5797 					 rsn_cap, 0, VDEV_CMD))
5798 			sme_err("Failed to update wmi_vdev_param_rsn_capability for vdev id %d",
5799 				vdev_id);
5800 	}
5801 
5802 	/*
5803 	 * Update the IEs after connection to reconfigure
5804 	 * any capability that changed during connection.
5805 	 */
5806 	if (mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g)
5807 		sme_set_vdev_ies_per_band(mac_handle, vdev_id,
5808 					  wlan_vdev_mlme_get_opmode(vdev));
5809 
5810 	return QDF_STATUS_SUCCESS;
5811 }
5812 
cm_csr_handle_diconnect_req(struct wlan_objmgr_vdev * vdev,struct wlan_cm_vdev_discon_req * req)5813 QDF_STATUS cm_csr_handle_diconnect_req(struct wlan_objmgr_vdev *vdev,
5814 				       struct wlan_cm_vdev_discon_req *req)
5815 {
5816 	struct mac_context *mac_ctx;
5817 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5818 	struct csr_roam_session *session;
5819 
5820 	/*
5821 	 * This API is to update legacy struct and should be removed once
5822 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5823 	 * vdev/pdev/psoc instead
5824 	 */
5825 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5826 	if (!mac_ctx)
5827 		return QDF_STATUS_E_INVAL;
5828 
5829 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
5830 	if (!session || !CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
5831 		sme_err("session not found for vdev_id %d", vdev_id);
5832 		return QDF_STATUS_E_INVAL;
5833 	}
5834 
5835 	cm_csr_set_joining(vdev_id);
5836 
5837 	/* Update the disconnect stats */
5838 	session->disconnect_stats.disconnection_cnt++;
5839 	if (req->req.source == CM_PEER_DISCONNECT) {
5840 		session->disconnect_stats.disassoc_by_peer++;
5841 	} else if (req->req.source == CM_SB_DISCONNECT) {
5842 		switch (req->req.reason_code) {
5843 		case REASON_DISASSOC_DUE_TO_INACTIVITY:
5844 			session->disconnect_stats.peer_kickout++;
5845 			break;
5846 		case REASON_BEACON_MISSED:
5847 			session->disconnect_stats.bmiss++;
5848 			break;
5849 		default:
5850 			/* Unknown reason code */
5851 			break;
5852 		}
5853 	} else if (req->req.source == CM_MLO_LINK_SWITCH_DISCONNECT) {
5854 		/* Do not update any stats as session is going to be deleted*/
5855 	} else {
5856 		session->disconnect_stats.disconnection_by_app++;
5857 	}
5858 
5859 	csr_update_prev_ap_info(session, vdev);
5860 	csr_qos_send_disconnect_ind(mac_ctx, vdev_id);
5861 
5862 	return QDF_STATUS_SUCCESS;
5863 }
5864 
5865 QDF_STATUS
cm_csr_disconnect_done_ind(struct wlan_objmgr_vdev * vdev,struct wlan_cm_discon_rsp * rsp)5866 cm_csr_disconnect_done_ind(struct wlan_objmgr_vdev *vdev,
5867 			   struct wlan_cm_discon_rsp *rsp)
5868 {
5869 	mac_handle_t mac_handle;
5870 	struct mac_context *mac_ctx;
5871 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5872 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
5873 
5874 	/*
5875 	 * This API is to update legacy struct and should be removed once
5876 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5877 	 * vdev/pdev/psoc instead
5878 	 */
5879 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
5880 
5881 	mac_ctx = MAC_CONTEXT(mac_handle);
5882 	if (!mac_ctx)
5883 		return QDF_STATUS_E_INVAL;
5884 
5885 	mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc);
5886 	if (!mlme_obj)
5887 		return QDF_STATUS_E_INVAL;
5888 
5889 	cm_csr_set_idle(vdev_id);
5890 	if (cm_is_vdev_roaming(vdev))
5891 		sme_qos_update_hand_off(vdev_id, false);
5892 	csr_set_default_dot11_mode(mac_ctx);
5893 
5894 	/*
5895 	 * Update the IEs after disconnection to remove
5896 	 * any connection specific capability change and
5897 	 * to reset back to self cap
5898 	 */
5899 	if (mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g) {
5900 		wlan_cm_set_force_20mhz_in_24ghz(vdev, true);
5901 		sme_set_vdev_ies_per_band(mac_handle, vdev_id,
5902 					  wlan_vdev_mlme_get_opmode(vdev));
5903 	}
5904 
5905 	return QDF_STATUS_SUCCESS;
5906 }
5907 
5908 #ifdef WLAN_FEATURE_HOST_ROAM
cm_csr_preauth_done(struct wlan_objmgr_vdev * vdev)5909 void cm_csr_preauth_done(struct wlan_objmgr_vdev *vdev)
5910 {
5911 	struct mac_context *mac_ctx;
5912 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
5913 	struct cm_roam_values_copy config;
5914 	bool is_11r;
5915 
5916 	/*
5917 	 * This API is to update legacy struct and should be removed once
5918 	 * CSR is cleaned up fully. No new params should be added to CSR, use
5919 	 * vdev/pdev/psoc instead
5920 	 */
5921 	mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
5922 	if (!mac_ctx) {
5923 		sme_err("mac_ctx is NULL");
5924 		return;
5925 	}
5926 
5927 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, vdev_id, IS_11R_CONNECTION,
5928 				   &config);
5929 	is_11r = config.bool_value;
5930 	if (is_11r || wlan_cm_get_ese_assoc(mac_ctx->pdev, vdev_id))
5931 		sme_qos_csr_event_ind(mac_ctx, vdev_id,
5932 				      SME_QOS_CSR_PREAUTH_SUCCESS_IND, NULL);
5933 }
5934 #endif
5935 
5936 /* */
csr_send_mb_disassoc_req_msg(struct mac_context * mac,uint32_t sessionId,tSirMacAddr bssId,uint16_t reasonCode)5937 QDF_STATUS csr_send_mb_disassoc_req_msg(struct mac_context *mac,
5938 					uint32_t sessionId,
5939 					tSirMacAddr bssId, uint16_t reasonCode)
5940 {
5941 	struct disassoc_req *pMsg;
5942 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
5943 
5944 	if (!CSR_IS_SESSION_VALID(mac, sessionId))
5945 		return QDF_STATUS_E_FAILURE;
5946 
5947 	pMsg = qdf_mem_malloc(sizeof(*pMsg));
5948 	if (!pMsg)
5949 		return QDF_STATUS_E_NOMEM;
5950 
5951 	pMsg->messageType = eWNI_SME_DISASSOC_REQ;
5952 	pMsg->length = sizeof(*pMsg);
5953 	pMsg->sessionId = sessionId;
5954 
5955 	wlan_mlme_get_mac_vdev_id(mac->pdev, sessionId, &pMsg->bssid);
5956 	qdf_mem_copy(&pMsg->peer_macaddr.bytes, bssId, QDF_MAC_ADDR_SIZE);
5957 	pMsg->reasonCode = reasonCode;
5958 
5959 	/* Update the disconnect stats */
5960 	pSession->disconnect_stats.disconnection_cnt++;
5961 	pSession->disconnect_stats.disconnection_by_app++;
5962 
5963 	return umac_send_mb_message_to_mac(pMsg);
5964 }
5965 
csr_send_chng_mcc_beacon_interval(struct mac_context * mac,uint32_t sessionId)5966 QDF_STATUS csr_send_chng_mcc_beacon_interval(struct mac_context *mac,
5967 						uint32_t sessionId)
5968 {
5969 	struct wlan_change_bi *pMsg;
5970 	uint16_t len = 0;
5971 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5972 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
5973 
5974 	if (!pSession) {
5975 		sme_err("session %d not found", sessionId);
5976 		return QDF_STATUS_E_FAILURE;
5977 	}
5978 	/* NO need to update the Beacon Params if update beacon parameter flag
5979 	 * is not set
5980 	 */
5981 	if (!mac->roam.roamSession[sessionId].update_bcn_int)
5982 		return QDF_STATUS_SUCCESS;
5983 
5984 	mac->roam.roamSession[sessionId].update_bcn_int =
5985 		false;
5986 
5987 	/* Create the message and send to lim */
5988 	len = sizeof(*pMsg);
5989 	pMsg = qdf_mem_malloc(len);
5990 	if (!pMsg)
5991 		status = QDF_STATUS_E_NOMEM;
5992 	else
5993 		status = QDF_STATUS_SUCCESS;
5994 	if (QDF_IS_STATUS_SUCCESS(status)) {
5995 		pMsg->message_type = eWNI_SME_CHNG_MCC_BEACON_INTERVAL;
5996 		pMsg->length = len;
5997 
5998 		wlan_mlme_get_mac_vdev_id(mac->pdev, sessionId,
5999 					  &pMsg->bssid);
6000 		sme_debug("CSR Attempting to change BI for Bssid= "
6001 			  QDF_MAC_ADDR_FMT,
6002 			  QDF_MAC_ADDR_REF(pMsg->bssid.bytes));
6003 		pMsg->session_id = sessionId;
6004 		sme_debug("session %d BeaconInterval %d",
6005 			sessionId,
6006 			mac->roam.roamSession[sessionId].bcn_int);
6007 		pMsg->beacon_interval =
6008 			mac->roam.roamSession[sessionId].bcn_int;
6009 		status = umac_send_mb_message_to_mac(pMsg);
6010 	}
6011 	return status;
6012 }
6013 
6014 #ifdef QCA_HT_2040_COEX
csr_set_ht2040_mode(struct mac_context * mac,uint32_t sessionId,ePhyChanBondState cbMode,bool obssEnabled)6015 QDF_STATUS csr_set_ht2040_mode(struct mac_context *mac, uint32_t sessionId,
6016 			       ePhyChanBondState cbMode, bool obssEnabled)
6017 {
6018 	struct set_ht2040_mode *pMsg;
6019 	uint16_t len = 0;
6020 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6021 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
6022 
6023 	if (!pSession) {
6024 		sme_err("session %d not found", sessionId);
6025 		return QDF_STATUS_E_FAILURE;
6026 	}
6027 
6028 	/* Create the message and send to lim */
6029 	len = sizeof(struct set_ht2040_mode);
6030 	pMsg = qdf_mem_malloc(len);
6031 	if (!pMsg)
6032 		status = QDF_STATUS_E_NOMEM;
6033 	else
6034 		status = QDF_STATUS_SUCCESS;
6035 	if (QDF_IS_STATUS_SUCCESS(status)) {
6036 		qdf_mem_zero(pMsg, sizeof(struct set_ht2040_mode));
6037 		pMsg->messageType = eWNI_SME_SET_HT_2040_MODE;
6038 		pMsg->length = len;
6039 
6040 		wlan_mlme_get_mac_vdev_id(mac->pdev, sessionId, &pMsg->bssid);
6041 		sme_debug(
6042 			"CSR Attempting to set HT20/40 mode for Bssid= "
6043 			 QDF_MAC_ADDR_FMT,
6044 			 QDF_MAC_ADDR_REF(pMsg->bssid.bytes));
6045 		pMsg->sessionId = sessionId;
6046 		sme_debug("  session %d HT20/40 mode %d",
6047 			sessionId, cbMode);
6048 		pMsg->cbMode = cbMode;
6049 		pMsg->obssEnabled = obssEnabled;
6050 		status = umac_send_mb_message_to_mac(pMsg);
6051 	}
6052 	return status;
6053 }
6054 #endif
6055 
csr_send_mb_deauth_req_msg(struct mac_context * mac,uint32_t vdev_id,tSirMacAddr bssId,uint16_t reasonCode)6056 QDF_STATUS csr_send_mb_deauth_req_msg(struct mac_context *mac,
6057 				      uint32_t vdev_id,
6058 				      tSirMacAddr bssId, uint16_t reasonCode)
6059 {
6060 	struct deauth_req *pMsg;
6061 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, vdev_id);
6062 
6063 	if (!CSR_IS_SESSION_VALID(mac, vdev_id))
6064 		return QDF_STATUS_E_FAILURE;
6065 
6066 	pMsg = qdf_mem_malloc(sizeof(*pMsg));
6067 	if (!pMsg)
6068 		return QDF_STATUS_E_NOMEM;
6069 
6070 	pMsg->messageType = eWNI_SME_DEAUTH_REQ;
6071 	pMsg->length = sizeof(*pMsg);
6072 	pMsg->vdev_id = vdev_id;
6073 
6074 	wlan_mlme_get_mac_vdev_id(mac->pdev, vdev_id, &pMsg->bssid);
6075 	/* Set the peer MAC address before sending the message to LIM */
6076 	qdf_mem_copy(&pMsg->peer_macaddr.bytes, bssId, QDF_MAC_ADDR_SIZE);
6077 	pMsg->reasonCode = reasonCode;
6078 
6079 	/* Update the disconnect stats */
6080 	pSession->disconnect_stats.disconnection_cnt++;
6081 	pSession->disconnect_stats.disconnection_by_app++;
6082 
6083 	return umac_send_mb_message_to_mac(pMsg);
6084 }
6085 
csr_send_mb_disassoc_cnf_msg(struct mac_context * mac,struct disassoc_ind * pDisassocInd)6086 QDF_STATUS csr_send_mb_disassoc_cnf_msg(struct mac_context *mac,
6087 					struct disassoc_ind *pDisassocInd)
6088 {
6089 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6090 	struct disassoc_cnf *pMsg;
6091 
6092 	do {
6093 		pMsg = qdf_mem_malloc(sizeof(*pMsg));
6094 		if (!pMsg)
6095 			status = QDF_STATUS_E_NOMEM;
6096 		else
6097 			status = QDF_STATUS_SUCCESS;
6098 		if (!QDF_IS_STATUS_SUCCESS(status))
6099 			break;
6100 		pMsg->messageType = eWNI_SME_DISASSOC_CNF;
6101 		pMsg->status_code = eSIR_SME_SUCCESS;
6102 		pMsg->length = sizeof(*pMsg);
6103 		pMsg->vdev_id = pDisassocInd->vdev_id;
6104 		qdf_copy_macaddr(&pMsg->peer_macaddr,
6105 				 &pDisassocInd->peer_macaddr);
6106 		status = QDF_STATUS_SUCCESS;
6107 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6108 			qdf_mem_free(pMsg);
6109 			break;
6110 		}
6111 
6112 		qdf_copy_macaddr(&pMsg->bssid, &pDisassocInd->bssid);
6113 		status = QDF_STATUS_SUCCESS;
6114 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6115 			qdf_mem_free(pMsg);
6116 			break;
6117 		}
6118 
6119 		status = umac_send_mb_message_to_mac(pMsg);
6120 	} while (0);
6121 	return status;
6122 }
6123 
csr_send_mb_deauth_cnf_msg(struct mac_context * mac,struct deauth_ind * pDeauthInd)6124 QDF_STATUS csr_send_mb_deauth_cnf_msg(struct mac_context *mac,
6125 				      struct deauth_ind *pDeauthInd)
6126 {
6127 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6128 	struct deauth_cnf *pMsg;
6129 
6130 	do {
6131 		pMsg = qdf_mem_malloc(sizeof(*pMsg));
6132 		if (!pMsg)
6133 			status = QDF_STATUS_E_NOMEM;
6134 		else
6135 			status = QDF_STATUS_SUCCESS;
6136 		if (!QDF_IS_STATUS_SUCCESS(status))
6137 			break;
6138 		pMsg->messageType = eWNI_SME_DEAUTH_CNF;
6139 		pMsg->status_code = eSIR_SME_SUCCESS;
6140 		pMsg->length = sizeof(*pMsg);
6141 		pMsg->vdev_id = pDeauthInd->vdev_id;
6142 		qdf_copy_macaddr(&pMsg->bssid, &pDeauthInd->bssid);
6143 		status = QDF_STATUS_SUCCESS;
6144 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6145 			qdf_mem_free(pMsg);
6146 			break;
6147 		}
6148 		qdf_copy_macaddr(&pMsg->peer_macaddr,
6149 				 &pDeauthInd->peer_macaddr);
6150 		status = QDF_STATUS_SUCCESS;
6151 		if (!QDF_IS_STATUS_SUCCESS(status)) {
6152 			qdf_mem_free(pMsg);
6153 			break;
6154 		}
6155 		status = umac_send_mb_message_to_mac(pMsg);
6156 	} while (0);
6157 	return status;
6158 }
6159 
csr_send_assoc_cnf_msg(struct mac_context * mac,struct assoc_ind * pAssocInd,QDF_STATUS Halstatus,enum wlan_status_code mac_status_code)6160 QDF_STATUS csr_send_assoc_cnf_msg(struct mac_context *mac,
6161 				  struct assoc_ind *pAssocInd,
6162 				  QDF_STATUS Halstatus,
6163 				  enum wlan_status_code mac_status_code)
6164 {
6165 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6166 	struct assoc_cnf *pMsg;
6167 	struct scheduler_msg msg = { 0 };
6168 
6169 	sme_debug("HalStatus: %d, mac_status_code %d",
6170 		  Halstatus, mac_status_code);
6171 	do {
6172 		pMsg = qdf_mem_malloc(sizeof(*pMsg));
6173 		if (!pMsg)
6174 			return QDF_STATUS_E_NOMEM;
6175 		pMsg->messageType = eWNI_SME_ASSOC_CNF;
6176 		pMsg->length = sizeof(*pMsg);
6177 		if (QDF_IS_STATUS_SUCCESS(Halstatus)) {
6178 			pMsg->status_code = eSIR_SME_SUCCESS;
6179 		} else {
6180 			pMsg->status_code = eSIR_SME_ASSOC_REFUSED;
6181 			pMsg->mac_status_code = mac_status_code;
6182 		}
6183 		/* bssId */
6184 		qdf_mem_copy(pMsg->bssid.bytes, pAssocInd->bssId,
6185 			     QDF_MAC_ADDR_SIZE);
6186 		/* peerMacAddr */
6187 		qdf_mem_copy(pMsg->peer_macaddr.bytes, pAssocInd->peerMacAddr,
6188 			     QDF_MAC_ADDR_SIZE);
6189 		/* aid */
6190 		pMsg->aid = pAssocInd->aid;
6191 		/* OWE IE */
6192 		if (pAssocInd->owe_ie_len) {
6193 			pMsg->owe_ie = qdf_mem_malloc(pAssocInd->owe_ie_len);
6194 			if (!pMsg->owe_ie)
6195 				return QDF_STATUS_E_NOMEM;
6196 			qdf_mem_copy(pMsg->owe_ie, pAssocInd->owe_ie,
6197 				     pAssocInd->owe_ie_len);
6198 			pMsg->owe_ie_len = pAssocInd->owe_ie_len;
6199 		}
6200 
6201 		if (pAssocInd->ft_ie_len) {
6202 			pMsg->ft_ie = qdf_mem_malloc(pAssocInd->ft_ie_len);
6203 			if (!pMsg->ft_ie)
6204 				return QDF_STATUS_E_NOMEM;
6205 			qdf_mem_copy(pMsg->ft_ie, pAssocInd->ft_ie,
6206 				     pAssocInd->ft_ie_len);
6207 			pMsg->ft_ie_len = pAssocInd->ft_ie_len;
6208 		}
6209 		pMsg->need_assoc_rsp_tx_cb = pAssocInd->need_assoc_rsp_tx_cb;
6210 
6211 		msg.type = pMsg->messageType;
6212 		msg.bodyval = 0;
6213 		msg.bodyptr = pMsg;
6214 		/* pMsg is freed by umac_send_mb_message_to_mac in anycase*/
6215 		status = scheduler_post_msg_by_priority(QDF_MODULE_ID_PE, &msg,
6216 							true);
6217 	} while (0);
6218 	return status;
6219 }
6220 
6221 /**
6222  * csr_store_oce_cfg_flags_in_vdev() - fill OCE flags from ini
6223  * @mac: mac_context.
6224  * @vdev: Pointer to pdev obj
6225  * @vdev_id: vdev_id
6226  *
6227  * This API will store the oce flags in vdev mlme priv object
6228  *
6229  * Return: none
6230  */
csr_store_oce_cfg_flags_in_vdev(struct mac_context * mac,struct wlan_objmgr_pdev * pdev,uint8_t vdev_id)6231 static void csr_store_oce_cfg_flags_in_vdev(struct mac_context *mac,
6232 					    struct wlan_objmgr_pdev *pdev,
6233 					    uint8_t vdev_id)
6234 {
6235 	uint8_t *vdev_dynamic_oce;
6236 	struct wlan_objmgr_vdev *vdev =
6237 	wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, WLAN_LEGACY_MAC_ID);
6238 
6239 	if (!vdev)
6240 		return;
6241 
6242 	vdev_dynamic_oce = mlme_get_dynamic_oce_flags(vdev);
6243 	if (vdev_dynamic_oce)
6244 		*vdev_dynamic_oce = mac->mlme_cfg->oce.feature_bitmap;
6245 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
6246 }
6247 
csr_send_set_ie(uint8_t type,uint8_t sub_type,uint8_t vdev_id)6248 void csr_send_set_ie(uint8_t type, uint8_t sub_type,
6249 		     uint8_t vdev_id)
6250 {
6251 	struct send_extcap_ie *msg;
6252 	QDF_STATUS status;
6253 
6254 	sme_debug("send SET IE msg to PE");
6255 
6256 	if (!(type == WLAN_VDEV_MLME_TYPE_STA ||
6257 	      (type == WLAN_VDEV_MLME_TYPE_AP &&
6258 	      sub_type == WLAN_VDEV_MLME_SUBTYPE_P2P_DEVICE))) {
6259 		sme_debug("Failed to send set IE req for vdev_%d", vdev_id);
6260 		return;
6261 	}
6262 
6263 	msg = qdf_mem_malloc(sizeof(*msg));
6264 	if (!msg)
6265 		return;
6266 
6267 	msg->msg_type = eWNI_SME_SET_IE_REQ;
6268 	msg->session_id = vdev_id;
6269 	msg->length = sizeof(*msg);
6270 	status = umac_send_mb_message_to_mac(msg);
6271 	if (!QDF_IS_STATUS_SUCCESS(status))
6272 		sme_debug("Failed to send set IE req for vdev_%d", vdev_id);
6273 }
6274 
csr_get_vdev_type_nss(enum QDF_OPMODE dev_mode,uint8_t * nss_2g,uint8_t * nss_5g)6275 void csr_get_vdev_type_nss(enum QDF_OPMODE dev_mode, uint8_t *nss_2g,
6276 			   uint8_t *nss_5g)
6277 {
6278 	struct mac_context *mac_ctx = sme_get_mac_context();
6279 
6280 	if (!mac_ctx) {
6281 		sme_err("Invalid MAC context");
6282 		return;
6283 	}
6284 
6285 	switch (dev_mode) {
6286 	case QDF_STA_MODE:
6287 		*nss_2g = mac_ctx->vdev_type_nss_2g.sta;
6288 		*nss_5g = mac_ctx->vdev_type_nss_5g.sta;
6289 		break;
6290 	case QDF_SAP_MODE:
6291 		*nss_2g = mac_ctx->vdev_type_nss_2g.sap;
6292 		*nss_5g = mac_ctx->vdev_type_nss_5g.sap;
6293 		break;
6294 	case QDF_P2P_CLIENT_MODE:
6295 		*nss_2g = mac_ctx->vdev_type_nss_2g.p2p_cli;
6296 		*nss_5g = mac_ctx->vdev_type_nss_5g.p2p_cli;
6297 		break;
6298 	case QDF_P2P_GO_MODE:
6299 		*nss_2g = mac_ctx->vdev_type_nss_2g.p2p_go;
6300 		*nss_5g = mac_ctx->vdev_type_nss_5g.p2p_go;
6301 		break;
6302 	case QDF_P2P_DEVICE_MODE:
6303 		*nss_2g = mac_ctx->vdev_type_nss_2g.p2p_dev;
6304 		*nss_5g = mac_ctx->vdev_type_nss_5g.p2p_dev;
6305 		break;
6306 	case QDF_IBSS_MODE:
6307 		*nss_2g = mac_ctx->vdev_type_nss_2g.ibss;
6308 		*nss_5g = mac_ctx->vdev_type_nss_5g.ibss;
6309 		break;
6310 	case QDF_OCB_MODE:
6311 		*nss_2g = mac_ctx->vdev_type_nss_2g.ocb;
6312 		*nss_5g = mac_ctx->vdev_type_nss_5g.ocb;
6313 		break;
6314 	case QDF_NAN_DISC_MODE:
6315 		*nss_2g = mac_ctx->vdev_type_nss_2g.nan;
6316 		*nss_5g = mac_ctx->vdev_type_nss_5g.nan;
6317 		break;
6318 	case QDF_NDI_MODE:
6319 		*nss_2g = mac_ctx->vdev_type_nss_2g.ndi;
6320 		*nss_5g = mac_ctx->vdev_type_nss_5g.ndi;
6321 		break;
6322 	default:
6323 		*nss_2g = 1;
6324 		*nss_5g = 1;
6325 		sme_err("Unknown device mode: %d", dev_mode);
6326 		break;
6327 	}
6328 	sme_debug("mode - %d: nss_2g - %d, 5g - %d",
6329 		  dev_mode, *nss_2g, *nss_5g);
6330 }
6331 
csr_setup_vdev_session(struct vdev_mlme_obj * vdev_mlme)6332 QDF_STATUS csr_setup_vdev_session(struct vdev_mlme_obj *vdev_mlme)
6333 {
6334 	QDF_STATUS status;
6335 	uint32_t existing_session_id;
6336 	struct csr_roam_session *session;
6337 	struct mlme_vht_capabilities_info *vht_cap_info;
6338 	u8 vdev_id;
6339 	struct qdf_mac_addr *mac_addr;
6340 	mac_handle_t mac_handle;
6341 	struct mac_context *mac_ctx;
6342 	struct wlan_objmgr_vdev *vdev;
6343 	struct wlan_vht_config vht_config;
6344 	struct wlan_ht_config ht_cap;
6345 
6346 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
6347 	mac_ctx = MAC_CONTEXT(mac_handle);
6348 	if (!mac_ctx) {
6349 		QDF_ASSERT(0);
6350 		return QDF_STATUS_E_INVAL;
6351 	}
6352 
6353 	if (!(mac_ctx->mlme_cfg)) {
6354 		sme_err("invalid mlme cfg");
6355 		return QDF_STATUS_E_FAILURE;
6356 	}
6357 	vht_cap_info = &mac_ctx->mlme_cfg->vht_caps.vht_cap_info;
6358 
6359 	vdev = vdev_mlme->vdev;
6360 
6361 	vdev_id = wlan_vdev_get_id(vdev);
6362 	mac_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_macaddr(vdev);
6363 	/* check to see if the mac address already belongs to a session */
6364 	status = csr_roam_get_session_id_from_bssid(mac_ctx, mac_addr,
6365 						    &existing_session_id);
6366 	if (QDF_IS_STATUS_SUCCESS(status)) {
6367 		sme_err("Session %d exists with mac address "QDF_MAC_ADDR_FMT,
6368 			existing_session_id,
6369 			QDF_MAC_ADDR_REF(mac_addr->bytes));
6370 		return QDF_STATUS_E_FAILURE;
6371 	}
6372 
6373 	/* attempt to retrieve session for Id */
6374 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
6375 	if (!session) {
6376 		sme_err("Session does not exist for interface %d", vdev_id);
6377 		return QDF_STATUS_E_FAILURE;
6378 	}
6379 
6380 	/* check to see if the session is already active */
6381 	if (session->sessionActive) {
6382 		sme_err("Cannot re-open active session with Id %d", vdev_id);
6383 		return QDF_STATUS_E_FAILURE;
6384 	}
6385 
6386 	session->sessionActive = true;
6387 	session->vdev_id = vdev_id;
6388 
6389 	ht_cap.caps = 0;
6390 	vht_config.caps = 0;
6391 	ht_cap.ht_caps = mac_ctx->mlme_cfg->ht_caps.ht_cap_info;
6392 	vdev_mlme->proto.ht_info.ht_caps = ht_cap.caps;
6393 
6394 	vht_config.max_mpdu_len = vht_cap_info->ampdu_len;
6395 	vht_config.supported_channel_widthset =
6396 			vht_cap_info->supp_chan_width;
6397 	vht_config.ldpc_coding = vht_cap_info->ldpc_coding_cap;
6398 	vht_config.shortgi80 = vht_cap_info->short_gi_80mhz;
6399 	vht_config.shortgi160and80plus80 =
6400 			vht_cap_info->short_gi_160mhz;
6401 	vht_config.tx_stbc = vht_cap_info->tx_stbc;
6402 	vht_config.rx_stbc = vht_cap_info->rx_stbc;
6403 	vht_config.su_beam_former = vht_cap_info->su_bformer;
6404 	vht_config.su_beam_formee = vht_cap_info->su_bformee;
6405 	vht_config.csnof_beamformer_antSup =
6406 			vht_cap_info->tx_bfee_ant_supp;
6407 	vht_config.num_soundingdim = vht_cap_info->num_soundingdim;
6408 	vht_config.mu_beam_former = vht_cap_info->mu_bformer;
6409 	vht_config.mu_beam_formee = vht_cap_info->enable_mu_bformee;
6410 	vht_config.vht_txops = vht_cap_info->txop_ps;
6411 	vht_config.htc_vhtcap = vht_cap_info->htc_vhtc;
6412 	vht_config.rx_antpattern = vht_cap_info->rx_antpattern;
6413 	vht_config.tx_antpattern = vht_cap_info->tx_antpattern;
6414 
6415 	vht_config.max_ampdu_lenexp =
6416 			vht_cap_info->ampdu_len_exponent;
6417 	vdev_mlme->proto.vht_info.caps = vht_config.caps;
6418 	csr_update_session_he_cap(mac_ctx, session);
6419 	csr_update_session_eht_cap(mac_ctx, session);
6420 
6421 	csr_send_set_ie(vdev_mlme->mgmt.generic.type,
6422 			vdev_mlme->mgmt.generic.subtype,
6423 			wlan_vdev_get_id(vdev));
6424 
6425 	if (vdev_mlme->mgmt.generic.type == WLAN_VDEV_MLME_TYPE_STA) {
6426 		csr_store_oce_cfg_flags_in_vdev(mac_ctx, mac_ctx->pdev,
6427 						wlan_vdev_get_id(vdev));
6428 		wlan_mlme_update_oce_flags(mac_ctx->pdev);
6429 	}
6430 
6431 	return QDF_STATUS_SUCCESS;
6432 }
6433 
csr_cleanup_vdev_session(struct mac_context * mac,uint8_t vdev_id)6434 void csr_cleanup_vdev_session(struct mac_context *mac, uint8_t vdev_id)
6435 {
6436 	if (CSR_IS_SESSION_VALID(mac, vdev_id)) {
6437 		struct csr_roam_session *pSession = CSR_GET_SESSION(mac,
6438 								vdev_id);
6439 
6440 		csr_flush_roam_scan_chan_lists(mac, vdev_id);
6441 		csr_roam_free_connected_info(mac, &pSession->connectedInfo);
6442 		csr_init_session(mac, vdev_id);
6443 	}
6444 }
6445 
csr_prepare_vdev_delete(struct mac_context * mac_ctx,struct wlan_objmgr_vdev * vdev)6446 QDF_STATUS csr_prepare_vdev_delete(struct mac_context *mac_ctx,
6447 				   struct wlan_objmgr_vdev *vdev)
6448 {
6449 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6450 	struct csr_roam_session *session;
6451 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
6452 
6453 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
6454 	if (!session)
6455 		return QDF_STATUS_E_INVAL;
6456 
6457 	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id))
6458 		return QDF_STATUS_E_INVAL;
6459 
6460 	if (CSR_IS_WAIT_FOR_KEY(mac_ctx, vdev_id)) {
6461 		sme_debug("Stop Wait for key timer and change substate to eCSR_ROAM_SUBSTATE_NONE");
6462 		cm_stop_wait_for_key_timer(mac_ctx->psoc, vdev_id);
6463 		csr_roam_substate_change(mac_ctx, eCSR_ROAM_SUBSTATE_NONE,
6464 					 vdev_id);
6465 	}
6466 
6467 	wlan_ser_vdev_queue_disable(vdev);
6468 	/* Flush all the commands for vdev */
6469 	wlan_serialization_purge_all_cmd_by_vdev_id(mac_ctx->pdev, vdev_id);
6470 	if (!mac_ctx->session_close_cb) {
6471 		sme_err("no close session callback registered");
6472 		return QDF_STATUS_E_FAILURE;
6473 	}
6474 
6475 	return status;
6476 }
6477 
csr_init_session(struct mac_context * mac,uint32_t sessionId)6478 static void csr_init_session(struct mac_context *mac, uint32_t sessionId)
6479 {
6480 	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
6481 
6482 	if (!pSession)
6483 		return;
6484 
6485 	pSession->sessionActive = false;
6486 	pSession->vdev_id = WLAN_UMAC_VDEV_ID_MAX;
6487 	pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
6488 	csr_roam_free_connected_info(mac, &pSession->connectedInfo);
6489 }
6490 
csr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev * pdev,void * object,void * arg)6491 static void csr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev,
6492 				       void *object, void *arg)
6493 {
6494 	struct bssid_search_arg *bssid_arg = arg;
6495 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
6496 	struct wlan_objmgr_peer *peer;
6497 
6498 	if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS)
6499 		return;
6500 
6501 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_LEGACY_SME_ID);
6502 	if (!peer)
6503 		return;
6504 
6505 	if (WLAN_ADDR_EQ(bssid_arg->peer_addr.bytes,
6506 			 wlan_peer_get_macaddr(peer)) == QDF_STATUS_SUCCESS)
6507 		bssid_arg->vdev_id = wlan_vdev_get_id(vdev);
6508 
6509 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_SME_ID);
6510 }
6511 
csr_roam_get_session_id_from_bssid(struct mac_context * mac,struct qdf_mac_addr * bssid,uint32_t * pSessionId)6512 QDF_STATUS csr_roam_get_session_id_from_bssid(struct mac_context *mac,
6513 					      struct qdf_mac_addr *bssid,
6514 					      uint32_t *pSessionId)
6515 {
6516 	struct bssid_search_arg bssid_arg;
6517 
6518 	qdf_copy_macaddr(&bssid_arg.peer_addr, bssid);
6519 	bssid_arg.vdev_id = WLAN_MAX_VDEVS;
6520 	wlan_objmgr_pdev_iterate_obj_list(mac->pdev, WLAN_VDEV_OP,
6521 					  csr_get_vdev_id_from_bssid,
6522 					  &bssid_arg, 0,
6523 					  WLAN_LEGACY_SME_ID);
6524 	if (bssid_arg.vdev_id >= WLAN_MAX_VDEVS) {
6525 		*pSessionId = 0;
6526 		return QDF_STATUS_E_FAILURE;
6527 	}
6528 
6529 	*pSessionId = bssid_arg.vdev_id;
6530 
6531 	return QDF_STATUS_SUCCESS;
6532 }
6533 
csr_get_snr(struct mac_context * mac,tCsrSnrCallback callback,struct qdf_mac_addr bssId,void * pContext)6534 QDF_STATUS csr_get_snr(struct mac_context *mac,
6535 		       tCsrSnrCallback callback,
6536 		       struct qdf_mac_addr bssId, void *pContext)
6537 {
6538 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6539 	struct scheduler_msg msg = {0};
6540 	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
6541 	tAniGetSnrReq *pMsg;
6542 
6543 	pMsg = qdf_mem_malloc(sizeof(tAniGetSnrReq));
6544 	if (!pMsg)
6545 		return QDF_STATUS_E_NOMEM;
6546 
6547 	status = csr_roam_get_session_id_from_bssid(mac, &bssId, &sessionId);
6548 	if (!QDF_IS_STATUS_SUCCESS(status)) {
6549 		qdf_mem_free(pMsg);
6550 		sme_err("Couldn't find session_id for given BSSID");
6551 		return status;
6552 	}
6553 
6554 	pMsg->msgType = eWNI_SME_GET_SNR_REQ;
6555 	pMsg->msgLen = (uint16_t) sizeof(tAniGetSnrReq);
6556 	pMsg->sessionId = sessionId;
6557 	pMsg->snrCallback = callback;
6558 	pMsg->pDevContext = pContext;
6559 	msg.type = eWNI_SME_GET_SNR_REQ;
6560 	msg.bodyptr = pMsg;
6561 	msg.reserved = 0;
6562 
6563 	if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME,
6564 							 QDF_MODULE_ID_SME,
6565 							 QDF_MODULE_ID_SME,
6566 							 &msg)) {
6567 		qdf_mem_free((void *)pMsg);
6568 		status = QDF_STATUS_E_FAILURE;
6569 	}
6570 
6571 	return status;
6572 }
6573 
6574 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
csr_invoke_neighbor_report_request(uint8_t session_id,struct sRrmNeighborReq * neighbor_report_req,bool send_resp_to_host)6575 QDF_STATUS csr_invoke_neighbor_report_request(
6576 				uint8_t session_id,
6577 				struct sRrmNeighborReq *neighbor_report_req,
6578 				bool send_resp_to_host)
6579 {
6580 	struct wmi_invoke_neighbor_report_params *invoke_params;
6581 	struct scheduler_msg msg = {0};
6582 
6583 	if (!neighbor_report_req) {
6584 		sme_err("Invalid params");
6585 		return QDF_STATUS_E_INVAL;
6586 	}
6587 
6588 	invoke_params = qdf_mem_malloc(sizeof(*invoke_params));
6589 	if (!invoke_params)
6590 		return QDF_STATUS_E_NOMEM;
6591 
6592 	invoke_params->vdev_id = session_id;
6593 	invoke_params->send_resp_to_host = send_resp_to_host;
6594 
6595 	if (!neighbor_report_req->no_ssid) {
6596 		invoke_params->ssid.length = neighbor_report_req->ssid.length;
6597 		qdf_mem_copy(invoke_params->ssid.ssid,
6598 			     neighbor_report_req->ssid.ssId,
6599 			     neighbor_report_req->ssid.length);
6600 	} else {
6601 		invoke_params->ssid.length = 0;
6602 	}
6603 
6604 	sme_debug("Sending SIR_HAL_INVOKE_NEIGHBOR_REPORT");
6605 
6606 	msg.type = SIR_HAL_INVOKE_NEIGHBOR_REPORT;
6607 	msg.reserved = 0;
6608 	msg.bodyptr = invoke_params;
6609 
6610 	if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME,
6611 							 QDF_MODULE_ID_WMA,
6612 							 QDF_MODULE_ID_WMA,
6613 							 &msg)) {
6614 		sme_err("Not able to post message to WMA");
6615 		qdf_mem_free(invoke_params);
6616 		return QDF_STATUS_E_FAILURE;
6617 	}
6618 
6619 	return QDF_STATUS_SUCCESS;
6620 }
6621 
6622 #ifdef FEATURE_WLAN_ESE
wlan_cm_ese_populate_additional_ies(struct wlan_objmgr_pdev * pdev,struct wlan_mlme_psoc_ext_obj * mlme_obj,uint8_t vdev_id,struct wlan_roam_scan_offload_params * rso_mode_cfg)6623 void wlan_cm_ese_populate_additional_ies(struct wlan_objmgr_pdev *pdev,
6624 			struct wlan_mlme_psoc_ext_obj *mlme_obj,
6625 			uint8_t vdev_id,
6626 			struct wlan_roam_scan_offload_params *rso_mode_cfg)
6627 {
6628 	uint8_t tspec_ie_hdr[SIR_MAC_OUI_WME_HDR_MIN]
6629 			= { 0x00, 0x50, 0xf2, 0x02, 0x02, 0x01 };
6630 	uint8_t tspec_ie_buf[DOT11F_IE_WMMTSPEC_MAX_LEN], j;
6631 	ese_wmm_tspec_ie *tspec_ie;
6632 	tESETspecInfo ese_tspec;
6633 	struct mac_context *mac_ctx;
6634 	struct csr_roam_session *session;
6635 
6636 	mac_ctx = sme_get_mac_context();
6637 	if (!mac_ctx) {
6638 		sme_err("mac_ctx is NULL");
6639 		return;
6640 	}
6641 
6642 	session = CSR_GET_SESSION(mac_ctx, vdev_id);
6643 	if (!session) {
6644 		sme_err("session is null %d", vdev_id);
6645 		return;
6646 	}
6647 
6648 	tspec_ie = (ese_wmm_tspec_ie *)(tspec_ie_buf + SIR_MAC_OUI_WME_HDR_MIN);
6649 	if (csr_is_wmm_supported(mac_ctx) &&
6650 	    mlme_obj->cfg.lfr.ese_enabled &&
6651 	    wlan_cm_get_ese_assoc(pdev, session->vdev_id)) {
6652 		ese_tspec.numTspecs = sme_qos_ese_retrieve_tspec_info(
6653 					mac_ctx, session->vdev_id,
6654 					(tTspecInfo *)&ese_tspec.tspec[0]);
6655 		qdf_mem_copy(tspec_ie_buf, tspec_ie_hdr,
6656 			     SIR_MAC_OUI_WME_HDR_MIN);
6657 		for (j = 0; j < ese_tspec.numTspecs; j++) {
6658 			/* Populate the tspec_ie */
6659 			ese_populate_wmm_tspec(&ese_tspec.tspec[j].tspec,
6660 					       tspec_ie);
6661 			wlan_cm_append_assoc_ies(rso_mode_cfg,
6662 						 WLAN_ELEMID_VENDOR,
6663 						  DOT11F_IE_WMMTSPEC_MAX_LEN,
6664 						 tspec_ie_buf);
6665 		}
6666 	}
6667 }
6668 #endif
6669 
wlan_cm_get_rrm_cap_ie_data(void)6670 uint8_t *wlan_cm_get_rrm_cap_ie_data(void)
6671 {
6672 	struct mac_context *mac_ctx;
6673 
6674 	mac_ctx = sme_get_mac_context();
6675 	if (!mac_ctx) {
6676 		sme_err("mac_ctx is NULL");
6677 		return NULL;
6678 	}
6679 
6680 	return (uint8_t *)&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps;
6681 }
6682 #endif
6683 
csr_get_command_buffer(struct mac_context * mac)6684 tSmeCmd *csr_get_command_buffer(struct mac_context *mac)
6685 {
6686 	tSmeCmd *pCmd = sme_get_command_buffer(mac);
6687 
6688 	if (pCmd)
6689 		mac->roam.sPendingCommands++;
6690 
6691 	return pCmd;
6692 }
6693 
csr_free_cmd_memory(struct mac_context * mac,tSmeCmd * pCommand)6694 static void csr_free_cmd_memory(struct mac_context *mac, tSmeCmd *pCommand)
6695 {
6696 	if (!pCommand) {
6697 		sme_err("pCommand is NULL");
6698 		return;
6699 	}
6700 	switch (pCommand->command) {
6701 	case eSmeCommandRoam:
6702 		csr_release_command_roam(mac, pCommand);
6703 		break;
6704 	case eSmeCommandWmStatusChange:
6705 		csr_release_command_wm_status_change(mac, pCommand);
6706 		break;
6707 	default:
6708 		break;
6709 	}
6710 }
6711 
csr_release_command_buffer(struct mac_context * mac,tSmeCmd * pCommand)6712 void csr_release_command_buffer(struct mac_context *mac, tSmeCmd *pCommand)
6713 {
6714 	if (mac->roam.sPendingCommands > 0) {
6715 		/*
6716 		 * All command allocated through csr_get_command_buffer
6717 		 * need to decrement the pending count when releasing
6718 		 */
6719 		mac->roam.sPendingCommands--;
6720 		csr_free_cmd_memory(mac, pCommand);
6721 		sme_release_command(mac, pCommand);
6722 	} else {
6723 		sme_err("no pending commands");
6724 		QDF_ASSERT(0);
6725 	}
6726 }
6727 
csr_release_command(struct mac_context * mac_ctx,tSmeCmd * sme_cmd)6728 void csr_release_command(struct mac_context *mac_ctx, tSmeCmd *sme_cmd)
6729 {
6730 	struct wlan_serialization_queued_cmd_info cmd_info;
6731 	struct wlan_serialization_command cmd;
6732 	struct wlan_objmgr_vdev *vdev;
6733 
6734 	if (!sme_cmd) {
6735 		sme_err("sme_cmd is NULL");
6736 		return;
6737 	}
6738 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
6739 			sme_cmd->vdev_id, WLAN_LEGACY_SME_ID);
6740 	if (!vdev) {
6741 		sme_err("Invalid vdev");
6742 		return;
6743 	}
6744 	qdf_mem_zero(&cmd_info,
6745 			sizeof(struct wlan_serialization_queued_cmd_info));
6746 	cmd_info.cmd_id = sme_cmd->cmd_id;
6747 	cmd_info.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD;
6748 	cmd_info.cmd_type = csr_get_cmd_type(sme_cmd);
6749 	cmd_info.vdev = vdev;
6750 	qdf_mem_zero(&cmd, sizeof(struct wlan_serialization_command));
6751 	cmd.cmd_id = cmd_info.cmd_id;
6752 	cmd.cmd_type = cmd_info.cmd_type;
6753 	cmd.vdev = cmd_info.vdev;
6754 	if (wlan_serialization_is_cmd_present_in_active_queue(
6755 				mac_ctx->psoc, &cmd)) {
6756 		cmd_info.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
6757 		wlan_serialization_remove_cmd(&cmd_info);
6758 	} else if (wlan_serialization_is_cmd_present_in_pending_queue(
6759 				mac_ctx->psoc, &cmd)) {
6760 		cmd_info.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
6761 		wlan_serialization_cancel_request(&cmd_info);
6762 	} else {
6763 		sme_debug("can't find cmd_id %d cmd_type %d", cmd_info.cmd_id,
6764 			  cmd_info.cmd_type);
6765 	}
6766 	if (cmd_info.vdev)
6767 		wlan_objmgr_vdev_release_ref(cmd_info.vdev, WLAN_LEGACY_SME_ID);
6768 }
6769 
6770 
csr_get_roam_cmd_type(tSmeCmd * sme_cmd)6771 static enum wlan_serialization_cmd_type csr_get_roam_cmd_type(
6772 		tSmeCmd *sme_cmd)
6773 {
6774 	enum wlan_serialization_cmd_type cmd_type = WLAN_SER_CMD_MAX;
6775 
6776 	switch (sme_cmd->u.roamCmd.roamReason) {
6777 	case eCsrForcedDisassocSta:
6778 		cmd_type = WLAN_SER_CMD_FORCE_DISASSOC_STA;
6779 		break;
6780 	case eCsrForcedDeauthSta:
6781 		cmd_type = WLAN_SER_CMD_FORCE_DEAUTH_STA;
6782 		break;
6783 	default:
6784 		break;
6785 	}
6786 
6787 	return cmd_type;
6788 }
6789 
csr_get_cmd_type(tSmeCmd * sme_cmd)6790 enum wlan_serialization_cmd_type csr_get_cmd_type(tSmeCmd *sme_cmd)
6791 {
6792 	enum wlan_serialization_cmd_type cmd_type = WLAN_SER_CMD_MAX;
6793 
6794 	switch (sme_cmd->command) {
6795 	case eSmeCommandRoam:
6796 		cmd_type = csr_get_roam_cmd_type(sme_cmd);
6797 		break;
6798 	case eSmeCommandWmStatusChange:
6799 		cmd_type = WLAN_SER_CMD_WM_STATUS_CHANGE;
6800 		break;
6801 	case eSmeCommandAddTs:
6802 		cmd_type = WLAN_SER_CMD_ADDTS;
6803 		break;
6804 	case eSmeCommandDelTs:
6805 		cmd_type = WLAN_SER_CMD_DELTS;
6806 		break;
6807 	case e_sme_command_set_hw_mode:
6808 		cmd_type = WLAN_SER_CMD_SET_HW_MODE;
6809 		break;
6810 	case e_sme_command_nss_update:
6811 		cmd_type = WLAN_SER_CMD_NSS_UPDATE;
6812 		break;
6813 	case e_sme_command_set_dual_mac_config:
6814 		cmd_type = WLAN_SER_CMD_SET_DUAL_MAC_CONFIG;
6815 		break;
6816 	case e_sme_command_set_antenna_mode:
6817 		cmd_type = WLAN_SER_CMD_SET_ANTENNA_MODE;
6818 		break;
6819 	case e_sme_command_sap_ch_width_update:
6820 		cmd_type = WLAN_SER_CMD_SAP_BW_UPDATE;
6821 		break;
6822 	default:
6823 		break;
6824 	}
6825 
6826 	return cmd_type;
6827 }
6828 
csr_get_monotonous_number(struct mac_context * mac_ctx)6829 static uint32_t csr_get_monotonous_number(struct mac_context *mac_ctx)
6830 {
6831 	uint32_t cmd_id;
6832 	uint32_t mask = 0x00FFFFFF, prefix = 0x0D000000;
6833 
6834 	cmd_id = qdf_atomic_inc_return(&mac_ctx->global_cmd_id);
6835 	cmd_id = (cmd_id & mask);
6836 	cmd_id = (cmd_id | prefix);
6837 
6838 	return cmd_id;
6839 }
6840 
csr_fill_cmd_timeout(struct wlan_serialization_command * cmd)6841 static void csr_fill_cmd_timeout(struct wlan_serialization_command *cmd)
6842 {
6843 	switch (cmd->cmd_type) {
6844 	case WLAN_SER_CMD_WM_STATUS_CHANGE:
6845 		cmd->cmd_timeout_duration = SME_CMD_PEER_DISCONNECT_TIMEOUT;
6846 		break;
6847 	case WLAN_SER_CMD_VDEV_START_BSS:
6848 		cmd->cmd_timeout_duration = SME_CMD_VDEV_START_BSS_TIMEOUT;
6849 		break;
6850 	case WLAN_SER_CMD_VDEV_STOP_BSS:
6851 		cmd->cmd_timeout_duration = SME_CMD_STOP_BSS_CMD_TIMEOUT;
6852 		break;
6853 	case WLAN_SER_CMD_FORCE_DISASSOC_STA:
6854 	case WLAN_SER_CMD_FORCE_DEAUTH_STA:
6855 		cmd->cmd_timeout_duration = SME_CMD_PEER_DISCONNECT_TIMEOUT;
6856 		break;
6857 
6858 	case WLAN_SER_CMD_ADDTS:
6859 	case WLAN_SER_CMD_DELTS:
6860 		cmd->cmd_timeout_duration = SME_CMD_ADD_DEL_TS_TIMEOUT;
6861 		break;
6862 	case WLAN_SER_CMD_SET_HW_MODE:
6863 	case WLAN_SER_CMD_NSS_UPDATE:
6864 	case WLAN_SER_CMD_SET_DUAL_MAC_CONFIG:
6865 	case WLAN_SER_CMD_SET_ANTENNA_MODE:
6866 	case WLAN_SER_CMD_SAP_BW_UPDATE:
6867 		cmd->cmd_timeout_duration = SME_CMD_POLICY_MGR_CMD_TIMEOUT;
6868 		break;
6869 	default:
6870 		cmd->cmd_timeout_duration = SME_ACTIVE_LIST_CMD_TIMEOUT_VALUE;
6871 		break;
6872 	}
6873 }
6874 
csr_set_serialization_params_to_cmd(struct mac_context * mac_ctx,tSmeCmd * sme_cmd,struct wlan_serialization_command * cmd,uint8_t high_priority)6875 QDF_STATUS csr_set_serialization_params_to_cmd(struct mac_context *mac_ctx,
6876 		tSmeCmd *sme_cmd, struct wlan_serialization_command *cmd,
6877 		uint8_t high_priority)
6878 {
6879 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
6880 
6881 	if (!sme_cmd) {
6882 		sme_err("Invalid sme_cmd");
6883 		return status;
6884 	}
6885 	if (!cmd) {
6886 		sme_err("Invalid serialization_cmd");
6887 		return status;
6888 	}
6889 
6890 	/*
6891 	 * no need to fill command id for non-scan as they will be
6892 	 * zero always
6893 	 */
6894 	sme_cmd->cmd_id = csr_get_monotonous_number(mac_ctx);
6895 	cmd->cmd_id = sme_cmd->cmd_id;
6896 
6897 	cmd->cmd_type = csr_get_cmd_type(sme_cmd);
6898 	if (cmd->cmd_type == WLAN_SER_CMD_MAX) {
6899 		sme_err("serialization enum not found for sme_cmd type %d",
6900 			sme_cmd->command);
6901 		return status;
6902 	}
6903 	cmd->vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
6904 				sme_cmd->vdev_id, WLAN_LEGACY_SME_ID);
6905 	if (!cmd->vdev) {
6906 		sme_err("vdev is NULL for vdev_id:%d", sme_cmd->vdev_id);
6907 		return status;
6908 	}
6909 	cmd->umac_cmd = sme_cmd;
6910 
6911 	csr_fill_cmd_timeout(cmd);
6912 
6913 	cmd->source = WLAN_UMAC_COMP_MLME;
6914 	cmd->cmd_cb = sme_ser_cmd_callback;
6915 	cmd->is_high_priority = high_priority;
6916 	cmd->is_blocking = true;
6917 
6918 	return QDF_STATUS_SUCCESS;
6919 }
6920 
csr_queue_sme_command(struct mac_context * mac_ctx,tSmeCmd * sme_cmd,bool high_priority)6921 QDF_STATUS csr_queue_sme_command(struct mac_context *mac_ctx, tSmeCmd *sme_cmd,
6922 				 bool high_priority)
6923 {
6924 	struct wlan_serialization_command cmd;
6925 	struct wlan_objmgr_vdev *vdev = NULL;
6926 	enum wlan_serialization_status ser_cmd_status;
6927 	QDF_STATUS status;
6928 
6929 	if (!SME_IS_START(mac_ctx)) {
6930 		sme_err("Sme in stop state");
6931 		QDF_ASSERT(0);
6932 		goto error;
6933 	}
6934 
6935 	qdf_mem_zero(&cmd, sizeof(struct wlan_serialization_command));
6936 	status = csr_set_serialization_params_to_cmd(mac_ctx, sme_cmd,
6937 					&cmd, high_priority);
6938 	if (QDF_IS_STATUS_ERROR(status)) {
6939 		sme_err("failed to set ser params");
6940 		goto error;
6941 	}
6942 
6943 	vdev = cmd.vdev;
6944 	ser_cmd_status = wlan_serialization_request(&cmd);
6945 
6946 	switch (ser_cmd_status) {
6947 	case WLAN_SER_CMD_PENDING:
6948 	case WLAN_SER_CMD_ACTIVE:
6949 		/* Command posted to active/pending list */
6950 		status = QDF_STATUS_SUCCESS;
6951 		break;
6952 	default:
6953 		sme_err("Failed to queue command %d with status:%d",
6954 			  sme_cmd->command, ser_cmd_status);
6955 		status = QDF_STATUS_E_FAILURE;
6956 		goto error;
6957 	}
6958 
6959 	return status;
6960 
6961 error:
6962 	if (vdev)
6963 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
6964 
6965 	csr_release_command_buffer(mac_ctx, sme_cmd);
6966 
6967 	return QDF_STATUS_E_FAILURE;
6968 }
6969 
csr_roam_update_config(struct mac_context * mac_ctx,uint8_t session_id,uint16_t capab,uint32_t value)6970 QDF_STATUS csr_roam_update_config(struct mac_context *mac_ctx, uint8_t session_id,
6971 				  uint16_t capab, uint32_t value)
6972 {
6973 	struct update_config *msg;
6974 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6975 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, session_id);
6976 
6977 	sme_debug("update HT config requested");
6978 	if (!session) {
6979 		sme_err("Session does not exist for session id %d", session_id);
6980 		return QDF_STATUS_E_FAILURE;
6981 	}
6982 
6983 	msg = qdf_mem_malloc(sizeof(*msg));
6984 	if (!msg)
6985 		return QDF_STATUS_E_NOMEM;
6986 
6987 	msg->messageType = eWNI_SME_UPDATE_CONFIG;
6988 	msg->vdev_id = session_id;
6989 	msg->capab = capab;
6990 	msg->value = value;
6991 	msg->length = sizeof(*msg);
6992 	status = umac_send_mb_message_to_mac(msg);
6993 
6994 	return status;
6995 }
6996 
csr_send_channel_change_req(struct mac_context * mac,struct channel_change_req * req)6997 QDF_STATUS csr_send_channel_change_req(struct mac_context *mac,
6998 				      struct channel_change_req *req)
6999 {
7000 	struct scheduler_msg msg = {0};
7001 	struct channel_change_req *ch_change_req;
7002 	QDF_STATUS status;
7003 
7004 	ch_change_req = qdf_mem_malloc(sizeof(*ch_change_req));
7005 	if (!ch_change_req)
7006 		return QDF_STATUS_E_NOMEM;
7007 
7008 	qdf_mem_copy(ch_change_req, req, sizeof(*ch_change_req));
7009 	msg.type = eWNI_SME_CHANNEL_CHANGE_REQ;
7010 	msg.bodyptr = ch_change_req;
7011 	msg.reserved = 0;
7012 
7013 	status = scheduler_post_message(QDF_MODULE_ID_SME,
7014 					QDF_MODULE_ID_PE,
7015 					QDF_MODULE_ID_PE,
7016 					&msg);
7017 	if (QDF_IS_STATUS_ERROR(status)) {
7018 		sme_err("Failed to send channel change request with status : %d",
7019 			status);
7020 		qdf_mem_free(ch_change_req);
7021 	}
7022 
7023 	return status;
7024 }
7025 /*
7026  * Post Beacon Tx Start request to LIM
7027  * immediately after SAP CAC WAIT is
7028  * completed without any RADAR indications.
7029  */
csr_roam_start_beacon_req(struct mac_context * mac,struct qdf_mac_addr bssid,uint8_t dfsCacWaitStatus)7030 QDF_STATUS csr_roam_start_beacon_req(struct mac_context *mac,
7031 				     struct qdf_mac_addr bssid,
7032 				     uint8_t dfsCacWaitStatus)
7033 {
7034 	QDF_STATUS status = QDF_STATUS_SUCCESS;
7035 	tSirStartBeaconIndication *pMsg;
7036 
7037 	pMsg = qdf_mem_malloc(sizeof(tSirStartBeaconIndication));
7038 	if (!pMsg)
7039 		return QDF_STATUS_E_NOMEM;
7040 
7041 	pMsg->messageType = eWNI_SME_START_BEACON_REQ;
7042 	pMsg->messageLen = sizeof(tSirStartBeaconIndication);
7043 	pMsg->beaconStartStatus = dfsCacWaitStatus;
7044 	qdf_mem_copy(pMsg->bssid, bssid.bytes, QDF_MAC_ADDR_SIZE);
7045 
7046 	status = umac_send_mb_message_to_mac(pMsg);
7047 
7048 	return status;
7049 }
7050 
7051 /*
7052  * csr_roam_modify_add_ies -
7053  * This function sends msg to modify the additional IE buffers in PE
7054  *
7055  * @mac: mac global structure
7056  * @pModifyIE: pointer to tSirModifyIE structure
7057  * @updateType: Type of buffer
7058  *
7059  *
7060  * Return: QDF_STATUS -  Success or failure
7061  */
7062 QDF_STATUS
csr_roam_modify_add_ies(struct mac_context * mac,tSirModifyIE * pModifyIE,eUpdateIEsType updateType)7063 csr_roam_modify_add_ies(struct mac_context *mac,
7064 			 tSirModifyIE *pModifyIE, eUpdateIEsType updateType)
7065 {
7066 	tpSirModifyIEsInd pModifyAddIEInd = NULL;
7067 	uint8_t *pLocalBuffer = NULL;
7068 	QDF_STATUS status;
7069 
7070 	/* following buffer will be freed by consumer (PE) */
7071 	pLocalBuffer = qdf_mem_malloc(pModifyIE->ieBufferlength);
7072 	if (!pLocalBuffer)
7073 		return QDF_STATUS_E_NOMEM;
7074 
7075 	pModifyAddIEInd = qdf_mem_malloc(sizeof(tSirModifyIEsInd));
7076 	if (!pModifyAddIEInd) {
7077 		qdf_mem_free(pLocalBuffer);
7078 		return QDF_STATUS_E_NOMEM;
7079 	}
7080 
7081 	/*copy the IE buffer */
7082 	qdf_mem_copy(pLocalBuffer, pModifyIE->pIEBuffer,
7083 		     pModifyIE->ieBufferlength);
7084 	qdf_mem_zero(pModifyAddIEInd, sizeof(tSirModifyIEsInd));
7085 
7086 	pModifyAddIEInd->msgType = eWNI_SME_MODIFY_ADDITIONAL_IES;
7087 	pModifyAddIEInd->msgLen = sizeof(tSirModifyIEsInd);
7088 
7089 	qdf_copy_macaddr(&pModifyAddIEInd->modifyIE.bssid, &pModifyIE->bssid);
7090 
7091 	pModifyAddIEInd->modifyIE.vdev_id = pModifyIE->vdev_id;
7092 	pModifyAddIEInd->modifyIE.notify = pModifyIE->notify;
7093 	pModifyAddIEInd->modifyIE.ieID = pModifyIE->ieID;
7094 	pModifyAddIEInd->modifyIE.ieIDLen = pModifyIE->ieIDLen;
7095 	pModifyAddIEInd->modifyIE.pIEBuffer = pLocalBuffer;
7096 	pModifyAddIEInd->modifyIE.ieBufferlength = pModifyIE->ieBufferlength;
7097 	pModifyAddIEInd->modifyIE.oui_length = pModifyIE->oui_length;
7098 
7099 	pModifyAddIEInd->updateType = updateType;
7100 
7101 	status = umac_send_mb_message_to_mac(pModifyAddIEInd);
7102 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7103 		sme_err("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg status %d",
7104 			status);
7105 		qdf_mem_free(pLocalBuffer);
7106 	}
7107 	return status;
7108 }
7109 
7110 /*
7111  * csr_roam_update_add_ies -
7112  * This function sends msg to updates the additional IE buffers in PE
7113  *
7114  * @mac: mac global structure
7115  * @sessionId: SME session id
7116  * @bssid: BSSID
7117  * @additionIEBuffer: buffer containing addition IE from hostapd
7118  * @length: length of buffer
7119  * @updateType: Type of buffer
7120  * @append: append or replace completely
7121  *
7122  *
7123  * Return: QDF_STATUS -  Success or failure
7124  */
7125 QDF_STATUS
csr_roam_update_add_ies(struct mac_context * mac,tSirUpdateIE * pUpdateIE,eUpdateIEsType updateType)7126 csr_roam_update_add_ies(struct mac_context *mac,
7127 			 tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType)
7128 {
7129 	tpSirUpdateIEsInd pUpdateAddIEs = NULL;
7130 	uint8_t *pLocalBuffer = NULL;
7131 	QDF_STATUS status;
7132 
7133 	if (pUpdateIE->ieBufferlength != 0) {
7134 		/* Following buffer will be freed by consumer (PE) */
7135 		pLocalBuffer = qdf_mem_malloc(pUpdateIE->ieBufferlength);
7136 		if (!pLocalBuffer) {
7137 			return QDF_STATUS_E_NOMEM;
7138 		}
7139 		qdf_mem_copy(pLocalBuffer, pUpdateIE->pAdditionIEBuffer,
7140 			     pUpdateIE->ieBufferlength);
7141 	}
7142 
7143 	pUpdateAddIEs = qdf_mem_malloc(sizeof(tSirUpdateIEsInd));
7144 	if (!pUpdateAddIEs) {
7145 		qdf_mem_free(pLocalBuffer);
7146 		return QDF_STATUS_E_NOMEM;
7147 	}
7148 
7149 	pUpdateAddIEs->msgType = eWNI_SME_UPDATE_ADDITIONAL_IES;
7150 	pUpdateAddIEs->msgLen = sizeof(tSirUpdateIEsInd);
7151 
7152 	qdf_copy_macaddr(&pUpdateAddIEs->updateIE.bssid, &pUpdateIE->bssid);
7153 
7154 	pUpdateAddIEs->updateIE.vdev_id = pUpdateIE->vdev_id;
7155 	pUpdateAddIEs->updateIE.append = pUpdateIE->append;
7156 	pUpdateAddIEs->updateIE.notify = pUpdateIE->notify;
7157 	pUpdateAddIEs->updateIE.ieBufferlength = pUpdateIE->ieBufferlength;
7158 	pUpdateAddIEs->updateIE.pAdditionIEBuffer = pLocalBuffer;
7159 
7160 	pUpdateAddIEs->updateType = updateType;
7161 
7162 	status = umac_send_mb_message_to_mac(pUpdateAddIEs);
7163 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7164 		sme_err("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg status %d",
7165 			status);
7166 		qdf_mem_free(pLocalBuffer);
7167 	}
7168 	return status;
7169 }
7170 
7171 /**
7172  * csr_send_ext_change_freq()- function to post send ECSA
7173  * action frame to lim.
7174  * @mac_ctx: pointer to global mac structure
7175  * @ch_freq: new channel freq to switch
7176  * @session_id: senssion it should be sent on.
7177  *
7178  * This function is called to post ECSA frame to lim.
7179  *
7180  * Return: success if msg posted to LIM else return failure
7181  */
csr_send_ext_change_freq(struct mac_context * mac_ctx,qdf_freq_t ch_freq,uint8_t session_id)7182 QDF_STATUS csr_send_ext_change_freq(struct mac_context *mac_ctx,
7183 				    qdf_freq_t ch_freq, uint8_t session_id)
7184 {
7185 	QDF_STATUS status = QDF_STATUS_SUCCESS;
7186 	struct sir_sme_ext_cng_chan_req *msg;
7187 
7188 	msg = qdf_mem_malloc(sizeof(*msg));
7189 	if (!msg)
7190 		return QDF_STATUS_E_NOMEM;
7191 
7192 	msg->message_type = eWNI_SME_EXT_CHANGE_CHANNEL;
7193 	msg->length = sizeof(*msg);
7194 	msg->new_ch_freq = ch_freq;
7195 	msg->vdev_id = session_id;
7196 	status = umac_send_mb_message_to_mac(msg);
7197 	return status;
7198 }
7199 
csr_csa_restart(struct mac_context * mac_ctx,uint8_t vdev_id)7200 QDF_STATUS csr_csa_restart(struct mac_context *mac_ctx, uint8_t vdev_id)
7201 {
7202 	QDF_STATUS status;
7203 	struct wlan_objmgr_vdev *vdev;
7204 	struct scheduler_msg message = {0};
7205 
7206 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
7207 						    WLAN_LEGACY_MAC_ID);
7208 	if (!vdev) {
7209 		sme_err("VDEV not found for vdev id: %d", vdev_id);
7210 		return QDF_STATUS_E_FAILURE;
7211 	}
7212 
7213 	if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_AP_CSA_START, NULL);
7214 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
7215 
7216 	/* Serialize the req through MC thread */
7217 	message.bodyval = vdev_id;
7218 	message.type    = eWNI_SME_CSA_RESTART_REQ;
7219 	status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_PE,
7220 					QDF_MODULE_ID_PE, &message);
7221 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7222 		sme_err("scheduler_post_msg failed!(err=%d)", status);
7223 		status = QDF_STATUS_E_FAILURE;
7224 	}
7225 
7226 	return status;
7227 }
7228 
csr_roam_send_chan_sw_ie_request(struct mac_context * mac_ctx,struct qdf_mac_addr bssid,uint32_t target_chan_freq,uint8_t csa_ie_reqd,struct ch_params * ch_params,uint32_t new_cac_ms)7229 QDF_STATUS csr_roam_send_chan_sw_ie_request(struct mac_context *mac_ctx,
7230 					    struct qdf_mac_addr bssid,
7231 					    uint32_t target_chan_freq,
7232 					    uint8_t csa_ie_reqd,
7233 					    struct ch_params *ch_params,
7234 					    uint32_t new_cac_ms)
7235 {
7236 	QDF_STATUS status = QDF_STATUS_SUCCESS;
7237 	tSirDfsCsaIeRequest *msg;
7238 
7239 	msg = qdf_mem_malloc(sizeof(tSirDfsCsaIeRequest));
7240 	if (!msg)
7241 		return QDF_STATUS_E_NOMEM;
7242 
7243 	msg->msgType = eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ;
7244 	msg->msgLen = sizeof(tSirDfsCsaIeRequest);
7245 
7246 	msg->target_chan_freq = target_chan_freq;
7247 	msg->csaIeRequired = csa_ie_reqd;
7248 	msg->ch_switch_beacon_cnt =
7249 		 mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt;
7250 	if (mac_ctx->sap.one_time_csa_count) {
7251 		msg->ch_switch_beacon_cnt = mac_ctx->sap.one_time_csa_count;
7252 		mac_ctx->sap.one_time_csa_count = 0;
7253 	}
7254 	msg->ch_switch_mode = mac_ctx->sap.SapDfsInfo.sap_ch_switch_mode;
7255 	msg->dfs_ch_switch_disable =
7256 		mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch;
7257 	msg->new_chan_cac_ms = new_cac_ms;
7258 	qdf_mem_copy(msg->bssid, bssid.bytes, QDF_MAC_ADDR_SIZE);
7259 	qdf_mem_copy(&msg->ch_params, ch_params, sizeof(struct ch_params));
7260 
7261 	status = umac_send_mb_message_to_mac(msg);
7262 
7263 	return status;
7264 }
7265 
csr_sta_continue_csa(struct mac_context * mac_ctx,uint8_t vdev_id)7266 QDF_STATUS csr_sta_continue_csa(struct mac_context *mac_ctx, uint8_t vdev_id)
7267 {
7268 	QDF_STATUS status;
7269 	struct scheduler_msg message = {0};
7270 
7271 	/* Serialize the req through MC thread */
7272 	message.bodyval = vdev_id;
7273 	message.type    = eWNI_SME_STA_CSA_CONTINUE_REQ;
7274 	status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_PE,
7275 					QDF_MODULE_ID_PE, &message);
7276 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7277 		sme_err("eWNI_SME_STA_CSA_CONTINUE_REQ failed!(err=%d)",
7278 			status);
7279 		status = QDF_STATUS_E_FAILURE;
7280 	}
7281 
7282 	return status;
7283 }
7284 
7285 /**
7286  * csr_update_op_class_array() - update op class for each band
7287  * @mac_ctx:          mac global context
7288  * @op_classes:       out param, operating class array to update
7289  * @channel_info:     channel info
7290  * @ch_name:          channel band name to display in debug messages
7291  * @i:                out param, stores number of operating classes
7292  *
7293  * Return: void
7294  */
7295 static void
csr_update_op_class_array(struct mac_context * mac_ctx,uint8_t * op_classes,struct csr_channel * channel_info,char * ch_name,uint8_t * i)7296 csr_update_op_class_array(struct mac_context *mac_ctx,
7297 			  uint8_t *op_classes,
7298 			  struct csr_channel *channel_info,
7299 			  char *ch_name,
7300 			  uint8_t *i)
7301 {
7302 	uint8_t j = 0, idx = 0, class = 0;
7303 	bool found = false;
7304 	uint8_t num_channels = channel_info->numChannels;
7305 	uint8_t ch_num;
7306 
7307 	sme_debug("Num %s channels,  %d", ch_name, num_channels);
7308 
7309 	for (idx = 0; idx < num_channels &&
7310 		*i < (REG_MAX_SUPP_OPER_CLASSES - 1); idx++) {
7311 		wlan_reg_freq_to_chan_op_class(
7312 			mac_ctx->pdev, channel_info->channel_freq_list[idx],
7313 			true, BIT(BEHAV_NONE), &class, &ch_num);
7314 
7315 		found = false;
7316 		for (j = 0; j < REG_MAX_SUPP_OPER_CLASSES - 1; j++) {
7317 			if (op_classes[j] == class) {
7318 				found = true;
7319 				break;
7320 			}
7321 		}
7322 
7323 		if (!found) {
7324 			op_classes[*i] = class;
7325 			*i = *i + 1;
7326 		}
7327 	}
7328 }
7329 
7330 /**
7331  * csr_init_operating_classes() - update op class for all bands
7332  * @mac: pointer to mac context.
7333  *
7334  * Return: void
7335  */
csr_init_operating_classes(struct mac_context * mac)7336 static void csr_init_operating_classes(struct mac_context *mac)
7337 {
7338 	uint8_t i = 0;
7339 	uint8_t j = 0;
7340 	uint8_t swap = 0;
7341 	uint8_t numClasses = 0;
7342 	uint8_t opClasses[REG_MAX_SUPP_OPER_CLASSES] = {0,};
7343 	uint8_t reg_cc[REG_ALPHA2_LEN + 1];
7344 
7345 	wlan_reg_read_current_country(mac->psoc, reg_cc);
7346 	sme_debug("Current Country = %s", reg_cc);
7347 
7348 	csr_update_op_class_array(mac, opClasses,
7349 				  &mac->scan.base_channels, "20MHz", &i);
7350 	numClasses = i;
7351 
7352 	/* As per spec the operating classes should be in ascending order.
7353 	 * Bubble sort is fine since we don't have many classes
7354 	 */
7355 	for (i = 0; i < (numClasses - 1); i++) {
7356 		for (j = 0; j < (numClasses - i - 1); j++) {
7357 			/* For decreasing order use < */
7358 			if (opClasses[j] > opClasses[j + 1]) {
7359 				swap = opClasses[j];
7360 				opClasses[j] = opClasses[j + 1];
7361 				opClasses[j + 1] = swap;
7362 			}
7363 		}
7364 	}
7365 
7366 	/* Set the ordered list of op classes in regdomain
7367 	 * for use by other modules
7368 	 */
7369 	wlan_reg_dmn_set_curr_opclasses(numClasses, &opClasses[0]);
7370 }
7371 
7372 /**
7373  * csr_process_set_hw_mode() - Set HW mode command to PE
7374  * @mac: Globacl MAC pointer
7375  * @command: Command received from SME
7376  *
7377  * Posts the set HW mode command to PE. This message passing
7378  * through PE is required for PE's internal management
7379  *
7380  * Return: None
7381  */
csr_process_set_hw_mode(struct mac_context * mac,tSmeCmd * command)7382 void csr_process_set_hw_mode(struct mac_context *mac, tSmeCmd *command)
7383 {
7384 	uint32_t len;
7385 	struct s_sir_set_hw_mode *cmd = NULL;
7386 	QDF_STATUS status;
7387 	struct scheduler_msg msg = {0};
7388 	struct sir_set_hw_mode_resp *param;
7389 	enum policy_mgr_hw_mode_change hw_mode;
7390 	enum policy_mgr_conc_next_action action;
7391 	enum set_hw_mode_status hw_mode_change_status =
7392 						SET_HW_MODE_STATUS_ECANCELED;
7393 
7394 	/* Setting HW mode is for the entire system.
7395 	 * So, no need to check session
7396 	 */
7397 
7398 	if (!command) {
7399 		sme_err("Set HW mode param is NULL");
7400 		goto fail;
7401 	}
7402 
7403 	len = sizeof(*cmd);
7404 	cmd = qdf_mem_malloc(len);
7405 	if (!cmd)
7406 		/* Probably the fail response will also fail during malloc.
7407 		 * Still proceeding to send response!
7408 		 */
7409 		goto fail;
7410 
7411 	action = command->u.set_hw_mode_cmd.action;
7412 
7413 	status = policy_mgr_validate_dbs_switch(mac->psoc, action);
7414 
7415 	if (QDF_IS_STATUS_ERROR(status)) {
7416 		sme_debug("Hw mode change not sent to FW status = %d", status);
7417 		if (status == QDF_STATUS_E_ALREADY)
7418 			hw_mode_change_status = SET_HW_MODE_STATUS_ALREADY;
7419 		goto fail;
7420 	}
7421 
7422 	hw_mode = policy_mgr_get_hw_mode_change_from_hw_mode_index(
7423 			mac->psoc, command->u.set_hw_mode_cmd.hw_mode_index);
7424 
7425 	if (POLICY_MGR_HW_MODE_NOT_IN_PROGRESS == hw_mode) {
7426 		sme_err("hw_mode %d, failing", hw_mode);
7427 		goto fail;
7428 	}
7429 
7430 	policy_mgr_set_hw_mode_change_in_progress(mac->psoc, hw_mode);
7431 	policy_mgr_reset_connection_update(mac->psoc);
7432 
7433 	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
7434 	     command->u.set_hw_mode_cmd.reason) &&
7435 	    (true == mac->sme.get_connection_info_cb(NULL, NULL))) {
7436 		sme_err("Set HW mode refused: conn in progress");
7437 		policy_mgr_restart_opportunistic_timer(mac->psoc, false);
7438 		goto reset_state;
7439 	}
7440 
7441 	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
7442 	     command->u.set_hw_mode_cmd.reason) &&
7443 	    (!command->u.set_hw_mode_cmd.hw_mode_index &&
7444 	     !policy_mgr_need_opportunistic_upgrade(mac->psoc, NULL))) {
7445 		sme_err("Set HW mode to SMM not needed anymore");
7446 		goto reset_state;
7447 	}
7448 
7449 	cmd->messageType = eWNI_SME_SET_HW_MODE_REQ;
7450 	cmd->length = len;
7451 	cmd->set_hw.hw_mode_index = command->u.set_hw_mode_cmd.hw_mode_index;
7452 	cmd->set_hw.reason = command->u.set_hw_mode_cmd.reason;
7453 	/*
7454 	 * Below callback and context info are not needed for PE as of now.
7455 	 * Storing the passed value in the same s_sir_set_hw_mode format.
7456 	 */
7457 	cmd->set_hw.set_hw_mode_cb = command->u.set_hw_mode_cmd.set_hw_mode_cb;
7458 
7459 	sme_debug(
7460 		"Posting set hw mode req to PE session:%d reason:%d",
7461 		command->u.set_hw_mode_cmd.session_id,
7462 		command->u.set_hw_mode_cmd.reason);
7463 
7464 	status = umac_send_mb_message_to_mac(cmd);
7465 	if (QDF_STATUS_SUCCESS != status) {
7466 		sme_err("Posting to PE failed");
7467 		cmd = NULL;
7468 		goto reset_state;
7469 	}
7470 	return;
7471 
7472 reset_state:
7473 	policy_mgr_set_hw_mode_change_in_progress(mac->psoc,
7474 			POLICY_MGR_HW_MODE_NOT_IN_PROGRESS);
7475 fail:
7476 	if (cmd)
7477 		qdf_mem_free(cmd);
7478 	param = qdf_mem_malloc(sizeof(*param));
7479 	if (!param)
7480 		return;
7481 
7482 	sme_debug("Sending set HW fail response to SME");
7483 	param->status = hw_mode_change_status;
7484 	param->cfgd_hw_mode_index = 0;
7485 	param->num_vdev_mac_entries = 0;
7486 	msg.type = eWNI_SME_SET_HW_MODE_RESP;
7487 	msg.bodyptr = param;
7488 	msg.bodyval = 0;
7489 	sys_process_mmh_msg(mac, &msg);
7490 }
7491 
7492 /**
7493  * csr_process_set_dual_mac_config() - Set HW mode command to PE
7494  * @mac: Global MAC pointer
7495  * @command: Command received from SME
7496  *
7497  * Posts the set dual mac config command to PE.
7498  *
7499  * Return: None
7500  */
csr_process_set_dual_mac_config(struct mac_context * mac,tSmeCmd * command)7501 void csr_process_set_dual_mac_config(struct mac_context *mac, tSmeCmd *command)
7502 {
7503 	uint32_t len;
7504 	struct sir_set_dual_mac_cfg *cmd;
7505 	QDF_STATUS status;
7506 	struct scheduler_msg msg = {0};
7507 	struct sir_dual_mac_config_resp *param;
7508 
7509 	/* Setting MAC configuration is for the entire system.
7510 	 * So, no need to check session
7511 	 */
7512 
7513 	if (!command) {
7514 		sme_err("Set HW mode param is NULL");
7515 		goto fail;
7516 	}
7517 
7518 	len = sizeof(*cmd);
7519 	cmd = qdf_mem_malloc(len);
7520 	if (!cmd)
7521 		/* Probably the fail response will also fail during malloc.
7522 		 * Still proceeding to send response!
7523 		 */
7524 		goto fail;
7525 
7526 	cmd->message_type = eWNI_SME_SET_DUAL_MAC_CFG_REQ;
7527 	cmd->length = len;
7528 	cmd->set_dual_mac.scan_config = command->u.set_dual_mac_cmd.scan_config;
7529 	cmd->set_dual_mac.fw_mode_config =
7530 		command->u.set_dual_mac_cmd.fw_mode_config;
7531 	/*
7532 	 * Below callback and context info are not needed for PE as of now.
7533 	 * Storing the passed value in the same sir_set_dual_mac_cfg format.
7534 	 */
7535 	cmd->set_dual_mac.set_dual_mac_cb =
7536 		command->u.set_dual_mac_cmd.set_dual_mac_cb;
7537 
7538 	sme_debug("Posting eWNI_SME_SET_DUAL_MAC_CFG_REQ to PE: %x %x",
7539 		  cmd->set_dual_mac.scan_config,
7540 		  cmd->set_dual_mac.fw_mode_config);
7541 
7542 	status = umac_send_mb_message_to_mac(cmd);
7543 	if (QDF_IS_STATUS_ERROR(status)) {
7544 		sme_err("Posting to PE failed");
7545 		goto fail;
7546 	}
7547 	return;
7548 fail:
7549 	param = qdf_mem_malloc(sizeof(*param));
7550 	if (!param)
7551 		return;
7552 
7553 	sme_err("Sending set dual mac fail response to SME");
7554 	param->status = SET_HW_MODE_STATUS_ECANCELED;
7555 	msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP;
7556 	msg.bodyptr = param;
7557 	msg.bodyval = 0;
7558 	sys_process_mmh_msg(mac, &msg);
7559 }
7560 
7561 /**
7562  * csr_process_set_antenna_mode() - Set antenna mode command to
7563  * PE
7564  * @mac: Global MAC pointer
7565  * @command: Command received from SME
7566  *
7567  * Posts the set dual mac config command to PE.
7568  *
7569  * Return: None
7570  */
csr_process_set_antenna_mode(struct mac_context * mac,tSmeCmd * command)7571 void csr_process_set_antenna_mode(struct mac_context *mac, tSmeCmd *command)
7572 {
7573 	uint32_t len;
7574 	struct sir_set_antenna_mode *cmd;
7575 	QDF_STATUS status;
7576 	struct scheduler_msg msg = {0};
7577 	struct sir_antenna_mode_resp *param;
7578 
7579 	/* Setting MAC configuration is for the entire system.
7580 	 * So, no need to check session
7581 	 */
7582 
7583 	if (!command) {
7584 		sme_err("Set antenna mode param is NULL");
7585 		goto fail;
7586 	}
7587 
7588 	len = sizeof(*cmd);
7589 	cmd = qdf_mem_malloc(len);
7590 	if (!cmd)
7591 		goto fail;
7592 
7593 	cmd->message_type = eWNI_SME_SET_ANTENNA_MODE_REQ;
7594 	cmd->length = len;
7595 	cmd->set_antenna_mode = command->u.set_antenna_mode_cmd;
7596 
7597 	sme_debug(
7598 		"Posting eWNI_SME_SET_ANTENNA_MODE_REQ to PE: %d %d",
7599 		cmd->set_antenna_mode.num_rx_chains,
7600 		cmd->set_antenna_mode.num_tx_chains);
7601 
7602 	status = umac_send_mb_message_to_mac(cmd);
7603 	if (QDF_STATUS_SUCCESS != status) {
7604 		sme_err("Posting to PE failed");
7605 		/*
7606 		 * umac_send_mb_message_to_mac would've released the mem
7607 		 * allocated by cmd.
7608 		 */
7609 		goto fail;
7610 	}
7611 
7612 	return;
7613 fail:
7614 	param = qdf_mem_malloc(sizeof(*param));
7615 	if (!param)
7616 		return;
7617 
7618 	sme_err("Sending set dual mac fail response to SME");
7619 	param->status = SET_ANTENNA_MODE_STATUS_ECANCELED;
7620 	msg.type = eWNI_SME_SET_ANTENNA_MODE_RESP;
7621 	msg.bodyptr = param;
7622 	msg.bodyval = 0;
7623 	sys_process_mmh_msg(mac, &msg);
7624 }
7625 
7626 /**
7627  * csr_process_nss_update_req() - Update nss command to PE
7628  * @mac: Globacl MAC pointer
7629  * @command: Command received from SME
7630  *
7631  * Posts the nss update command to PE. This message passing
7632  * through PE is required for PE's internal management
7633  *
7634  * Return: None
7635  */
csr_process_nss_update_req(struct mac_context * mac,tSmeCmd * command)7636 void csr_process_nss_update_req(struct mac_context *mac, tSmeCmd *command)
7637 {
7638 	uint32_t len;
7639 	struct sir_nss_update_request *msg;
7640 	QDF_STATUS status;
7641 	struct scheduler_msg msg_return = {0};
7642 	struct sir_bcn_update_rsp *param;
7643 	struct csr_roam_session *session;
7644 
7645 
7646 	if (!CSR_IS_SESSION_VALID(mac, command->vdev_id)) {
7647 		sme_err("Invalid session id %d", command->vdev_id);
7648 		goto fail;
7649 	}
7650 	session = CSR_GET_SESSION(mac, command->vdev_id);
7651 
7652 	len = sizeof(*msg);
7653 	msg = qdf_mem_malloc(len);
7654 	if (!msg)
7655 		/* Probably the fail response is also fail during malloc.
7656 		 * Still proceeding to send response!
7657 		 */
7658 		goto fail;
7659 
7660 	msg->msgType = eWNI_SME_NSS_UPDATE_REQ;
7661 	msg->msgLen = sizeof(*msg);
7662 
7663 	msg->new_nss = command->u.nss_update_cmd.new_nss;
7664 	msg->ch_width = command->u.nss_update_cmd.ch_width;
7665 	msg->vdev_id = command->u.nss_update_cmd.session_id;
7666 
7667 	sme_debug("Posting eWNI_SME_NSS_UPDATE_REQ to PE");
7668 
7669 	status = umac_send_mb_message_to_mac(msg);
7670 	if (QDF_IS_STATUS_SUCCESS(status))
7671 		return;
7672 
7673 	sme_err("Posting to PE failed");
7674 fail:
7675 	param = qdf_mem_malloc(sizeof(*param));
7676 	if (!param)
7677 		return;
7678 
7679 	sme_err("Sending nss update fail response to SME");
7680 	param->status = QDF_STATUS_E_FAILURE;
7681 	param->vdev_id = command->u.nss_update_cmd.session_id;
7682 	param->reason = REASON_NSS_UPDATE;
7683 	msg_return.type = eWNI_SME_NSS_UPDATE_RSP;
7684 	msg_return.bodyptr = param;
7685 	msg_return.bodyval = 0;
7686 	sys_process_mmh_msg(mac, &msg_return);
7687 }
7688 
7689 /**
7690  * csr_process_sap_ch_width_update() - Update ch_width command to PE
7691  * @mac: Globacl MAC pointer
7692  * @command: Command received from SME
7693  *
7694  * Posts the ch_width update command to PE. This message passing
7695  * through PE is required for PE's internal management
7696  *
7697  * Return: None
7698  */
csr_process_sap_ch_width_update(struct mac_context * mac,tSmeCmd * command)7699 void csr_process_sap_ch_width_update(struct mac_context *mac, tSmeCmd *command)
7700 {
7701 	uint32_t len;
7702 	struct sir_sap_ch_width_update *msg;
7703 	QDF_STATUS status;
7704 	struct scheduler_msg msg_return = {0};
7705 	struct sir_bcn_update_rsp *param;
7706 	enum policy_mgr_conn_update_reason reason =
7707 				command->u.bw_update_cmd.reason;
7708 
7709 	if (!CSR_IS_SESSION_VALID(mac, command->vdev_id)) {
7710 		sme_err("Invalid session id %d", command->vdev_id);
7711 		goto fail;
7712 	}
7713 
7714 	if ((reason == POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC) &&
7715 	    (mac->sme.get_connection_info_cb(NULL, NULL))) {
7716 		policy_mgr_restart_opportunistic_timer(mac->psoc, false);
7717 		sme_info("Vdev %d : Avoid set BW as conn in progress",
7718 			 command->vdev_id);
7719 		goto fail;
7720 	}
7721 
7722 	if ((reason == POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC) &&
7723 	    (!policy_mgr_need_opportunistic_upgrade(mac->psoc, &reason))) {
7724 		sme_info("Vdev %d: BW update not needed anymore",
7725 			 command->vdev_id);
7726 		goto fail;
7727 	}
7728 
7729 	len = sizeof(*msg);
7730 	msg = qdf_mem_malloc(len);
7731 	if (!msg)
7732 		/* Probably the fail response is also fail during malloc.
7733 		 * Still proceeding to send response!
7734 		 */
7735 		goto fail;
7736 
7737 	msg->msgType = eWNI_SME_SAP_CH_WIDTH_UPDATE_REQ;
7738 	msg->msgLen = sizeof(*msg);
7739 
7740 	msg->ch_width = command->u.bw_update_cmd.ch_width;
7741 	msg->vdev_id = command->u.bw_update_cmd.vdev_id;
7742 
7743 	sme_debug("Posting eWNI_SME_SAP_CH_WIDTH_UPDATE_REQ to PE");
7744 
7745 	status = umac_send_mb_message_to_mac(msg);
7746 	if (QDF_IS_STATUS_SUCCESS(status))
7747 		return;
7748 
7749 	sme_err("Posting to PE failed");
7750 fail:
7751 	param = qdf_mem_malloc(sizeof(*param));
7752 	if (param) {
7753 		param->status = QDF_STATUS_E_FAILURE;
7754 		param->vdev_id = command->u.bw_update_cmd.vdev_id;
7755 		param->reason = REASON_CH_WIDTH_UPDATE;
7756 	}
7757 	msg_return.type = eWNI_SME_SAP_CH_WIDTH_UPDATE_RSP;
7758 	msg_return.bodyptr = param;
7759 	msg_return.bodyval = 0;
7760 	sys_process_mmh_msg(mac, &msg_return);
7761 }
7762 
7763 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
7764 #ifdef WLAN_FEATURE_SAE
7765 /**
7766  * csr_process_roam_auth_sae_callback() - API to trigger the
7767  * WPA3 pre-auth event for candidate AP received from firmware.
7768  * @mac_ctx: Global mac context pointer
7769  * @vdev_id: vdev id
7770  * @roam_bssid: Candidate BSSID to roam
7771  * @akm: Candidate AKM
7772  *
7773  * This function calls the hdd_sme_roam_callback with reason
7774  * eCSR_ROAM_SAE_COMPUTE to trigger SAE auth to supplicant.
7775  */
7776 static QDF_STATUS
csr_process_roam_auth_sae_callback(struct mac_context * mac_ctx,uint8_t vdev_id,struct qdf_mac_addr roam_bssid,uint32_t akm)7777 csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
7778 				   uint8_t vdev_id,
7779 				   struct qdf_mac_addr roam_bssid,
7780 				   uint32_t akm)
7781 {
7782 	struct csr_roam_info *roam_info;
7783 	struct sir_sae_info sae_info;
7784 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id);
7785 
7786 	if (!session) {
7787 		sme_err("WPA3 Preauth event with invalid session id:%d",
7788 			vdev_id);
7789 		return QDF_STATUS_E_FAILURE;
7790 	}
7791 
7792 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
7793 	if (!roam_info)
7794 		return QDF_STATUS_E_FAILURE;
7795 
7796 	sae_info.msg_len = sizeof(sae_info);
7797 	sae_info.vdev_id = vdev_id;
7798 	sae_info.akm = akm;
7799 	wlan_cm_get_roam_offload_ssid(mac_ctx->psoc, vdev_id,
7800 				      sae_info.ssid.ssId,
7801 				      &sae_info.ssid.length);
7802 	qdf_mem_copy(sae_info.peer_mac_addr.bytes,
7803 		     roam_bssid.bytes, QDF_MAC_ADDR_SIZE);
7804 
7805 	roam_info->sae_info = &sae_info;
7806 
7807 	csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
7808 			       eCSR_ROAM_SAE_COMPUTE, eCSR_ROAM_RESULT_NONE);
7809 
7810 	qdf_mem_free(roam_info);
7811 
7812 	return QDF_STATUS_SUCCESS;
7813 }
7814 #else
7815 static inline QDF_STATUS
csr_process_roam_auth_sae_callback(struct mac_context * mac_ctx,uint8_t vdev_id,struct qdf_mac_addr roam_bssid,uint32_t akm)7816 csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
7817 				   uint8_t vdev_id,
7818 				   struct qdf_mac_addr roam_bssid,
7819 				   uint32_t akm)
7820 {
7821 	return QDF_STATUS_E_NOSUPPORT;
7822 }
7823 #endif
7824 
7825 QDF_STATUS
csr_roam_auth_offload_callback(struct mac_context * mac_ctx,uint8_t vdev_id,struct qdf_mac_addr bssid,uint32_t akm)7826 csr_roam_auth_offload_callback(struct mac_context *mac_ctx, uint8_t vdev_id,
7827 			       struct qdf_mac_addr bssid, uint32_t akm)
7828 {
7829 	QDF_STATUS status;
7830 
7831 	status = sme_acquire_global_lock(&mac_ctx->sme);
7832 	if (!QDF_IS_STATUS_SUCCESS(status))
7833 		return status;
7834 
7835 	status = csr_process_roam_auth_sae_callback(mac_ctx, vdev_id,
7836 						    bssid, akm);
7837 
7838 	sme_release_global_lock(&mac_ctx->sme);
7839 
7840 	return status;
7841 
7842 }
7843 #endif
7844 
csr_update_owe_info(struct mac_context * mac,struct assoc_ind * assoc_ind)7845 QDF_STATUS csr_update_owe_info(struct mac_context *mac,
7846 			       struct assoc_ind *assoc_ind)
7847 {
7848 	uint32_t session_id = WLAN_UMAC_VDEV_ID_MAX;
7849 	QDF_STATUS status;
7850 
7851 	status = csr_roam_get_session_id_from_bssid(mac,
7852 					(struct qdf_mac_addr *)assoc_ind->bssId,
7853 					&session_id);
7854 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7855 		sme_debug("Couldn't find session_id for given BSSID");
7856 		return QDF_STATUS_E_FAILURE;
7857 	}
7858 
7859 	/* Send Association completion message to PE */
7860 	if (assoc_ind->owe_status)
7861 		status = QDF_STATUS_E_INVAL;
7862 	status = csr_send_assoc_cnf_msg(mac, assoc_ind, status,
7863 					assoc_ind->owe_status);
7864 	/*
7865 	 * send a message to CSR itself just to avoid the EAPOL frames
7866 	 * going OTA before association response
7867 	 */
7868 	if (assoc_ind->owe_status == 0)
7869 		status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac,
7870 								   assoc_ind,
7871 								   status,
7872 								   session_id);
7873 
7874 	return status;
7875 }
7876 
csr_update_ft_info(struct mac_context * mac,struct assoc_ind * assoc_ind)7877 QDF_STATUS csr_update_ft_info(struct mac_context *mac,
7878 			      struct assoc_ind *assoc_ind)
7879 {
7880 	QDF_STATUS status;
7881 
7882 	/* Send Association completion message to PE */
7883 	status = assoc_ind->ft_status ? QDF_STATUS_E_INVAL : QDF_STATUS_SUCCESS;
7884 	assoc_ind->need_assoc_rsp_tx_cb = true;
7885 	status = csr_send_assoc_cnf_msg(mac, assoc_ind, status,
7886 					assoc_ind->ft_status);
7887 	return status;
7888 }
7889 
7890 /**
7891  * csr_set_sap_ser_params() - API to fill serialization parameters for
7892  * SAP requests
7893  * @cmd : Serialization command
7894  * @cmd_type: Type of serialization command
7895  *
7896  * Return: Void
7897  */
csr_set_sap_ser_params(struct wlan_serialization_command * cmd,enum wlan_serialization_cmd_type cmd_type)7898 static void csr_set_sap_ser_params(struct wlan_serialization_command *cmd,
7899 				   enum wlan_serialization_cmd_type cmd_type)
7900 {
7901 	cmd->cmd_type = cmd_type;
7902 	cmd->source = WLAN_UMAC_COMP_MLME;
7903 	cmd->cmd_cb = sme_sap_ser_callback;
7904 	cmd->is_high_priority =  false;
7905 	cmd->is_blocking = true;
7906 	return;
7907 }
7908 
csr_bss_start(struct mac_context * mac,uint32_t vdev_id,struct start_bss_config * bss_config)7909 QDF_STATUS csr_bss_start(struct mac_context *mac, uint32_t vdev_id,
7910 			 struct start_bss_config *bss_config)
7911 {
7912 	struct wlan_serialization_command cmd = {0};
7913 	struct wlan_objmgr_vdev *vdev;
7914 	struct start_bss_config *start_bss_cfg = NULL;
7915 	enum QDF_OPMODE persona;
7916 	enum wlan_serialization_status status;
7917 	struct csr_roam_session *session;
7918 	struct validate_bss_data candidate;
7919 
7920 	session = CSR_GET_SESSION(mac, vdev_id);
7921 	if (!session)
7922 		return QDF_STATUS_E_FAILURE;
7923 
7924 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac->pdev, vdev_id,
7925 						    WLAN_LEGACY_MAC_ID);
7926 	if (!vdev) {
7927 		sme_err("VDEV not found for vdev id : %d", vdev_id);
7928 		return QDF_STATUS_E_FAILURE;
7929 	}
7930 
7931 	persona = wlan_vdev_mlme_get_opmode(vdev);
7932 	if (persona != QDF_SAP_MODE && persona != QDF_NDI_MODE &&
7933 	    persona != QDF_P2P_GO_MODE) {
7934 		sme_err("Start BSS request for invalid mode %d", persona);
7935 		goto error;
7936 	}
7937 
7938 	start_bss_cfg = qdf_mem_malloc(sizeof(struct start_bss_config));
7939 	if (!start_bss_cfg) {
7940 		sme_err("SAP BSS config allocation failed");
7941 		goto error;
7942 	}
7943 
7944 	qdf_mem_copy(start_bss_cfg, bss_config,
7945 		     sizeof(struct start_bss_config));
7946 	start_bss_cfg->cmd_id = csr_get_monotonous_number(mac);
7947 
7948 	session->cb_mode = start_bss_cfg->sec_ch_offset;
7949 	session->bcn_int = bss_config->beaconInterval;
7950 	candidate.beacon_interval = session->bcn_int;
7951 	candidate.chan_freq = bss_config->oper_ch_freq;
7952 	if_mgr_is_beacon_interval_valid(mac->pdev, vdev_id,
7953 					&candidate);
7954 	bss_config->beaconInterval = candidate.beacon_interval;
7955 	session->bcn_int = candidate.beacon_interval;
7956 
7957 	cmd.cmd_id = start_bss_cfg->cmd_id;
7958 	csr_set_sap_ser_params(&cmd, WLAN_SER_CMD_VDEV_START_BSS);
7959 	cmd.umac_cmd = start_bss_cfg;
7960 	cmd.vdev = vdev;
7961 	csr_fill_cmd_timeout(&cmd);
7962 
7963 	status = wlan_vdev_mlme_ser_start_bss(&cmd);
7964 	switch (status) {
7965 	case WLAN_SER_CMD_PENDING:
7966 	case WLAN_SER_CMD_ACTIVE:
7967 		break;
7968 	default:
7969 		sme_err("ser cmd status %d", status);
7970 		goto error;
7971 	}
7972 
7973 	return QDF_STATUS_SUCCESS;
7974 error:
7975 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
7976 	if (start_bss_cfg)
7977 		qdf_mem_free(start_bss_cfg);
7978 
7979 	return QDF_STATUS_E_FAILURE;
7980 }
7981 
csr_roam_issue_stop_bss_cmd(struct mac_context * mac,uint8_t vdev_id,eCsrRoamBssType bss_type)7982 QDF_STATUS csr_roam_issue_stop_bss_cmd(struct mac_context *mac,
7983 				       uint8_t vdev_id,
7984 				       eCsrRoamBssType bss_type)
7985 {
7986 	struct wlan_objmgr_vdev *vdev;
7987 	struct wlan_serialization_command cmd = {0};
7988 	enum wlan_serialization_status status;
7989 	struct stop_bss_req *stop_bss_req;
7990 
7991 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac->pdev, vdev_id,
7992 						    WLAN_LEGACY_MAC_ID);
7993 	if (!vdev) {
7994 		sme_err("VDEV not found for vdev id : %d", vdev_id);
7995 		return QDF_STATUS_E_FAILURE;
7996 	}
7997 
7998 	/* Change the substate in case it is wait-for-key */
7999 	if (CSR_IS_WAIT_FOR_KEY(mac, vdev_id)) {
8000 		cm_stop_wait_for_key_timer(mac->psoc, vdev_id);
8001 		csr_roam_substate_change(mac, eCSR_ROAM_SUBSTATE_NONE,
8002 					 vdev_id);
8003 	}
8004 
8005 	sme_debug("Stop BSS vdev_id: %d bss_type %d", vdev_id, bss_type);
8006 	stop_bss_req = qdf_mem_malloc(sizeof(*stop_bss_req));
8007 	if (!stop_bss_req)
8008 		goto error;
8009 
8010 	stop_bss_req->vdev_id = vdev_id;
8011 	stop_bss_req->cmd_id = csr_get_monotonous_number(mac);
8012 
8013 	cmd.cmd_id = stop_bss_req->cmd_id;
8014 	csr_set_sap_ser_params(&cmd, WLAN_SER_CMD_VDEV_STOP_BSS);
8015 	cmd.umac_cmd = stop_bss_req;
8016 	cmd.vdev = vdev;
8017 	csr_fill_cmd_timeout(&cmd);
8018 
8019 	status = wlan_vdev_mlme_ser_stop_bss(&cmd);
8020 	switch (status) {
8021 	case WLAN_SER_CMD_PENDING:
8022 	case WLAN_SER_CMD_ACTIVE:
8023 		break;
8024 	default:
8025 		sme_err("ser cmd status %d", status);
8026 		goto error;
8027 	}
8028 	return QDF_STATUS_SUCCESS;
8029 
8030 error:
8031 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
8032 	qdf_mem_free(stop_bss_req);
8033 	return QDF_STATUS_E_FAILURE;
8034 }
8035 
csr_process_stop_bss_response(struct mac_context * mac_ctx,uint32_t vdev_id)8036 static void csr_process_stop_bss_response(struct mac_context *mac_ctx,
8037 					  uint32_t vdev_id)
8038 {
8039 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id);
8040 
8041 	if (CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac_ctx, vdev_id)) {
8042 		csr_roam_free_connected_info(mac_ctx, &session->connectedInfo);
8043 		csr_set_default_dot11_mode(mac_ctx);
8044 	}
8045 
8046 	csr_roam_call_callback(mac_ctx, vdev_id, NULL, eCSR_ROAM_INFRA_IND,
8047 			       eCSR_ROAM_RESULT_INFRA_STOPPED);
8048 	return;
8049 }
8050 
8051 /**
8052  * csr_process_sap_results() - API to process the LIM response for
8053  * the messages posted by SAP module
8054  * @mac_ctx: mac context
8055  * @req: Serialization command posted by SAP
8056  * @rsp: Response from LIM
8057  * @result: Result from LIM
8058  * @vdev_id : vdev id
8059  *
8060  * Return: void
8061  */
csr_process_sap_results(struct mac_context * mac_ctx,void * rsp,enum csr_sap_response_type result,uint8_t vdev_id)8062 static bool csr_process_sap_results(struct mac_context *mac_ctx,
8063 				    void *rsp,
8064 				    enum csr_sap_response_type result,
8065 				    uint8_t vdev_id)
8066 {
8067 	struct csr_roam_info *roam_info;
8068 	struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, vdev_id);
8069 	eRoamCmdStatus roam_status = eCSR_ROAM_INFRA_IND;
8070 	eCsrRoamResult roam_result = eCSR_ROAM_RESULT_INFRA_START_FAILED;
8071 	enum QDF_OPMODE opmode;
8072 
8073 	if (!session) {
8074 		sme_err("session %d not found ", vdev_id);
8075 		return false;
8076 	}
8077 
8078 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
8079 	if (!roam_info)
8080 		return false;
8081 
8082 	opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id);
8083 	sme_debug("SAP result : %d", result);
8084 
8085 	switch (result) {
8086 	case CSR_SAP_START_BSS_SUCCESS:
8087 		csr_roam_process_start_bss_success(mac_ctx, roam_info,
8088 						   rsp, vdev_id);
8089 		break;
8090 	case CSR_SAP_START_BSS_FAILURE:
8091 		if (opmode == QDF_NDI_MODE) {
8092 			csr_roam_update_ndp_return_params(mac_ctx,
8093 							  CSR_SAP_START_BSS_FAILURE,
8094 							  &roam_status,
8095 							  &roam_result,
8096 							  roam_info);
8097 		}
8098 		csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
8099 				       roam_status, roam_result);
8100 		csr_set_default_dot11_mode(mac_ctx);
8101 		break;
8102 	case CSR_SAP_STOP_BSS_SUCCESS:
8103 	case CSR_SAP_STOP_BSS_FAILURE:
8104 		if (opmode == QDF_NDI_MODE) {
8105 			qdf_mem_zero(roam_info, sizeof(*roam_info));
8106 			csr_roam_update_ndp_return_params(mac_ctx, result,
8107 							  &roam_status,
8108 							  &roam_result,
8109 							  roam_info);
8110 			csr_roam_call_callback(mac_ctx, vdev_id, roam_info,
8111 					       roam_status, roam_result);
8112 		} else {
8113 			csr_process_stop_bss_response(mac_ctx, vdev_id);
8114 		}
8115 		break;
8116 	default:
8117 		sme_err("Invalid response");
8118 		break;
8119 	}
8120 	qdf_mem_free(roam_info);
8121 	return true;
8122 }
8123 
8124 static enum wlan_serialization_cmd_type
get_cmd_type_from_result(enum csr_sap_response_type result)8125 get_cmd_type_from_result(enum csr_sap_response_type result)
8126 {
8127 	switch (result) {
8128 	case CSR_SAP_START_BSS_SUCCESS:
8129 	case CSR_SAP_START_BSS_FAILURE:
8130 		return WLAN_SER_CMD_VDEV_START_BSS;
8131 	case CSR_SAP_STOP_BSS_SUCCESS:
8132 	case CSR_SAP_STOP_BSS_FAILURE:
8133 		return WLAN_SER_CMD_VDEV_STOP_BSS;
8134 	default:
8135 		return WLAN_SER_CMD_MAX;
8136 	}
8137 }
8138 
8139 static inline
get_cmd_id_from_cmd_type(void * cmd,enum wlan_serialization_cmd_type cmd_type)8140 uint32_t get_cmd_id_from_cmd_type(void *cmd,
8141 				  enum wlan_serialization_cmd_type cmd_type)
8142 {
8143 	switch (cmd_type) {
8144 	case WLAN_SER_CMD_VDEV_START_BSS:
8145 		return ((struct start_bss_config *)cmd)->cmd_id;
8146 	case WLAN_SER_CMD_VDEV_STOP_BSS:
8147 		return ((struct stop_bss_req *)cmd)->cmd_id;
8148 	default:
8149 		sme_err("Invalid cmd_type %d to be dequeued", cmd_type);
8150 		return 0;
8151 	}
8152 }
8153 
csr_process_sap_response(struct mac_context * mac_ctx,enum csr_sap_response_type result,void * rsp,uint8_t vdev_id)8154 void csr_process_sap_response(struct mac_context *mac_ctx,
8155 			      enum csr_sap_response_type result,
8156 			      void *rsp, uint8_t vdev_id)
8157 {
8158 	struct wlan_objmgr_vdev *vdev;
8159 	void *req;
8160 	uint32_t cmd_id;
8161 	enum wlan_serialization_cmd_type cmd_type =
8162 				get_cmd_type_from_result(result);
8163 
8164 	if (cmd_type >= WLAN_SER_CMD_MAX) {
8165 		sme_err("Invalid command to be dequeued %d", cmd_type);
8166 		return;
8167 	}
8168 
8169 	req = wlan_serialization_get_active_cmd(mac_ctx->psoc,
8170 						vdev_id, cmd_type);
8171 	if (!req) {
8172 		sme_err("No active command for response from LIM for cmd: %d vdev: %d",
8173 			cmd_type, vdev_id);
8174 		csr_process_sap_results(mac_ctx, rsp, result, vdev_id);
8175 		return;
8176 	}
8177 
8178 	csr_process_sap_results(mac_ctx, rsp, result, vdev_id);
8179 
8180 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
8181 						    WLAN_LEGACY_MAC_ID);
8182 	if (!vdev) {
8183 		sme_err("vdev not found for vdev id: %d", vdev_id);
8184 		return;
8185 	}
8186 
8187 	cmd_id = get_cmd_id_from_cmd_type(req, cmd_type);
8188 	sme_debug("Dequeue cmd id : %d type : %d", cmd_id, cmd_type);
8189 
8190 	wlan_vdev_mlme_ser_remove_request(vdev, cmd_id, cmd_type);
8191 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
8192 }
8193 
csr_set_vdev_ies_per_band(mac_handle_t mac_handle,uint8_t vdev_id,enum QDF_OPMODE device_mode)8194 void csr_set_vdev_ies_per_band(mac_handle_t mac_handle, uint8_t vdev_id,
8195 			       enum QDF_OPMODE device_mode)
8196 {
8197 	struct sir_set_vdev_ies_per_band *p_msg;
8198 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
8199 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
8200 	enum csr_cfgdot11mode curr_dot11_mode =
8201 			mac_ctx->roam.configParam.uCfgDot11Mode;
8202 
8203 	p_msg = qdf_mem_malloc(sizeof(*p_msg));
8204 	if (!p_msg)
8205 		return;
8206 
8207 	p_msg->vdev_id = vdev_id;
8208 	p_msg->device_mode = device_mode;
8209 	p_msg->dot11_mode = csr_get_vdev_dot11_mode(mac_ctx, vdev_id,
8210 						    curr_dot11_mode);
8211 	p_msg->msg_type = eWNI_SME_SET_VDEV_IES_PER_BAND;
8212 	p_msg->len = sizeof(*p_msg);
8213 	sme_debug("SET_VDEV_IES_PER_BAND: vdev_id %d dot11mode %d dev_mode %d",
8214 		  vdev_id, p_msg->dot11_mode, device_mode);
8215 	status = umac_send_mb_message_to_mac(p_msg);
8216 	if (QDF_STATUS_SUCCESS != status)
8217 		sme_err("Send eWNI_SME_SET_VDEV_IES_PER_BAND fail");
8218 }
8219