1 /*
2 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: This file contains definitions for target_if roaming events.
20 */
21 #include "qdf_types.h"
22 #include "wlan_objmgr_psoc_obj.h"
23 #include "wlan_objmgr_pdev_obj.h"
24 #include "wlan_objmgr_vdev_obj.h"
25 #include "wmi_unified_api.h"
26 #include "scheduler_api.h"
27 #include <wmi_unified.h>
28 #include "target_if_cm_roam_event.h"
29 #include "wlan_psoc_mlme_api.h"
30 #include "wlan_mlme_main.h"
31 #include <../../core/src/wlan_cm_roam_i.h>
32 #include "wlan_cm_roam_api.h"
33 #include "target_if_cm_roam_offload.h"
34 #include <target_if_vdev_mgr_rx_ops.h>
35 #include <target_if_psoc_wake_lock.h>
36 #include "wlan_mlo_mgr_peer.h"
37 #include "wlan_crypto_global_api.h"
38
39 struct wlan_cm_roam_rx_ops *
target_if_cm_get_roam_rx_ops(struct wlan_objmgr_psoc * psoc)40 target_if_cm_get_roam_rx_ops(struct wlan_objmgr_psoc *psoc)
41 {
42 struct wlan_mlme_psoc_ext_obj *psoc_ext_priv;
43 struct wlan_cm_roam_rx_ops *rx_ops;
44
45 if (!psoc) {
46 target_if_err("psoc object is NULL");
47 return NULL;
48 }
49 psoc_ext_priv = wlan_psoc_mlme_get_ext_hdl(psoc);
50 if (!psoc_ext_priv) {
51 target_if_err("psoc legacy private object is NULL");
52 return NULL;
53 }
54
55 rx_ops = &psoc_ext_priv->rso_rx_ops;
56 return rx_ops;
57 }
58
59 #ifdef WLAN_VENDOR_HANDOFF_CONTROL
target_if_cm_roam_register_vendor_handoff_rx_ops(struct wlan_cm_roam_rx_ops * rx_ops)60 static void target_if_cm_roam_register_vendor_handoff_rx_ops(
61 struct wlan_cm_roam_rx_ops *rx_ops)
62 {
63 rx_ops->roam_vendor_handoff_event =
64 cm_roam_vendor_handoff_event_handler;
65 }
66 #else
67 static inline void
target_if_cm_roam_register_vendor_handoff_rx_ops(struct wlan_cm_roam_rx_ops * rx_ops)68 target_if_cm_roam_register_vendor_handoff_rx_ops(
69 struct wlan_cm_roam_rx_ops *rx_ops)
70 {
71 }
72 #endif
73
74 void
target_if_cm_roam_register_rx_ops(struct wlan_cm_roam_rx_ops * rx_ops)75 target_if_cm_roam_register_rx_ops(struct wlan_cm_roam_rx_ops *rx_ops)
76 {
77 rx_ops->roam_sync_event = cm_roam_sync_event_handler;
78 rx_ops->roam_sync_frame_event = cm_roam_sync_frame_event_handler;
79 rx_ops->roam_sync_key_event = cm_roam_sync_key_event_handler;
80 rx_ops->roam_event_rx = cm_roam_event_handler;
81 rx_ops->btm_denylist_event = cm_btm_denylist_event_handler;
82 rx_ops->vdev_disconnect_event = cm_vdev_disconnect_event_handler;
83 rx_ops->roam_scan_chan_list_event = cm_roam_scan_ch_list_event_handler;
84 rx_ops->roam_stats_event_rx = cm_roam_stats_event_handler;
85 rx_ops->roam_auth_offload_event = cm_roam_auth_offload_event_handler;
86 rx_ops->roam_pmkid_request_event_rx = cm_roam_pmkid_request_handler;
87 rx_ops->roam_candidate_frame_event = cm_roam_candidate_event_handler;
88 target_if_cm_roam_register_vendor_handoff_rx_ops(rx_ops);
89 }
90
target_if_cm_roam_event(ol_scn_t scn,uint8_t * event,uint32_t len)91 int target_if_cm_roam_event(ol_scn_t scn, uint8_t *event, uint32_t len)
92 {
93 QDF_STATUS qdf_status;
94 struct wmi_unified *wmi_handle;
95 struct roam_offload_roam_event *roam_event = NULL;
96 struct wlan_objmgr_psoc *psoc;
97 struct wlan_cm_roam_rx_ops *roam_rx_ops;
98
99 psoc = target_if_get_psoc_from_scn_hdl(scn);
100 if (!psoc) {
101 target_if_err("psoc is null");
102 return -EINVAL;
103 }
104
105 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
106 if (!wmi_handle) {
107 target_if_err("wmi_handle is null");
108 return -EINVAL;
109 }
110
111 roam_event = qdf_mem_malloc(sizeof(*roam_event));
112 if (!roam_event)
113 return -ENOMEM;
114
115 qdf_status = wmi_extract_roam_event(wmi_handle, event, len, roam_event);
116 if (QDF_IS_STATUS_ERROR(qdf_status)) {
117 target_if_err("parsing of event failed, %d", qdf_status);
118 qdf_status = QDF_STATUS_E_INVAL;
119 goto done;
120 }
121
122 roam_event->psoc = psoc;
123
124 /**
125 * Stop the timer upon RSO stop status success. The timer shall continue
126 * to run upon HO_FAIL status and would be stopped upon HO_FAILED event
127 */
128 if ((roam_event->reason == ROAM_REASON_RSO_STATUS &&
129 roam_event->notif_params == WMI_ROAM_SCAN_MODE_NONE) ||
130 roam_event->reason == ROAM_REASON_HO_FAILED)
131 target_if_stop_rso_stop_timer(roam_event);
132
133 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
134 if (!roam_rx_ops || !roam_rx_ops->roam_event_rx) {
135 target_if_err("No valid roam rx ops");
136 qdf_status = QDF_STATUS_E_INVAL;
137 goto done;
138 }
139
140 /**
141 * This can be called from IRQ context for WOW events such as
142 * WOW_REASON_LOW_RSSI and WOW_REASON_HO_FAIL. There is no issue
143 * currently, as these events are posted to schedular thread from
144 * cm_roam_event_handler, to access umac which use mutex.
145 * If any new ROAM event is added in IRQ context in future, avoid taking
146 * mutex. If mutex/sleep is needed, post a message to scheduler thread.
147 */
148 qdf_status = roam_rx_ops->roam_event_rx(roam_event);
149
150 done:
151 qdf_mem_free(roam_event);
152 return qdf_status_to_os_return(qdf_status);
153 }
154
155 QDF_STATUS
target_if_roam_register_common_events(struct wlan_objmgr_psoc * psoc)156 target_if_roam_register_common_events(struct wlan_objmgr_psoc *psoc)
157 {
158 QDF_STATUS ret;
159 wmi_unified_t handle = get_wmi_unified_hdl_from_psoc(psoc);
160
161 if (!handle) {
162 target_if_err("handle is NULL");
163 return QDF_STATUS_E_FAILURE;
164 }
165
166 /* Register for LFR2/3 common roam event */
167 ret = wmi_unified_register_event_handler(handle, wmi_roam_event_id,
168 target_if_cm_roam_event,
169 WMI_RX_SERIALIZER_CTX);
170 if (QDF_IS_STATUS_ERROR(ret)) {
171 target_if_err("wmi event registration failed, ret: %d", ret);
172 return QDF_STATUS_E_FAILURE;
173 }
174
175 return QDF_STATUS_SUCCESS;
176 }
177
178 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
179 static void
target_if_free_roam_synch_frame_ind(struct roam_synch_frame_ind * frame_ind)180 target_if_free_roam_synch_frame_ind(struct roam_synch_frame_ind *frame_ind)
181 {
182 if (frame_ind->bcn_probe_rsp) {
183 qdf_mem_free(frame_ind->bcn_probe_rsp);
184 frame_ind->bcn_probe_rsp_len = 0;
185 frame_ind->bcn_probe_rsp = NULL;
186 }
187 if (frame_ind->link_bcn_probe_rsp) {
188 qdf_mem_free(frame_ind->link_bcn_probe_rsp);
189 frame_ind->link_bcn_probe_rsp_len = 0;
190 frame_ind->link_bcn_probe_rsp = NULL;
191 }
192 if (frame_ind->reassoc_req) {
193 qdf_mem_free(frame_ind->reassoc_req);
194 frame_ind->reassoc_req_len = 0;
195 frame_ind->reassoc_req = NULL;
196 }
197 if (frame_ind->reassoc_rsp) {
198 qdf_mem_free(frame_ind->reassoc_rsp);
199 frame_ind->reassoc_rsp_len = 0;
200 frame_ind->reassoc_rsp = NULL;
201 }
202
203 qdf_mem_free(frame_ind);
204 }
205
206 int
target_if_cm_roam_sync_frame_event(ol_scn_t scn,uint8_t * event,uint32_t len)207 target_if_cm_roam_sync_frame_event(ol_scn_t scn,
208 uint8_t *event,
209 uint32_t len)
210 {
211 QDF_STATUS qdf_status;
212 struct roam_synch_frame_ind *frame_ind_ptr;
213 struct wmi_unified *wmi_handle;
214 struct wlan_objmgr_psoc *psoc;
215 struct wlan_cm_roam_rx_ops *roam_rx_ops;
216 int status = 0;
217
218 psoc = target_if_get_psoc_from_scn_hdl(scn);
219 if (!psoc) {
220 target_if_err("psoc is null");
221 return -EINVAL;
222 }
223
224 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
225 if (!wmi_handle) {
226 target_if_err("wmi_handle is null");
227 return -EINVAL;
228 }
229
230 frame_ind_ptr = qdf_mem_malloc(sizeof(*frame_ind_ptr));
231 if (!frame_ind_ptr)
232 return -ENOMEM;
233
234 qdf_status = wmi_extract_roam_sync_frame_event(wmi_handle, event,
235 len,
236 frame_ind_ptr);
237 if (QDF_IS_STATUS_ERROR(qdf_status)) {
238 target_if_err("parsing of event failed, %d", qdf_status);
239 status = -EINVAL;
240 goto err;
241 }
242
243 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
244
245 if (!roam_rx_ops || !roam_rx_ops->roam_sync_frame_event) {
246 target_if_err("No valid roam rx ops");
247 status = -EINVAL;
248 goto err;
249 }
250
251 qdf_status = roam_rx_ops->roam_sync_frame_event(psoc,
252 frame_ind_ptr);
253
254 if (QDF_IS_STATUS_ERROR(qdf_status)) {
255 status = -EINVAL;
256 goto err;
257 }
258 qdf_mem_free(frame_ind_ptr);
259
260 return 0;
261
262 err:
263 target_if_free_roam_synch_frame_ind(frame_ind_ptr);
264
265 return status;
266 }
267
target_if_cm_roam_sync_event(ol_scn_t scn,uint8_t * event,uint32_t len)268 int target_if_cm_roam_sync_event(ol_scn_t scn, uint8_t *event,
269 uint32_t len)
270 {
271 QDF_STATUS qdf_status;
272 struct wmi_unified *wmi_handle;
273 struct wlan_objmgr_psoc *psoc;
274 struct wlan_cm_roam_rx_ops *roam_rx_ops;
275 struct roam_offload_synch_ind *sync_ind = NULL;
276 int status = 0;
277
278 psoc = target_if_get_psoc_from_scn_hdl(scn);
279 if (!psoc) {
280 target_if_err("psoc is null");
281 return -EINVAL;
282 }
283
284 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
285 if (!wmi_handle) {
286 target_if_err("wmi_handle is null");
287 return -EINVAL;
288 }
289
290 target_if_prevent_pm_during_roam_sync(psoc);
291
292 qdf_status = wmi_extract_roam_sync_event(wmi_handle, event,
293 len, &sync_ind);
294 if (QDF_IS_STATUS_ERROR(qdf_status)) {
295 target_if_err("parsing of event failed, %d", qdf_status);
296 status = -EINVAL;
297 goto err;
298 }
299
300 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
301
302 if (!roam_rx_ops || !roam_rx_ops->roam_sync_event) {
303 target_if_err("No valid roam rx ops");
304 status = -EINVAL;
305 goto err;
306 }
307
308 qdf_status = roam_rx_ops->roam_sync_event(psoc,
309 event,
310 len,
311 sync_ind);
312
313 if (QDF_IS_STATUS_ERROR(qdf_status))
314 status = -EINVAL;
315
316 err:
317 if (status == -EINVAL)
318 target_if_allow_pm_after_roam_sync(psoc);
319
320 if (sync_ind && sync_ind->ric_tspec_data)
321 qdf_mem_free(sync_ind->ric_tspec_data);
322 if (sync_ind)
323 qdf_mem_free(sync_ind);
324 return status;
325 }
326
327 static int
target_if_cm_btm_denylist_event(ol_scn_t scn,uint8_t * event,uint32_t len)328 target_if_cm_btm_denylist_event(ol_scn_t scn, uint8_t *event, uint32_t len)
329 {
330 QDF_STATUS qdf_status;
331 int status = 0;
332 struct roam_denylist_event *dst_list = NULL;
333 struct wmi_unified *wmi_handle;
334 struct wlan_objmgr_psoc *psoc;
335 struct wlan_cm_roam_rx_ops *roam_rx_ops;
336
337 psoc = target_if_get_psoc_from_scn_hdl(scn);
338 if (!psoc) {
339 target_if_err("psoc is null");
340 return -EINVAL;
341 }
342
343 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
344 if (!wmi_handle) {
345 target_if_err("wmi_handle is null");
346 return -EINVAL;
347 }
348
349 qdf_status = wmi_extract_btm_denylist_event(wmi_handle, event, len,
350 &dst_list);
351 if (QDF_IS_STATUS_ERROR(qdf_status)) {
352 target_if_err("parsing of event failed, %d", qdf_status);
353 return -EINVAL;
354 }
355
356 if (!dst_list) {
357 /* No APs to denylist, just return */
358 target_if_err_rl("No APs in denylist received");
359 return 0;
360 }
361
362 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
363 if (!roam_rx_ops || !roam_rx_ops->btm_denylist_event) {
364 target_if_err("No valid roam rx ops");
365 status = -EINVAL;
366 goto done;
367 }
368 qdf_status = roam_rx_ops->btm_denylist_event(psoc, dst_list);
369 if (QDF_IS_STATUS_ERROR(qdf_status))
370 status = -EINVAL;
371
372 done:
373 qdf_mem_free(dst_list);
374 return status;
375 }
376
377 int
target_if_cm_roam_vdev_disconnect_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)378 target_if_cm_roam_vdev_disconnect_event_handler(ol_scn_t scn, uint8_t *event,
379 uint32_t len)
380 {
381 QDF_STATUS qdf_status;
382 struct wmi_unified *wmi_handle;
383 struct wlan_objmgr_psoc *psoc;
384 struct vdev_disconnect_event_data *data;
385 struct wlan_cm_roam_rx_ops *roam_rx_ops;
386
387 psoc = target_if_get_psoc_from_scn_hdl(scn);
388 if (!psoc) {
389 target_if_err("psoc is null");
390 return -EINVAL;
391 }
392
393 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
394 if (!wmi_handle) {
395 target_if_err("wmi_handle is null");
396 return -EINVAL;
397 }
398
399 data = qdf_mem_malloc(sizeof(*data));
400 if (!data)
401 return -ENOMEM;
402 qdf_status = wmi_extract_vdev_disconnect_event(wmi_handle, event, len,
403 data);
404 if (QDF_IS_STATUS_ERROR(qdf_status)) {
405 target_if_err("parsing of event failed, %d", qdf_status);
406 goto done;
407 }
408
409 data->psoc = psoc;
410 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
411 if (!roam_rx_ops || !roam_rx_ops->vdev_disconnect_event) {
412 target_if_err("No valid roam rx ops");
413 qdf_status = QDF_STATUS_E_INVAL;
414 goto done;
415 }
416
417 /**
418 * This can be called from IRQ context for WOW events. There is no
419 * issue currently as this event is posted to scheduler thread from
420 * wma_handle_disconnect_reason(). Avoid acquiring mutex/sleep in this
421 * context in future and post a message to scheduler thread if needed.
422 */
423 qdf_status = roam_rx_ops->vdev_disconnect_event(data);
424
425 done:
426 qdf_mem_free(data);
427 return qdf_status_to_os_return(qdf_status);
428 }
429
430 int
target_if_cm_roam_scan_chan_list_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)431 target_if_cm_roam_scan_chan_list_event_handler(ol_scn_t scn, uint8_t *event,
432 uint32_t len)
433 {
434 QDF_STATUS qdf_status;
435 int status = 0;
436 struct wmi_unified *wmi_handle;
437 struct wlan_objmgr_psoc *psoc;
438 struct wlan_cm_roam_rx_ops *roam_rx_ops;
439 struct cm_roam_scan_ch_resp *data = NULL;
440
441 psoc = target_if_get_psoc_from_scn_hdl(scn);
442 if (!psoc) {
443 target_if_err("psoc is null");
444 return -EINVAL;
445 }
446
447 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
448 if (!wmi_handle) {
449 target_if_err("wmi_handle is null");
450 return -EINVAL;
451 }
452
453 qdf_status = wmi_extract_roam_scan_chan_list(wmi_handle, event, len,
454 &data);
455 if (QDF_IS_STATUS_ERROR(qdf_status)) {
456 target_if_err("parsing of event failed, %d", qdf_status);
457 return -EINVAL;
458 }
459
460 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
461 if (!roam_rx_ops || !roam_rx_ops->roam_scan_chan_list_event) {
462 target_if_err("No valid roam rx ops");
463 qdf_mem_free(data);
464 return -EINVAL;
465 }
466 qdf_status = roam_rx_ops->roam_scan_chan_list_event(data);
467 if (QDF_IS_STATUS_ERROR(qdf_status))
468 status = -EINVAL;
469
470 return status;
471 }
472
473 int
target_if_cm_roam_stats_event(ol_scn_t scn,uint8_t * event,uint32_t len)474 target_if_cm_roam_stats_event(ol_scn_t scn, uint8_t *event, uint32_t len)
475 {
476 QDF_STATUS qdf_status;
477 int status = 0;
478 struct wmi_unified *wmi_handle;
479 struct wlan_objmgr_psoc *psoc;
480 struct wlan_cm_roam_rx_ops *roam_rx_ops;
481 struct roam_stats_event *stats_info = NULL;
482
483 psoc = target_if_get_psoc_from_scn_hdl(scn);
484 if (!psoc) {
485 target_if_err("psoc is null");
486 return -EINVAL;
487 }
488
489 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
490 if (!wmi_handle) {
491 target_if_err("wmi_handle is null");
492 return -EINVAL;
493 }
494
495 qdf_status = wmi_extract_roam_stats_event(wmi_handle, event, len,
496 &stats_info);
497 if (QDF_IS_STATUS_ERROR(qdf_status)) {
498 target_if_err("parsing of event failed, %d", qdf_status);
499 return -EINVAL;
500 }
501
502 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
503 if (!roam_rx_ops || !roam_rx_ops->roam_stats_event_rx) {
504 target_if_err("No valid roam rx ops");
505 status = -EINVAL;
506 if (stats_info) {
507 if (stats_info->roam_msg_info)
508 qdf_mem_free(stats_info->roam_msg_info);
509 qdf_mem_free(stats_info);
510 }
511 goto err;
512 }
513
514 qdf_status = roam_rx_ops->roam_stats_event_rx(psoc, stats_info);
515 if (QDF_IS_STATUS_ERROR(qdf_status))
516 status = -EINVAL;
517
518 err:
519 return status;
520 }
521
522 int
target_if_cm_roam_auth_offload_event(ol_scn_t scn,uint8_t * event,uint32_t len)523 target_if_cm_roam_auth_offload_event(ol_scn_t scn, uint8_t *event, uint32_t len)
524 {
525 QDF_STATUS qdf_status;
526 int status = 0;
527 struct wmi_unified *wmi_handle;
528 struct wlan_objmgr_psoc *psoc;
529 struct wlan_cm_roam_rx_ops *roam_rx_ops;
530 struct auth_offload_event auth_event = {0};
531
532 psoc = target_if_get_psoc_from_scn_hdl(scn);
533 if (!psoc) {
534 target_if_err("psoc is null");
535 return -EINVAL;
536 }
537
538 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
539 if (!wmi_handle) {
540 target_if_err("wmi_handle is null");
541 return -EINVAL;
542 }
543
544 qdf_status = wmi_extract_auth_offload_event(wmi_handle, event, len,
545 &auth_event);
546 if (QDF_IS_STATUS_ERROR(qdf_status)) {
547 target_if_err("parsing of event failed, %d", qdf_status);
548 return -EINVAL;
549 }
550
551 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
552 if (!roam_rx_ops || !roam_rx_ops->roam_auth_offload_event) {
553 target_if_err("No valid roam rx ops");
554 return -EINVAL;
555 }
556 qdf_status = roam_rx_ops->roam_auth_offload_event(&auth_event);
557 if (QDF_IS_STATUS_ERROR(status))
558 status = -EINVAL;
559
560 return status;
561 }
562
563 int
target_if_pmkid_request_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)564 target_if_pmkid_request_event_handler(ol_scn_t scn, uint8_t *event,
565 uint32_t len)
566 {
567 QDF_STATUS qdf_status;
568 struct wmi_unified *wmi_handle;
569 struct wlan_objmgr_psoc *psoc;
570 struct roam_pmkid_req_event *data = NULL;
571 struct wlan_cm_roam_rx_ops *roam_rx_ops;
572
573 psoc = target_if_get_psoc_from_scn_hdl(scn);
574 if (!psoc) {
575 target_if_err("psoc is null");
576 return -EINVAL;
577 }
578
579 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
580 if (!wmi_handle) {
581 target_if_err("wmi_handle is null");
582 return -EINVAL;
583 }
584
585 qdf_status = wmi_extract_roam_pmkid_request(wmi_handle, event, len,
586 &data);
587 if (QDF_IS_STATUS_ERROR(qdf_status)) {
588 target_if_err("parsing of event failed, %d", qdf_status);
589 goto done;
590 }
591
592 data->psoc = psoc;
593
594 roam_rx_ops = target_if_cm_get_roam_rx_ops(data->psoc);
595 if (!roam_rx_ops || !roam_rx_ops->roam_pmkid_request_event_rx) {
596 target_if_err("No valid roam rx ops");
597 qdf_status = QDF_STATUS_E_INVAL;
598 goto done;
599 }
600
601 /**
602 * This can be called from IRQ context for WOW events. There is no
603 * issue currently as this event doesn't take any mutex.
604 * If there is a mutex/sleep is needed in future, post a message to
605 * scheduler thread.
606 */
607 qdf_status = roam_rx_ops->roam_pmkid_request_event_rx(data);
608
609 done:
610 if (data)
611 qdf_mem_free(data);
612 return qdf_status_to_os_return(qdf_status);
613 }
614
615 int
target_if_roam_frame_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)616 target_if_roam_frame_event_handler(ol_scn_t scn, uint8_t *event,
617 uint32_t len)
618 {
619 struct wlan_objmgr_psoc *psoc;
620 struct wmi_unified *wmi_handle;
621 struct roam_scan_candidate_frame frame = {0};
622 struct wlan_cm_roam_rx_ops *roam_rx_ops;
623 QDF_STATUS qdf_status;
624
625 psoc = target_if_get_psoc_from_scn_hdl(scn);
626 if (!psoc) {
627 target_if_err("psoc is null");
628 return -EINVAL;
629 }
630
631 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
632 if (!wmi_handle) {
633 target_if_err("wmi_handle is null");
634 return -EINVAL;
635 }
636
637 qdf_status = wmi_extract_roam_candidate_frame_event(wmi_handle, event,
638 len, &frame);
639 if (QDF_IS_STATUS_ERROR(qdf_status)) {
640 target_if_err("parsing of event failed, %d", qdf_status);
641 return -EINVAL;
642 }
643
644 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
645 if (!roam_rx_ops || !roam_rx_ops->roam_candidate_frame_event) {
646 target_if_err("No valid roam rx ops");
647 return -EINVAL;
648 }
649
650 qdf_status = roam_rx_ops->roam_candidate_frame_event(psoc,
651 &frame);
652 if (QDF_IS_STATUS_ERROR(qdf_status))
653 return -EINVAL;
654
655 return QDF_STATUS_SUCCESS;
656 }
657
658 #ifdef WLAN_VENDOR_HANDOFF_CONTROL
target_if_get_roam_vendor_control_param_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)659 int target_if_get_roam_vendor_control_param_event_handler(ol_scn_t scn,
660 uint8_t *event,
661 uint32_t len)
662 {
663 struct wlan_objmgr_psoc *psoc;
664 struct wmi_unified *wmi_handle;
665 struct roam_vendor_handoff_params *vendor_handoff_params = NULL;
666 struct wlan_cm_roam_rx_ops *roam_rx_ops;
667 QDF_STATUS qdf_status;
668 int ret = 0;
669
670 psoc = target_if_get_psoc_from_scn_hdl(scn);
671 if (!psoc) {
672 target_if_err("psoc is null");
673 return -EINVAL;
674 }
675
676 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
677 if (!wmi_handle) {
678 target_if_err("wmi_handle is null");
679 return -EINVAL;
680 }
681
682 qdf_status = wmi_extract_roam_vendor_control_param_event(wmi_handle,
683 event, len,
684 &vendor_handoff_params);
685 if (QDF_IS_STATUS_ERROR(qdf_status)) {
686 target_if_err("parsing of event failed, %d", qdf_status);
687 ret = -EINVAL;
688 goto done;
689 }
690
691 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
692 if (!roam_rx_ops || !roam_rx_ops->roam_vendor_handoff_event) {
693 target_if_err("No valid roam rx ops");
694 ret = -EINVAL;
695 goto done;
696 }
697
698 roam_rx_ops->roam_vendor_handoff_event(psoc, vendor_handoff_params);
699
700 done:
701 if (vendor_handoff_params)
702 qdf_mem_free(vendor_handoff_params);
703
704 return ret;
705 }
706
707 static QDF_STATUS
target_if_register_roam_vendor_control_param_event(wmi_unified_t handle)708 target_if_register_roam_vendor_control_param_event(wmi_unified_t handle)
709 {
710 QDF_STATUS ret;
711
712 ret = wmi_unified_register_event_handler(handle,
713 wmi_get_roam_vendor_control_param_event_id,
714 target_if_get_roam_vendor_control_param_event_handler,
715 WMI_RX_SERIALIZER_CTX);
716 if (QDF_IS_STATUS_ERROR(ret)) {
717 target_if_err("wmi event(%u) registration failed, ret: %d",
718 wmi_get_roam_vendor_control_param_event_id, ret);
719 return QDF_STATUS_E_FAILURE;
720 }
721
722 return QDF_STATUS_SUCCESS;
723 }
724 #else
725 static inline QDF_STATUS
target_if_register_roam_vendor_control_param_event(wmi_unified_t handle)726 target_if_register_roam_vendor_control_param_event(wmi_unified_t handle)
727 {
728 return QDF_STATUS_SUCCESS;
729 }
730 #endif
731
732 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO)
733 static void
target_if_update_pairwise_key_peer_mac(struct wlan_crypto_key_entry * crypto_entry,struct qdf_mac_addr * ap_link_addr)734 target_if_update_pairwise_key_peer_mac(struct wlan_crypto_key_entry *crypto_entry,
735 struct qdf_mac_addr *ap_link_addr)
736 {
737 uint8_t i;
738
739 if (crypto_entry->link_id == MLO_INVALID_LINK_IDX)
740 return;
741
742 for (i = 0; i < WLAN_CRYPTO_MAX_VLANKEYIX; i++) {
743 if (!crypto_entry->keys.key[i])
744 continue;
745
746 if (crypto_entry->keys.key[i]->key_type ==
747 WLAN_CRYPTO_KEY_TYPE_UNICAST)
748 qdf_copy_macaddr((struct qdf_mac_addr *)crypto_entry->keys.key[i]->macaddr,
749 ap_link_addr);
750 }
751 }
752
753 static int
target_if_roam_synch_key_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)754 target_if_roam_synch_key_event_handler(ol_scn_t scn, uint8_t *event,
755 uint32_t len)
756 {
757 struct wlan_objmgr_psoc *psoc;
758 struct wmi_unified *wmi_handle;
759 struct wlan_cm_roam_rx_ops *roam_rx_ops;
760 struct wlan_crypto_key_entry *keys;
761 struct qdf_mac_addr mld_addr;
762 struct wlan_mlo_dev_context *ml_ctx = NULL;
763 struct wlan_objmgr_vdev *vdev_list;
764 struct mlo_link_info *link_info;
765 uint8_t num_keys = 0;
766 int ret = 0;
767 QDF_STATUS status;
768 uint8_t i, j;
769
770 psoc = target_if_get_psoc_from_scn_hdl(scn);
771 if (!psoc) {
772 target_if_err("psoc is null");
773 return -EINVAL;
774 }
775
776 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
777 if (!wmi_handle) {
778 target_if_err("wmi_handle is null");
779 return -EINVAL;
780 }
781
782 status = wmi_extract_roam_synch_key_event(wmi_handle, event, len, &keys,
783 &num_keys, &mld_addr);
784 if (QDF_IS_STATUS_ERROR(status)) {
785 target_if_err("parsing of roam sync key event failed");
786 ret = -EINVAL;
787 goto done;
788 }
789
790 wlan_mlo_get_mlpeer_by_peer_mladdr(&mld_addr, &ml_ctx);
791 if (!ml_ctx) {
792 target_if_err("ML context is not found mld addr: "
793 QDF_MAC_ADDR_FMT,
794 QDF_MAC_ADDR_REF(mld_addr.bytes));
795 ret = -EINVAL;
796 goto done;
797 }
798
799 target_if_debug("num_keys:%d ML context is found mld addr: "
800 QDF_MAC_ADDR_FMT, num_keys,
801 QDF_MAC_ADDR_REF(mld_addr.bytes));
802
803 /*
804 * Fill VDEV ID & AP mac address for the pairwise keys
805 * from link id received in the key event
806 */
807 for (i = 0; i < num_keys; i++) {
808 keys[i].vdev_id = WLAN_INVALID_VDEV_ID;
809 for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) {
810 vdev_list = ml_ctx->wlan_vdev_list[j];
811 if (!vdev_list)
812 continue;
813
814 if (keys[i].link_id ==
815 wlan_vdev_get_link_id(vdev_list)) {
816 keys[i].vdev_id = wlan_vdev_get_id(vdev_list);
817 qdf_copy_macaddr((struct qdf_mac_addr *)keys[i].mac_addr.raw,
818 (struct qdf_mac_addr *)vdev_list->vdev_mlme.linkaddr);
819 link_info = mlo_mgr_get_ap_link_by_link_id(
820 vdev_list->mlo_dev_ctx,
821 keys[i].link_id);
822 if (!link_info) {
823 target_if_err("Link info not found for link_id:%d",
824 keys[i].link_id);
825 break;
826 }
827 target_if_debug("i:%d link_id:%d vdev_id:%d self link_addr: " QDF_MAC_ADDR_FMT " AP link addr: " QDF_MAC_ADDR_FMT,
828 i, keys[i].link_id, keys[i].vdev_id,
829 QDF_MAC_ADDR_REF(keys[i].mac_addr.raw),
830 QDF_MAC_ADDR_REF(link_info->ap_link_addr.bytes));
831
832 target_if_update_pairwise_key_peer_mac(&keys[i], &link_info->ap_link_addr);
833 break;
834 }
835 }
836
837 /* update for standby vdev also here from link_switch context*/
838 if (keys[i].vdev_id == WLAN_INVALID_VDEV_ID &&
839 keys[i].link_id != MLO_INVALID_LINK_IDX &&
840 ml_ctx->link_ctx) {
841 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) {
842 link_info = &ml_ctx->link_ctx->links_info[j];
843 if (qdf_is_macaddr_zero(&link_info->ap_link_addr))
844 continue;
845
846 if (qdf_is_macaddr_zero(&link_info->link_addr))
847 continue;
848
849 if (link_info->link_id == keys[i].link_id) {
850 target_if_debug("i:%d Standby vdev: link_id:%d ap_link_addr: " QDF_MAC_ADDR_FMT,
851 i, keys[i].link_id,
852 QDF_MAC_ADDR_REF(link_info->ap_link_addr.bytes));
853 qdf_copy_macaddr((struct qdf_mac_addr *)keys[i].mac_addr.raw,
854 &link_info->link_addr);
855 target_if_update_pairwise_key_peer_mac(&keys[i],
856 &link_info->ap_link_addr);
857 }
858 }
859 }
860 }
861
862 roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc);
863 if (!roam_rx_ops || !roam_rx_ops->roam_sync_key_event) {
864 target_if_err("No valid roam rx ops");
865 ret = -EINVAL;
866 goto done;
867 }
868
869 status = roam_rx_ops->roam_sync_key_event(psoc, keys, num_keys);
870 if (QDF_IS_STATUS_ERROR(status)) {
871 target_if_err("Add keys failed");
872 ret = 0;
873 }
874 done:
875 qdf_mem_zero(keys, WLAN_MAX_ML_BSS_LINKS * sizeof(*keys));
876 qdf_mem_free(keys);
877
878 return ret;
879 }
880 #endif
881
882 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO)
target_if_register_mlo_roam_events(wmi_unified_t handle)883 static void target_if_register_mlo_roam_events(wmi_unified_t handle)
884 {
885 QDF_STATUS status;
886
887 status = wmi_unified_register_event_handler(
888 handle,
889 wmi_roam_synch_key_event_id,
890 target_if_roam_synch_key_event_handler,
891 WMI_RX_SERIALIZER_CTX);
892 if (QDF_IS_STATUS_ERROR(status))
893 target_if_err("wmi event(%u) registration failed, status: %d",
894 wmi_roam_synch_key_event_id, status);
895 }
896 #else
target_if_register_mlo_roam_events(wmi_unified_t handle)897 static inline void target_if_register_mlo_roam_events(wmi_unified_t handle)
898 {}
899 #endif
900
901 QDF_STATUS
target_if_roam_offload_register_events(struct wlan_objmgr_psoc * psoc)902 target_if_roam_offload_register_events(struct wlan_objmgr_psoc *psoc)
903 {
904 QDF_STATUS ret;
905 wmi_unified_t handle = get_wmi_unified_hdl_from_psoc(psoc);
906
907 if (!handle) {
908 target_if_err("handle is NULL");
909 return QDF_STATUS_E_FAILURE;
910 }
911
912 /* Register for roam offload event */
913 ret = wmi_unified_register_event_handler(handle,
914 wmi_roam_synch_event_id,
915 target_if_cm_roam_sync_event,
916 WMI_RX_SERIALIZER_CTX);
917 if (QDF_IS_STATUS_ERROR(ret)) {
918 target_if_err("wmi event registration failed, ret: %d", ret);
919 return QDF_STATUS_E_FAILURE;
920 }
921
922 /* Register for roam offload event */
923 ret = wmi_unified_register_event_handler(handle,
924 wmi_roam_synch_frame_event_id,
925 target_if_cm_roam_sync_frame_event,
926 WMI_RX_SERIALIZER_CTX);
927 if (QDF_IS_STATUS_ERROR(ret)) {
928 target_if_err("wmi event registration failed, ret: %d", ret);
929 return QDF_STATUS_E_FAILURE;
930 }
931
932 ret = wmi_unified_register_event_handler(handle,
933 wmi_roam_denylist_event_id,
934 target_if_cm_btm_denylist_event,
935 WMI_RX_SERIALIZER_CTX);
936 if (QDF_IS_STATUS_ERROR(ret)) {
937 target_if_err("wmi event(%u) registration failed, ret: %d",
938 wmi_roam_denylist_event_id, ret);
939 return QDF_STATUS_E_FAILURE;
940 }
941
942 ret = wmi_unified_register_event_handler(handle,
943 wmi_vdev_disconnect_event_id,
944 target_if_cm_roam_vdev_disconnect_event_handler,
945 WMI_RX_SERIALIZER_CTX);
946 if (QDF_IS_STATUS_ERROR(ret)) {
947 target_if_err("wmi event(%u) registration failed, ret: %d",
948 wmi_vdev_disconnect_event_id, ret);
949 return QDF_STATUS_E_FAILURE;
950 }
951
952 ret = wmi_unified_register_event_handler(handle,
953 wmi_roam_scan_chan_list_id,
954 target_if_cm_roam_scan_chan_list_event_handler,
955 WMI_RX_SERIALIZER_CTX);
956 if (QDF_IS_STATUS_ERROR(ret)) {
957 target_if_err("wmi event(%u) registration failed, ret: %d",
958 wmi_roam_scan_chan_list_id, ret);
959 return QDF_STATUS_E_FAILURE;
960 }
961
962 ret = wmi_unified_register_event_handler(handle,
963 wmi_roam_stats_event_id,
964 target_if_cm_roam_stats_event,
965 WMI_RX_SERIALIZER_CTX);
966 if (QDF_IS_STATUS_ERROR(ret)) {
967 target_if_err("wmi event registration failed, ret: %d", ret);
968 return QDF_STATUS_E_FAILURE;
969 }
970
971 ret = wmi_unified_register_event_handler(handle,
972 wmi_roam_auth_offload_event_id,
973 target_if_cm_roam_auth_offload_event,
974 WMI_RX_SERIALIZER_CTX);
975 if (QDF_IS_STATUS_ERROR(ret)) {
976 target_if_err("wmi event(%u) registration failed, ret: %d",
977 wmi_roam_auth_offload_event_id, ret);
978 return QDF_STATUS_E_FAILURE;
979 }
980
981 ret = wmi_unified_register_event_handler(handle,
982 wmi_roam_pmkid_request_event_id,
983 target_if_pmkid_request_event_handler,
984 WMI_RX_SERIALIZER_CTX);
985 if (QDF_IS_STATUS_ERROR(ret)) {
986 target_if_err("wmi event(%u) registration failed, ret: %d",
987 wmi_roam_stats_event_id, ret);
988 return QDF_STATUS_E_FAILURE;
989 }
990
991 target_if_register_roam_vendor_control_param_event(handle);
992
993 ret = wmi_unified_register_event_handler(handle,
994 wmi_roam_frame_event_id,
995 target_if_roam_frame_event_handler,
996 WMI_RX_SERIALIZER_CTX);
997 if (QDF_IS_STATUS_ERROR(ret)) {
998 target_if_err("wmi event(%u) registration failed, ret: %d",
999 wmi_roam_frame_event_id, ret);
1000 return QDF_STATUS_E_FAILURE;
1001 }
1002
1003 target_if_register_mlo_roam_events(handle);
1004
1005 return QDF_STATUS_SUCCESS;
1006 }
1007 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
1008