xref: /wlan-dirver/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c (revision a86b23ee68a2491aede2e03991f3fb37046f4e41)
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 
35 static inline
36 void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc,
37 					uint8_t vdev_id,
38 					enum qdf_hang_reason recovery_reason,
39 					uint16_t rsp_pos)
40 {
41 	mlme_nofl_err("PSOC_%d VDEV_%d: %s rsp timeout", wlan_psoc_get_id(psoc),
42 		      vdev_id, string_from_rsp_bit(rsp_pos));
43 	if (target_if_vdev_mgr_is_panic_allowed())
44 		qdf_trigger_self_recovery(psoc, recovery_reason);
45 	else
46 		mlme_nofl_debug("PSOC_%d VDEV_%d: Panic not allowed",
47 				wlan_psoc_get_id(psoc), vdev_id);
48 }
49 
50 void target_if_vdev_mgr_rsp_timer_cb(void *arg)
51 {
52 	struct wlan_objmgr_psoc *psoc;
53 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
54 	struct vdev_start_response start_rsp = {0};
55 	struct vdev_stop_response stop_rsp = {0};
56 	struct vdev_delete_response del_rsp = {0};
57 	struct peer_delete_all_response peer_del_all_rsp = {0};
58 	struct vdev_response_timer *vdev_rsp = arg;
59 	enum qdf_hang_reason recovery_reason;
60 	uint8_t vdev_id;
61 	uint16_t rsp_pos = RESPONSE_BIT_MAX;
62 
63 	if (!vdev_rsp) {
64 		mlme_err("Vdev response timer is NULL");
65 		return;
66 	}
67 
68 	psoc = vdev_rsp->psoc;
69 	if (!psoc) {
70 		mlme_err("PSOC is NULL");
71 		return;
72 	}
73 
74 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
75 	if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) {
76 		mlme_err("No Rx Ops");
77 		return;
78 	}
79 
80 	if (!qdf_atomic_test_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
81 	    !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
82 	    !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
83 	    !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status) &&
84 	    !qdf_atomic_test_bit(
85 			PEER_DELETE_ALL_RESPONSE_BIT,
86 			&vdev_rsp->rsp_status)) {
87 		mlme_debug("No response bit is set, ignoring actions :%d",
88 			   vdev_rsp->vdev_id);
89 		return;
90 	}
91 
92 	vdev_id = vdev_rsp->vdev_id;
93 	if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
94 		mlme_err("Invalid VDEV_%d PSOC_%d", vdev_id,
95 			 wlan_psoc_get_id(psoc));
96 		return;
97 	}
98 
99 	vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT;
100 	if (qdf_atomic_test_bit(START_RESPONSE_BIT,
101 				&vdev_rsp->rsp_status) ||
102 	    qdf_atomic_test_bit(RESTART_RESPONSE_BIT,
103 				&vdev_rsp->rsp_status)) {
104 		start_rsp.vdev_id = vdev_id;
105 		start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT;
106 		if (qdf_atomic_test_bit(START_RESPONSE_BIT,
107 					&vdev_rsp->rsp_status)) {
108 			start_rsp.resp_type =
109 				WMI_HOST_VDEV_START_RESP_EVENT;
110 			rsp_pos = START_RESPONSE_BIT;
111 			recovery_reason = QDF_VDEV_START_RESPONSE_TIMED_OUT;
112 		} else {
113 			start_rsp.resp_type =
114 				WMI_HOST_VDEV_RESTART_RESP_EVENT;
115 			rsp_pos = RESTART_RESPONSE_BIT;
116 			recovery_reason = QDF_VDEV_RESTART_RESPONSE_TIMED_OUT;
117 		}
118 
119 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
120 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
121 						   recovery_reason, rsp_pos);
122 		rx_ops->vdev_mgr_start_response(psoc, &start_rsp);
123 	} else if (qdf_atomic_test_bit(STOP_RESPONSE_BIT,
124 				       &vdev_rsp->rsp_status)) {
125 		rsp_pos = STOP_RESPONSE_BIT;
126 		stop_rsp.vdev_id = vdev_id;
127 		recovery_reason = QDF_VDEV_STOP_RESPONSE_TIMED_OUT;
128 
129 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
130 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
131 						   recovery_reason, rsp_pos);
132 		rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp);
133 	} else if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT,
134 				       &vdev_rsp->rsp_status)) {
135 		del_rsp.vdev_id = vdev_id;
136 		rsp_pos = DELETE_RESPONSE_BIT;
137 		recovery_reason = QDF_VDEV_DELETE_RESPONSE_TIMED_OUT;
138 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
139 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
140 						   recovery_reason, rsp_pos);
141 		rx_ops->vdev_mgr_delete_response(psoc, &del_rsp);
142 	} else if (qdf_atomic_test_bit(PEER_DELETE_ALL_RESPONSE_BIT,
143 				&vdev_rsp->rsp_status)) {
144 		peer_del_all_rsp.vdev_id = vdev_id;
145 		rsp_pos = PEER_DELETE_ALL_RESPONSE_BIT;
146 		recovery_reason = QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
147 		target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos);
148 		target_if_vdev_mgr_handle_recovery(psoc, vdev_id,
149 						   recovery_reason, rsp_pos);
150 		rx_ops->vdev_mgr_peer_delete_all_response(psoc,
151 							  &peer_del_all_rsp);
152 	} else {
153 		mlme_err("PSOC_%d VDEV_%d: Unknown error",
154 			 wlan_psoc_get_id(psoc), vdev_id);
155 		return;
156 	}
157 }
158 
159 #ifdef SERIALIZE_VDEV_RESP
160 static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg)
161 {
162 	struct vdev_response_timer *vdev_rsp;
163 	struct wlan_objmgr_psoc *psoc;
164 
165 	if (!msg->bodyptr) {
166 		mlme_err("Message bodyptr is NULL");
167 		return QDF_STATUS_E_INVAL;
168 	}
169 
170 	vdev_rsp = msg->bodyptr;
171 	if (!vdev_rsp) {
172 		mlme_err("vdev response timer is NULL");
173 		return QDF_STATUS_E_INVAL;
174 	}
175 
176 	psoc = vdev_rsp->psoc;
177 	if (!psoc) {
178 		mlme_err("PSOC is NULL");
179 		return QDF_STATUS_E_INVAL;
180 	}
181 
182 	if (vdev_rsp->rsp_status)
183 		wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID);
184 
185 	return QDF_STATUS_SUCCESS;
186 }
187 
188 static void
189 target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg)
190 {
191 	struct scheduler_msg msg = {0};
192 	struct vdev_response_timer *vdev_rsp = arg;
193 	struct wlan_objmgr_psoc *psoc;
194 
195 	psoc = vdev_rsp->psoc;
196 	if (!psoc) {
197 		mlme_err("PSOC is NULL");
198 		return;
199 	}
200 
201 	msg.type = SYS_MSG_ID_MC_TIMER;
202 	msg.reserved = SYS_MSG_COOKIE;
203 
204 	/* msg.callback will explicitly cast back to qdf_mc_timer_callback_t
205 	 * in scheduler_timer_q_mq_handler.
206 	 * but in future we do not want to introduce more this kind of
207 	 * typecast by properly using QDF MC timer for MCC from get go in
208 	 * common code.
209 	 */
210 	msg.callback =
211 		(scheduler_msg_process_fn_t)target_if_vdev_mgr_rsp_timer_cb;
212 	msg.bodyptr = arg;
213 	msg.bodyval = 0;
214 	msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb;
215 
216 	if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
217 				   QDF_MODULE_ID_TARGET_IF,
218 				   QDF_MODULE_ID_SYS, &msg) ==
219 				   QDF_STATUS_SUCCESS)
220 		return;
221 
222 	mlme_err("Could not enqueue timer to timer queue");
223 	if (psoc)
224 		wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID);
225 }
226 
227 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg)
228 {
229 	target_if_vdev_mgr_rsp_cb_mc_ctx(arg);
230 }
231 
232 #define VDEV_RSP_RX_CTX WMI_RX_SERIALIZER_CTX
233 #else
234 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg)
235 {
236 	target_if_vdev_mgr_rsp_timer_cb(arg);
237 }
238 
239 #define VDEV_RSP_RX_CTX WMI_RX_UMAC_CTX
240 #endif
241 
242 static int target_if_vdev_mgr_start_response_handler(ol_scn_t scn,
243 						     uint8_t *data,
244 						     uint32_t datalen)
245 {
246 	QDF_STATUS status = QDF_STATUS_E_INVAL;
247 	struct wlan_objmgr_psoc *psoc;
248 	struct wmi_unified *wmi_handle;
249 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
250 	struct vdev_start_response vdev_start_resp = {0};
251 	uint8_t vdev_id;
252 	struct vdev_response_timer *vdev_rsp;
253 
254 	if (!scn || !data) {
255 		mlme_err("Invalid input");
256 		return -EINVAL;
257 	}
258 
259 	psoc = target_if_get_psoc_from_scn_hdl(scn);
260 	if (!psoc) {
261 		mlme_err("PSOC is NULL");
262 		return -EINVAL;
263 	}
264 
265 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
266 	if (!rx_ops || !rx_ops->vdev_mgr_start_response) {
267 		mlme_err("No Rx Ops");
268 		return -EINVAL;
269 	}
270 
271 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
272 	if (!wmi_handle) {
273 		mlme_err("wmi_handle is null");
274 		return -EINVAL;
275 	}
276 
277 	if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) {
278 		mlme_err("WMI extract failed");
279 		return -EINVAL;
280 	}
281 
282 	vdev_id = vdev_start_resp.vdev_id;
283 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id);
284 	if (!vdev_rsp) {
285 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
286 			 vdev_id, wlan_psoc_get_id(psoc));
287 		return -EINVAL;
288 	}
289 
290 	if (vdev_start_resp.resp_type == WMI_HOST_VDEV_RESTART_RESP_EVENT)
291 		status = target_if_vdev_mgr_rsp_timer_stop(
292 							psoc, vdev_rsp,
293 							RESTART_RESPONSE_BIT);
294 	else
295 		status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp,
296 							   START_RESPONSE_BIT);
297 
298 	if (QDF_IS_STATUS_ERROR(status)) {
299 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
300 			 psoc->soc_objmgr.psoc_id, vdev_id);
301 		goto err;
302 	}
303 
304 	status = rx_ops->vdev_mgr_start_response(psoc, &vdev_start_resp);
305 
306 err:
307 	return qdf_status_to_os_return(status);
308 }
309 
310 static int target_if_vdev_mgr_stop_response_handler(ol_scn_t scn,
311 						    uint8_t *data,
312 						    uint32_t datalen)
313 {
314 	QDF_STATUS status = QDF_STATUS_E_INVAL;
315 	struct wlan_objmgr_psoc *psoc;
316 	struct wmi_unified *wmi_handle;
317 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
318 	struct vdev_stop_response rsp = {0};
319 	uint32_t vdev_id;
320 	struct vdev_response_timer *vdev_rsp;
321 
322 	if (!scn || !data) {
323 		mlme_err("Invalid input");
324 		return -EINVAL;
325 	}
326 
327 	psoc = target_if_get_psoc_from_scn_hdl(scn);
328 	if (!psoc) {
329 		mlme_err("PSOC is NULL");
330 		return -EINVAL;
331 	}
332 
333 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
334 	if (!rx_ops || !rx_ops->vdev_mgr_stop_response) {
335 		mlme_err("No Rx Ops");
336 		return -EINVAL;
337 	}
338 
339 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
340 	if (!wmi_handle) {
341 		mlme_err("wmi_handle is null");
342 		return -EINVAL;
343 	}
344 
345 	if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) {
346 		mlme_err("WMI extract failed");
347 		return -EINVAL;
348 	}
349 
350 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id);
351 	if (!vdev_rsp) {
352 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
353 			 vdev_id, wlan_psoc_get_id(psoc));
354 		return -EINVAL;
355 	}
356 
357 	status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp,
358 						   STOP_RESPONSE_BIT);
359 
360 	if (QDF_IS_STATUS_ERROR(status)) {
361 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
362 			 psoc->soc_objmgr.psoc_id, vdev_id);
363 		goto err;
364 	}
365 
366 	rsp.vdev_id = vdev_id;
367 	status = rx_ops->vdev_mgr_stop_response(psoc, &rsp);
368 
369 err:
370 	return qdf_status_to_os_return(status);
371 }
372 
373 static int target_if_vdev_mgr_delete_response_handler(ol_scn_t scn,
374 						      uint8_t *data,
375 						      uint32_t datalen)
376 {
377 	QDF_STATUS status = QDF_STATUS_E_INVAL;
378 	struct wlan_objmgr_psoc *psoc;
379 	struct wmi_unified *wmi_handle;
380 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
381 	struct vdev_delete_response vdev_del_resp = {0};
382 	struct vdev_response_timer *vdev_rsp;
383 
384 	if (!scn || !data) {
385 		mlme_err("Invalid input");
386 		return -EINVAL;
387 	}
388 
389 	psoc = target_if_get_psoc_from_scn_hdl(scn);
390 	if (!psoc) {
391 		mlme_err("PSOC is NULL");
392 		return -EINVAL;
393 	}
394 
395 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
396 	if (!rx_ops || !rx_ops->vdev_mgr_delete_response) {
397 		mlme_err("No Rx Ops");
398 		return -EINVAL;
399 	}
400 
401 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
402 	if (!wmi_handle) {
403 		mlme_err("wmi_handle is null");
404 		return -EINVAL;
405 	}
406 
407 	if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) {
408 		mlme_err("WMI extract failed");
409 		return -EINVAL;
410 	}
411 
412 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc,
413 							 vdev_del_resp.vdev_id);
414 	if (!vdev_rsp) {
415 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
416 			 vdev_del_resp.vdev_id, wlan_psoc_get_id(psoc));
417 		return -EINVAL;
418 	}
419 
420 	status = target_if_vdev_mgr_rsp_timer_stop(
421 						psoc, vdev_rsp,
422 						DELETE_RESPONSE_BIT);
423 
424 	if (QDF_IS_STATUS_ERROR(status)) {
425 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
426 			 wlan_psoc_get_id(psoc), vdev_del_resp.vdev_id);
427 		goto err;
428 	}
429 
430 	status = rx_ops->vdev_mgr_delete_response(psoc, &vdev_del_resp);
431 
432 err:
433 	return qdf_status_to_os_return(status);
434 }
435 
436 static int target_if_vdev_mgr_peer_delete_all_response_handler(
437 							ol_scn_t scn,
438 							uint8_t *data,
439 							uint32_t datalen)
440 {
441 	QDF_STATUS status = QDF_STATUS_E_INVAL;
442 	struct wlan_objmgr_psoc *psoc;
443 	struct wmi_unified *wmi_handle;
444 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
445 	struct peer_delete_all_response vdev_peer_del_all_resp = {0};
446 	struct vdev_response_timer *vdev_rsp;
447 
448 	if (!scn || !data) {
449 		mlme_err("Invalid input");
450 		return -EINVAL;
451 	}
452 
453 	psoc = target_if_get_psoc_from_scn_hdl(scn);
454 	if (!psoc) {
455 		mlme_err("PSOC is NULL");
456 		return -EINVAL;
457 	}
458 
459 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
460 	if (!rx_ops || !rx_ops->vdev_mgr_peer_delete_all_response) {
461 		mlme_err("No Rx Ops");
462 		return -EINVAL;
463 	}
464 
465 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
466 	if (!wmi_handle) {
467 		mlme_err("wmi_handle is null");
468 		return -EINVAL;
469 	}
470 
471 	if (wmi_extract_vdev_peer_delete_all_response_event(
472 						wmi_handle, data,
473 						&vdev_peer_del_all_resp)) {
474 		mlme_err("WMI extract failed");
475 		return -EINVAL;
476 	}
477 
478 	vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc,
479 						vdev_peer_del_all_resp.vdev_id);
480 	if (!vdev_rsp) {
481 		mlme_err("vdev response timer is null VDEV_%d PSOC_%d",
482 			 vdev_peer_del_all_resp.vdev_id,
483 			 wlan_psoc_get_id(psoc));
484 		return -EINVAL;
485 	}
486 
487 	status = target_if_vdev_mgr_rsp_timer_stop(
488 						psoc,
489 						vdev_rsp,
490 						PEER_DELETE_ALL_RESPONSE_BIT);
491 
492 	if (QDF_IS_STATUS_ERROR(status)) {
493 		mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
494 			 psoc->soc_objmgr.psoc_id,
495 			 vdev_peer_del_all_resp.vdev_id);
496 		goto err;
497 	}
498 
499 	status = rx_ops->vdev_mgr_peer_delete_all_response(
500 						psoc,
501 						&vdev_peer_del_all_resp);
502 
503 err:
504 	return qdf_status_to_os_return(status);
505 }
506 
507 int target_if_vdev_mgr_offload_bcn_tx_status_handler(
508 					ol_scn_t scn,
509 					uint8_t *data,
510 					uint32_t datalen)
511 {
512 	QDF_STATUS status;
513 	struct wlan_objmgr_psoc *psoc;
514 	struct wmi_unified *wmi_handle;
515 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
516 	uint32_t vdev_id, tx_status;
517 
518 	if (!scn || !data) {
519 		mlme_err("Invalid input");
520 		return -EINVAL;
521 	}
522 	psoc = target_if_get_psoc_from_scn_hdl(scn);
523 	if (!psoc) {
524 		mlme_err("PSOC is NULL");
525 		return -EINVAL;
526 	}
527 
528 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
529 	if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) {
530 		mlme_err("No Rx Ops");
531 		return -EINVAL;
532 	}
533 
534 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
535 	if (!wmi_handle) {
536 		mlme_err("wmi_handle is null");
537 		return -EINVAL;
538 	}
539 
540 	if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data,
541 						  &vdev_id, &tx_status)) {
542 		mlme_err("WMI extract failed");
543 		return -EINVAL;
544 	}
545 
546 	status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle(
547 								vdev_id,
548 								tx_status);
549 
550 	return qdf_status_to_os_return(status);
551 }
552 
553 int target_if_vdev_mgr_tbttoffset_update_handler(
554 						ol_scn_t scn, uint8_t *data,
555 						uint32_t datalen)
556 {
557 	QDF_STATUS status;
558 	struct wlan_objmgr_psoc *psoc;
559 	struct wmi_unified *wmi_handle;
560 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
561 	uint32_t num_vdevs = 0;
562 
563 	if (!scn || !data) {
564 		mlme_err("Invalid input");
565 		return -EINVAL;
566 	}
567 	psoc = target_if_get_psoc_from_scn_hdl(scn);
568 	if (!psoc) {
569 		mlme_err("PSOC is NULL");
570 		return -EINVAL;
571 	}
572 
573 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
574 	if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) {
575 		mlme_err("No Rx Ops");
576 		return -EINVAL;
577 	}
578 
579 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
580 	if (!wmi_handle) {
581 		mlme_err("wmi_handle is null");
582 		return -EINVAL;
583 	}
584 
585 	if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) {
586 		mlme_err("WMI extract failed");
587 		return -EINVAL;
588 	}
589 
590 	status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs,
591 							   false);
592 
593 	return qdf_status_to_os_return(status);
594 }
595 
596 int target_if_vdev_mgr_ext_tbttoffset_update_handler(
597 						ol_scn_t scn,
598 						uint8_t *data,
599 						uint32_t datalen)
600 {
601 	QDF_STATUS status;
602 	struct wlan_objmgr_psoc *psoc;
603 	struct wmi_unified *wmi_handle;
604 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
605 	uint32_t num_vdevs = 0;
606 
607 	if (!scn || !data) {
608 		mlme_err("Invalid input");
609 		return -EINVAL;
610 	}
611 	psoc = target_if_get_psoc_from_scn_hdl(scn);
612 	if (!psoc) {
613 		mlme_err("PSOC is NULL");
614 		return -EINVAL;
615 	}
616 
617 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
618 	if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) {
619 		mlme_err("No Rx Ops");
620 		return -EINVAL;
621 	}
622 
623 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
624 	if (!wmi_handle) {
625 		mlme_err("wmi_handle is null");
626 		return -EINVAL;
627 	}
628 
629 	if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data,
630 						 &num_vdevs)) {
631 		mlme_err("WMI extract failed");
632 		return -EINVAL;
633 	}
634 
635 	status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs,
636 							   true);
637 
638 	return qdf_status_to_os_return(status);
639 }
640 
641 static int target_if_vdev_mgr_multi_vdev_restart_resp_handler(
642 							ol_scn_t scn,
643 							uint8_t *data,
644 							uint32_t datalen)
645 {
646 	QDF_STATUS status = QDF_STATUS_E_INVAL;
647 	struct wlan_objmgr_psoc *psoc;
648 	struct wmi_unified *wmi_handle;
649 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
650 	struct multi_vdev_restart_resp restart_resp;
651 	struct vdev_response_timer *vdev_rsp;
652 	uint8_t max_vdevs, vdev_idx;
653 
654 	if (!scn || !data) {
655 		mlme_err("Invalid input");
656 		return -EINVAL;
657 	}
658 
659 	psoc = target_if_get_psoc_from_scn_hdl(scn);
660 	if (!psoc) {
661 		mlme_err("PSOC is NULL");
662 		return -EINVAL;
663 	}
664 
665 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
666 	if (!rx_ops || !rx_ops->vdev_mgr_multi_vdev_restart_resp ||
667 	    !rx_ops->psoc_get_vdev_response_timer_info) {
668 		mlme_err("No Rx Ops");
669 		return -EINVAL;
670 	}
671 
672 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
673 	if (!wmi_handle) {
674 		mlme_err("wmi_handle is null");
675 		return -EINVAL;
676 	}
677 
678 	qdf_mem_zero(&restart_resp, sizeof(restart_resp));
679 	if (wmi_extract_multi_vdev_restart_resp_event(wmi_handle, data,
680 						      &restart_resp)) {
681 		mlme_err("WMI extract failed");
682 		return -EINVAL;
683 	}
684 
685 	max_vdevs = wlan_psoc_get_max_vdev_count(psoc);
686 	for (vdev_idx = 0; vdev_idx < max_vdevs; vdev_idx++) {
687 		if (!qdf_test_bit(vdev_idx, restart_resp.vdev_id_bmap))
688 			continue;
689 
690 		mlme_debug("PSOC_%d VDEV_%d: Restart resp received",
691 			   wlan_psoc_get_id(psoc), vdev_idx);
692 		vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc,
693 								     vdev_idx);
694 		if (!vdev_rsp) {
695 			mlme_err("PSOC_%d VDEV_%d: VDEV RSP is NULL",
696 				 wlan_psoc_get_id(psoc), vdev_idx);
697 			continue;
698 		}
699 
700 		status = target_if_vdev_mgr_rsp_timer_stop(
701 				psoc, vdev_rsp, RESTART_RESPONSE_BIT);
702 		if (QDF_IS_STATUS_ERROR(status))
703 			mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed",
704 				 wlan_psoc_get_id(psoc), vdev_idx);
705 	}
706 
707 	status = rx_ops->vdev_mgr_multi_vdev_restart_resp(psoc, &restart_resp);
708 
709 	return qdf_status_to_os_return(status);
710 }
711 
712 QDF_STATUS target_if_vdev_mgr_wmi_event_register(
713 				struct wlan_objmgr_psoc *psoc)
714 {
715 	int retval = 0;
716 	struct wmi_unified *wmi_handle;
717 
718 	if (!psoc) {
719 		mlme_err("PSOC is NULL");
720 		return QDF_STATUS_E_NULL_VALUE;
721 	}
722 
723 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
724 	if (!wmi_handle) {
725 		mlme_err("wmi_handle is null");
726 		return QDF_STATUS_E_INVAL;
727 	}
728 
729 	retval = wmi_unified_register_event_handler(
730 				wmi_handle,
731 				wmi_vdev_stopped_event_id,
732 				target_if_vdev_mgr_stop_response_handler,
733 				VDEV_RSP_RX_CTX);
734 	if (retval)
735 		mlme_err("failed to register for stop response");
736 
737 	retval = wmi_unified_register_event_handler(
738 				wmi_handle,
739 				wmi_vdev_delete_resp_event_id,
740 				target_if_vdev_mgr_delete_response_handler,
741 				VDEV_RSP_RX_CTX);
742 	if (retval)
743 		mlme_err("failed to register for delete response");
744 
745 	retval = wmi_unified_register_event_handler(
746 				wmi_handle,
747 				wmi_vdev_start_resp_event_id,
748 				target_if_vdev_mgr_start_response_handler,
749 				VDEV_RSP_RX_CTX);
750 	if (retval)
751 		mlme_err("failed to register for start response");
752 
753 	retval = wmi_unified_register_event_handler(
754 			wmi_handle,
755 			wmi_peer_delete_all_response_event_id,
756 			target_if_vdev_mgr_peer_delete_all_response_handler,
757 			VDEV_RSP_RX_CTX);
758 	if (retval)
759 		mlme_err("failed to register for peer delete all response");
760 
761 	retval = wmi_unified_register_event_handler(
762 			wmi_handle,
763 			wmi_pdev_multi_vdev_restart_response_event_id,
764 			target_if_vdev_mgr_multi_vdev_restart_resp_handler,
765 			VDEV_RSP_RX_CTX);
766 	if (retval)
767 		mlme_err("failed to register for multivdev restart response");
768 
769 	return qdf_status_from_os_return(retval);
770 }
771 
772 QDF_STATUS target_if_vdev_mgr_wmi_event_unregister(
773 					struct wlan_objmgr_psoc *psoc)
774 {
775 	struct wmi_unified *wmi_handle;
776 
777 	if (!psoc) {
778 		mlme_err("PSOC is NULL");
779 		return QDF_STATUS_E_INVAL;
780 	}
781 
782 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
783 	if (!wmi_handle) {
784 		mlme_err("wmi_handle is null");
785 		return QDF_STATUS_E_INVAL;
786 	}
787 
788 	wmi_unified_unregister_event_handler(
789 			wmi_handle,
790 			wmi_pdev_multi_vdev_restart_response_event_id);
791 
792 	wmi_unified_unregister_event_handler(
793 			wmi_handle,
794 			wmi_peer_delete_all_response_event_id);
795 
796 	wmi_unified_unregister_event_handler(wmi_handle,
797 					     wmi_vdev_start_resp_event_id);
798 
799 	wmi_unified_unregister_event_handler(wmi_handle,
800 					     wmi_vdev_delete_resp_event_id);
801 
802 	wmi_unified_unregister_event_handler(wmi_handle,
803 					     wmi_vdev_stopped_event_id);
804 
805 	return QDF_STATUS_SUCCESS;
806 }
807