1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * This file lim_send_sme_rspMessages.cc contains the functions
22  * for sending SME response/notification messages to applications
23  * above MAC software.
24  * Author:        Chandra Modumudi
25  * Date:          02/13/02
26  * History:-
27  * Date           Modified by    Modification Information
28  * --------------------------------------------------------------------
29  */
30 
31 #include "qdf_types.h"
32 #include "wni_api.h"
33 #include "sir_common.h"
34 #include "ani_global.h"
35 
36 #include "wni_cfg.h"
37 #include "sys_def.h"
38 
39 #include "sch_api.h"
40 #include "utils_api.h"
41 #include "lim_utils.h"
42 #include "lim_security_utils.h"
43 #include "lim_ser_des_utils.h"
44 #include "lim_send_sme_rsp_messages.h"
45 #include "lim_session_utils.h"
46 #include "lim_types.h"
47 #include "sir_api.h"
48 #include "cds_regdomain.h"
49 #include "lim_send_messages.h"
50 #include "nan_datapath.h"
51 #include "lim_assoc_utils.h"
52 #include "wlan_reg_services_api.h"
53 #include "wlan_utility.h"
54 
55 #include "wlan_tdls_tgt_api.h"
56 #include "lim_process_fils.h"
57 #include "wma.h"
58 #include "wma_he.h"
59 #include <../../core/src/wlan_cm_vdev_api.h>
60 #include <wlan_mlo_mgr_sta.h>
61 #include <spatial_reuse_api.h>
62 #include <wlan_mlo_mgr_cmn.h>
63 
lim_send_sme_rsp(struct mac_context * mac_ctx,uint16_t msg_type,tSirResultCodes result_code,uint8_t vdev_id)64 void lim_send_sme_rsp(struct mac_context *mac_ctx, uint16_t msg_type,
65 		      tSirResultCodes result_code, uint8_t vdev_id)
66 {
67 	struct scheduler_msg msg = {0};
68 	tSirSmeRsp *sme_rsp;
69 
70 	pe_debug("Sending message: %s with reasonCode: %s",
71 		lim_msg_str(msg_type), lim_result_code_str(result_code));
72 
73 	sme_rsp = qdf_mem_malloc(sizeof(tSirSmeRsp));
74 	if (!sme_rsp)
75 		return;
76 
77 	sme_rsp->messageType = msg_type;
78 	sme_rsp->length = sizeof(tSirSmeRsp);
79 	sme_rsp->status_code = result_code;
80 	sme_rsp->vdev_id = vdev_id;
81 
82 	msg.type = msg_type;
83 	msg.bodyptr = sme_rsp;
84 	msg.bodyval = 0;
85 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_TX_SME_MSG, vdev_id, msg.type));
86 
87 	lim_sys_process_mmh_msg_api(mac_ctx, &msg);
88 }
89 
90 void
lim_send_stop_bss_response(struct mac_context * mac_ctx,uint8_t vdev_id,tSirResultCodes result_code)91 lim_send_stop_bss_response(struct mac_context *mac_ctx, uint8_t vdev_id,
92 			   tSirResultCodes result_code)
93 {
94 	struct scheduler_msg msg = {0};
95 	struct stop_bss_rsp *stop_bss_rsp;
96 	struct pe_session *pe_session;
97 	struct pe_session *sta_session;
98 
99 	pe_debug("Sending stop bss response with reasonCode: %s",
100 		 lim_result_code_str(result_code));
101 
102 	pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
103 	if (!pe_session) {
104 		pe_err("Unable to find session for stop bss response");
105 		return;
106 	}
107 
108 	/*
109 	 * STA LPI + SAP VLP is supported. For this STA should operate in VLP
110 	 * power level of the SAP.
111 	 *
112 	 * For the STA, if the TPC is changed to VLP, then restore the original
113 	 * power for the STA when SAP disconnects.
114 	 */
115 	if (wlan_get_tpc_update_required_for_sta(pe_session->vdev)) {
116 		sta_session = lim_get_concurrent_session(mac_ctx, vdev_id,
117 							 pe_session->opmode);
118 		if (sta_session &&
119 		    sta_session->curr_op_freq == pe_session->curr_op_freq)
120 			lim_update_tx_power(mac_ctx, pe_session,
121 					    sta_session, true);
122 	}
123 
124 	stop_bss_rsp = qdf_mem_malloc(sizeof(*stop_bss_rsp));
125 	if (!stop_bss_rsp)
126 		return;
127 
128 	stop_bss_rsp->status_code = result_code;
129 	stop_bss_rsp->vdev_id = vdev_id;
130 
131 	msg.type = eWNI_SME_STOP_BSS_RSP;
132 	msg.bodyptr = stop_bss_rsp;
133 	msg.bodyval = 0;
134 
135 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
136 	lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_STOP_BSS_RSP_EVENT,
137 			      NULL, (uint16_t) result_code, 0);
138 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
139 	lim_sys_process_mmh_msg_api(mac_ctx, &msg);
140 }
141 
142 #ifdef WLAN_FEATURE_11AX
143 /**
144  * lim_get_he_rate_info_flag() - Get he tx rate info flag
145  * @sta_ds: Pointer to station ds structure
146  *
147  * This function is called to get the he tx rate info.
148  *
149  * Return: Returns he tx rate flag
150  */
151 static enum tx_rate_info
lim_get_he_rate_info_flag(tpDphHashNode sta_ds)152 lim_get_he_rate_info_flag(tpDphHashNode sta_ds)
153 {
154 	tDot11fIEhe_cap *peer_he = &sta_ds->he_config;
155 
156 	if (peer_he->chan_width_3 || peer_he->chan_width_2)
157 		return TX_RATE_HE160;
158 	else if (peer_he->chan_width_1)
159 		return TX_RATE_HE80;
160 	else if (peer_he->chan_width_0)
161 		return TX_RATE_HE40;
162 	else
163 		return TX_RATE_HE20;
164 }
165 #else
166 static enum tx_rate_info
lim_get_he_rate_info_flag(tpDphHashNode sta_ds)167 lim_get_he_rate_info_flag(tpDphHashNode sta_ds)
168 {
169 	return TX_RATE_LEGACY;
170 }
171 #endif
172 
173 #ifdef WLAN_FEATURE_11BE
174 /**
175  * lim_get_eht_rate_info_flag() - Get eht tx rate info flag
176  * @sta_ds: Pointer to station ds structure
177  *
178  * This function is called to get the eht tx rate info.
179  *
180  * Return: Returns eht tx rate flag
181  */
182 static enum tx_rate_info
lim_get_eht_rate_info_flag(tpDphHashNode sta_ds)183 lim_get_eht_rate_info_flag(tpDphHashNode sta_ds)
184 {
185 	if (sta_ds->eht_config.support_320mhz_6ghz)
186 		return  TX_RATE_EHT320;
187 	else if (sta_ds->ch_width == CH_WIDTH_160MHZ)
188 		return  TX_RATE_EHT160;
189 	else if (sta_ds->ch_width == CH_WIDTH_80MHZ)
190 		return TX_RATE_EHT80;
191 	else if (sta_ds->ch_width == CH_WIDTH_40MHZ)
192 		return TX_RATE_EHT40;
193 	else
194 		return TX_RATE_EHT20;
195 }
196 #else
197 static enum tx_rate_info
lim_get_eht_rate_info_flag(tpDphHashNode sta_ds)198 lim_get_eht_rate_info_flag(tpDphHashNode sta_ds)
199 {
200 	return TX_RATE_LEGACY;
201 }
202 #endif
203 
204 /**
205  * lim_get_max_rate_flags() - Get rate flags
206  * @mac_ctx: Pointer to global MAC structure
207  * @sta_ds: Pointer to station ds structure
208  *
209  * This function is called to get the rate flags for a connection
210  * from the station ds structure depending on the ht and the vht
211  * channel width supported.
212  *
213  * Return: Returns the populated rate_flags
214  */
lim_get_max_rate_flags(struct mac_context * mac_ctx,tpDphHashNode sta_ds)215 uint32_t lim_get_max_rate_flags(struct mac_context *mac_ctx, tpDphHashNode sta_ds)
216 {
217 	uint32_t rate_flags = 0;
218 
219 	if (!sta_ds) {
220 		pe_err("sta_ds is NULL");
221 		return rate_flags;
222 	}
223 
224 	if (!lim_is_sta_eht_capable(sta_ds) &&
225 	    !sta_ds->mlmStaContext.htCapability &&
226 	    !sta_ds->mlmStaContext.vhtCapability &&
227 	    !lim_is_sta_he_capable(sta_ds)) {
228 		rate_flags |= TX_RATE_LEGACY;
229 	} else {
230 		if (lim_is_sta_eht_capable(sta_ds)) {
231 			rate_flags |= lim_get_eht_rate_info_flag(sta_ds);
232 		} else if (lim_is_sta_he_capable(sta_ds)) {
233 			rate_flags |= lim_get_he_rate_info_flag(sta_ds);
234 		} else if (sta_ds->mlmStaContext.vhtCapability) {
235 			if (WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ ==
236 			   sta_ds->vhtSupportedChannelWidthSet ||
237 			   WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ ==
238 			   sta_ds->vhtSupportedChannelWidthSet) {
239 				rate_flags |= TX_RATE_VHT160;
240 			} else if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ ==
241 				sta_ds->vhtSupportedChannelWidthSet) {
242 				rate_flags |= TX_RATE_VHT80;
243 			} else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ ==
244 					sta_ds->vhtSupportedChannelWidthSet) {
245 				if (sta_ds->htSupportedChannelWidthSet)
246 					rate_flags |= TX_RATE_VHT40;
247 				else
248 					rate_flags |= TX_RATE_VHT20;
249 			}
250 		} else if (sta_ds->mlmStaContext.htCapability) {
251 			if (sta_ds->htSupportedChannelWidthSet)
252 				rate_flags |= TX_RATE_HT40;
253 			else
254 				rate_flags |= TX_RATE_HT20;
255 		}
256 	}
257 
258 	if (sta_ds->htShortGI20Mhz || sta_ds->htShortGI40Mhz)
259 		rate_flags |= TX_RATE_SGI;
260 
261 	return rate_flags;
262 }
263 
lim_send_smps_intolerent(struct mac_context * mac_ctx,struct pe_session * pe_session,uint32_t bcn_len,uint8_t * bcn_ptr)264 static void lim_send_smps_intolerent(struct mac_context *mac_ctx,
265 				     struct pe_session *pe_session,
266 				     uint32_t bcn_len, uint8_t *bcn_ptr)
267 {
268 	const uint8_t *vendor_ap_1;
269 	uint32_t bcn_ie_len;
270 	uint8_t *bcn_ie_ptr;
271 
272 	if (!bcn_ptr || (bcn_len <= (sizeof(struct wlan_frame_hdr) +
273 			  offsetof(struct wlan_bcn_frame, ie))))
274 		return;
275 
276 	bcn_ie_len = bcn_len - sizeof(struct wlan_frame_hdr) -
277 			offsetof(struct wlan_bcn_frame, ie);
278 	bcn_ie_ptr = bcn_ptr + sizeof(struct wlan_frame_hdr) +
279 			offsetof(struct wlan_bcn_frame, ie);
280 
281 	vendor_ap_1 =
282 		wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_VENDOR_AP_1_OUI,
283 						SIR_MAC_VENDOR_AP_1_OUI_LEN,
284 						bcn_ie_ptr, bcn_ie_len);
285 	if (mac_ctx->roam.configParam.is_force_1x1 &&
286 	    vendor_ap_1 && (pe_session->nss == 2) &&
287 	    (!mac_ctx->mlme_cfg->gen.as_enabled ||
288 	     wlan_reg_is_5ghz_ch_freq(pe_session->curr_op_freq))) {
289 		/* SET vdev param */
290 		pe_debug("sending SMPS intolrent vdev_param");
291 		wma_cli_set_command(pe_session->vdev_id,
292 				    (int)wmi_vdev_param_smps_intolerant,
293 				    1, VDEV_CMD);
294 	}
295 }
296 
297 #ifdef WLAN_FEATURE_FILS_SK
lim_set_fils_connection(struct wlan_cm_connect_resp * connect_rsp,struct pe_session * session_entry)298 static void lim_set_fils_connection(struct wlan_cm_connect_resp *connect_rsp,
299 				    struct pe_session *session_entry)
300 {
301 	if (lim_is_fils_connection(session_entry))
302 		connect_rsp->is_fils_connection = true;
303 	pe_debug("is_fils_connection %d", connect_rsp->is_fils_connection);
304 }
305 #else
306 static inline
lim_set_fils_connection(struct wlan_cm_connect_resp * connect_rsp,struct pe_session * session_entry)307 void lim_set_fils_connection(struct wlan_cm_connect_resp *connect_rsp,
308 			     struct pe_session *session_entry)
309 {}
310 #endif
311 
312 #ifdef FEATURE_WLAN_ESE
lim_copy_tspec_ie(struct pe_session * pe_session,struct cm_vdev_join_rsp * rsp)313 static void lim_copy_tspec_ie(struct pe_session *pe_session,
314 			      struct cm_vdev_join_rsp *rsp)
315 {
316 	if (pe_session->tspecIes) {
317 		rsp->tspec_ie.len = pe_session->tspecLen;
318 		rsp->tspec_ie.ptr =
319 		    qdf_mem_malloc(rsp->tspec_ie.len);
320 		if (!rsp->tspec_ie.ptr)
321 			return;
322 
323 		qdf_mem_copy(rsp->tspec_ie.ptr, pe_session->tspecIes,
324 			     rsp->tspec_ie.len);
325 		pe_debug("ESE-TspecLen: %d", rsp->tspec_ie.len);
326 	}
327 }
328 
lim_free_tspec_ie(struct pe_session * pe_session)329 static void lim_free_tspec_ie(struct pe_session *pe_session)
330 {
331 	if (pe_session->tspecIes) {
332 		qdf_mem_free(pe_session->tspecIes);
333 		pe_session->tspecIes = NULL;
334 		pe_session->tspecLen = 0;
335 	}
336 }
337 #else
lim_copy_tspec_ie(struct pe_session * pe_session,struct cm_vdev_join_rsp * rsp)338 static inline void lim_copy_tspec_ie(struct pe_session *pe_session,
339 				     struct cm_vdev_join_rsp *rsp)
340 {}
lim_free_tspec_ie(struct pe_session * pe_session)341 static inline void lim_free_tspec_ie(struct pe_session *pe_session)
342 {}
343 #endif
344 
lim_cm_fill_rsp_from_stads(struct mac_context * mac_ctx,struct pe_session * pe_session,struct cm_vdev_join_rsp * rsp)345 static void lim_cm_fill_rsp_from_stads(struct mac_context *mac_ctx,
346 				       struct pe_session *pe_session,
347 				       struct cm_vdev_join_rsp *rsp)
348 {
349 	tpDphHashNode sta_ds;
350 
351 	sta_ds = dph_get_hash_entry(mac_ctx,
352 				    DPH_STA_HASH_INDEX_PEER,
353 				    &pe_session->dph.dphHashTable);
354 	if (!sta_ds)
355 		return;
356 
357 	rsp->nss = sta_ds->nss;
358 }
359 
360 static QDF_STATUS
lim_cm_prepare_join_rsp_from_pe_session(struct mac_context * mac_ctx,struct pe_session * pe_session,struct cm_vdev_join_rsp * rsp,enum wlan_cm_connect_fail_reason reason,QDF_STATUS connect_status,enum wlan_status_code status_code)361 lim_cm_prepare_join_rsp_from_pe_session(struct mac_context *mac_ctx,
362 					struct pe_session *pe_session,
363 					struct cm_vdev_join_rsp *rsp,
364 					enum wlan_cm_connect_fail_reason reason,
365 					QDF_STATUS connect_status,
366 					enum wlan_status_code status_code)
367 {
368 	struct wlan_cm_connect_resp *connect_rsp = &rsp->connect_rsp;
369 	struct wlan_connect_rsp_ies *connect_ie = &rsp->connect_rsp.connect_ies;
370 	uint32_t bcn_len;
371 	uint8_t *bcn_ptr;
372 
373 	connect_rsp->cm_id = pe_session->cm_id;
374 	connect_rsp->vdev_id = pe_session->vdev_id;
375 	qdf_ether_addr_copy(connect_rsp->bssid.bytes, pe_session->bssId);
376 	wlan_cm_connect_resp_fill_mld_addr_from_cm_id(pe_session->vdev,
377 						      pe_session->cm_id,
378 						      connect_rsp);
379 	connect_rsp->freq = pe_session->curr_op_freq;
380 	connect_rsp->connect_status = connect_status;
381 	connect_rsp->reason = reason;
382 	connect_rsp->status_code = status_code;
383 	connect_rsp->ssid.length =
384 			QDF_MIN(WLAN_SSID_MAX_LEN, pe_session->ssId.length);
385 	qdf_mem_copy(connect_rsp->ssid.ssid, pe_session->ssId.ssId,
386 		     connect_rsp->ssid.length);
387 
388 	lim_set_fils_connection(connect_rsp, pe_session);
389 	if (pe_session->beacon) {
390 		connect_ie->bcn_probe_rsp.len = pe_session->bcnLen;
391 		connect_ie->bcn_probe_rsp.ptr =
392 			qdf_mem_malloc(connect_ie->bcn_probe_rsp.len);
393 		if (!connect_ie->bcn_probe_rsp.ptr)
394 			return QDF_STATUS_E_NOMEM;
395 
396 		qdf_mem_copy(connect_ie->bcn_probe_rsp.ptr, pe_session->beacon,
397 			     connect_ie->bcn_probe_rsp.len);
398 	}
399 	bcn_len = connect_ie->bcn_probe_rsp.len;
400 	bcn_ptr = connect_ie->bcn_probe_rsp.ptr;
401 
402 	if (pe_session->assoc_req) {
403 		connect_ie->assoc_req.len = pe_session->assocReqLen;
404 		connect_ie->assoc_req.ptr =
405 				qdf_mem_malloc(connect_ie->assoc_req.len);
406 		if (!connect_ie->assoc_req.ptr)
407 			return QDF_STATUS_E_NOMEM;
408 
409 		qdf_mem_copy(connect_ie->assoc_req.ptr, pe_session->assoc_req,
410 			     connect_ie->assoc_req.len);
411 	}
412 
413 	if (pe_session->assocRsp) {
414 		connect_ie->assoc_rsp.len = pe_session->assocRspLen;
415 		connect_ie->assoc_rsp.ptr =
416 			qdf_mem_malloc(connect_ie->assoc_rsp.len);
417 		if (!connect_ie->assoc_rsp.ptr)
418 			return QDF_STATUS_E_NOMEM;
419 
420 		qdf_mem_copy(connect_ie->assoc_rsp.ptr, pe_session->assocRsp,
421 			     connect_ie->assoc_rsp.len);
422 	}
423 	connect_rsp->is_wps_connection = pe_session->wps_registration;
424 	connect_rsp->is_osen_connection = pe_session->isOSENConnection;
425 
426 	if (QDF_IS_STATUS_SUCCESS(connect_status)) {
427 		connect_rsp->status_code = STATUS_SUCCESS;
428 		populate_fils_connect_params(mac_ctx, pe_session, connect_rsp);
429 		connect_rsp->aid = pe_session->limAID;
430 
431 		/* move ric date to cm_vdev_join_rsp to fill in csr session */
432 		if (pe_session->ricData) {
433 			rsp->ric_resp_ie.len = pe_session->RICDataLen;
434 			rsp->ric_resp_ie.ptr =
435 			    qdf_mem_malloc(rsp->ric_resp_ie.len);
436 			if (!rsp->ric_resp_ie.ptr)
437 				return QDF_STATUS_E_NOMEM;
438 
439 			qdf_mem_copy(rsp->ric_resp_ie.ptr, pe_session->ricData,
440 				     rsp->ric_resp_ie.len);
441 		}
442 
443 		lim_copy_tspec_ie(pe_session, rsp);
444 
445 		lim_send_smps_intolerent(mac_ctx, pe_session, bcn_len, bcn_ptr);
446 		lim_cm_fill_rsp_from_stads(mac_ctx, pe_session, rsp);
447 		rsp->uapsd_mask = pe_session->gUapsdPerAcBitmask;
448 	}
449 
450 	return QDF_STATUS_SUCCESS;
451 }
452 
453 static void
lim_cm_fill_join_rsp_from_connect_req(struct cm_vdev_join_req * req,struct cm_vdev_join_rsp * rsp,enum wlan_cm_connect_fail_reason reason)454 lim_cm_fill_join_rsp_from_connect_req(struct cm_vdev_join_req *req,
455 				      struct cm_vdev_join_rsp *rsp,
456 				      enum wlan_cm_connect_fail_reason reason)
457 {
458 	struct wlan_cm_connect_resp *connect_rsp = &rsp->connect_rsp;
459 
460 	connect_rsp->cm_id = req->cm_id;
461 	connect_rsp->vdev_id = req->vdev_id;
462 	qdf_copy_macaddr(&connect_rsp->bssid, &req->entry->bssid);
463 	connect_rsp->freq = req->entry->channel.chan_freq;
464 	connect_rsp->connect_status = QDF_STATUS_E_FAILURE;
465 	connect_rsp->reason = reason;
466 	connect_rsp->ssid = req->entry->ssid;
467 	connect_rsp->is_wps_connection = req->is_wps_connection;
468 	connect_rsp->is_osen_connection = req->is_osen_connection;
469 	wlan_cm_connect_resp_fill_mld_addr_from_vdev_id(rsp->psoc, req->vdev_id,
470 							req->entry,
471 							connect_rsp);
472 }
473 
lim_cm_flush_connect_rsp(struct scheduler_msg * msg)474 static QDF_STATUS lim_cm_flush_connect_rsp(struct scheduler_msg *msg)
475 {
476 	struct cm_vdev_join_rsp *rsp;
477 
478 	if (!msg || !msg->bodyptr)
479 		return QDF_STATUS_E_INVAL;
480 
481 	rsp = msg->bodyptr;
482 	wlan_cm_free_connect_rsp(rsp);
483 
484 	return QDF_STATUS_SUCCESS;
485 }
486 
lim_free_pession_ies(struct pe_session * pe_session)487 static void lim_free_pession_ies(struct pe_session *pe_session)
488 {
489 	if (pe_session->beacon) {
490 		qdf_mem_free(pe_session->beacon);
491 		pe_session->beacon = NULL;
492 		pe_session->bcnLen = 0;
493 	}
494 	if (pe_session->assoc_req) {
495 		qdf_mem_free(pe_session->assoc_req);
496 		pe_session->assoc_req = NULL;
497 		pe_session->assocReqLen = 0;
498 	}
499 	if (pe_session->assocRsp) {
500 		qdf_mem_free(pe_session->assocRsp);
501 		pe_session->assocRsp = NULL;
502 		pe_session->assocRspLen = 0;
503 	}
504 	if (pe_session->ricData) {
505 		qdf_mem_free(pe_session->ricData);
506 		pe_session->ricData = NULL;
507 		pe_session->RICDataLen = 0;
508 	}
509 	lim_free_tspec_ie(pe_session);
510 }
511 
512 #ifdef WLAN_FEATURE_11BE_MLO
lim_copy_ml_partner_info(struct cm_vdev_join_rsp * rsp,struct pe_session * pe_session)513 static void lim_copy_ml_partner_info(struct cm_vdev_join_rsp *rsp,
514 				     struct pe_session *pe_session)
515 {
516 	int i;
517 	struct mlo_partner_info *partner_info;
518 	struct mlo_partner_info *rsp_partner_info;
519 	uint8_t chan = 0, op_class, link_id;
520 
521 	partner_info = &pe_session->ml_partner_info;
522 	rsp_partner_info = &rsp->connect_rsp.ml_parnter_info;
523 
524 	rsp_partner_info->num_partner_links = partner_info->num_partner_links;
525 
526 	for (i = 0; i < rsp_partner_info->num_partner_links; i++) {
527 		link_id = partner_info->partner_link_info[i].link_id;
528 		rsp_partner_info->partner_link_info[i].link_id = link_id;
529 		qdf_copy_macaddr(
530 			&rsp_partner_info->partner_link_info[i].link_addr,
531 			&partner_info->partner_link_info[i].link_addr);
532 
533 		wlan_get_chan_by_bssid_from_rnr(
534 			pe_session->vdev,
535 			pe_session->cm_id,
536 			&partner_info->partner_link_info[i].link_addr,
537 			&chan, &op_class);
538 		if (!chan)
539 			wlan_get_chan_by_link_id_from_rnr(
540 						pe_session->vdev,
541 						pe_session->cm_id,
542 						link_id, &chan, &op_class);
543 		if (chan) {
544 			rsp_partner_info->partner_link_info[i].chan_freq =
545 				wlan_reg_chan_opclass_to_freq_auto(chan,
546 								   op_class,
547 								   false);
548 		} else {
549 			pe_debug("Failed to get channel info for link ID:%d",
550 				 link_id);
551 		}
552 	}
553 }
554 #else /* WLAN_FEATURE_11BE_MLO */
555 static inline void
lim_copy_ml_partner_info(struct cm_vdev_join_rsp * rsp,struct pe_session * pe_session)556 lim_copy_ml_partner_info(struct cm_vdev_join_rsp *rsp,
557 			 struct pe_session *pe_session)
558 {
559 }
560 #endif /* WLAN_FEATURE_11BE_MLO */
561 
lim_cm_send_connect_rsp(struct mac_context * mac_ctx,struct pe_session * pe_session,struct cm_vdev_join_req * req,enum wlan_cm_connect_fail_reason reason,QDF_STATUS connect_status,enum wlan_status_code status_code,bool is_reassoc)562 void lim_cm_send_connect_rsp(struct mac_context *mac_ctx,
563 			     struct pe_session *pe_session,
564 			     struct cm_vdev_join_req *req,
565 			     enum wlan_cm_connect_fail_reason reason,
566 			     QDF_STATUS connect_status,
567 			     enum wlan_status_code status_code,
568 			     bool is_reassoc)
569 {
570 	struct cm_vdev_join_rsp *rsp;
571 	QDF_STATUS status;
572 	struct scheduler_msg msg;
573 
574 	if (!pe_session && !req)
575 		return;
576 
577 	rsp = qdf_mem_malloc(sizeof(*rsp));
578 	if (!rsp)
579 		return;
580 
581 	rsp->psoc = mac_ctx->psoc;
582 
583 	if (!pe_session) {
584 		lim_cm_fill_join_rsp_from_connect_req(req, rsp, reason);
585 	} else {
586 		status =
587 			lim_cm_prepare_join_rsp_from_pe_session(mac_ctx,
588 								pe_session,
589 								rsp,
590 								reason,
591 								connect_status,
592 								status_code);
593 		lim_free_pession_ies(pe_session);
594 		lim_copy_ml_partner_info(rsp, pe_session);
595 		if (QDF_IS_STATUS_ERROR(status)) {
596 			pe_err("vdev_id: %d cm_id 0x%x : fail to prepare rsp",
597 			       rsp->connect_rsp.vdev_id,
598 			       rsp->connect_rsp.cm_id);
599 			wlan_cm_free_connect_rsp(rsp);
600 			return;
601 		}
602 	}
603 
604 	rsp->connect_rsp.is_reassoc = is_reassoc;
605 	qdf_mem_zero(&msg, sizeof(msg));
606 
607 	msg.bodyptr = rsp;
608 	msg.callback = wlan_cm_send_connect_rsp;
609 	msg.flush_callback = lim_cm_flush_connect_rsp;
610 
611 	status = scheduler_post_message(QDF_MODULE_ID_PE,
612 					QDF_MODULE_ID_OS_IF,
613 					QDF_MODULE_ID_OS_IF, &msg);
614 
615 	if (QDF_IS_STATUS_ERROR(status)) {
616 		pe_err("vdev_id: %d cm_id 0x%x : msg post fails",
617 		       rsp->connect_rsp.vdev_id, rsp->connect_rsp.cm_id);
618 		wlan_cm_free_connect_rsp(rsp);
619 	}
620 }
621 
622 static enum wlan_cm_connect_fail_reason
lim_cm_get_fail_reason_from_result_code(tSirResultCodes result_code)623 lim_cm_get_fail_reason_from_result_code(tSirResultCodes result_code)
624 {
625 	enum wlan_cm_connect_fail_reason fail_reason;
626 
627 	switch (result_code) {
628 	case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
629 		fail_reason = CM_JOIN_TIMEOUT;
630 		break;
631 	case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
632 		fail_reason = CM_AUTH_TIMEOUT;
633 		break;
634 	case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
635 	case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE:
636 	case eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE:
637 		fail_reason = CM_ASSOC_TIMEOUT;
638 		break;
639 	case eSIR_SME_AUTH_REFUSED:
640 	case eSIR_SME_INVALID_WEP_DEFAULT_KEY:
641 		fail_reason = CM_AUTH_FAILED;
642 		break;
643 	case eSIR_SME_ASSOC_REFUSED:
644 	case eSIR_SME_REASSOC_REFUSED:
645 	case eSIR_SME_FT_REASSOC_FAILURE:
646 	case eSIR_SME_INVALID_ASSOC_RSP_RXED:
647 	case eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA:
648 		fail_reason = CM_ASSOC_FAILED;
649 		break;
650 	default:
651 		fail_reason = CM_JOIN_FAILED;
652 		break;
653 	}
654 
655 	return fail_reason;
656 }
657 
658 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
659 static
lim_send_assoc_rsp_diag_event(struct mac_context * mac_ctx,struct pe_session * session_entry,uint16_t msg_type,uint16_t result_code)660 void lim_send_assoc_rsp_diag_event(struct mac_context *mac_ctx,
661 				   struct pe_session *session_entry,
662 				   uint16_t msg_type, uint16_t result_code)
663 {
664 	if (msg_type == eWNI_SME_REASSOC_RSP)
665 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_RSP_EVENT,
666 				      session_entry, result_code, 0);
667 	else
668 		lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_RSP_EVENT,
669 				      session_entry, result_code, 0);
670 }
671 #else
672 static inline
lim_send_assoc_rsp_diag_event(struct mac_context * mac_ctx,struct pe_session * session_entry,uint16_t msg_type,uint16_t result_code)673 void lim_send_assoc_rsp_diag_event(struct mac_context *mac_ctx,
674 				   struct pe_session *session_entry,
675 				   uint16_t msg_type, uint16_t result_code)
676 {}
677 #endif
678 
lim_send_sme_join_reassoc_rsp(struct mac_context * mac_ctx,uint16_t msg_type,tSirResultCodes result_code,uint16_t prot_status_code,struct pe_session * session_entry,uint8_t vdev_id)679 void lim_send_sme_join_reassoc_rsp(struct mac_context *mac_ctx,
680 				   uint16_t msg_type,
681 				   tSirResultCodes result_code,
682 				   uint16_t prot_status_code,
683 				   struct pe_session *session_entry,
684 				   uint8_t vdev_id)
685 {
686 	QDF_STATUS connect_status;
687 	enum wlan_cm_connect_fail_reason fail_reason = 0;
688 
689 	lim_send_assoc_rsp_diag_event(mac_ctx, session_entry, msg_type,
690 				      result_code);
691 
692 	pe_debug("Sending message: %s with reasonCode: %s",
693 		 lim_msg_str(msg_type), lim_result_code_str(result_code));
694 
695 	if (result_code == eSIR_SME_SUCCESS) {
696 		connect_status = QDF_STATUS_SUCCESS;
697 	} else {
698 		connect_status = QDF_STATUS_E_FAILURE;
699 		fail_reason =
700 			lim_cm_get_fail_reason_from_result_code(result_code);
701 	}
702 
703 	return lim_cm_send_connect_rsp(mac_ctx, session_entry, NULL,
704 				       fail_reason, connect_status,
705 				       prot_status_code,
706 				       msg_type == eWNI_SME_JOIN_RSP ?
707 				       false : true);
708 
709 	/* add reassoc resp API */
710 }
711 
lim_send_sme_start_bss_rsp(struct mac_context * mac,tSirResultCodes resultCode,struct pe_session * pe_session,uint8_t smesessionId)712 void lim_send_sme_start_bss_rsp(struct mac_context *mac,
713 				tSirResultCodes resultCode,
714 				struct pe_session *pe_session,
715 				uint8_t smesessionId)
716 {
717 
718 	struct scheduler_msg mmhMsg = {0};
719 	struct start_bss_rsp *start_bss_rsp;
720 
721 	pe_debug("Sending start bss response with reasonCode: %s",
722 		 lim_result_code_str(resultCode));
723 
724 	start_bss_rsp = qdf_mem_malloc(sizeof(*start_bss_rsp));
725 	if (!start_bss_rsp)
726 		return;
727 	start_bss_rsp->vdev_id = smesessionId;
728 	start_bss_rsp->status_code = resultCode;
729 
730 	mmhMsg.type = eWNI_SME_START_BSS_RSP;
731 	mmhMsg.bodyptr = start_bss_rsp;
732 	mmhMsg.bodyval = 0;
733 	if (!pe_session) {
734 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
735 				 NO_SESSION, mmhMsg.type));
736 	} else {
737 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
738 				 pe_session->peSessionId, mmhMsg.type));
739 	}
740 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
741 	lim_diag_event_report(mac, WLAN_PE_DIAG_START_BSS_RSP_EVENT,
742 			      pe_session, (uint16_t) resultCode, 0);
743 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
744 
745 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
746 } /*** end lim_send_sme_start_bss_rsp() ***/
747 
lim_send_sta_disconnect_ind(struct mac_context * mac,struct scheduler_msg * msg)748 static void lim_send_sta_disconnect_ind(struct mac_context *mac,
749 					struct scheduler_msg *msg)
750 {
751 	struct cm_vdev_discon_ind *ind;
752 	struct disassoc_ind *disassoc;
753 	struct deauth_ind *deauth;
754 	struct scheduler_msg ind_msg = {0};
755 	QDF_STATUS status;
756 
757 	ind = qdf_mem_malloc(sizeof(*ind));
758 	if (!ind) {
759 		qdf_mem_free(msg->bodyptr);
760 		return;
761 	}
762 
763 	ind->psoc = mac->psoc;
764 	if (msg->type == eWNI_SME_DISASSOC_IND) {
765 		disassoc = (struct disassoc_ind *)msg->bodyptr;
766 		ind->disconnect_param.vdev_id = disassoc->vdev_id;
767 		ind->disconnect_param.bssid = disassoc->bssid;
768 		ind->disconnect_param.reason_code = disassoc->reasonCode;
769 		if (disassoc->from_ap)
770 			ind->disconnect_param.source = CM_PEER_DISCONNECT;
771 		else
772 			ind->disconnect_param.source = CM_SB_DISCONNECT;
773 	} else {
774 		deauth = (struct deauth_ind *)msg->bodyptr;
775 		ind->disconnect_param.vdev_id = deauth->vdev_id;
776 		ind->disconnect_param.bssid = deauth->bssid;
777 		ind->disconnect_param.reason_code = deauth->reasonCode;
778 		if (deauth->from_ap)
779 			ind->disconnect_param.source = CM_PEER_DISCONNECT;
780 		else
781 			ind->disconnect_param.source = CM_SB_DISCONNECT;
782 	}
783 	ind_msg.bodyptr = ind;
784 	ind_msg.callback = cm_send_sb_disconnect_req;
785 	ind_msg.type = msg->type;
786 	qdf_mem_free(msg->bodyptr);
787 
788 	status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_OS_IF,
789 					QDF_MODULE_ID_OS_IF, &ind_msg);
790 
791 	if (QDF_IS_STATUS_ERROR(status)) {
792 		pe_err("vdev_id: %d, source %d, reason %d, type %d msg post fails",
793 		       ind->disconnect_param.vdev_id,
794 		       ind->disconnect_param.source,
795 		       ind->disconnect_param.reason_code, ind_msg.type);
796 		qdf_mem_free(ind);
797 	}
798 }
799 
lim_cm_send_disconnect_rsp(struct mac_context * mac_ctx,uint8_t vdev_id)800 void lim_cm_send_disconnect_rsp(struct mac_context *mac_ctx, uint8_t vdev_id)
801 {
802 	QDF_STATUS status;
803 	struct scheduler_msg rsp_msg = {0};
804 	struct cm_vdev_disconnect_rsp *rsp;
805 
806 	rsp = qdf_mem_malloc(sizeof(*rsp));
807 	if (!rsp)
808 		return;
809 
810 	rsp->vdev_id = vdev_id;
811 	rsp->psoc = mac_ctx->psoc;
812 
813 	rsp_msg.bodyptr = rsp;
814 	rsp_msg.callback = cm_handle_disconnect_resp;
815 
816 	status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_OS_IF,
817 					QDF_MODULE_ID_OS_IF, &rsp_msg);
818 
819 	if (QDF_IS_STATUS_ERROR(status)) {
820 		pe_err("Failed to post disconnect rsp to sme vdev_id %d",
821 		       vdev_id);
822 		qdf_mem_free(rsp);
823 	}
824 }
825 
lim_sap_send_sme_disassoc_deauth_ntf(struct mac_context * mac,QDF_STATUS status,uint32_t * pCtx)826 static void lim_sap_send_sme_disassoc_deauth_ntf(struct mac_context *mac,
827 						 QDF_STATUS status,
828 						 uint32_t *pCtx)
829 {
830 	struct scheduler_msg mmhMsg = {0};
831 	struct scheduler_msg *pMsg = (struct scheduler_msg *)pCtx;
832 
833 	mmhMsg.type = pMsg->type;
834 	mmhMsg.bodyptr = pMsg;
835 	mmhMsg.bodyval = 0;
836 
837 	MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, NO_SESSION, mmhMsg.type));
838 
839 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
840 }
841 
lim_send_sme_disassoc_deauth_ntf(struct mac_context * mac,QDF_STATUS status,uint32_t * pCtx)842 void lim_send_sme_disassoc_deauth_ntf(struct mac_context *mac,
843 				      QDF_STATUS status, uint32_t *pCtx)
844 {
845 	struct scheduler_msg *msg = (struct scheduler_msg *)pCtx;
846 	struct disassoc_rsp *disassoc;
847 	struct deauth_rsp *deauth;
848 	struct sir_sme_discon_done_ind *discon;
849 	uint8_t vdev_id;
850 	enum QDF_OPMODE opmode;
851 
852 	switch (msg->type) {
853 	case eWNI_SME_DISASSOC_RSP:
854 		disassoc = (struct disassoc_rsp *)pCtx;
855 		vdev_id = disassoc->sessionId;
856 		break;
857 	case eWNI_SME_DEAUTH_RSP:
858 		deauth = (struct deauth_rsp *)pCtx;
859 		vdev_id = deauth->sessionId;
860 		break;
861 	case eWNI_SME_DISCONNECT_DONE_IND:
862 		discon = (struct sir_sme_discon_done_ind *)pCtx;
863 		vdev_id = discon->session_id;
864 		break;
865 	default:
866 		pe_err("Received invalid disconnect rsp type %d", msg->type);
867 		qdf_mem_free(pCtx);
868 		return;
869 	}
870 
871 	opmode = wlan_get_opmode_from_vdev_id(mac->pdev, vdev_id);
872 	/* Use connection manager for STA and CLI */
873 	if (opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) {
874 		qdf_mem_free(pCtx);
875 		lim_cm_send_disconnect_rsp(mac, vdev_id);
876 		return;
877 	}
878 
879 	lim_sap_send_sme_disassoc_deauth_ntf(mac, status, pCtx);
880 }
881 
lim_send_sme_disassoc_ntf(struct mac_context * mac,tSirMacAddr peerMacAddr,tSirResultCodes reasonCode,uint16_t disassocTrigger,uint16_t aid,uint8_t smesessionId,struct pe_session * pe_session)882 void lim_send_sme_disassoc_ntf(struct mac_context *mac,
883 			       tSirMacAddr peerMacAddr,
884 			       tSirResultCodes reasonCode,
885 			       uint16_t disassocTrigger,
886 			       uint16_t aid,
887 			       uint8_t smesessionId,
888 			       struct pe_session *pe_session)
889 {
890 	struct disassoc_rsp *pSirSmeDisassocRsp;
891 	struct disassoc_ind *pSirSmeDisassocInd = NULL;
892 	uint32_t *pMsg = NULL;
893 	bool failure = false;
894 	struct pe_session *session = NULL;
895 	uint16_t i, assoc_id;
896 	tpDphHashNode sta_ds = NULL;
897 	QDF_STATUS status;
898 	enum QDF_OPMODE opmode;
899 
900 	pe_debug("Disassoc Ntf with trigger : %d reasonCode: %d",
901 		disassocTrigger, reasonCode);
902 
903 	switch (disassocTrigger) {
904 	case eLIM_DUPLICATE_ENTRY:
905 		/*
906 		 * Duplicate entry is removed at LIM.
907 		 * Initiate new entry for other session
908 		 */
909 		pe_debug("Rcvd eLIM_DUPLICATE_ENTRY for " QDF_MAC_ADDR_FMT,
910 			QDF_MAC_ADDR_REF(peerMacAddr));
911 
912 		for (i = 0; i < mac->lim.maxBssId; i++) {
913 			session = &mac->lim.gpSession[i];
914 			if (session->valid &&
915 			    (session->opmode == QDF_SAP_MODE)) {
916 				/* Find the sta ds entry in another session */
917 				sta_ds = dph_lookup_hash_entry(mac,
918 						peerMacAddr, &assoc_id,
919 						&session->dph.dphHashTable);
920 				if (sta_ds)
921 					break;
922 			}
923 		}
924 		if (sta_ds) {
925 			if (lim_add_sta(mac, sta_ds, false, session) !=
926 					QDF_STATUS_SUCCESS)
927 					pe_err("could not Add STA with assocId: %d",
928 					sta_ds->assocId);
929 		}
930 		status = lim_prepare_disconnect_done_ind(mac, &pMsg,
931 							 smesessionId,
932 							 reasonCode,
933 							 &peerMacAddr[0]);
934 		if (!QDF_IS_STATUS_SUCCESS(status)) {
935 			pe_err("Failed to prepare message");
936 			return;
937 		}
938 		break;
939 
940 	case eLIM_HOST_DISASSOC:
941 		/**
942 		 * Disassociation response due to
943 		 * host triggered disassociation
944 		 */
945 
946 		pSirSmeDisassocRsp = qdf_mem_malloc(sizeof(struct disassoc_rsp));
947 		if (!pSirSmeDisassocRsp) {
948 			failure = true;
949 			goto error;
950 		}
951 		pe_debug("send eWNI_SME_DISASSOC_RSP with retCode: %d for "
952 			 QDF_MAC_ADDR_FMT,
953 			 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr));
954 		pSirSmeDisassocRsp->messageType = eWNI_SME_DISASSOC_RSP;
955 		pSirSmeDisassocRsp->length = sizeof(struct disassoc_rsp);
956 		pSirSmeDisassocRsp->sessionId = smesessionId;
957 		pSirSmeDisassocRsp->status_code = reasonCode;
958 		qdf_mem_copy(pSirSmeDisassocRsp->peer_macaddr.bytes,
959 			     peerMacAddr, sizeof(tSirMacAddr));
960 
961 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
962 
963 		lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_RSP_EVENT,
964 				      pe_session, (uint16_t) reasonCode, 0);
965 #endif
966 		pMsg = (uint32_t *) pSirSmeDisassocRsp;
967 		break;
968 
969 	case eLIM_PEER_ENTITY_DISASSOC:
970 	case eLIM_LINK_MONITORING_DISASSOC:
971 		status = lim_prepare_disconnect_done_ind(mac, &pMsg,
972 						smesessionId,
973 						reasonCode, &peerMacAddr[0]);
974 		if (!QDF_IS_STATUS_SUCCESS(status)) {
975 			pe_err("Failed to prepare message");
976 			return;
977 		}
978 		break;
979 
980 	default:
981 		/**
982 		 * Disassociation indication due to Disassociation
983 		 * frame reception from peer entity or due to
984 		 * loss of link with peer entity.
985 		 */
986 		pSirSmeDisassocInd =
987 				qdf_mem_malloc(sizeof(*pSirSmeDisassocInd));
988 		if (!pSirSmeDisassocInd) {
989 			failure = true;
990 			goto error;
991 		}
992 		pe_debug("send eWNI_SME_DISASSOC_IND with retCode: %d for "
993 			 QDF_MAC_ADDR_FMT,
994 			 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr));
995 		pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND;
996 		pSirSmeDisassocInd->length = sizeof(*pSirSmeDisassocInd);
997 		pSirSmeDisassocInd->vdev_id = smesessionId;
998 		pSirSmeDisassocInd->reasonCode = reasonCode;
999 		pSirSmeDisassocInd->status_code = reasonCode;
1000 		qdf_mem_copy(pSirSmeDisassocInd->bssid.bytes,
1001 			     pe_session->bssId, sizeof(tSirMacAddr));
1002 		qdf_mem_copy(pSirSmeDisassocInd->peer_macaddr.bytes,
1003 			     peerMacAddr, sizeof(tSirMacAddr));
1004 
1005 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1006 		lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_IND_EVENT,
1007 				      pe_session, (uint16_t) reasonCode, 0);
1008 #endif
1009 		pMsg = (uint32_t *) pSirSmeDisassocInd;
1010 
1011 		break;
1012 	}
1013 
1014 error:
1015 	/* Delete the PE session Created */
1016 	if ((pe_session) && LIM_IS_STA_ROLE(pe_session))
1017 		pe_delete_session(mac, pe_session);
1018 
1019 	if (failure)
1020 		return;
1021 
1022 	opmode = wlan_get_opmode_from_vdev_id(mac->pdev, smesessionId);
1023 	if ((opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) &&
1024 	    pSirSmeDisassocInd &&
1025 	    pSirSmeDisassocInd->messageType == eWNI_SME_DISASSOC_IND) {
1026 		struct scheduler_msg msg = {0};
1027 
1028 		msg.type = pSirSmeDisassocInd->messageType;
1029 		msg.bodyptr = pSirSmeDisassocInd;
1030 
1031 		return lim_send_sta_disconnect_ind(mac, &msg);
1032 	}
1033 
1034 	lim_send_sme_disassoc_deauth_ntf(mac, QDF_STATUS_SUCCESS,
1035 					 (uint32_t *)pMsg);
1036 } /*** end lim_send_sme_disassoc_ntf() ***/
1037 
lim_is_disconnect_from_ap(enum eLimDisassocTrigger trigger)1038 static bool lim_is_disconnect_from_ap(enum eLimDisassocTrigger trigger)
1039 {
1040 	if (trigger == eLIM_PEER_ENTITY_DEAUTH ||
1041 	    trigger == eLIM_PEER_ENTITY_DISASSOC)
1042 		return true;
1043 
1044 	return false;
1045 }
1046 
1047 /** -----------------------------------------------------------------
1048    \brief lim_send_sme_disassoc_ind() - sends SME_DISASSOC_IND
1049 
1050    After receiving disassociation frame from peer entity, this
1051    function sends a eWNI_SME_DISASSOC_IND to SME with a specific
1052    reason code.
1053 
1054    \param mac - global mac structure
1055    \param sta - station dph hash node
1056    \return none
1057    \sa
1058    ----------------------------------------------------------------- */
1059 void
lim_send_sme_disassoc_ind(struct mac_context * mac,tpDphHashNode sta,struct pe_session * pe_session)1060 lim_send_sme_disassoc_ind(struct mac_context *mac, tpDphHashNode sta,
1061 			  struct pe_session *pe_session)
1062 {
1063 	struct scheduler_msg mmhMsg = {0};
1064 	struct disassoc_ind *pSirSmeDisassocInd;
1065 
1066 	pSirSmeDisassocInd = qdf_mem_malloc(sizeof(*pSirSmeDisassocInd));
1067 	if (!pSirSmeDisassocInd)
1068 		return;
1069 
1070 	pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND;
1071 	pSirSmeDisassocInd->length = sizeof(*pSirSmeDisassocInd);
1072 
1073 	pSirSmeDisassocInd->vdev_id = pe_session->smeSessionId;
1074 	pSirSmeDisassocInd->status_code = eSIR_SME_DEAUTH_STATUS;
1075 	pSirSmeDisassocInd->reasonCode = sta->mlmStaContext.disassocReason;
1076 
1077 	qdf_mem_copy(pSirSmeDisassocInd->bssid.bytes, pe_session->bssId,
1078 		     QDF_MAC_ADDR_SIZE);
1079 
1080 	qdf_mem_copy(pSirSmeDisassocInd->peer_macaddr.bytes, sta->staAddr,
1081 		     QDF_MAC_ADDR_SIZE);
1082 
1083 	if (LIM_IS_STA_ROLE(pe_session))
1084 		pSirSmeDisassocInd->from_ap =
1085 		lim_is_disconnect_from_ap(sta->mlmStaContext.cleanupTrigger);
1086 
1087 	mmhMsg.type = eWNI_SME_DISASSOC_IND;
1088 	mmhMsg.bodyptr = pSirSmeDisassocInd;
1089 	mmhMsg.bodyval = 0;
1090 
1091 	MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1092 			 pe_session->peSessionId, mmhMsg.type));
1093 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1094 	lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, pe_session,
1095 			      0, (uint16_t) sta->mlmStaContext.disassocReason);
1096 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1097 
1098 	if (LIM_IS_STA_ROLE(pe_session))
1099 		return lim_send_sta_disconnect_ind(mac, &mmhMsg);
1100 
1101 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
1102 
1103 } /*** end lim_send_sme_disassoc_ind() ***/
1104 
1105 /** -----------------------------------------------------------------
1106    \brief lim_send_sme_deauth_ind() - sends SME_DEAUTH_IND
1107 
1108    After receiving deauthentication frame from peer entity, this
1109    function sends a eWNI_SME_DEAUTH_IND to SME with a specific
1110    reason code.
1111 
1112    \param mac - global mac structure
1113    \param sta - station dph hash node
1114    \return none
1115    \sa
1116    ----------------------------------------------------------------- */
1117 void
lim_send_sme_deauth_ind(struct mac_context * mac,tpDphHashNode sta,struct pe_session * pe_session)1118 lim_send_sme_deauth_ind(struct mac_context *mac, tpDphHashNode sta,
1119 			struct pe_session *pe_session)
1120 {
1121 	struct scheduler_msg mmhMsg = {0};
1122 	struct deauth_ind *pSirSmeDeauthInd;
1123 
1124 	pSirSmeDeauthInd = qdf_mem_malloc(sizeof(*pSirSmeDeauthInd));
1125 	if (!pSirSmeDeauthInd)
1126 		return;
1127 
1128 	pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND;
1129 	pSirSmeDeauthInd->length = sizeof(*pSirSmeDeauthInd);
1130 
1131 	pSirSmeDeauthInd->vdev_id = pe_session->smeSessionId;
1132 	if (eSIR_INFRA_AP_MODE == pe_session->bssType) {
1133 		pSirSmeDeauthInd->status_code =
1134 			(tSirResultCodes) sta->mlmStaContext.cleanupTrigger;
1135 	} else {
1136 		/* Need to indicate the reason code over the air */
1137 		pSirSmeDeauthInd->status_code =
1138 			(tSirResultCodes) sta->mlmStaContext.disassocReason;
1139 	}
1140 	/* BSSID */
1141 	qdf_mem_copy(pSirSmeDeauthInd->bssid.bytes, pe_session->bssId,
1142 		     QDF_MAC_ADDR_SIZE);
1143 	/* peerMacAddr */
1144 	qdf_mem_copy(pSirSmeDeauthInd->peer_macaddr.bytes, sta->staAddr,
1145 		     QDF_MAC_ADDR_SIZE);
1146 	pSirSmeDeauthInd->reasonCode = sta->mlmStaContext.disassocReason;
1147 
1148 	if (sta->mlmStaContext.disassocReason == REASON_STA_LEAVING)
1149 		pSirSmeDeauthInd->rssi = sta->del_sta_ctx_rssi;
1150 
1151 	if (LIM_IS_STA_ROLE(pe_session))
1152 		pSirSmeDeauthInd->from_ap =
1153 		lim_is_disconnect_from_ap(sta->mlmStaContext.cleanupTrigger);
1154 
1155 	mmhMsg.type = eWNI_SME_DEAUTH_IND;
1156 	mmhMsg.bodyptr = pSirSmeDeauthInd;
1157 	mmhMsg.bodyval = 0;
1158 
1159 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, mmhMsg.type));
1160 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1161 	lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, pe_session,
1162 			      0, sta->mlmStaContext.cleanupTrigger);
1163 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1164 
1165 	if (LIM_IS_STA_ROLE(pe_session))
1166 		return lim_send_sta_disconnect_ind(mac, &mmhMsg);
1167 
1168 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
1169 	return;
1170 } /*** end lim_send_sme_deauth_ind() ***/
1171 
1172 #ifdef FEATURE_WLAN_TDLS
1173 /**
1174  * lim_send_sme_tdls_del_sta_ind()
1175  *
1176  ***FUNCTION:
1177  * This function is called to send the TDLS STA context deletion to SME.
1178  *
1179  ***LOGIC:
1180  *
1181  ***ASSUMPTIONS:
1182  *
1183  ***NOTE:
1184  * NA
1185  *
1186  * @param  mac   - Pointer to global MAC structure
1187  * @param  sta - Pointer to internal STA Datastructure
1188  * @param  pe_session - Pointer to the session entry
1189  * @param  reasonCode - Reason for TDLS sta deletion
1190  * @return None
1191  */
1192 void
lim_send_sme_tdls_del_sta_ind(struct mac_context * mac,tpDphHashNode sta,struct pe_session * pe_session,uint16_t reasonCode)1193 lim_send_sme_tdls_del_sta_ind(struct mac_context *mac, tpDphHashNode sta,
1194 			      struct pe_session *pe_session, uint16_t reasonCode)
1195 {
1196 	struct tdls_event_info info;
1197 
1198 	pe_debug("Delete TDLS Peer "QDF_MAC_ADDR_FMT "with reason code: %d",
1199 			QDF_MAC_ADDR_REF(sta->staAddr), reasonCode);
1200 	info.vdev_id = pe_session->smeSessionId;
1201 	qdf_mem_copy(info.peermac.bytes, sta->staAddr, QDF_MAC_ADDR_SIZE);
1202 	info.message_type = TDLS_PEER_DISCONNECTED;
1203 	info.peer_reason = TDLS_DISCONNECTED_PEER_DELETE;
1204 
1205 	tgt_tdls_event_handler(mac->psoc, &info);
1206 
1207 	return;
1208 } /*** end lim_send_sme_tdls_del_sta_ind() ***/
1209 
1210 /**
1211  * lim_send_sme_mgmt_tx_completion()
1212  *
1213  ***FUNCTION:
1214  * This function is called to send the eWNI_SME_MGMT_FRM_TX_COMPLETION_IND
1215  * message to SME.
1216  *
1217  ***LOGIC:
1218  *
1219  ***ASSUMPTIONS:
1220  *
1221  ***NOTE:
1222  * NA
1223  *
1224  * @param  mac   - Pointer to global MAC structure
1225  * @param  pe_session - Pointer to the session entry
1226  * @param  txCompleteStatus - TX Complete Status of Mgmt Frames
1227  * @return None
1228  */
1229 void
lim_send_sme_mgmt_tx_completion(struct mac_context * mac,uint32_t vdev_id,uint32_t txCompleteStatus)1230 lim_send_sme_mgmt_tx_completion(struct mac_context *mac,
1231 				uint32_t vdev_id,
1232 				uint32_t txCompleteStatus)
1233 {
1234 	struct scheduler_msg msg = {0};
1235 	struct tdls_mgmt_tx_completion_ind *mgmt_tx_completion_ind;
1236 	QDF_STATUS status;
1237 
1238 	mgmt_tx_completion_ind =
1239 		qdf_mem_malloc(sizeof(*mgmt_tx_completion_ind));
1240 	if (!mgmt_tx_completion_ind)
1241 		return;
1242 
1243 	/* sessionId */
1244 	mgmt_tx_completion_ind->vdev_id = vdev_id;
1245 
1246 	mgmt_tx_completion_ind->tx_complete_status = txCompleteStatus;
1247 
1248 	msg.type = eWNI_SME_MGMT_FRM_TX_COMPLETION_IND;
1249 	msg.bodyptr = mgmt_tx_completion_ind;
1250 	msg.bodyval = 0;
1251 
1252 	mgmt_tx_completion_ind->psoc = mac->psoc;
1253 	msg.callback = tgt_tdls_send_mgmt_tx_completion;
1254 	status = scheduler_post_message(QDF_MODULE_ID_PE,
1255 			       QDF_MODULE_ID_TDLS,
1256 			       QDF_MODULE_ID_TARGET_IF, &msg);
1257 	if (QDF_IS_STATUS_ERROR(status)) {
1258 		pe_err("post msg fail, %d", status);
1259 		qdf_mem_free(mgmt_tx_completion_ind);
1260 	}
1261 } /*** end lim_send_sme_tdls_delete_all_peer_ind() ***/
1262 
1263 #endif /* FEATURE_WLAN_TDLS */
1264 
lim_prepare_disconnect_done_ind(struct mac_context * mac_ctx,uint32_t ** msg,uint8_t session_id,tSirResultCodes reason_code,uint8_t * peer_mac_addr)1265 QDF_STATUS lim_prepare_disconnect_done_ind(struct mac_context *mac_ctx,
1266 					   uint32_t **msg,
1267 					   uint8_t session_id,
1268 					   tSirResultCodes reason_code,
1269 					   uint8_t *peer_mac_addr)
1270 {
1271 	struct sir_sme_discon_done_ind *sir_sme_dis_ind;
1272 
1273 	sir_sme_dis_ind = qdf_mem_malloc(sizeof(*sir_sme_dis_ind));
1274 	if (!sir_sme_dis_ind)
1275 		return QDF_STATUS_E_FAILURE;
1276 
1277 	pe_debug("Prepare eWNI_SME_DISCONNECT_DONE_IND withretCode: %d",
1278 		 reason_code);
1279 
1280 	sir_sme_dis_ind->message_type = eWNI_SME_DISCONNECT_DONE_IND;
1281 	sir_sme_dis_ind->length = sizeof(*sir_sme_dis_ind);
1282 	sir_sme_dis_ind->session_id = session_id;
1283 	if (peer_mac_addr)
1284 		qdf_mem_copy(sir_sme_dis_ind->peer_mac,
1285 			     peer_mac_addr, ETH_ALEN);
1286 
1287 	/*
1288 	 * Instead of sending deauth reason code as 505 which is
1289 	 * internal value(eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE)
1290 	 * Send reason code as zero to Supplicant
1291 	 */
1292 	if (reason_code == eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE)
1293 		sir_sme_dis_ind->reason_code = 0;
1294 	else
1295 		sir_sme_dis_ind->reason_code = reason_code;
1296 
1297 	*msg = (uint32_t *)sir_sme_dis_ind;
1298 
1299 	return QDF_STATUS_SUCCESS;
1300 }
1301 
lim_send_sme_deauth_ntf(struct mac_context * mac,tSirMacAddr peerMacAddr,tSirResultCodes reasonCode,uint16_t deauthTrigger,uint16_t aid,uint8_t smesessionId)1302 void lim_send_sme_deauth_ntf(struct mac_context *mac, tSirMacAddr peerMacAddr,
1303 			     tSirResultCodes reasonCode, uint16_t deauthTrigger,
1304 			     uint16_t aid, uint8_t smesessionId)
1305 {
1306 	uint8_t *pBuf;
1307 	struct deauth_rsp *pSirSmeDeauthRsp;
1308 	struct deauth_ind *pSirSmeDeauthInd = NULL;
1309 	struct pe_session *pe_session;
1310 	uint8_t sessionId;
1311 	uint32_t *pMsg = NULL;
1312 	QDF_STATUS status;
1313 	enum QDF_OPMODE opmode;
1314 
1315 	pe_session = pe_find_session_by_bssid(mac, peerMacAddr, &sessionId);
1316 	switch (deauthTrigger) {
1317 	case eLIM_HOST_DEAUTH:
1318 		/**
1319 		 * Deauthentication response to host triggered
1320 		 * deauthentication.
1321 		 */
1322 		pSirSmeDeauthRsp = qdf_mem_malloc(sizeof(*pSirSmeDeauthRsp));
1323 		if (!pSirSmeDeauthRsp)
1324 			return;
1325 		pe_debug("send eWNI_SME_DEAUTH_RSP with retCode: %d for "
1326 			 QDF_MAC_ADDR_FMT,
1327 			 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr));
1328 		pSirSmeDeauthRsp->messageType = eWNI_SME_DEAUTH_RSP;
1329 		pSirSmeDeauthRsp->length = sizeof(*pSirSmeDeauthRsp);
1330 		pSirSmeDeauthRsp->status_code = reasonCode;
1331 		pSirSmeDeauthRsp->sessionId = smesessionId;
1332 
1333 		pBuf = (uint8_t *) pSirSmeDeauthRsp->peer_macaddr.bytes;
1334 		qdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr));
1335 
1336 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1337 		lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_RSP_EVENT,
1338 				      pe_session, 0, (uint16_t) reasonCode);
1339 #endif
1340 		pMsg = (uint32_t *) pSirSmeDeauthRsp;
1341 
1342 		break;
1343 
1344 	case eLIM_PEER_ENTITY_DEAUTH:
1345 	case eLIM_LINK_MONITORING_DEAUTH:
1346 		status = lim_prepare_disconnect_done_ind(mac, &pMsg,
1347 						smesessionId, reasonCode,
1348 						&peerMacAddr[0]);
1349 		if (!QDF_IS_STATUS_SUCCESS(status)) {
1350 			pe_err("Failed to prepare message");
1351 			return;
1352 		}
1353 		break;
1354 	default:
1355 		/**
1356 		 * Deauthentication indication due to Deauthentication
1357 		 * frame reception from peer entity or due to
1358 		 * loss of link with peer entity.
1359 		 */
1360 		pSirSmeDeauthInd = qdf_mem_malloc(sizeof(*pSirSmeDeauthInd));
1361 		if (!pSirSmeDeauthInd)
1362 			return;
1363 		pe_debug("send eWNI_SME_DEAUTH_IND with retCode: %d for "
1364 			 QDF_MAC_ADDR_FMT,
1365 			 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr));
1366 		pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND;
1367 		pSirSmeDeauthInd->length = sizeof(*pSirSmeDeauthInd);
1368 		pSirSmeDeauthInd->reasonCode = REASON_UNSPEC_FAILURE;
1369 		pSirSmeDeauthInd->vdev_id = smesessionId;
1370 		pSirSmeDeauthInd->status_code = reasonCode;
1371 		qdf_mem_copy(pSirSmeDeauthInd->bssid.bytes, pe_session->bssId,
1372 			     sizeof(tSirMacAddr));
1373 		qdf_mem_copy(pSirSmeDeauthInd->peer_macaddr.bytes, peerMacAddr,
1374 			     QDF_MAC_ADDR_SIZE);
1375 
1376 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1377 		lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_IND_EVENT,
1378 				      pe_session, 0, (uint16_t) reasonCode);
1379 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1380 		pMsg = (uint32_t *) pSirSmeDeauthInd;
1381 
1382 		break;
1383 	}
1384 
1385 	/*Delete the PE session  created */
1386 	if (pe_session && LIM_IS_STA_ROLE(pe_session))
1387 		pe_delete_session(mac, pe_session);
1388 
1389 	opmode = wlan_get_opmode_from_vdev_id(mac->pdev, smesessionId);
1390 	if ((opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) &&
1391 	    pSirSmeDeauthInd &&
1392 	    pSirSmeDeauthInd->messageType == eWNI_SME_DEAUTH_IND) {
1393 		struct scheduler_msg msg = {0};
1394 
1395 		msg.type = pSirSmeDeauthInd->messageType;
1396 		msg.bodyptr = pSirSmeDeauthInd;
1397 		return lim_send_sta_disconnect_ind(mac, &msg);
1398 	}
1399 
1400 	lim_send_sme_disassoc_deauth_ntf(mac, QDF_STATUS_SUCCESS,
1401 					 (uint32_t *) pMsg);
1402 
1403 } /*** end lim_send_sme_deauth_ntf() ***/
1404 
lim_send_sme_set_context_rsp(struct mac_context * mac,struct qdf_mac_addr peer_macaddr,uint16_t aid,tSirResultCodes resultCode,struct pe_session * pe_session,uint8_t smesessionId)1405 void lim_send_sme_set_context_rsp(struct mac_context *mac,
1406 				  struct qdf_mac_addr peer_macaddr,
1407 				  uint16_t aid,
1408 				  tSirResultCodes resultCode,
1409 				  struct pe_session *pe_session,
1410 				  uint8_t smesessionId)
1411 {
1412 	struct scheduler_msg mmhMsg = {0};
1413 	struct set_context_rsp *set_context_rsp;
1414 
1415 	set_context_rsp = qdf_mem_malloc(sizeof(*set_context_rsp));
1416 	if (!set_context_rsp)
1417 		return;
1418 
1419 	set_context_rsp->messageType = eWNI_SME_SETCONTEXT_RSP;
1420 	set_context_rsp->length = sizeof(*set_context_rsp);
1421 	set_context_rsp->status_code = resultCode;
1422 
1423 	qdf_copy_macaddr(&set_context_rsp->peer_macaddr, &peer_macaddr);
1424 
1425 	set_context_rsp->sessionId = smesessionId;
1426 
1427 	mmhMsg.type = eWNI_SME_SETCONTEXT_RSP;
1428 	mmhMsg.bodyptr = set_context_rsp;
1429 	mmhMsg.bodyval = 0;
1430 	if (!pe_session) {
1431 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1432 				 NO_SESSION, mmhMsg.type));
1433 	} else {
1434 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1435 				 pe_session->peSessionId, mmhMsg.type));
1436 	}
1437 
1438 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1439 	lim_diag_event_report(mac, WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT,
1440 			      pe_session, (uint16_t) resultCode, 0);
1441 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1442 
1443 	mac->lim.sme_msg_callback(mac, &mmhMsg);
1444 } /*** end lim_send_sme_set_context_rsp() ***/
1445 
lim_send_sme_addts_rsp(struct mac_context * mac,uint8_t rspReqd,uint32_t status,struct pe_session * pe_session,struct mac_tspec_ie tspec,uint8_t smesessionId)1446 void lim_send_sme_addts_rsp(struct mac_context *mac,
1447 			    uint8_t rspReqd, uint32_t status,
1448 			    struct pe_session *pe_session,
1449 			    struct mac_tspec_ie tspec,
1450 			    uint8_t smesessionId)
1451 {
1452 	tpSirAddtsRsp rsp;
1453 	struct scheduler_msg mmhMsg = {0};
1454 
1455 	if (!rspReqd)
1456 		return;
1457 
1458 	rsp = qdf_mem_malloc(sizeof(tSirAddtsRsp));
1459 	if (!rsp)
1460 		return;
1461 
1462 	rsp->messageType = eWNI_SME_ADDTS_RSP;
1463 	rsp->rc = status;
1464 	rsp->rsp.status = (enum wlan_status_code)status;
1465 	rsp->rsp.tspec = tspec;
1466 	rsp->sessionId = smesessionId;
1467 
1468 	mmhMsg.type = eWNI_SME_ADDTS_RSP;
1469 	mmhMsg.bodyptr = rsp;
1470 	mmhMsg.bodyval = 0;
1471 	if (!pe_session) {
1472 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1473 				 NO_SESSION, mmhMsg.type));
1474 	} else {
1475 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1476 				 pe_session->peSessionId, mmhMsg.type));
1477 	}
1478 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1479 	lim_diag_event_report(mac, WLAN_PE_DIAG_ADDTS_RSP_EVENT, pe_session, 0,
1480 			      0);
1481 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1482 
1483 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
1484 	return;
1485 }
1486 
lim_send_sme_delts_rsp(struct mac_context * mac,tpSirDeltsReq delts,uint32_t status,struct pe_session * pe_session,uint8_t smesessionId)1487 void lim_send_sme_delts_rsp(struct mac_context *mac, tpSirDeltsReq delts,
1488 			    uint32_t status, struct pe_session *pe_session,
1489 			    uint8_t smesessionId)
1490 {
1491 	tpSirDeltsRsp rsp;
1492 	struct scheduler_msg mmhMsg = {0};
1493 
1494 	pe_debug("SendSmeDeltsRsp aid: %d tsid: %d up: %d status: %d",
1495 		delts->aid,
1496 		delts->req.tsinfo.traffic.tsid,
1497 		delts->req.tsinfo.traffic.userPrio, status);
1498 	if (!delts->rspReqd)
1499 		return;
1500 
1501 	rsp = qdf_mem_malloc(sizeof(tSirDeltsRsp));
1502 	if (!rsp)
1503 		return;
1504 
1505 	if (pe_session) {
1506 
1507 		rsp->aid = delts->aid;
1508 		qdf_copy_macaddr(&rsp->macaddr, &delts->macaddr);
1509 		qdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) &delts->req,
1510 			     sizeof(struct delts_req_info));
1511 	}
1512 
1513 	rsp->messageType = eWNI_SME_DELTS_RSP;
1514 	rsp->rc = status;
1515 	rsp->sessionId = smesessionId;
1516 
1517 	mmhMsg.type = eWNI_SME_DELTS_RSP;
1518 	mmhMsg.bodyptr = rsp;
1519 	mmhMsg.bodyval = 0;
1520 	if (!pe_session) {
1521 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1522 				 NO_SESSION, mmhMsg.type));
1523 	} else {
1524 		MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1525 				 pe_session->peSessionId, mmhMsg.type));
1526 	}
1527 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1528 	lim_diag_event_report(mac, WLAN_PE_DIAG_DELTS_RSP_EVENT, pe_session,
1529 			      (uint16_t) status, 0);
1530 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1531 
1532 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
1533 }
1534 
1535 void
lim_send_sme_delts_ind(struct mac_context * mac,struct delts_req_info * delts,uint16_t aid,struct pe_session * pe_session)1536 lim_send_sme_delts_ind(struct mac_context *mac, struct delts_req_info *delts,
1537 		       uint16_t aid, struct pe_session *pe_session)
1538 {
1539 	tpSirDeltsRsp rsp;
1540 	struct scheduler_msg mmhMsg = {0};
1541 
1542 	pe_debug("SendSmeDeltsInd aid: %d tsid: %d up: %d",
1543 		aid, delts->tsinfo.traffic.tsid, delts->tsinfo.traffic.userPrio);
1544 
1545 	rsp = qdf_mem_malloc(sizeof(tSirDeltsRsp));
1546 	if (!rsp)
1547 		return;
1548 
1549 	rsp->messageType = eWNI_SME_DELTS_IND;
1550 	rsp->rc = QDF_STATUS_SUCCESS;
1551 	rsp->aid = aid;
1552 	qdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) delts, sizeof(*delts));
1553 	rsp->sessionId = pe_session->smeSessionId;
1554 
1555 	mmhMsg.type = eWNI_SME_DELTS_IND;
1556 	mmhMsg.bodyptr = rsp;
1557 	mmhMsg.bodyval = 0;
1558 	MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, mmhMsg.type));
1559 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM    /* FEATURE_WLAN_DIAG_SUPPORT */
1560 	lim_diag_event_report(mac, WLAN_PE_DIAG_DELTS_IND_EVENT, pe_session, 0,
1561 			      0);
1562 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
1563 
1564 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
1565 }
1566 
1567 #ifdef FEATURE_WLAN_ESE
1568 /**
1569  * lim_send_sme_pe_ese_tsm_rsp() - send tsm response
1570  * @mac:   Pointer to global mac structure
1571  * @pStats: Pointer to TSM Stats
1572  *
1573  * This function is called to send tsm stats response to HDD.
1574  * This function posts the result back to HDD. This is a response to
1575  * HDD's request to get tsm stats.
1576  *
1577  * Return: None
1578  */
lim_send_sme_pe_ese_tsm_rsp(struct mac_context * mac,tAniGetTsmStatsRsp * pStats)1579 void lim_send_sme_pe_ese_tsm_rsp(struct mac_context *mac,
1580 				 tAniGetTsmStatsRsp *pStats)
1581 {
1582 	struct scheduler_msg mmhMsg = {0};
1583 	uint8_t sessionId;
1584 	tAniGetTsmStatsRsp *pPeStats = (tAniGetTsmStatsRsp *) pStats;
1585 	struct pe_session *pPeSessionEntry = NULL;
1586 
1587 	/* Get the Session Id based on Sta Id */
1588 	pPeSessionEntry = pe_find_session_by_bssid(mac, pPeStats->bssid.bytes,
1589 						   &sessionId);
1590 	/* Fill the Session Id */
1591 	if (pPeSessionEntry) {
1592 		/* Fill the Session Id */
1593 		pPeStats->sessionId = pPeSessionEntry->smeSessionId;
1594 	} else {
1595 		pe_err("Session not found for the Sta peer:" QDF_MAC_ADDR_FMT,
1596 		       QDF_MAC_ADDR_REF(pPeStats->bssid.bytes));
1597 		qdf_mem_free(pPeStats->tsmStatsReq);
1598 		qdf_mem_free(pPeStats);
1599 		return;
1600 	}
1601 
1602 	pPeStats->msgType = eWNI_SME_GET_TSM_STATS_RSP;
1603 	pPeStats->tsmMetrics.RoamingCount
1604 		= pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingCount;
1605 	pPeStats->tsmMetrics.RoamingDly
1606 		= pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingDly;
1607 
1608 	mmhMsg.type = eWNI_SME_GET_TSM_STATS_RSP;
1609 	mmhMsg.bodyptr = pStats;
1610 	mmhMsg.bodyval = 0;
1611 	MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, sessionId, mmhMsg.type));
1612 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
1613 
1614 	return;
1615 } /*** end lim_send_sme_pe_ese_tsm_rsp() ***/
1616 
1617 #endif /* FEATURE_WLAN_ESE */
1618 
1619 /**
1620  * lim_process_csa_wbw_ie() - Process CSA Wide BW IE
1621  * @mac_ctx:         pointer to global adapter context
1622  * @csa_params:      pointer to CSA parameters
1623  * @chnl_switch_info:pointer to channel switch parameters
1624  * @session_entry:   session pointer
1625  *
1626  * Return: None
1627  */
lim_process_csa_wbw_ie(struct mac_context * mac_ctx,struct csa_offload_params * csa_params,tLimWiderBWChannelSwitchInfo * chnl_switch_info,struct pe_session * session_entry)1628 static QDF_STATUS lim_process_csa_wbw_ie(struct mac_context *mac_ctx,
1629 		struct csa_offload_params *csa_params,
1630 		tLimWiderBWChannelSwitchInfo *chnl_switch_info,
1631 		struct pe_session *session_entry)
1632 {
1633 	struct ch_params ch_params = {0};
1634 	enum phy_ch_width ap_new_ch_width;
1635 	uint8_t center_freq_diff;
1636 	uint32_t fw_vht_ch_wd = wma_get_vht_ch_width() + 1;
1637 	uint32_t cent_freq1, cent_freq2;
1638 	uint32_t csa_cent_freq, csa_cent_freq1 = 0, csa_cent_freq2 = 0;
1639 
1640 	ap_new_ch_width = csa_params->new_ch_width;
1641 
1642 	if (!csa_params->new_ch_freq_seg1 && !csa_params->new_ch_freq_seg2)
1643 		return QDF_STATUS_E_INVAL;
1644 
1645 	csa_cent_freq = csa_params->csa_chan_freq;
1646 	if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
1647 				      csa_params->new_op_class)) {
1648 		cent_freq1 = wlan_reg_chan_opclass_to_freq(
1649 					csa_params->new_ch_freq_seg1,
1650 					csa_params->new_op_class, false);
1651 		cent_freq2 = wlan_reg_chan_opclass_to_freq(
1652 					csa_params->new_ch_freq_seg2,
1653 					csa_params->new_op_class, false);
1654 	} else {
1655 		cent_freq1 = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev,
1656 					csa_params->new_ch_freq_seg1);
1657 		cent_freq2 = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev,
1658 					csa_params->new_ch_freq_seg2);
1659 	}
1660 
1661 	switch (ap_new_ch_width) {
1662 	case CH_WIDTH_80MHZ:
1663 		csa_cent_freq1 = cent_freq1;
1664 		if (csa_params->new_ch_freq_seg2) {
1665 			center_freq_diff = abs(csa_params->new_ch_freq_seg2 -
1666 					       csa_params->new_ch_freq_seg1);
1667 			if (center_freq_diff == CENTER_FREQ_DIFF_160MHz) {
1668 				ap_new_ch_width = CH_WIDTH_160MHZ;
1669 				csa_cent_freq1 = cent_freq2;
1670 				csa_params->new_ch_freq_seg1 =
1671 						csa_params->new_ch_freq_seg2;
1672 				csa_params->new_ch_freq_seg2 = 0;
1673 			} else if (center_freq_diff > CENTER_FREQ_DIFF_160MHz) {
1674 				ap_new_ch_width = CH_WIDTH_80P80MHZ;
1675 				csa_cent_freq2 = cent_freq2;
1676 			}
1677 		}
1678 		break;
1679 	case CH_WIDTH_80P80MHZ:
1680 		csa_cent_freq1 = cent_freq1;
1681 		csa_cent_freq2 = cent_freq2;
1682 		break;
1683 	case CH_WIDTH_160MHZ:
1684 		csa_cent_freq1 = cent_freq1;
1685 		break;
1686 	default:
1687 		pe_debug("CSA wide BW IE has ch_width %d", ap_new_ch_width);
1688 		return QDF_STATUS_E_INVAL;
1689 	}
1690 
1691 	/* Verify whether the bandwidth and channel segments are valid. */
1692 	switch (ap_new_ch_width) {
1693 	case CH_WIDTH_80MHZ:
1694 		if (abs(csa_cent_freq1 - csa_cent_freq) != 10 &&
1695 		    abs(csa_cent_freq1 - csa_cent_freq) != 30) {
1696 			pe_err("CSA WBW 80MHz has invalid seg0 freq %d",
1697 			       csa_cent_freq1);
1698 			return QDF_STATUS_E_INVAL;
1699 		}
1700 		if (csa_cent_freq2) {
1701 			pe_err("CSA WBW 80MHz has invalid seg1 freq %d",
1702 			       csa_cent_freq2);
1703 			return QDF_STATUS_E_INVAL;
1704 		}
1705 		break;
1706 	case CH_WIDTH_80P80MHZ:
1707 		if (abs(csa_cent_freq1 - csa_cent_freq) != 10 &&
1708 		    abs(csa_cent_freq1 - csa_cent_freq) != 30) {
1709 			pe_err("CSA WBW 80MHz has invalid seg0 freq %d",
1710 			       csa_cent_freq1);
1711 			return QDF_STATUS_E_INVAL;
1712 		}
1713 		if (!csa_cent_freq2) {
1714 			pe_err("CSA WBW 80MHz has invalid seg1 freq %d",
1715 			       csa_cent_freq2);
1716 			return QDF_STATUS_E_INVAL;
1717 		}
1718 		/* adjacent is not allowed -- that's a 160 MHz channel */
1719 		if (abs(csa_cent_freq1 - csa_cent_freq2) == 80) {
1720 			pe_err("CSA WBW wrong bandwidth");
1721 			return QDF_STATUS_E_INVAL;
1722 		}
1723 		break;
1724 	case CH_WIDTH_160MHZ:
1725 		if (abs(csa_cent_freq1 - csa_cent_freq) != 70 &&
1726 		    abs(csa_cent_freq1 - csa_cent_freq) != 50 &&
1727 		    abs(csa_cent_freq1 - csa_cent_freq) != 30 &&
1728 		    abs(csa_cent_freq1 - csa_cent_freq) != 10) {
1729 			pr_err("CSA WBW 160MHz has invalid seg0 freq %d",
1730 			       csa_cent_freq1);
1731 			return QDF_STATUS_E_INVAL;
1732 		}
1733 		if (csa_cent_freq2) {
1734 			pe_err("CSA WBW 80MHz has invalid seg1 freq %d",
1735 			       csa_cent_freq2);
1736 			return QDF_STATUS_E_INVAL;
1737 		}
1738 		break;
1739 	default:
1740 		pe_err("CSA wide BW IE has wrong ch_width %d", ap_new_ch_width);
1741 		return QDF_STATUS_E_INVAL;
1742 	}
1743 
1744 	if (ap_new_ch_width > fw_vht_ch_wd) {
1745 		pe_debug("New BW is not supported, downgrade BW to %d",
1746 			 fw_vht_ch_wd);
1747 		ap_new_ch_width = fw_vht_ch_wd;
1748 	}
1749 	ch_params.ch_width = ap_new_ch_width;
1750 	wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
1751 						csa_params->csa_chan_freq,
1752 						0, &ch_params,
1753 						REG_CURRENT_PWR_MODE);
1754 	ap_new_ch_width = ch_params.ch_width;
1755 	csa_params->new_ch_freq_seg1 = ch_params.center_freq_seg0;
1756 	csa_params->new_ch_freq_seg2 = ch_params.center_freq_seg1;
1757 
1758 	session_entry->gLimChannelSwitch.state =
1759 		eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
1760 
1761 	chnl_switch_info->newChanWidth = ap_new_ch_width;
1762 	chnl_switch_info->newCenterChanFreq0 = csa_params->new_ch_freq_seg1;
1763 	chnl_switch_info->newCenterChanFreq1 = csa_params->new_ch_freq_seg2;
1764 
1765 	return QDF_STATUS_SUCCESS;
1766 }
1767 
lim_is_csa_channel_allowed(struct mac_context * mac_ctx,struct pe_session * session_entry,qdf_freq_t ch_freq1,struct csa_offload_params * csa_params)1768 static bool lim_is_csa_channel_allowed(struct mac_context *mac_ctx,
1769 				       struct pe_session *session_entry,
1770 				       qdf_freq_t ch_freq1,
1771 				       struct csa_offload_params *csa_params)
1772 {
1773 	bool is_allowed = true;
1774 	u32 cnx_count = 0;
1775 	enum QDF_OPMODE mode;
1776 	qdf_freq_t csa_freq = csa_params->csa_chan_freq, sec_ch_2g_freq = 0;
1777 	enum phy_ch_width new_ch_width = csa_params->new_ch_width;
1778 	enum channel_state chan_state;
1779 
1780 	if (!session_entry->vdev ||
1781 	    wlan_cm_is_vdev_disconnecting(session_entry->vdev) ||
1782 	    wlan_cm_is_vdev_disconnected(session_entry->vdev)) {
1783 		pe_warn("CSA is ignored, vdev %d is disconnecting/ed",
1784 			session_entry->vdev_id);
1785 		return false;
1786 	}
1787 
1788 	/*
1789 	 * This is a temporary check and will be removed once ll_lt_sap CSA
1790 	 * support is added.
1791 	 */
1792 	if (policy_mgr_get_ll_lt_sap_freq(mac_ctx->psoc) == csa_freq) {
1793 		pe_err("CSA not allowed on LL_LT_SAP freq %d", csa_freq);
1794 		lim_tear_down_link_with_ap(mac_ctx, session_entry->peSessionId,
1795 					   REASON_CHANNEL_SWITCH_FAILED,
1796 					   eLIM_HOST_DISASSOC);
1797 		return false;
1798 	}
1799 
1800 	if (WLAN_REG_IS_24GHZ_CH_FREQ(csa_freq) &&
1801 	    wlan_reg_get_bw_value(new_ch_width) > 20) {
1802 		if (csa_params->new_ch_freq_seg1 == csa_params->channel + 2)
1803 			sec_ch_2g_freq = csa_freq + HT40_SEC_OFFSET;
1804 		else if (csa_params->new_ch_freq_seg1 == csa_params->channel - 2)
1805 			sec_ch_2g_freq = csa_freq - HT40_SEC_OFFSET;
1806 	}
1807 
1808 	chan_state = wlan_reg_get_bonded_channel_state_for_pwrmode(
1809 						mac_ctx->pdev,
1810 						csa_freq, new_ch_width,
1811 						sec_ch_2g_freq,
1812 						REG_CURRENT_PWR_MODE);
1813 	if (chan_state == CHANNEL_STATE_INVALID ||
1814 	    chan_state == CHANNEL_STATE_DISABLE) {
1815 		pe_err("Invalid csa_freq %d ch_width %d ccfs0 %d ccfs1 %d sec_ch %d. Disconnect",
1816 		       csa_freq, new_ch_width, csa_params->new_ch_freq_seg1,
1817 		       csa_params->new_ch_freq_seg2, sec_ch_2g_freq);
1818 		lim_tear_down_link_with_ap(mac_ctx,
1819 					   session_entry->peSessionId,
1820 					   REASON_CHANNEL_SWITCH_FAILED,
1821 					   eLIM_HOST_DISASSOC);
1822 		return false;
1823 	}
1824 
1825 	mode = wlan_vdev_mlme_get_opmode(session_entry->vdev);
1826 	cnx_count = policy_mgr_get_connection_count(mac_ctx->psoc);
1827 	if ((cnx_count > 1) && !policy_mgr_is_hw_dbs_capable(mac_ctx->psoc) &&
1828 	    !policy_mgr_is_interband_mcc_supported(mac_ctx->psoc)) {
1829 		is_allowed = wlan_reg_is_same_band_freqs(ch_freq1, csa_freq);
1830 	} else if (cnx_count > 2) {
1831 		is_allowed =
1832 		policy_mgr_allow_concurrency_csa(
1833 			mac_ctx->psoc,
1834 			policy_mgr_qdf_opmode_to_pm_con_mode(mac_ctx->psoc,
1835 							     mode,
1836 							     session_entry->vdev_id),
1837 			csa_freq,
1838 			policy_mgr_get_bw(new_ch_width),
1839 			session_entry->vdev_id, false,
1840 			CSA_REASON_UNKNOWN);
1841 	}
1842 
1843 	return is_allowed;
1844 }
1845 
1846 #ifdef WLAN_FEATURE_11BE
1847 /**
1848  * lim_set_csa_chan_param_11be() - set csa chan params for 11be
1849  * @session: pointer to pe session
1850  * @csa_param: pointer to csa_offload_params
1851  * @ch_param: channel parameters to get
1852  *
1853  * Return: void
1854  */
lim_set_csa_chan_param_11be(struct pe_session * session,struct csa_offload_params * csa_param,struct ch_params * ch_param)1855 static void lim_set_csa_chan_param_11be(struct pe_session *session,
1856 					struct csa_offload_params *csa_param,
1857 					struct ch_params *ch_param)
1858 {
1859 	if (!session || !csa_param || !ch_param || !session->vdev) {
1860 		pe_err("invalid input parameter");
1861 		return;
1862 	}
1863 
1864 	if (csa_param->new_ch_width == CH_WIDTH_320MHZ &&
1865 	    !session->eht_config.support_320mhz_6ghz)
1866 		ch_param->ch_width = CH_WIDTH_160MHZ;
1867 
1868 	wlan_cm_sta_set_chan_param(session->vdev,
1869 				   csa_param->csa_chan_freq,
1870 				   csa_param->new_ch_width,
1871 				   csa_param->new_punct_bitmap,
1872 				   csa_param->new_ch_freq_seg1,
1873 				   csa_param->new_ch_freq_seg2,
1874 				   ch_param);
1875 }
1876 
1877 /**
1878  * lim_set_chan_sw_puncture() - set puncture to channel switch info
1879  * @lim_ch_switch: pointer to tLimChannelSwitchInfo
1880  * @ch_param: pointer to ch_params
1881  *
1882  * Return: void
1883  */
lim_set_chan_sw_puncture(tLimChannelSwitchInfo * lim_ch_switch,struct ch_params * ch_param)1884 static void lim_set_chan_sw_puncture(tLimChannelSwitchInfo *lim_ch_switch,
1885 				     struct ch_params *ch_param)
1886 {
1887 	lim_ch_switch->puncture_bitmap = ch_param->reg_punc_bitmap;
1888 }
1889 
1890 /**
1891  * lim_reset_csa_puncture() - reset puncture of channel switch
1892  * @lim_ch_switch: pointer to tLimChannelSwitchInfo
1893  *
1894  * Return: void
1895  */
lim_reset_csa_puncture(tLimChannelSwitchInfo * lim_ch_switch)1896 static void lim_reset_csa_puncture(tLimChannelSwitchInfo *lim_ch_switch)
1897 {
1898 	lim_ch_switch->puncture_bitmap = 0;
1899 }
1900 
1901 /**
1902  * lim_is_puncture_same() - Check whether puncture changed
1903  * @lim_ch_switch: pointer to tLimChannelSwitchInfo
1904  * @session: pe session
1905  *
1906  * Return: bool, true: puncture changed
1907  */
lim_is_puncture_same(tLimChannelSwitchInfo * lim_ch_switch,struct pe_session * session)1908 static bool lim_is_puncture_same(tLimChannelSwitchInfo *lim_ch_switch,
1909 				 struct pe_session *session)
1910 {
1911 	pe_debug("vdevid %d puncture, old: 0x%x, new: 0x%x", session->vdev_id,
1912 		 session->puncture_bitmap,
1913 		 lim_ch_switch->puncture_bitmap);
1914 	return lim_ch_switch->puncture_bitmap == session->puncture_bitmap;
1915 }
1916 
update_csa_link_info(struct wlan_objmgr_vdev * vdev,uint8_t link_id,struct csa_offload_params * csa_params)1917 static void update_csa_link_info(struct wlan_objmgr_vdev *vdev,
1918 				 uint8_t link_id,
1919 				 struct csa_offload_params *csa_params)
1920 {
1921 	struct wlan_objmgr_pdev *pdev;
1922 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
1923 
1924 	pdev = wlan_vdev_get_pdev(vdev);
1925 	if (!pdev) {
1926 		pe_err("pdev is null");
1927 		return;
1928 	}
1929 
1930 	mlo_mgr_update_csa_link_info(pdev, vdev->mlo_dev_ctx,
1931 				     csa_params, link_id);
1932 	pe_debug("vdev_id: %d link id %d mlo csa sta param updated ",
1933 		 vdev_id, link_id);
1934 }
1935 
1936 static bool
lim_mlo_is_csa_allow(struct wlan_objmgr_vdev * vdev,uint16_t csa_freq)1937 lim_mlo_is_csa_allow(struct wlan_objmgr_vdev *vdev, uint16_t csa_freq)
1938 {
1939 	return wlan_mlo_is_csa_allow(vdev, csa_freq);
1940 }
1941 
1942 #else
lim_set_csa_chan_param_11be(struct pe_session * session,struct csa_offload_params * csa_param,struct ch_params * ch_param)1943 static void lim_set_csa_chan_param_11be(struct pe_session *session,
1944 					struct csa_offload_params *csa_param,
1945 					struct ch_params *ch_param)
1946 {
1947 }
1948 
lim_set_chan_sw_puncture(tLimChannelSwitchInfo * lim_ch_switch,struct ch_params * ch_param)1949 static void lim_set_chan_sw_puncture(tLimChannelSwitchInfo *lim_ch_switch,
1950 				     struct ch_params *ch_param)
1951 {
1952 }
1953 
lim_reset_csa_puncture(tLimChannelSwitchInfo * lim_ch_switch)1954 static void lim_reset_csa_puncture(tLimChannelSwitchInfo *lim_ch_switch)
1955 {
1956 }
1957 
lim_is_puncture_same(tLimChannelSwitchInfo * lim_ch_switch,struct pe_session * session)1958 static bool lim_is_puncture_same(tLimChannelSwitchInfo *lim_ch_switch,
1959 				 struct pe_session *session)
1960 {
1961 	return true;
1962 }
1963 
update_csa_link_info(struct wlan_objmgr_vdev * vdev,uint8_t link_id,struct csa_offload_params * csa_params)1964 static void update_csa_link_info(struct wlan_objmgr_vdev *vdev,
1965 				 uint8_t link_id,
1966 				 struct csa_offload_params *csa_params)
1967 {
1968 }
1969 
1970 static bool
lim_mlo_is_csa_allow(struct wlan_objmgr_vdev * vdev,uint16_t csa_freq)1971 lim_mlo_is_csa_allow(struct wlan_objmgr_vdev *vdev, uint16_t csa_freq)
1972 {
1973 	return true;
1974 }
1975 #endif
1976 
1977 /**
1978  * lim_sta_follow_csa() - Check if STA needs to follow CSA
1979  * @session_entry: Session pointer
1980  * @csa_params: Pointer to CSA params
1981  * @lim_ch_switch: Pointer to lim channel switch info
1982  * @ch_params: Channel params
1983  *
1984  * Return: True if CSA is required, else return false.
1985  */
lim_sta_follow_csa(struct pe_session * session_entry,struct csa_offload_params * csa_params,tLimChannelSwitchInfo * lim_ch_switch,struct ch_params ch_params)1986 static bool lim_sta_follow_csa(struct pe_session *session_entry,
1987 			       struct csa_offload_params *csa_params,
1988 			       tLimChannelSwitchInfo *lim_ch_switch,
1989 			       struct ch_params ch_params)
1990 {
1991 	if (session_entry->curr_op_freq == csa_params->csa_chan_freq &&
1992 	    session_entry->ch_width == ch_params.ch_width &&
1993 	    lim_is_puncture_same(lim_ch_switch, session_entry)) {
1994 		pe_debug("Ignore CSA, no change in ch, bw and puncture");
1995 		return false;
1996 	}
1997 	return true;
1998 }
1999 
lim_handle_sta_csa_param(struct mac_context * mac_ctx,struct csa_offload_params * csa_params,bool send_status)2000 void lim_handle_sta_csa_param(struct mac_context *mac_ctx,
2001 			      struct csa_offload_params *csa_params,
2002 			      bool send_status)
2003 {
2004 	struct pe_session *session_entry;
2005 	struct mlme_legacy_priv *mlme_priv;
2006 	tpDphHashNode sta_ds = NULL;
2007 	uint8_t session_id;
2008 	uint16_t aid = 0;
2009 	uint16_t chan_space = 0;
2010 	struct ch_params ch_params = {0};
2011 	uint32_t channel_bonding_mode;
2012 	uint8_t country_code[CDS_COUNTRY_CODE_LEN + 1];
2013 	tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL;
2014 	tLimChannelSwitchInfo *lim_ch_switch = NULL;
2015 	uint8_t link_id;
2016 
2017 	if (!csa_params) {
2018 		pe_err("limMsgQ body ptr is NULL");
2019 		return;
2020 	}
2021 
2022 	session_entry =
2023 		pe_find_session_by_bssid(mac_ctx,
2024 			csa_params->bssid.bytes, &session_id);
2025 	if (!session_entry) {
2026 		pe_err("Session does not exists for "QDF_MAC_ADDR_FMT,
2027 		       QDF_MAC_ADDR_REF(csa_params->bssid.bytes));
2028 		goto free;
2029 	}
2030 	sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->bssId, &aid,
2031 		&session_entry->dph.dphHashTable);
2032 
2033 	if (!sta_ds) {
2034 		pe_err("sta_ds does not exist");
2035 		goto send_event;
2036 	}
2037 
2038 	if (!LIM_IS_STA_ROLE(session_entry)) {
2039 		pe_debug("Invalid role to handle CSA");
2040 		goto send_event;
2041 	}
2042 
2043 	lim_ch_switch = &session_entry->gLimChannelSwitch;
2044 	ch_params.ch_width = csa_params->new_ch_width;
2045 
2046 	if (IS_DOT11_MODE_EHT(session_entry->dot11mode))
2047 		lim_set_csa_chan_param_11be(session_entry, csa_params,
2048 					    &ch_params);
2049 	else
2050 		wlan_reg_set_channel_params_for_pwrmode(
2051 					     mac_ctx->pdev,
2052 					     csa_params->csa_chan_freq,
2053 					     0, &ch_params,
2054 					     REG_CURRENT_PWR_MODE);
2055 	lim_set_chan_sw_puncture(lim_ch_switch, &ch_params);
2056 
2057 	if (!lim_sta_follow_csa(session_entry, csa_params,
2058 				lim_ch_switch, ch_params))
2059 		goto send_event;
2060 	else
2061 		qdf_mem_zero(&ch_params, sizeof(struct ch_params));
2062 
2063 	if (!lim_is_csa_channel_allowed(mac_ctx, session_entry,
2064 					session_entry->curr_op_freq,
2065 					csa_params)) {
2066 		pe_debug("Channel switch is not allowed");
2067 		goto send_event;
2068 	}
2069 
2070 	if (!lim_mlo_is_csa_allow(session_entry->vdev,
2071 				  csa_params->csa_chan_freq)) {
2072 		pe_debug("Channel switch for MLO vdev is not allowed");
2073 		goto send_event;
2074 	}
2075 	/*
2076 	 * on receiving channel switch announcement from AP, delete all
2077 	 * TDLS peers before leaving BSS and proceed for channel switch
2078 	 */
2079 
2080 	lim_update_tdls_set_state_for_fw(session_entry, false);
2081 	lim_delete_tdls_peers(mac_ctx, session_entry);
2082 
2083 	lim_ch_switch->switchMode = csa_params->switch_mode;
2084 	/* timer already started by firmware, switch immediately */
2085 	lim_ch_switch->switchCount = 0;
2086 	lim_ch_switch->primaryChannel =
2087 		csa_params->channel;
2088 	lim_ch_switch->sw_target_freq =
2089 		csa_params->csa_chan_freq;
2090 	lim_ch_switch->state =
2091 		eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
2092 	lim_ch_switch->ch_width = CH_WIDTH_20MHZ;
2093 	lim_reset_csa_puncture(lim_ch_switch);
2094 
2095 	lim_ch_switch->sec_ch_offset =
2096 		session_entry->htSecondaryChannelOffset;
2097 	lim_ch_switch->ch_center_freq_seg0 = 0;
2098 	lim_ch_switch->ch_center_freq_seg1 = 0;
2099 	chnl_switch_info =
2100 		&session_entry->gLimWiderBWChannelSwitch;
2101 
2102 	channel_bonding_mode = lim_get_cb_mode_for_freq(mac_ctx, session_entry,
2103 						   csa_params->csa_chan_freq);
2104 
2105 	pe_debug("Session %d vdev %d: vht: %d ht: %d he %d cbmode %d",
2106 		 session_entry->peSessionId, session_entry->vdev_id,
2107 		 session_entry->vhtCapability,
2108 		 session_entry->htSupportedChannelWidthSet,
2109 		 lim_is_session_he_capable(session_entry),
2110 		 channel_bonding_mode);
2111 
2112 	session_entry->htSupportedChannelWidthSet = false;
2113 	wlan_reg_read_current_country(mac_ctx->psoc, country_code);
2114 	if (!csa_params->ies_present_flag ||
2115 	    (csa_params->ies_present_flag & MLME_CSWRAP_IE_EXT_V2_PRESENT)) {
2116 		pe_debug("new freq: %u, width: %d", csa_params->csa_chan_freq,
2117 			 csa_params->new_ch_width);
2118 		ch_params.ch_width = csa_params->new_ch_width;
2119 		if (IS_DOT11_MODE_EHT(session_entry->dot11mode))
2120 			lim_set_csa_chan_param_11be(session_entry, csa_params,
2121 						    &ch_params);
2122 		else
2123 			wlan_reg_set_channel_params_for_pwrmode(
2124 						     mac_ctx->pdev,
2125 						     csa_params->csa_chan_freq,
2126 						     0, &ch_params,
2127 						     REG_CURRENT_PWR_MODE);
2128 		pe_debug("idea width: %d, chn_seg0 %u chn_seg1 %u freq_seg0 %u freq_seg1 %u",
2129 			 ch_params.ch_width, ch_params.center_freq_seg0,
2130 			 ch_params.center_freq_seg1, ch_params.mhz_freq_seg0,
2131 			 ch_params.mhz_freq_seg1);
2132 
2133 		lim_ch_switch->sec_ch_offset = ch_params.sec_ch_offset;
2134 		lim_ch_switch->ch_width = ch_params.ch_width;
2135 		lim_ch_switch->ch_center_freq_seg0 = ch_params.center_freq_seg0;
2136 		lim_ch_switch->ch_center_freq_seg1 = ch_params.center_freq_seg1;
2137 		lim_set_chan_sw_puncture(lim_ch_switch, &ch_params);
2138 
2139 		if (ch_params.ch_width == CH_WIDTH_20MHZ) {
2140 			lim_ch_switch->state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
2141 			session_entry->htSupportedChannelWidthSet = false;
2142 		} else {
2143 			chnl_switch_info->newChanWidth =
2144 				lim_ch_switch->ch_width;
2145 			chnl_switch_info->newCenterChanFreq0 =
2146 				lim_ch_switch->ch_center_freq_seg0;
2147 			chnl_switch_info->newCenterChanFreq1 =
2148 				lim_ch_switch->ch_center_freq_seg1;
2149 			lim_ch_switch->state =
2150 				eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
2151 			session_entry->htSupportedChannelWidthSet = true;
2152 		}
2153 	} else if (channel_bonding_mode &&
2154 	    ((session_entry->vhtCapability && session_entry->htCapability) ||
2155 	      lim_is_session_he_capable(session_entry))) {
2156 		if ((csa_params->ies_present_flag & MLME_WBW_IE_PRESENT) &&
2157 		    (QDF_STATUS_SUCCESS == lim_process_csa_wbw_ie(
2158 					mac_ctx, csa_params, chnl_switch_info,
2159 					session_entry))) {
2160 			lim_ch_switch->sec_ch_offset =
2161 				PHY_SINGLE_CHANNEL_CENTERED;
2162 			if (chnl_switch_info->newChanWidth) {
2163 				ch_params.ch_width =
2164 					chnl_switch_info->newChanWidth;
2165 				wlan_reg_set_channel_params_for_pwrmode(
2166 						mac_ctx->pdev,
2167 						csa_params->csa_chan_freq,
2168 						0, &ch_params,
2169 						REG_CURRENT_PWR_MODE);
2170 				lim_ch_switch->sec_ch_offset =
2171 					ch_params.sec_ch_offset;
2172 				session_entry->htSupportedChannelWidthSet =
2173 									true;
2174 			}
2175 		} else if (csa_params->ies_present_flag
2176 				& MLME_XCSA_IE_PRESENT) {
2177 			uint32_t fw_vht_ch_wd = wma_get_vht_ch_width();
2178 
2179 			if (wlan_reg_is_6ghz_op_class
2180 				(mac_ctx->pdev, csa_params->new_op_class)) {
2181 				chan_space = wlan_reg_get_op_class_width
2182 					(mac_ctx->pdev,
2183 					 csa_params->new_op_class, true);
2184 			} else {
2185 				chan_space =
2186 				wlan_reg_dmn_get_chanwidth_from_opclass_auto(
2187 						country_code,
2188 						csa_params->channel,
2189 						csa_params->new_op_class);
2190 			}
2191 			if (chan_space >= 160 && fw_vht_ch_wd <
2192 					WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
2193 				chan_space = 80;
2194 			lim_ch_switch->state =
2195 				eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
2196 			if (chan_space == 160) {
2197 				chnl_switch_info->newChanWidth =
2198 					CH_WIDTH_160MHZ;
2199 			} else if (chan_space == 80) {
2200 				chnl_switch_info->newChanWidth =
2201 					CH_WIDTH_80MHZ;
2202 				session_entry->htSupportedChannelWidthSet =
2203 									true;
2204 			} else if (chan_space == 40) {
2205 				chnl_switch_info->newChanWidth =
2206 					CH_WIDTH_40MHZ;
2207 				session_entry->htSupportedChannelWidthSet =
2208 									true;
2209 			} else {
2210 				chnl_switch_info->newChanWidth =
2211 					CH_WIDTH_20MHZ;
2212 				lim_ch_switch->state =
2213 					eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
2214 			}
2215 
2216 			ch_params.ch_width =
2217 				chnl_switch_info->newChanWidth;
2218 			wlan_reg_set_channel_params_for_pwrmode(
2219 				mac_ctx->pdev, csa_params->csa_chan_freq, 0,
2220 				&ch_params, REG_CURRENT_PWR_MODE);
2221 			chnl_switch_info->newCenterChanFreq0 =
2222 				ch_params.center_freq_seg0;
2223 			/*
2224 			 * This is not applicable for 20/40/80 MHz.
2225 			 * Only used when we support 80+80 MHz operation.
2226 			 * In case of 80+80 MHz, this parameter indicates
2227 			 * center channel frequency index of 80 MHz
2228 			 * channel offrequency segment 1.
2229 			 */
2230 			chnl_switch_info->newCenterChanFreq1 =
2231 				ch_params.center_freq_seg1;
2232 			lim_ch_switch->sec_ch_offset =
2233 				ch_params.sec_ch_offset;
2234 		} else {
2235 			lim_ch_switch->state =
2236 				eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
2237 			ch_params.ch_width = CH_WIDTH_40MHZ;
2238 			wlan_reg_set_channel_params_for_pwrmode(
2239 						mac_ctx->pdev,
2240 						csa_params->csa_chan_freq,
2241 						0, &ch_params,
2242 						REG_CURRENT_PWR_MODE);
2243 			lim_ch_switch->sec_ch_offset =
2244 				ch_params.sec_ch_offset;
2245 			chnl_switch_info->newChanWidth = CH_WIDTH_40MHZ;
2246 			chnl_switch_info->newCenterChanFreq0 =
2247 				ch_params.center_freq_seg0;
2248 			chnl_switch_info->newCenterChanFreq1 = 0;
2249 			session_entry->htSupportedChannelWidthSet = true;
2250 		}
2251 		lim_ch_switch->ch_center_freq_seg0 =
2252 			chnl_switch_info->newCenterChanFreq0;
2253 		lim_ch_switch->ch_center_freq_seg1 =
2254 			chnl_switch_info->newCenterChanFreq1;
2255 		lim_ch_switch->ch_width =
2256 			chnl_switch_info->newChanWidth;
2257 
2258 	} else if (channel_bonding_mode && session_entry->htCapability) {
2259 		if (csa_params->ies_present_flag
2260 				& MLME_XCSA_IE_PRESENT) {
2261 			chan_space =
2262 				wlan_reg_dmn_get_chanwidth_from_opclass_auto(
2263 						country_code,
2264 						csa_params->channel,
2265 						csa_params->new_op_class);
2266 			lim_ch_switch->state =
2267 				eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
2268 			if (chan_space == 40) {
2269 				lim_ch_switch->ch_width =
2270 					CH_WIDTH_40MHZ;
2271 				chnl_switch_info->newChanWidth =
2272 					CH_WIDTH_40MHZ;
2273 				ch_params.ch_width =
2274 					chnl_switch_info->newChanWidth;
2275 				wlan_reg_set_channel_params_for_pwrmode(
2276 						mac_ctx->pdev,
2277 						csa_params->csa_chan_freq,
2278 						0, &ch_params,
2279 						REG_CURRENT_PWR_MODE);
2280 				lim_ch_switch->ch_center_freq_seg0 =
2281 					ch_params.center_freq_seg0;
2282 				lim_ch_switch->sec_ch_offset =
2283 					ch_params.sec_ch_offset;
2284 				session_entry->htSupportedChannelWidthSet =
2285 									true;
2286 			} else {
2287 				lim_ch_switch->ch_width =
2288 					CH_WIDTH_20MHZ;
2289 				chnl_switch_info->newChanWidth =
2290 					CH_WIDTH_20MHZ;
2291 				lim_ch_switch->state =
2292 					eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
2293 				lim_ch_switch->sec_ch_offset =
2294 					PHY_SINGLE_CHANNEL_CENTERED;
2295 			}
2296 		} else {
2297 			lim_ch_switch->ch_width =
2298 				CH_WIDTH_40MHZ;
2299 			lim_ch_switch->state =
2300 				eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
2301 			ch_params.ch_width = CH_WIDTH_40MHZ;
2302 			wlan_reg_set_channel_params_for_pwrmode(
2303 						mac_ctx->pdev,
2304 						csa_params->csa_chan_freq,
2305 						0, &ch_params,
2306 						REG_CURRENT_PWR_MODE);
2307 			lim_ch_switch->ch_center_freq_seg0 =
2308 				ch_params.center_freq_seg0;
2309 			lim_ch_switch->sec_ch_offset =
2310 				ch_params.sec_ch_offset;
2311 			session_entry->htSupportedChannelWidthSet = true;
2312 		}
2313 	}
2314 
2315 	lim_cp_stats_cstats_log_csa_evt(session_entry, CSTATS_DIR_RX,
2316 					lim_ch_switch->sw_target_freq,
2317 					lim_ch_switch->ch_width,
2318 					lim_ch_switch->switchMode);
2319 
2320 	pe_debug("new ch %d: freq %d width: %d freq0 %d freq1 %d ht width %d, current freq %d: bw %d",
2321 		 lim_ch_switch->primaryChannel, lim_ch_switch->sw_target_freq,
2322 		 lim_ch_switch->ch_width, lim_ch_switch->ch_center_freq_seg0,
2323 		 lim_ch_switch->ch_center_freq_seg1,
2324 		 lim_ch_switch->sec_ch_offset, session_entry->curr_op_freq,
2325 		 session_entry->ch_width);
2326 
2327 	if (!lim_sta_follow_csa(session_entry, csa_params,
2328 				lim_ch_switch, ch_params))
2329 		goto send_event;
2330 
2331 	if (wlan_vdev_mlme_is_mlo_vdev(session_entry->vdev)) {
2332 		link_id = wlan_vdev_get_link_id(session_entry->vdev);
2333 		update_csa_link_info(session_entry->vdev, link_id, csa_params);
2334 	} else {
2335 		mlme_priv = wlan_vdev_mlme_get_ext_hdl(session_entry->vdev);
2336 		if (!mlme_priv)
2337 			return;
2338 		mlme_priv->connect_info.assoc_chan_info.assoc_ch_width =
2339 						csa_params->new_ch_width;
2340 	}
2341 
2342 	if (WLAN_REG_IS_24GHZ_CH_FREQ(csa_params->csa_chan_freq) &&
2343 	    session_entry->dot11mode == MLME_DOT11_MODE_11A)
2344 		session_entry->dot11mode = MLME_DOT11_MODE_11G;
2345 	else if (!WLAN_REG_IS_24GHZ_CH_FREQ(csa_params->csa_chan_freq) &&
2346 		 ((session_entry->dot11mode == MLME_DOT11_MODE_11G) ||
2347 		 (session_entry->dot11mode == MLME_DOT11_MODE_11G_ONLY)))
2348 		session_entry->dot11mode = MLME_DOT11_MODE_11A;
2349 
2350 	/* Send RSO Stop to FW before triggering the vdev restart for CSA */
2351 	if (mac_ctx->lim.stop_roaming_callback)
2352 		mac_ctx->lim.stop_roaming_callback(MAC_HANDLE(mac_ctx),
2353 						   session_entry->smeSessionId,
2354 						   REASON_VDEV_RESTART_FROM_HOST,
2355 						   RSO_CHANNEL_SWITCH);
2356 
2357 	if (mlo_is_any_link_disconnecting(session_entry->vdev)) {
2358 		pe_info_rl("Ignore CSA, vdev is in not in conncted state");
2359 		goto send_event;
2360 	}
2361 
2362 	lim_prepare_for11h_channel_switch(mac_ctx, session_entry);
2363 
2364 	lim_flush_bssid(mac_ctx, session_entry->bssId);
2365 
2366 #ifdef FEATURE_WLAN_DIAG_SUPPORT
2367 	lim_diag_event_report(mac_ctx,
2368 			WLAN_PE_DIAG_SWITCH_CHL_IND_EVENT, session_entry,
2369 			QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
2370 #endif
2371 free:
2372 	qdf_mem_free(csa_params);
2373 	return;
2374 send_event:
2375 	if (send_status)
2376 		wlan_mlme_send_csa_event_status_ind(session_entry->vdev, 0);
2377 	qdf_mem_free(csa_params);
2378 }
2379 
lim_handle_csa_offload_msg(struct mac_context * mac_ctx,struct scheduler_msg * msg)2380 void lim_handle_csa_offload_msg(struct mac_context *mac_ctx,
2381 				struct scheduler_msg *msg)
2382 {
2383 	struct pe_session *session;
2384 	struct csa_offload_params *csa_params =
2385 				(struct csa_offload_params *)(msg->bodyptr);
2386 	uint8_t session_id;
2387 
2388 	if (!csa_params) {
2389 		pe_err("limMsgQ body ptr is NULL");
2390 		return;
2391 	}
2392 
2393 	session = pe_find_session_by_bssid(
2394 				mac_ctx, csa_params->bssid.bytes, &session_id);
2395 	if (!session) {
2396 		pe_err("Session does not exists for " QDF_MAC_ADDR_FMT,
2397 		       QDF_MAC_ADDR_REF(csa_params->bssid.bytes));
2398 		qdf_mem_free(csa_params);
2399 		return;
2400 	}
2401 	if (wlan_vdev_mlme_is_mlo_vdev(session->vdev) &&
2402 	    mlo_is_sta_csa_param_handled(session->vdev, csa_params)) {
2403 		pe_debug("vdev_id: %d, csa param is already handled. return",
2404 			 session_id);
2405 		qdf_mem_free(csa_params);
2406 		return;
2407 	}
2408 	lim_handle_sta_csa_param(mac_ctx, csa_params, true);
2409 }
2410 
2411 #ifdef WLAN_FEATURE_11BE_MLO
lim_handle_mlo_sta_csa_param(struct wlan_objmgr_vdev * vdev,struct csa_offload_params * csa_params)2412 void lim_handle_mlo_sta_csa_param(struct wlan_objmgr_vdev *vdev,
2413 				  struct csa_offload_params *csa_params)
2414 {
2415 	struct mac_context *mac;
2416 	struct csa_offload_params *tmp_csa_params;
2417 
2418 	mac = cds_get_context(QDF_MODULE_ID_PE);
2419 	if (!mac) {
2420 		pe_err("mac ctx is null");
2421 		return;
2422 	}
2423 
2424 	tmp_csa_params = qdf_mem_malloc(sizeof(*tmp_csa_params));
2425 	if (!tmp_csa_params) {
2426 		pe_err("tmp_csa_params allocation fails");
2427 		return;
2428 	}
2429 
2430 	qdf_mem_copy(tmp_csa_params, csa_params, sizeof(*tmp_csa_params));
2431 
2432 	lim_handle_sta_csa_param(mac, tmp_csa_params, false);
2433 }
2434 #endif
2435 
2436 /*--------------------------------------------------------------------------
2437    \brief pe_delete_session() - Handle the Delete BSS Response from HAL.
2438 
2439    \param mac                   - pointer to global adapter context
2440    \param sessionId             - Message pointer.
2441 
2442    \sa
2443    --------------------------------------------------------------------------*/
2444 
lim_handle_delete_bss_rsp(struct mac_context * mac,struct del_bss_resp * del_bss_rsp)2445 void lim_handle_delete_bss_rsp(struct mac_context *mac,
2446 			       struct del_bss_resp *del_bss_rsp)
2447 {
2448 	struct pe_session *pe_session;
2449 
2450 	pe_session =
2451 	   pe_find_session_by_vdev_id_and_state(mac,
2452 						del_bss_rsp->vdev_id,
2453 						eLIM_MLM_WT_DEL_BSS_RSP_STATE);
2454 	if (!pe_session) {
2455 		qdf_mem_free(del_bss_rsp);
2456 		return;
2457 	}
2458 
2459 	/*
2460 	 * During DEL BSS handling, the PE Session will be deleted, but it is
2461 	 * better to clear this flag if the session is hanging around due
2462 	 * to some error conditions so that the next DEL_BSS request does
2463 	 * not take the HO_FAIL path
2464 	 */
2465 	pe_session->process_ho_fail = false;
2466 	if (LIM_IS_UNKNOWN_ROLE(pe_session))
2467 		lim_process_sme_del_bss_rsp(mac, pe_session);
2468 	else if (LIM_IS_NDI_ROLE(pe_session))
2469 		lim_ndi_del_bss_rsp(mac, del_bss_rsp, pe_session);
2470 	else
2471 		lim_process_mlm_del_bss_rsp(mac, del_bss_rsp, pe_session);
2472 
2473 	qdf_mem_free(del_bss_rsp);
2474 }
2475 
2476 /** -----------------------------------------------------------------
2477    \brief lim_send_sme_aggr_qos_rsp() - sends SME FT AGGR QOS RSP
2478  \      This function sends a eWNI_SME_FT_AGGR_QOS_RSP to SME.
2479  \      SME only looks at rc and tspec field.
2480    \param mac - global mac structure
2481    \param rspReqd - is SmeAddTsRsp required
2482    \param status - status code of eWNI_SME_FT_AGGR_QOS_RSP
2483    \return tspec
2484    \sa
2485    ----------------------------------------------------------------- */
2486 void
lim_send_sme_aggr_qos_rsp(struct mac_context * mac,tpSirAggrQosRsp aggrQosRsp,uint8_t smesessionId)2487 lim_send_sme_aggr_qos_rsp(struct mac_context *mac, tpSirAggrQosRsp aggrQosRsp,
2488 			  uint8_t smesessionId)
2489 {
2490 	struct scheduler_msg mmhMsg = {0};
2491 
2492 	mmhMsg.type = eWNI_SME_FT_AGGR_QOS_RSP;
2493 	mmhMsg.bodyptr = aggrQosRsp;
2494 	mmhMsg.bodyval = 0;
2495 	MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
2496 			 smesessionId, mmhMsg.type));
2497 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
2498 
2499 	return;
2500 }
2501 
lim_send_sme_max_assoc_exceeded_ntf(struct mac_context * mac,tSirMacAddr peerMacAddr,uint8_t smesessionId)2502 void lim_send_sme_max_assoc_exceeded_ntf(struct mac_context *mac, tSirMacAddr peerMacAddr,
2503 					 uint8_t smesessionId)
2504 {
2505 	struct scheduler_msg mmhMsg = {0};
2506 	tSmeMaxAssocInd *pSmeMaxAssocInd;
2507 
2508 	pSmeMaxAssocInd = qdf_mem_malloc(sizeof(tSmeMaxAssocInd));
2509 	if (!pSmeMaxAssocInd)
2510 		return;
2511 	qdf_mem_copy((uint8_t *) pSmeMaxAssocInd->peer_mac.bytes,
2512 		     (uint8_t *) peerMacAddr, QDF_MAC_ADDR_SIZE);
2513 	pSmeMaxAssocInd->mesgType = eWNI_SME_MAX_ASSOC_EXCEEDED;
2514 	pSmeMaxAssocInd->mesgLen = sizeof(tSmeMaxAssocInd);
2515 	pSmeMaxAssocInd->sessionId = smesessionId;
2516 	mmhMsg.type = pSmeMaxAssocInd->mesgType;
2517 	mmhMsg.bodyptr = pSmeMaxAssocInd;
2518 	pe_debug("msgType: %s peerMacAddr "QDF_MAC_ADDR_FMT "sme session id %d",
2519 		"eWNI_SME_MAX_ASSOC_EXCEEDED", QDF_MAC_ADDR_REF(peerMacAddr),
2520 		pSmeMaxAssocInd->sessionId);
2521 	MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
2522 			 smesessionId, mmhMsg.type));
2523 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
2524 
2525 	return;
2526 }
2527 
2528 /** -----------------------------------------------------------------
2529    \brief lim_send_sme_ap_channel_switch_resp() - sends
2530    eWNI_SME_CHANNEL_CHANGE_RSP
2531    After receiving WMA_SWITCH_CHANNEL_RSP indication this
2532    function sends a eWNI_SME_CHANNEL_CHANGE_RSP to SME to notify
2533    that the Channel change has been done to the specified target
2534    channel in the Channel change request
2535    \param mac - global mac structure
2536    \param pe_session - session info
2537    \param pChnlParams - Channel switch params
2538    --------------------------------------------------------------------*/
2539 void
lim_send_sme_ap_channel_switch_resp(struct mac_context * mac,struct pe_session * pe_session,struct vdev_start_response * rsp)2540 lim_send_sme_ap_channel_switch_resp(struct mac_context *mac,
2541 				    struct pe_session *pe_session,
2542 				    struct vdev_start_response *rsp)
2543 {
2544 	struct scheduler_msg mmhMsg = {0};
2545 	struct sSirChanChangeResponse *chan_change_rsp;
2546 	bool is_ch_dfs = false;
2547 	enum phy_ch_width ch_width;
2548 	uint32_t ch_cfreq1 = 0;
2549 	enum reg_wifi_band band;
2550 
2551 	qdf_runtime_pm_allow_suspend(&pe_session->ap_ecsa_runtime_lock);
2552 	qdf_wake_lock_release(&pe_session->ap_ecsa_wakelock, 0);
2553 
2554 	chan_change_rsp =
2555 		qdf_mem_malloc(sizeof(struct sSirChanChangeResponse));
2556 	if (!chan_change_rsp)
2557 		return;
2558 
2559 	chan_change_rsp->new_op_freq = pe_session->curr_op_freq;
2560 	chan_change_rsp->channelChangeStatus = rsp->status;
2561 	/*
2562 	 * Pass the sme sessionID to SME instead
2563 	 * PE session ID.
2564 	 */
2565 	chan_change_rsp->sessionId = rsp->vdev_id;
2566 
2567 	mmhMsg.type = eWNI_SME_CHANNEL_CHANGE_RSP;
2568 	mmhMsg.bodyptr = (void *)chan_change_rsp;
2569 	mmhMsg.bodyval = 0;
2570 	lim_sys_process_mmh_msg_api(mac, &mmhMsg);
2571 
2572 	if (QDF_IS_STATUS_ERROR(rsp->status)) {
2573 		pe_err("failed to change sap freq to %u",
2574 		       pe_session->curr_op_freq);
2575 		return;
2576 	}
2577 
2578 	/*
2579 	 * We should start beacon transmission only if the new
2580 	 * channel after channel change is Non-DFS. For a DFS
2581 	 * channel, PE will receive an explicit request from
2582 	 * upper layers to start the beacon transmission .
2583 	 */
2584 	ch_width = pe_session->ch_width;
2585 	band = wlan_reg_freq_to_band(pe_session->curr_op_freq);
2586 	if (pe_session->ch_center_freq_seg1)
2587 		ch_cfreq1 = wlan_reg_chan_band_to_freq(
2588 				mac->pdev,
2589 				pe_session->ch_center_freq_seg1,
2590 				BIT(band));
2591 
2592 	if (ch_width == CH_WIDTH_160MHZ) {
2593 		struct ch_params ch_params = {0};
2594 
2595 		if (IS_DOT11_MODE_EHT(pe_session->dot11mode))
2596 			wlan_reg_set_create_punc_bitmap(&ch_params, true);
2597 		ch_params.ch_width = ch_width;
2598 		if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(mac->pdev,
2599 								     pe_session->curr_op_freq,
2600 								     &ch_params,
2601 								     REG_CURRENT_PWR_MODE) ==
2602 		    CHANNEL_STATE_DFS)
2603 			is_ch_dfs = true;
2604 	} else if (ch_width == CH_WIDTH_80P80MHZ) {
2605 		if (wlan_reg_get_channel_state_for_pwrmode(
2606 						mac->pdev,
2607 						pe_session->curr_op_freq,
2608 						REG_CURRENT_PWR_MODE) ==
2609 		    CHANNEL_STATE_DFS ||
2610 		    wlan_reg_get_channel_state_for_pwrmode(
2611 						mac->pdev,
2612 						ch_cfreq1,
2613 						REG_CURRENT_PWR_MODE) ==
2614 				CHANNEL_STATE_DFS)
2615 			is_ch_dfs = true;
2616 	} else {
2617 		/* Indoor channels are also marked DFS, therefore
2618 		 * check if the channel has REGULATORY_CHAN_RADAR
2619 		 * channel flag to identify if the channel is DFS
2620 		 */
2621 		if (wlan_reg_is_dfs_for_freq(mac->pdev,
2622 					     pe_session->curr_op_freq))
2623 			is_ch_dfs = true;
2624 	}
2625 	if (WLAN_REG_IS_6GHZ_CHAN_FREQ(pe_session->curr_op_freq))
2626 		is_ch_dfs = false;
2627 
2628 	if (is_ch_dfs) {
2629 		lim_sap_move_to_cac_wait_state(pe_session);
2630 
2631 	} else {
2632 		lim_apply_configuration(mac, pe_session);
2633 		lim_send_beacon(mac, pe_session);
2634 		lim_obss_send_detection_cfg(mac, pe_session, true);
2635 	}
2636 	return;
2637 }
2638 
2639 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
2640 /**
2641  *  lim_send_bss_color_change_ie_update() - update bss color change IE in
2642  *   beacon template
2643  *
2644  *  @mac_ctx: pointer to global adapter context
2645  *  @session: session pointer
2646  *
2647  *  Return: none
2648  */
2649 static void
lim_send_bss_color_change_ie_update(struct mac_context * mac_ctx,struct pe_session * session)2650 lim_send_bss_color_change_ie_update(struct mac_context *mac_ctx,
2651 						struct pe_session *session)
2652 {
2653 	/* Update the beacon template and send to FW */
2654 	if (sch_set_fixed_beacon_fields(mac_ctx, session) != QDF_STATUS_SUCCESS) {
2655 		pe_err("Unable to set BSS color change IE in beacon");
2656 		return;
2657 	}
2658 
2659 	/* Send update beacon template message */
2660 	lim_send_beacon_ind(mac_ctx, session, REASON_COLOR_CHANGE);
2661 	pe_debug("Updated BSS color change countdown = %d",
2662 		 session->he_bss_color_change.countdown);
2663 }
2664 
2665 #ifdef WLAN_FEATURE_SR
2666 static void
lim_update_spatial_reuse(struct pe_session * session)2667 lim_update_spatial_reuse(struct pe_session *session)
2668 {
2669 	struct wlan_objmgr_psoc *psoc;
2670 	uint32_t conc_vdev_id;
2671 	uint8_t mac_id, sr_ctrl, non_srg_pd_max_offset;
2672 	uint8_t vdev_id = session->vdev_id;
2673 
2674 	sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(session->vdev);
2675 	non_srg_pd_max_offset =
2676 		wlan_vdev_mlme_get_non_srg_pd_offset(session->vdev);
2677 	if (non_srg_pd_max_offset && sr_ctrl &&
2678 	    wlan_vdev_mlme_get_he_spr_enabled(session->vdev)) {
2679 		psoc = wlan_vdev_get_psoc(session->vdev);
2680 		policy_mgr_get_mac_id_by_session_id(psoc,
2681 						    vdev_id,
2682 						    &mac_id);
2683 		conc_vdev_id = policy_mgr_get_conc_vdev_on_same_mac(psoc,
2684 								    vdev_id,
2685 								    mac_id);
2686 		if (conc_vdev_id == WLAN_INVALID_VDEV_ID ||
2687 		    policy_mgr_sr_same_mac_conc_enabled(psoc)) {
2688 			wlan_vdev_mlme_set_sr_disable_due_conc(session->vdev,
2689 							       false);
2690 			wlan_spatial_reuse_config_set(session->vdev, sr_ctrl,
2691 						      non_srg_pd_max_offset);
2692 			wlan_spatial_reuse_osif_event(session->vdev,
2693 						      SR_OPERATION_RESUME,
2694 						      SR_REASON_CODE_CONCURRENCY);
2695 		} else {
2696 			wlan_vdev_mlme_set_sr_disable_due_conc(session->vdev,
2697 							       true);
2698 			wlan_spatial_reuse_config_set(session->vdev, sr_ctrl,
2699 						 NON_SR_PD_THRESHOLD_DISABLED);
2700 			wlan_spatial_reuse_osif_event(session->vdev,
2701 						      SR_OPERATION_SUSPEND,
2702 						      SR_REASON_CODE_CONCURRENCY);
2703 		}
2704 	}
2705 }
2706 #else
2707 static void
lim_update_spatial_reuse(struct pe_session * session)2708 lim_update_spatial_reuse(struct pe_session *session)
2709 {
2710 }
2711 #endif
2712 
2713 static void
lim_handle_bss_color_change_ie(struct mac_context * mac_ctx,struct pe_session * session)2714 lim_handle_bss_color_change_ie(struct mac_context *mac_ctx,
2715 					struct pe_session *session)
2716 {
2717 	tUpdateBeaconParams beacon_params;
2718 
2719 	/* handle bss color change IE */
2720 	if (LIM_IS_AP_ROLE(session) &&
2721 	    session->he_op.bss_col_disabled &&
2722 	    session->he_bss_color_change.new_color) {
2723 		pe_debug("countdown: %d, new_color: %d",
2724 			 session->he_bss_color_change.countdown,
2725 			 session->he_bss_color_change.new_color);
2726 		if (session->he_bss_color_change.countdown > 0) {
2727 			session->he_bss_color_change.countdown--;
2728 		} else {
2729 			session->bss_color_changing = 0;
2730 			/*
2731 			 * On OBSS color collision detection, spatial reuse
2732 			 * gets disabled. Enable spatial reuse if it was
2733 			 * enabled during AP start
2734 			 */
2735 			lim_update_spatial_reuse(session);
2736 			qdf_mem_zero(&beacon_params, sizeof(beacon_params));
2737 			session->he_op.bss_col_disabled = 0;
2738 			session->he_op.bss_color =
2739 				session->he_bss_color_change.new_color;
2740 			session->he_bss_color_change.new_color = 0;
2741 			beacon_params.paramChangeBitmap |=
2742 				PARAM_BSS_COLOR_CHANGED;
2743 			beacon_params.bss_color_disabled = 0;
2744 			beacon_params.bss_color = session->he_op.bss_color;
2745 			lim_send_beacon_params(mac_ctx,
2746 					       &beacon_params,
2747 					       session);
2748 			lim_send_obss_color_collision_cfg(
2749 				mac_ctx, session,
2750 				OBSS_COLOR_COLLISION_DETECTION);
2751 			wma_allow_suspend_after_obss_color_change(
2752 								session->vdev);
2753 		}
2754 		lim_send_bss_color_change_ie_update(mac_ctx, session);
2755 	}
2756 }
2757 
2758 #else
2759 static void
lim_handle_bss_color_change_ie(struct mac_context * mac_ctx,struct pe_session * session)2760 lim_handle_bss_color_change_ie(struct mac_context *mac_ctx,
2761 					struct pe_session *session)
2762 {
2763 }
2764 #endif
2765 
2766 void
lim_process_beacon_tx_success_ind(struct mac_context * mac_ctx,uint16_t msgType,void * event)2767 lim_process_beacon_tx_success_ind(struct mac_context *mac_ctx, uint16_t msgType,
2768 				  void *event)
2769 {
2770 	struct pe_session *session;
2771 	struct wlan_objmgr_vdev *vdev;
2772 	bool csa_tx_offload, is_sap_go_moved_before_sta = false;
2773 	tpSirFirstBeaconTxCompleteInd bcn_ind =
2774 		(tSirFirstBeaconTxCompleteInd *) event;
2775 
2776 	session = pe_find_session_by_vdev_id(mac_ctx, bcn_ind->bss_idx);
2777 	if (!session) {
2778 		pe_err("Session Does not exist for given session id");
2779 		return;
2780 	}
2781 
2782 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
2783 						    session->vdev_id,
2784 						    WLAN_LEGACY_MAC_ID);
2785 	if (vdev) {
2786 		is_sap_go_moved_before_sta =
2787 			wlan_vdev_mlme_is_sap_go_move_before_sta(vdev);
2788 		wlan_vdev_mlme_set_sap_go_move_before_sta(vdev, false);
2789 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
2790 	}
2791 	pe_debug("role: %d swIe: %d opIe: %d switch cnt:%d Is SAP / GO Moved before STA: %d",
2792 		 GET_LIM_SYSTEM_ROLE(session),
2793 		 session->dfsIncludeChanSwIe,
2794 		 session->gLimOperatingMode.present,
2795 		 session->gLimChannelSwitch.switchCount,
2796 		 is_sap_go_moved_before_sta);
2797 
2798 	if (!LIM_IS_AP_ROLE(session))
2799 		return;
2800 	csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc,
2801 						WLAN_SOC_CEXT_CSA_TX_OFFLOAD);
2802 	if ((session->dfsIncludeChanSwIe && !csa_tx_offload &&
2803 	     ((session->gLimChannelSwitch.switchCount ==
2804 	       mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt) ||
2805 	      (session->gLimChannelSwitch.switchCount == 1) ||
2806 	      is_sap_go_moved_before_sta)) ||
2807 	     session->bw_update_include_ch_sw_ie)
2808 		lim_process_ap_ecsa_timeout(session);
2809 
2810 	if (session->gLimOperatingMode.present)
2811 		/* Done with nss update */
2812 		session->gLimOperatingMode.present = 0;
2813 
2814 	lim_handle_bss_color_change_ie(mac_ctx, session);
2815 
2816 	return;
2817 }
2818 
lim_nss_or_ch_width_update_rsp(struct mac_context * mac_ctx,uint8_t vdev_id,QDF_STATUS status,enum sir_bcn_update_reason reason)2819 void lim_nss_or_ch_width_update_rsp(struct mac_context *mac_ctx,
2820 				    uint8_t vdev_id, QDF_STATUS status,
2821 				    enum sir_bcn_update_reason reason)
2822 {
2823 	struct scheduler_msg msg = {0};
2824 	struct sir_bcn_update_rsp *rsp;
2825 	QDF_STATUS qdf_status = QDF_STATUS_E_INVAL;
2826 
2827 	rsp = qdf_mem_malloc(sizeof(*rsp));
2828 	if (rsp) {
2829 		rsp->vdev_id = vdev_id;
2830 		rsp->status = status;
2831 		rsp->reason = reason;
2832 	}
2833 
2834 	if (reason == REASON_NSS_UPDATE)
2835 		msg.type = eWNI_SME_NSS_UPDATE_RSP;
2836 	else if (reason == REASON_CH_WIDTH_UPDATE)
2837 		msg.type = eWNI_SME_SAP_CH_WIDTH_UPDATE_RSP;
2838 	else
2839 		goto done;
2840 
2841 	msg.bodyptr = rsp;
2842 	msg.bodyval = 0;
2843 	qdf_status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_SME,
2844 					    QDF_MODULE_ID_SME, &msg);
2845 done:
2846 	if (QDF_IS_STATUS_ERROR(qdf_status))
2847 		qdf_mem_free(rsp);
2848 }
2849