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