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