xref: /wlan-dirver/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: target_if_vdev_mgr_rx_ops.c
21  *
22  * This file provide definition for APIs registered through events received
23  * from FW
24  */
25 #include <target_if_vdev_mgr_rx_ops.h>
26 #include <target_if_vdev_mgr_tx_ops.h>
27 #include <wlan_vdev_mgr_tgt_if_rx_defs.h>
28 #include <wlan_vdev_mgr_tgt_if_tx_defs.h>
29 #include <wmi_unified_param.h>
30 #include <wlan_mlme_dbg.h>
31 #include <target_if.h>
32 #include <wlan_vdev_mlme_main.h>
33 #include <wmi_unified_vdev_api.h>
34 #include <target_if_psoc_wake_lock.h>
35 
36 static inline
37 void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc,
38 					uint8_t vdev_id,
39 					enum qdf_hang_reason recovery_reason,
40 					uint16_t rsp_pos)
41 {
42 	mlme_nofl_err("PSOC_%d VDEV_%d: %s rsp timeout", wlan_psoc_get_id(psoc),
43 		      vdev_id, string_from_rsp_bit(rsp_pos));
44 	if (target_if_vdev_mgr_is_panic_allowed())
45 		qdf_trigger_self_recovery(psoc, recovery_reason);
46 	else
47 		mlme_nofl_debug("PSOC_%d VDEV_%d: Panic not allowed",
48 				wlan_psoc_get_id(psoc), vdev_id);
49 }
50 
51 void target_if_vdev_mgr_rsp_timer_cb(void *arg)
52 {
53 	struct wlan_objmgr_psoc *psoc;
54 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
55 	struct vdev_start_response start_rsp = {0};
56 	struct vdev_stop_response stop_rsp = {0};
57 	struct vdev_delete_response del_rsp = {0};
58 	struct peer_delete_all_response peer_del_all_rsp = {0};
59 	struct vdev_response_timer *vdev_rsp = arg;
60 	enum qdf_hang_reason recovery_reason;
61 	uint8_t vdev_id;
62 	uint16_t rsp_pos = RESPONSE_BIT_MAX;
63 
64 	if (!vdev_rsp) {
65 		mlme_err("Vdev response timer is NULL");
66 		return;
67 	}
68 
69 	psoc = vdev_rsp->psoc;
70 	if (!psoc) {
71 		mlme_err("PSOC is NULL");
72 		return;
73 	}
74 
75 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
76 	if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) {
77 		mlme_err("No Rx Ops");
78 		return;
79 	}
80 
81 	if (!qdf_atomic_test_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
82 	    !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
83 	    !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
84 	    !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
85 	    !qdf_atomic_test_bit(
86 			PEER_DELETE_ALL_RESPONSE_BIT,
87 			&vdev_rsp->rsp_status)) {
88 		mlme_debug("No response bit is set, ignoring actions :%d",
89 			   vdev_rsp->vdev_id);
90 		return;
91 	}
92 
93 	vdev_id = vdev_rsp->vdev_id;
94 	if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
95 		mlme_err("Invalid VDEV_%d PSOC_%d", vdev_id,
96 			 wlan_psoc_get_id(psoc));
97 		return;
98 	}
99 
100 	vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT;
101 	if (qdf_atomic_test_bit(START_RESPONSE_BIT,
102 				&vdev_rsp->rsp_status) ||
103 	    qdf_atomic_test_bit(RESTART_RESPONSE_BIT,
104 				&vdev_rsp->rsp_status)) {
105 		start_rsp.vdev_id = vdev_id;
106 		start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT;
107 		if (qdf_atomic_test_bit(START_RESPONSE_BIT,
108 					&vdev_rsp->rsp_status)) {
109 			start_rsp.resp_type =
110 				WMI_HOST_VDEV_START_RESP_EVENT;
111 			rsp_pos = START_RESPONSE_BIT;
112 			recovery_reason = QDF_VDEV_START_RESPONSE_TIMED_OUT;
113 		} else {
114 			start_rsp.resp_type =
115 				WMI_HOST_VDEV_RESTART_RESP_EVENT;
116 			rsp_pos = RESTART_RESPONSE_BIT;
117 			recovery_reason = QDF_VDEV_RESTART_RESPONSE_TIMED_OUT;
118 		}
119 
120 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
121 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
122 						   recovery_reason, rsp_pos);
123 		rx_ops->vdev_mgr_start_response(psoc, &start_rsp);
124 	} else if (qdf_atomic_test_bit(STOP_RESPONSE_BIT,
125 				       &vdev_rsp->rsp_status)) {
126 		rsp_pos = STOP_RESPONSE_BIT;
127 		stop_rsp.vdev_id = vdev_id;
128 		recovery_reason = QDF_VDEV_STOP_RESPONSE_TIMED_OUT;
129 
130 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
131 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
132 						   recovery_reason, rsp_pos);
133 		rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp);
134 	} else if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT,
135 				       &vdev_rsp->rsp_status)) {
136 		del_rsp.vdev_id = vdev_id;
137 		rsp_pos = DELETE_RESPONSE_BIT;
138 		recovery_reason = QDF_VDEV_DELETE_RESPONSE_TIMED_OUT;
139 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
140 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
141 						   recovery_reason, rsp_pos);
142 		rx_ops->vdev_mgr_delete_response(psoc, &del_rsp);
143 	} else if (qdf_atomic_test_bit(PEER_DELETE_ALL_RESPONSE_BIT,
144 				&vdev_rsp->rsp_status)) {
145 		peer_del_all_rsp.vdev_id = vdev_id;
146 		rsp_pos = PEER_DELETE_ALL_RESPONSE_BIT;
147 		recovery_reason = QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
148 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
149 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
150 						   recovery_reason, rsp_pos);
151 		rx_ops->vdev_mgr_peer_delete_all_response(psoc,
152 							  &peer_del_all_rsp);
153 	} else {
154 		mlme_err("PSOC_%d VDEV_%d: Unknown error",
155 			 wlan_psoc_get_id(psoc), vdev_id);
156 		return;
157 	}
158 }
159 
160 #ifdef SERIALIZE_VDEV_RESP
161 static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg)
162 {
163 	struct vdev_response_timer *vdev_rsp;
164 	struct wlan_objmgr_psoc *psoc;
165 
166 	if (!msg->bodyptr) {
167 		mlme_err("Message bodyptr is NULL");
168 		return QDF_STATUS_E_INVAL;
169 	}
170 
171 	vdev_rsp = msg->bodyptr;
172 	if (!vdev_rsp) {
173 		mlme_err("vdev response timer is NULL");
174 		return QDF_STATUS_E_INVAL;
175 	}
176 
177 	psoc = vdev_rsp->psoc;
178 	if (!psoc) {
179 		mlme_err("PSOC is NULL");
180 		return QDF_STATUS_E_INVAL;
181 	}
182 
183 	if (vdev_rsp->rsp_status)
184 		wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID);
185 
186 	return QDF_STATUS_SUCCESS;
187 }
188 
189 static void
190 target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg)
191 {
192 	struct scheduler_msg msg = {0};
193 	struct vdev_response_timer *vdev_rsp = arg;
194 	struct wlan_objmgr_psoc *psoc;
195 
196 	psoc = vdev_rsp->psoc;
197 	if (!psoc) {
198 		mlme_err("PSOC is NULL");
199 		return;
200 	}
201 
202 	msg.type = SYS_MSG_ID_MC_TIMER;
203 	msg.reserved = SYS_MSG_COOKIE;
204 
205 	/* msg.callback will explicitly cast back to qdf_mc_timer_callback_t
206 	 * in scheduler_timer_q_mq_handler.
207 	 * but in future we do not want to introduce more this kind of
208 	 * typecast by properly using QDF MC timer for MCC from get go in
209 	 * common code.
210 	 */
211 	msg.callback =
212 		(scheduler_msg_process_fn_t)target_if_vdev_mgr_rsp_timer_cb;
213 	msg.bodyptr = arg;
214 	msg.bodyval = 0;
215 	msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb;
216 
217 	if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
218 				   QDF_MODULE_ID_TARGET_IF,
219 				   QDF_MODULE_ID_SYS, &msg) ==
220 				   QDF_STATUS_SUCCESS)
221 		return;
222 
223 	mlme_err("Could not enqueue timer to timer queue");
224 	if (psoc)
225 		wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID);
226 }
227 
228 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg)
229 {
230 	target_if_vdev_mgr_rsp_cb_mc_ctx(arg);
231 }
232 
233 #define VDEV_RSP_RX_CTX WMI_RX_SERIALIZER_CTX
234 #else
235 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg)
236 {
237 	target_if_vdev_mgr_rsp_timer_cb(arg);
238 }
239 
240 #define VDEV_RSP_RX_CTX WMI_RX_UMAC_CTX
241 #endif
242 
243 static int target_if_vdev_mgr_start_response_handler(ol_scn_t scn,
244 						     uint8_t *data,
245 						     uint32_t datalen)
246 {
247 	QDF_STATUS status = QDF_STATUS_E_INVAL;
248 	struct wlan_objmgr_psoc *psoc;
249 	struct wmi_unified *wmi_handle;
250 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
251 	struct vdev_start_response vdev_start_resp = {0};
252 	uint8_t vdev_id;
253 	struct vdev_response_timer *vdev_rsp;
254 
255 	if (!scn || !data) {
256 		mlme_err("Invalid input");
257 		return -EINVAL;
258 	}
259 
260 	psoc = target_if_get_psoc_from_scn_hdl(scn);
261 	if (!psoc) {
262 		mlme_err("PSOC is NULL");
263 		return -EINVAL;
264 	}
265 
266 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
267 	if (!rx_ops || !rx_ops->vdev_mgr_start_response) {
268 		mlme_err("No Rx Ops");
269 		return -EINVAL;
270 	}
271 
272 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
273 	if (!wmi_handle) {
274 		mlme_err("wmi_handle is null");
275 		return -EINVAL;
276 	}
277 
278 	if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) {
279 		mlme_err("WMI extract failed");
280 		return -EINVAL;
281 	}
282 
283 	vdev_id = vdev_start_resp.vdev_id;
284 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id);
285 	if (!vdev_rsp) {
286 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
287 			 vdev_id, wlan_psoc_get_id(psoc));
288 		return -EINVAL;
289 	}
290 
291 	if (vdev_start_resp.resp_type == WMI_HOST_VDEV_RESTART_RESP_EVENT)
292 		status = target_if_vdev_mgr_rsp_timer_stop(
293 							psoc, vdev_rsp,
294 							RESTART_RESPONSE_BIT);
295 	else
296 		status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp,
297 							   START_RESPONSE_BIT);
298 
299 	if (QDF_IS_STATUS_ERROR(status)) {
300 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
301 			 psoc->soc_objmgr.psoc_id, vdev_id);
302 		goto err;
303 	}
304 
305 	status = rx_ops->vdev_mgr_start_response(psoc, &vdev_start_resp);
306 
307 err:
308 	return qdf_status_to_os_return(status);
309 }
310 
311 static int target_if_vdev_mgr_stop_response_handler(ol_scn_t scn,
312 						    uint8_t *data,
313 						    uint32_t datalen)
314 {
315 	QDF_STATUS status = QDF_STATUS_E_INVAL;
316 	struct wlan_objmgr_psoc *psoc;
317 	struct wmi_unified *wmi_handle;
318 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
319 	struct vdev_stop_response rsp = {0};
320 	uint32_t vdev_id;
321 	struct vdev_response_timer *vdev_rsp;
322 
323 	if (!scn || !data) {
324 		mlme_err("Invalid input");
325 		return -EINVAL;
326 	}
327 
328 	psoc = target_if_get_psoc_from_scn_hdl(scn);
329 	if (!psoc) {
330 		mlme_err("PSOC is NULL");
331 		return -EINVAL;
332 	}
333 
334 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
335 	if (!rx_ops || !rx_ops->vdev_mgr_stop_response) {
336 		mlme_err("No Rx Ops");
337 		return -EINVAL;
338 	}
339 
340 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
341 	if (!wmi_handle) {
342 		mlme_err("wmi_handle is null");
343 		return -EINVAL;
344 	}
345 
346 	if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) {
347 		mlme_err("WMI extract failed");
348 		return -EINVAL;
349 	}
350 
351 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id);
352 	if (!vdev_rsp) {
353 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
354 			 vdev_id, wlan_psoc_get_id(psoc));
355 		return -EINVAL;
356 	}
357 
358 	status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp,
359 						   STOP_RESPONSE_BIT);
360 
361 	if (QDF_IS_STATUS_ERROR(status)) {
362 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
363 			 psoc->soc_objmgr.psoc_id, vdev_id);
364 		goto err;
365 	}
366 
367 	rsp.vdev_id = vdev_id;
368 	status = rx_ops->vdev_mgr_stop_response(psoc, &rsp);
369 
370 err:
371 	return qdf_status_to_os_return(status);
372 }
373 
374 static int target_if_vdev_mgr_delete_response_handler(ol_scn_t scn,
375 						      uint8_t *data,
376 						      uint32_t datalen)
377 {
378 	QDF_STATUS status = QDF_STATUS_E_INVAL;
379 	struct wlan_objmgr_psoc *psoc;
380 	struct wmi_unified *wmi_handle;
381 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
382 	struct vdev_delete_response vdev_del_resp = {0};
383 	struct vdev_response_timer *vdev_rsp;
384 
385 	if (!scn || !data) {
386 		mlme_err("Invalid input");
387 		return -EINVAL;
388 	}
389 
390 	psoc = target_if_get_psoc_from_scn_hdl(scn);
391 	if (!psoc) {
392 		mlme_err("PSOC is NULL");
393 		return -EINVAL;
394 	}
395 
396 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
397 	if (!rx_ops || !rx_ops->vdev_mgr_delete_response) {
398 		mlme_err("No Rx Ops");
399 		return -EINVAL;
400 	}
401 
402 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
403 	if (!wmi_handle) {
404 		mlme_err("wmi_handle is null");
405 		return -EINVAL;
406 	}
407 
408 	if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) {
409 		mlme_err("WMI extract failed");
410 		return -EINVAL;
411 	}
412 
413 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc,
414 							 vdev_del_resp.vdev_id);
415 	if (!vdev_rsp) {
416 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
417 			 vdev_del_resp.vdev_id, wlan_psoc_get_id(psoc));
418 		return -EINVAL;
419 	}
420 
421 	status = target_if_vdev_mgr_rsp_timer_stop(
422 						psoc, vdev_rsp,
423 						DELETE_RESPONSE_BIT);
424 
425 	if (QDF_IS_STATUS_ERROR(status)) {
426 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
427 			 wlan_psoc_get_id(psoc), vdev_del_resp.vdev_id);
428 		goto err;
429 	}
430 
431 	status = rx_ops->vdev_mgr_delete_response(psoc, &vdev_del_resp);
432 	target_if_wake_lock_timeout_release(psoc, DELETE_WAKELOCK);
433 err:
434 	return qdf_status_to_os_return(status);
435 }
436 
437 static int target_if_vdev_mgr_peer_delete_all_response_handler(
438 							ol_scn_t scn,
439 							uint8_t *data,
440 							uint32_t datalen)
441 {
442 	QDF_STATUS status = QDF_STATUS_E_INVAL;
443 	struct wlan_objmgr_psoc *psoc;
444 	struct wmi_unified *wmi_handle;
445 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
446 	struct peer_delete_all_response vdev_peer_del_all_resp = {0};
447 	struct vdev_response_timer *vdev_rsp;
448 
449 	if (!scn || !data) {
450 		mlme_err("Invalid input");
451 		return -EINVAL;
452 	}
453 
454 	psoc = target_if_get_psoc_from_scn_hdl(scn);
455 	if (!psoc) {
456 		mlme_err("PSOC is NULL");
457 		return -EINVAL;
458 	}
459 
460 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
461 	if (!rx_ops || !rx_ops->vdev_mgr_peer_delete_all_response) {
462 		mlme_err("No Rx Ops");
463 		return -EINVAL;
464 	}
465 
466 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
467 	if (!wmi_handle) {
468 		mlme_err("wmi_handle is null");
469 		return -EINVAL;
470 	}
471 
472 	if (wmi_extract_vdev_peer_delete_all_response_event(
473 						wmi_handle, data,
474 						&vdev_peer_del_all_resp)) {
475 		mlme_err("WMI extract failed");
476 		return -EINVAL;
477 	}
478 
479 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc,
480 						vdev_peer_del_all_resp.vdev_id);
481 	if (!vdev_rsp) {
482 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
483 			 vdev_peer_del_all_resp.vdev_id,
484 			 wlan_psoc_get_id(psoc));
485 		return -EINVAL;
486 	}
487 
488 	status = target_if_vdev_mgr_rsp_timer_stop(
489 						psoc,
490 						vdev_rsp,
491 						PEER_DELETE_ALL_RESPONSE_BIT);
492 
493 	if (QDF_IS_STATUS_ERROR(status)) {
494 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
495 			 psoc->soc_objmgr.psoc_id,
496 			 vdev_peer_del_all_resp.vdev_id);
497 		goto err;
498 	}
499 
500 	status = rx_ops->vdev_mgr_peer_delete_all_response(
501 						psoc,
502 						&vdev_peer_del_all_resp);
503 
504 err:
505 	return qdf_status_to_os_return(status);
506 }
507 
508 int target_if_vdev_mgr_offload_bcn_tx_status_handler(
509 					ol_scn_t scn,
510 					uint8_t *data,
511 					uint32_t datalen)
512 {
513 	QDF_STATUS status;
514 	struct wlan_objmgr_psoc *psoc;
515 	struct wmi_unified *wmi_handle;
516 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
517 	uint32_t vdev_id, tx_status;
518 
519 	if (!scn || !data) {
520 		mlme_err("Invalid input");
521 		return -EINVAL;
522 	}
523 	psoc = target_if_get_psoc_from_scn_hdl(scn);
524 	if (!psoc) {
525 		mlme_err("PSOC is NULL");
526 		return -EINVAL;
527 	}
528 
529 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
530 	if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) {
531 		mlme_err("No Rx Ops");
532 		return -EINVAL;
533 	}
534 
535 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
536 	if (!wmi_handle) {
537 		mlme_err("wmi_handle is null");
538 		return -EINVAL;
539 	}
540 
541 	if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data,
542 						  &vdev_id, &tx_status)) {
543 		mlme_err("WMI extract failed");
544 		return -EINVAL;
545 	}
546 
547 	status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle(
548 								vdev_id,
549 								tx_status);
550 
551 	return qdf_status_to_os_return(status);
552 }
553 
554 int target_if_vdev_mgr_tbttoffset_update_handler(
555 						ol_scn_t scn, uint8_t *data,
556 						uint32_t datalen)
557 {
558 	QDF_STATUS status;
559 	struct wlan_objmgr_psoc *psoc;
560 	struct wmi_unified *wmi_handle;
561 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
562 	uint32_t num_vdevs = 0;
563 
564 	if (!scn || !data) {
565 		mlme_err("Invalid input");
566 		return -EINVAL;
567 	}
568 	psoc = target_if_get_psoc_from_scn_hdl(scn);
569 	if (!psoc) {
570 		mlme_err("PSOC is NULL");
571 		return -EINVAL;
572 	}
573 
574 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
575 	if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) {
576 		mlme_err("No Rx Ops");
577 		return -EINVAL;
578 	}
579 
580 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
581 	if (!wmi_handle) {
582 		mlme_err("wmi_handle is null");
583 		return -EINVAL;
584 	}
585 
586 	if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) {
587 		mlme_err("WMI extract failed");
588 		return -EINVAL;
589 	}
590 
591 	status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs,
592 							   false);
593 
594 	return qdf_status_to_os_return(status);
595 }
596 
597 int target_if_vdev_mgr_ext_tbttoffset_update_handler(
598 						ol_scn_t scn,
599 						uint8_t *data,
600 						uint32_t datalen)
601 {
602 	QDF_STATUS status;
603 	struct wlan_objmgr_psoc *psoc;
604 	struct wmi_unified *wmi_handle;
605 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
606 	uint32_t num_vdevs = 0;
607 
608 	if (!scn || !data) {
609 		mlme_err("Invalid input");
610 		return -EINVAL;
611 	}
612 	psoc = target_if_get_psoc_from_scn_hdl(scn);
613 	if (!psoc) {
614 		mlme_err("PSOC is NULL");
615 		return -EINVAL;
616 	}
617 
618 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
619 	if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) {
620 		mlme_err("No Rx Ops");
621 		return -EINVAL;
622 	}
623 
624 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
625 	if (!wmi_handle) {
626 		mlme_err("wmi_handle is null");
627 		return -EINVAL;
628 	}
629 
630 	if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data,
631 						 &num_vdevs)) {
632 		mlme_err("WMI extract failed");
633 		return -EINVAL;
634 	}
635 
636 	status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs,
637 							   true);
638 
639 	return qdf_status_to_os_return(status);
640 }
641 
642 static int target_if_vdev_mgr_multi_vdev_restart_resp_handler(
643 							ol_scn_t scn,
644 							uint8_t *data,
645 							uint32_t datalen)
646 {
647 	QDF_STATUS status = QDF_STATUS_E_INVAL;
648 	struct wlan_objmgr_psoc *psoc;
649 	struct wmi_unified *wmi_handle;
650 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
651 	struct multi_vdev_restart_resp restart_resp;
652 	struct vdev_response_timer *vdev_rsp;
653 	uint8_t max_vdevs, vdev_idx;
654 
655 	if (!scn || !data) {
656 		mlme_err("Invalid input");
657 		return -EINVAL;
658 	}
659 
660 	psoc = target_if_get_psoc_from_scn_hdl(scn);
661 	if (!psoc) {
662 		mlme_err("PSOC is NULL");
663 		return -EINVAL;
664 	}
665 
666 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
667 	if (!rx_ops || !rx_ops->vdev_mgr_multi_vdev_restart_resp ||
668 	    !rx_ops->psoc_get_vdev_response_timer_info) {
669 		mlme_err("No Rx Ops");
670 		return -EINVAL;
671 	}
672 
673 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
674 	if (!wmi_handle) {
675 		mlme_err("wmi_handle is null");
676 		return -EINVAL;
677 	}
678 
679 	qdf_mem_zero(&restart_resp, sizeof(restart_resp));
680 	if (wmi_extract_multi_vdev_restart_resp_event(wmi_handle, data,
681 						      &restart_resp)) {
682 		mlme_err("WMI extract failed");
683 		return -EINVAL;
684 	}
685 
686 	max_vdevs = wlan_psoc_get_max_vdev_count(psoc);
687 	for (vdev_idx = 0; vdev_idx < max_vdevs; vdev_idx++) {
688 		if (!qdf_test_bit(vdev_idx, restart_resp.vdev_id_bmap))
689 			continue;
690 
691 		mlme_debug("PSOC_%d VDEV_%d: Restart resp received",
692 			   wlan_psoc_get_id(psoc), vdev_idx);
693 		vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc,
694 								     vdev_idx);
695 		if (!vdev_rsp) {
696 			mlme_err("PSOC_%d VDEV_%d: VDEV RSP is NULL",
697 				 wlan_psoc_get_id(psoc), vdev_idx);
698 			continue;
699 		}
700 
701 		status = target_if_vdev_mgr_rsp_timer_stop(
702 				psoc, vdev_rsp, RESTART_RESPONSE_BIT);
703 		if (QDF_IS_STATUS_ERROR(status))
704 			mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
705 				 wlan_psoc_get_id(psoc), vdev_idx);
706 	}
707 
708 	status = rx_ops->vdev_mgr_multi_vdev_restart_resp(psoc, &restart_resp);
709 
710 	return qdf_status_to_os_return(status);
711 }
712 
713 /**
714  * target_if_vdev_csa_complete - CSA complete event handler
715  * @psoc: psoc
716  * @vdev_id: vdev id
717  *
718  * Return: 0 on success
719  */
720 static int target_if_vdev_csa_complete(struct wlan_objmgr_psoc *psoc,
721 				       uint8_t vdev_id)
722 {
723 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
724 	struct vdev_mlme_obj *vdev_mlme;
725 	struct wlan_objmgr_vdev *vdev;
726 	int ret = 0;
727 
728 	if (!psoc) {
729 		mlme_err("Invalid input");
730 		return -EINVAL;
731 	}
732 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
733 						    WLAN_VDEV_TARGET_IF_ID);
734 	if (!vdev) {
735 		mlme_err("VDEV is NULL");
736 		return -EINVAL;
737 	}
738 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
739 	if (!vdev_mlme) {
740 		mlme_err("VDEV_%d: PSOC_%d VDEV_MLME is NULL", vdev_id,
741 			 wlan_psoc_get_id(psoc));
742 		ret = -EINVAL;
743 		goto end;
744 	}
745 
746 	if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_csa_complete) {
747 		status = vdev_mlme->ops->mlme_vdev_csa_complete(vdev_mlme);
748 		if (QDF_IS_STATUS_ERROR(status)) {
749 			mlme_err("vdev csa complete failed");
750 			ret = -EINVAL;
751 		}
752 	}
753 end:
754 	wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID);
755 	return ret;
756 }
757 
758 /**
759  * target_if_pdev_csa_status_event_handler - CSA event handler
760  * @scn: Pointer to scn structure
761  * @data: pointer to event data
762  * @datalen: event data length
763  *
764  * Return: 0 on success
765  */
766 static int target_if_pdev_csa_status_event_handler(
767 		ol_scn_t scn,
768 		uint8_t *data,
769 		uint32_t datalen)
770 {
771 	struct pdev_csa_switch_count_status csa_status;
772 	struct wlan_objmgr_psoc *psoc;
773 	struct wmi_unified *wmi_handle;
774 	struct target_psoc_info *tgt_hdl;
775 	int i;
776 	QDF_STATUS status;
777 
778 	if (!scn || !data) {
779 		mlme_err("Invalid input");
780 		return -EINVAL;
781 	}
782 
783 	psoc = target_if_get_psoc_from_scn_hdl(scn);
784 	if (!psoc) {
785 		mlme_err("PSOC is NULL");
786 		return -EINVAL;
787 	}
788 
789 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
790 	if (!wmi_handle) {
791 		mlme_err("wmi_handle is null");
792 		return -EINVAL;
793 	}
794 
795 	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
796 	if (!tgt_hdl) {
797 		mlme_err("target_psoc_info is null");
798 		return -EINVAL;
799 	}
800 
801 	qdf_mem_zero(&csa_status, sizeof(csa_status));
802 	status = wmi_extract_pdev_csa_switch_count_status(
803 			wmi_handle, data, &csa_status);
804 	if (QDF_IS_STATUS_ERROR(status)) {
805 		mlme_err("Extracting CSA switch count status event failed");
806 		return -EINVAL;
807 	}
808 
809 	if (wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_CSA_TX_OFFLOAD)) {
810 		for (i = 0; i < csa_status.num_vdevs; i++) {
811 			if (!csa_status.current_switch_count)
812 				target_if_vdev_csa_complete(psoc,
813 							csa_status.vdev_ids[i]);
814 		}
815 	}
816 
817 	return target_if_csa_switch_count_status(psoc, tgt_hdl, csa_status);
818 }
819 
820 QDF_STATUS target_if_vdev_mgr_wmi_event_register(
821 				struct wlan_objmgr_psoc *psoc)
822 {
823 	QDF_STATUS retval = QDF_STATUS_SUCCESS;
824 	struct wmi_unified *wmi_handle;
825 
826 	if (!psoc) {
827 		mlme_err("PSOC is NULL");
828 		return QDF_STATUS_E_NULL_VALUE;
829 	}
830 
831 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
832 	if (!wmi_handle) {
833 		mlme_err("wmi_handle is null");
834 		return QDF_STATUS_E_INVAL;
835 	}
836 
837 	retval = wmi_unified_register_event_handler(
838 				wmi_handle,
839 				wmi_vdev_stopped_event_id,
840 				target_if_vdev_mgr_stop_response_handler,
841 				VDEV_RSP_RX_CTX);
842 	if (QDF_IS_STATUS_ERROR(retval))
843 		mlme_err("failed to register for stop response");
844 
845 	retval = wmi_unified_register_event_handler(
846 				wmi_handle,
847 				wmi_vdev_delete_resp_event_id,
848 				target_if_vdev_mgr_delete_response_handler,
849 				VDEV_RSP_RX_CTX);
850 	if (QDF_IS_STATUS_ERROR(retval))
851 		mlme_err("failed to register for delete response");
852 
853 	retval = wmi_unified_register_event_handler(
854 				wmi_handle,
855 				wmi_vdev_start_resp_event_id,
856 				target_if_vdev_mgr_start_response_handler,
857 				VDEV_RSP_RX_CTX);
858 	if (QDF_IS_STATUS_ERROR(retval))
859 		mlme_err("failed to register for start response");
860 
861 	retval = wmi_unified_register_event_handler(
862 			wmi_handle,
863 			wmi_peer_delete_all_response_event_id,
864 			target_if_vdev_mgr_peer_delete_all_response_handler,
865 			VDEV_RSP_RX_CTX);
866 	if (QDF_IS_STATUS_ERROR(retval))
867 		mlme_err("failed to register for peer delete all response");
868 
869 	retval = wmi_unified_register_event_handler(
870 			wmi_handle,
871 			wmi_pdev_multi_vdev_restart_response_event_id,
872 			target_if_vdev_mgr_multi_vdev_restart_resp_handler,
873 			VDEV_RSP_RX_CTX);
874 	if (QDF_IS_STATUS_ERROR(retval))
875 		mlme_err("failed to register for multivdev restart response");
876 
877 	if (wmi_service_enabled(wmi_handle, wmi_service_beacon_offload)) {
878 		retval = wmi_unified_register_event_handler(
879 				wmi_handle,
880 				wmi_pdev_csa_switch_count_status_event_id,
881 				target_if_pdev_csa_status_event_handler,
882 				VDEV_RSP_RX_CTX);
883 		if (QDF_IS_STATUS_ERROR(retval))
884 			mlme_err("failed to register for csa event handler");
885 	}
886 
887 	return retval;
888 }
889 
890 QDF_STATUS target_if_vdev_mgr_wmi_event_unregister(
891 					struct wlan_objmgr_psoc *psoc)
892 {
893 	struct wmi_unified *wmi_handle;
894 
895 	if (!psoc) {
896 		mlme_err("PSOC is NULL");
897 		return QDF_STATUS_E_INVAL;
898 	}
899 
900 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
901 	if (!wmi_handle) {
902 		mlme_err("wmi_handle is null");
903 		return QDF_STATUS_E_INVAL;
904 	}
905 
906 	wmi_unified_unregister_event_handler(
907 			wmi_handle,
908 			wmi_pdev_multi_vdev_restart_response_event_id);
909 
910 	wmi_unified_unregister_event_handler(
911 			wmi_handle,
912 			wmi_peer_delete_all_response_event_id);
913 
914 	wmi_unified_unregister_event_handler(wmi_handle,
915 					     wmi_vdev_start_resp_event_id);
916 
917 	wmi_unified_unregister_event_handler(wmi_handle,
918 					     wmi_vdev_delete_resp_event_id);
919 
920 	wmi_unified_unregister_event_handler(wmi_handle,
921 					     wmi_vdev_stopped_event_id);
922 
923 	return QDF_STATUS_SUCCESS;
924 }
925