1 /*
2  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  *  DOC: target_if_ext_twt_evt.c
19  *  This file contains twt component's target related function definitions
20  */
21 #include <qdf_util.h>
22 #include <wlan_twt_public_structs.h>
23 #include <wlan_lmac_if_def.h>
24 #include <target_if.h>
25 #include <target_if_ext_twt.h>
26 #include <wlan_twt_api.h>
27 #include "twt/core/src/wlan_twt_main.h"
28 
29 static int
target_if_twt_setup_complete_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)30 target_if_twt_setup_complete_event_handler(ol_scn_t scn, uint8_t *event,
31 					   uint32_t len)
32 {
33 	QDF_STATUS qdf_status;
34 	struct wmi_unified *wmi_handle;
35 	struct wlan_objmgr_psoc *psoc;
36 	struct twt_add_dialog_complete_event *data;
37 	struct wlan_lmac_if_twt_rx_ops *twt_rx_ops;
38 
39 	TARGET_IF_ENTER();
40 
41 	psoc = target_if_get_psoc_from_scn_hdl(scn);
42 	if (!psoc) {
43 		target_if_err("psoc is null");
44 		return -EINVAL;
45 	}
46 
47 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
48 	if (!wmi_handle) {
49 		target_if_err("wmi_handle is null");
50 		return -EINVAL;
51 	}
52 
53 	twt_rx_ops = wlan_twt_get_rx_ops(psoc);
54 	if (!twt_rx_ops || !twt_rx_ops->twt_setup_comp_cb) {
55 		target_if_err("No valid twt setup complete rx ops");
56 		return -EINVAL;
57 	}
58 
59 	data = qdf_mem_malloc(sizeof(*data));
60 	if (!data)
61 		return -ENOMEM;
62 
63 	qdf_status = wmi_extract_twt_add_dialog_comp_event(wmi_handle,
64 						event, &data->params);
65 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
66 		target_if_err("extract twt add dialog event failed (status=%d)",
67 			      qdf_status);
68 		goto done;
69 	}
70 
71 	if (data->params.num_additional_twt_params) {
72 		qdf_status = wmi_extract_twt_add_dialog_comp_additional_params(
73 						wmi_handle, event, len, 0,
74 						&data->additional_params);
75 		if (QDF_IS_STATUS_ERROR(qdf_status))
76 			goto done;
77 	}
78 
79 	qdf_status = twt_rx_ops->twt_setup_comp_cb(psoc, data);
80 
81 done:
82 	qdf_mem_free(data);
83 
84 	return qdf_status_to_os_return(qdf_status);
85 }
86 
87 static int
target_if_twt_teardown_complete_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)88 target_if_twt_teardown_complete_event_handler(ol_scn_t scn, uint8_t *event,
89 					      uint32_t len)
90 {
91 	QDF_STATUS qdf_status;
92 	struct wmi_unified *wmi_handle;
93 	struct wlan_objmgr_psoc *psoc;
94 	struct twt_del_dialog_complete_event_param *data;
95 	struct wlan_lmac_if_twt_rx_ops *twt_rx_ops;
96 
97 	TARGET_IF_ENTER();
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 	twt_rx_ops = wlan_twt_get_rx_ops(psoc);
112 	if (!twt_rx_ops || !twt_rx_ops->twt_teardown_comp_cb) {
113 		target_if_err("No valid twt teardown complete rx ops");
114 		return -EINVAL;
115 	}
116 
117 	data = qdf_mem_malloc(sizeof(*data));
118 	if (!data)
119 		return -ENOMEM;
120 
121 	qdf_status = wmi_extract_twt_del_dialog_comp_event(wmi_handle,
122 							   event, data);
123 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
124 		target_if_err("extract twt del dialog event failed (status=%d)",
125 			      qdf_status);
126 		goto done;
127 	}
128 
129 	qdf_status = twt_rx_ops->twt_teardown_comp_cb(psoc, data);
130 
131 done:
132 	qdf_mem_free(data);
133 
134 	return qdf_status_to_os_return(qdf_status);
135 
136 }
137 
138 /**
139  * target_if_twt_pause_complete_event_handler - TWT pause complete handler
140  * @scn: scn
141  * @event: buffer with event
142  * @len: buffer length
143  *
144  * Return: 0 on success, negative value on failure
145  */
146 static int
target_if_twt_pause_complete_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)147 target_if_twt_pause_complete_event_handler(ol_scn_t scn, uint8_t *event,
148 					   uint32_t len)
149 {
150 	QDF_STATUS qdf_status;
151 	struct wmi_unified *wmi_handle;
152 	struct wlan_objmgr_psoc *psoc;
153 	struct twt_pause_dialog_complete_event_param *param;
154 	struct wlan_lmac_if_twt_rx_ops *twt_rx_ops;
155 
156 	TARGET_IF_ENTER();
157 
158 	psoc = target_if_get_psoc_from_scn_hdl(scn);
159 	if (!psoc) {
160 		target_if_err("psoc is null");
161 		return -EINVAL;
162 	}
163 
164 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
165 	if (!wmi_handle) {
166 		target_if_err("wmi_handle is null");
167 		return -EINVAL;
168 	}
169 
170 	twt_rx_ops = wlan_twt_get_rx_ops(psoc);
171 	if (!twt_rx_ops || !twt_rx_ops->twt_pause_comp_cb) {
172 		target_if_err("No valid twt pause complete rx ops");
173 		return -EINVAL;
174 	}
175 
176 	param = qdf_mem_malloc(sizeof(*param));
177 	if (!param)
178 		return -ENOMEM;
179 
180 	qdf_status = wmi_extract_twt_pause_dialog_comp_event(wmi_handle,
181 							     event, param);
182 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
183 		target_if_err("extract twt pause dialog event failed (status=%d)",
184 			     qdf_status);
185 		goto done;
186 	}
187 
188 	qdf_status = twt_rx_ops->twt_pause_comp_cb(psoc, param);
189 
190 done:
191 	qdf_mem_free(param);
192 
193 	return qdf_status_to_os_return(qdf_status);
194 }
195 
196 /**
197  * target_if_twt_resume_complete_event_handler - TWT resume complete evt handler
198  * @scn: scn
199  * @event: buffer with event
200  * @len: buffer length
201  *
202  * Return: 0 on success, negative value on failure
203  */
204 static int
target_if_twt_resume_complete_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)205 target_if_twt_resume_complete_event_handler(ol_scn_t scn, uint8_t *event,
206 					    uint32_t len)
207 {
208 	QDF_STATUS qdf_status;
209 	struct wmi_unified *wmi_handle;
210 	struct wlan_objmgr_psoc *psoc;
211 	struct twt_resume_dialog_complete_event_param *param;
212 	struct wlan_lmac_if_twt_rx_ops *twt_rx_ops;
213 
214 	TARGET_IF_ENTER();
215 
216 	psoc = target_if_get_psoc_from_scn_hdl(scn);
217 	if (!psoc) {
218 		target_if_err("psoc is null");
219 		return -EINVAL;
220 	}
221 
222 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
223 	if (!wmi_handle) {
224 		target_if_err("wmi_handle is null");
225 		return -EINVAL;
226 	}
227 
228 	twt_rx_ops = wlan_twt_get_rx_ops(psoc);
229 	if (!twt_rx_ops || !twt_rx_ops->twt_resume_comp_cb) {
230 		target_if_err("No valid twt resume complete rx ops");
231 		return -EINVAL;
232 	}
233 
234 	param = qdf_mem_malloc(sizeof(*param));
235 	if (!param)
236 		return -ENOMEM;
237 
238 	qdf_status = wmi_extract_twt_resume_dialog_comp_event(wmi_handle,
239 							      event, param);
240 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
241 		target_if_err("extract twt resume event failed (status=%d)",
242 			      qdf_status);
243 		goto done;
244 	}
245 
246 	qdf_status = twt_rx_ops->twt_resume_comp_cb(psoc, param);
247 
248 done:
249 	qdf_mem_free(param);
250 
251 	return qdf_status_to_os_return(qdf_status);
252 }
253 
254 /**
255  * target_if_twt_nudge_complete_event_handler - TWT nudge complete evt handler
256  * @scn: scn
257  * @event: buffer with event
258  * @len: buffer length
259  *
260  * Return: 0 on success, negative value on failure
261  */
262 static int
target_if_twt_nudge_complete_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)263 target_if_twt_nudge_complete_event_handler(ol_scn_t scn, uint8_t *event,
264 					   uint32_t len)
265 {
266 	QDF_STATUS qdf_status;
267 	struct wmi_unified *wmi_handle;
268 	struct wlan_objmgr_psoc *psoc;
269 	struct twt_nudge_dialog_complete_event_param *param;
270 	struct wlan_lmac_if_twt_rx_ops *twt_rx_ops;
271 
272 	TARGET_IF_ENTER();
273 
274 	psoc = target_if_get_psoc_from_scn_hdl(scn);
275 	if (!psoc) {
276 		target_if_err("psoc is null");
277 		return -EINVAL;
278 	}
279 
280 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
281 	if (!wmi_handle) {
282 		target_if_err("wmi_handle is null");
283 		return -EINVAL;
284 	}
285 
286 	twt_rx_ops = wlan_twt_get_rx_ops(psoc);
287 	if (!twt_rx_ops || !twt_rx_ops->twt_nudge_comp_cb) {
288 		target_if_err("No valid twt nudge complete rx ops");
289 		return -EINVAL;
290 	}
291 
292 	param = qdf_mem_malloc(sizeof(*param));
293 	if (!param)
294 		return -ENOMEM;
295 
296 	qdf_status = wmi_extract_twt_nudge_dialog_comp_event(wmi_handle,
297 							     event, param);
298 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
299 		target_if_err("extract twt nudge event failed (status=%d)",
300 			      qdf_status);
301 		goto done;
302 	}
303 
304 	qdf_status = twt_rx_ops->twt_nudge_comp_cb(psoc, param);
305 
306 done:
307 	qdf_mem_free(param);
308 
309 	return qdf_status_to_os_return(qdf_status);
310 }
311 
312 static int
target_if_twt_notify_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)313 target_if_twt_notify_event_handler(ol_scn_t scn, uint8_t *event,
314 				   uint32_t len)
315 {
316 	QDF_STATUS qdf_status;
317 	struct wmi_unified *wmi_handle;
318 	struct wlan_objmgr_psoc *psoc;
319 	struct twt_notify_event_param *data;
320 	struct wlan_lmac_if_twt_rx_ops *twt_rx_ops;
321 
322 	TARGET_IF_ENTER();
323 
324 	psoc = target_if_get_psoc_from_scn_hdl(scn);
325 	if (!psoc) {
326 		target_if_err("psoc is null");
327 		return -EINVAL;
328 	}
329 
330 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
331 	if (!wmi_handle) {
332 		target_if_err("wmi_handle is null");
333 		return -EINVAL;
334 	}
335 
336 	twt_rx_ops = wlan_twt_get_rx_ops(psoc);
337 	if (!twt_rx_ops || !twt_rx_ops->twt_notify_comp_cb) {
338 		target_if_err("No valid twt notify rx ops");
339 		return -EINVAL;
340 	}
341 
342 	data = qdf_mem_malloc(sizeof(*data));
343 	if (!data)
344 		return -ENOMEM;
345 
346 	qdf_status = wmi_extract_twt_notify_event(wmi_handle, event, data);
347 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
348 		target_if_err("extract twt notify event failed (status=%d)",
349 			      qdf_status);
350 		goto done;
351 	}
352 
353 	qdf_status = twt_rx_ops->twt_notify_comp_cb(psoc, data);
354 
355 done:
356 	qdf_mem_free(data);
357 
358 	return qdf_status_to_os_return(qdf_status);
359 }
360 
361 static int
target_if_twt_ack_complete_event_handler(ol_scn_t scn,uint8_t * event,uint32_t len)362 target_if_twt_ack_complete_event_handler(ol_scn_t scn, uint8_t *event,
363 					 uint32_t len)
364 {
365 	QDF_STATUS qdf_status;
366 	struct wmi_unified *wmi_handle;
367 	struct wlan_objmgr_psoc *psoc;
368 	struct twt_ack_complete_event_param *data;
369 	struct wlan_lmac_if_twt_rx_ops *twt_rx_ops;
370 
371 	TARGET_IF_ENTER();
372 
373 	psoc = target_if_get_psoc_from_scn_hdl(scn);
374 	if (!psoc) {
375 		target_if_err("psoc is null");
376 		return -EINVAL;
377 	}
378 
379 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
380 	if (!wmi_handle) {
381 		target_if_err("wmi_handle is null");
382 		return -EINVAL;
383 	}
384 
385 	twt_rx_ops = wlan_twt_get_rx_ops(psoc);
386 	if (!twt_rx_ops || !twt_rx_ops->twt_ack_comp_cb) {
387 		target_if_err("No valid twt ack rx ops");
388 		return -EINVAL;
389 	}
390 
391 	data = qdf_mem_malloc(sizeof(*data));
392 	if (!data)
393 		return -ENOMEM;
394 
395 	qdf_status = wmi_extract_twt_ack_comp_event(wmi_handle, event, data);
396 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
397 		target_if_err("extract twt ack event failed (status=%d)",
398 			      qdf_status);
399 		goto done;
400 	}
401 
402 	qdf_status = twt_rx_ops->twt_ack_comp_cb(psoc, data);
403 
404 done:
405 	qdf_mem_free(data);
406 
407 	return qdf_status_to_os_return(qdf_status);
408 }
409 
410 QDF_STATUS
target_if_twt_register_ext_events(struct wlan_objmgr_psoc * psoc)411 target_if_twt_register_ext_events(struct wlan_objmgr_psoc *psoc)
412 {
413 	QDF_STATUS status;
414 	struct wmi_unified *wmi_handle;
415 
416 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
417 	if (!wmi_handle) {
418 		target_if_err("wmi_handle is null!");
419 		return QDF_STATUS_E_INVAL;
420 	}
421 
422 	status = wmi_unified_register_event_handler
423 			(wmi_handle,
424 			 wmi_twt_add_dialog_complete_event_id,
425 			 target_if_twt_setup_complete_event_handler,
426 			 WMI_RX_WORK_CTX);
427 	if (QDF_IS_STATUS_ERROR(status)) {
428 		target_if_err("Failed to register twt add dialog event cb");
429 		return status;
430 	}
431 
432 	status = wmi_unified_register_event_handler
433 			(wmi_handle,
434 			 wmi_twt_del_dialog_complete_event_id,
435 			 target_if_twt_teardown_complete_event_handler,
436 			 WMI_RX_WORK_CTX);
437 	if (QDF_IS_STATUS_ERROR(status)) {
438 		target_if_err("Failed to register twt del dialog event cb");
439 		return status;
440 	}
441 
442 	status = wmi_unified_register_event_handler
443 			(wmi_handle,
444 			 wmi_twt_pause_dialog_complete_event_id,
445 			 target_if_twt_pause_complete_event_handler,
446 			 WMI_RX_WORK_CTX);
447 	if (QDF_IS_STATUS_ERROR(status)) {
448 		target_if_err("Failed to register twt pause dialog event cb");
449 		return status;
450 	}
451 
452 	status = wmi_unified_register_event_handler
453 			(wmi_handle,
454 			 wmi_twt_resume_dialog_complete_event_id,
455 			 target_if_twt_resume_complete_event_handler,
456 			 WMI_RX_WORK_CTX);
457 	if (QDF_IS_STATUS_ERROR(status)) {
458 		target_if_err("Failed to register twt resume dialog event cb");
459 		return status;
460 	}
461 
462 	status = wmi_unified_register_event_handler
463 			(wmi_handle,
464 			 wmi_twt_nudge_dialog_complete_event_id,
465 			 target_if_twt_nudge_complete_event_handler,
466 			 WMI_RX_WORK_CTX);
467 	if (QDF_IS_STATUS_ERROR(status)) {
468 		target_if_err("Failed to register twt nudge dialog event cb");
469 		return status;
470 	}
471 
472 	status = wmi_unified_register_event_handler
473 				(wmi_handle,
474 				 wmi_twt_notify_event_id,
475 				 target_if_twt_notify_event_handler,
476 				 WMI_RX_WORK_CTX);
477 	if (QDF_IS_STATUS_ERROR(status)) {
478 		target_if_err("Failed to register twt notify event cb");
479 		return status;
480 	}
481 
482 	status = wmi_unified_register_event_handler
483 				(wmi_handle,
484 				 wmi_twt_ack_complete_event_id,
485 				 target_if_twt_ack_complete_event_handler,
486 				 WMI_RX_WORK_CTX);
487 	if (QDF_IS_STATUS_ERROR(status)) {
488 		target_if_err("Failed to register twt ack event cb");
489 		return status;
490 	}
491 
492 	return status;
493 }
494 
495 QDF_STATUS
target_if_twt_deregister_ext_events(struct wlan_objmgr_psoc * psoc)496 target_if_twt_deregister_ext_events(struct wlan_objmgr_psoc *psoc)
497 {
498 	QDF_STATUS status;
499 	struct wmi_unified *wmi_handle;
500 
501 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
502 	if (!wmi_handle) {
503 		target_if_err("wmi_handle is null");
504 		return QDF_STATUS_E_NULL_VALUE;
505 	}
506 
507 	status = wmi_unified_unregister_event_handler(wmi_handle,
508 					wmi_twt_add_dialog_complete_event_id);
509 	if (QDF_IS_STATUS_ERROR(status)) {
510 		target_if_err("Failed to deregister twt add dialog event cb");
511 		return status;
512 	}
513 
514 	status = wmi_unified_unregister_event_handler(wmi_handle,
515 					wmi_twt_del_dialog_complete_event_id);
516 	if (QDF_IS_STATUS_ERROR(status)) {
517 		target_if_err("Failed to deregister twt del dialog event cb");
518 		return status;
519 	}
520 
521 	status = wmi_unified_unregister_event_handler(wmi_handle,
522 					wmi_twt_pause_dialog_complete_event_id);
523 	if (QDF_IS_STATUS_ERROR(status)) {
524 		target_if_err("Failed to deregister twt pause dialog event cb");
525 		return status;
526 	}
527 
528 	status = wmi_unified_unregister_event_handler(wmi_handle,
529 				wmi_twt_resume_dialog_complete_event_id);
530 	if (QDF_IS_STATUS_ERROR(status)) {
531 		target_if_err("Failed to deregister twt resume dialog event");
532 		return status;
533 	}
534 
535 	status = wmi_unified_unregister_event_handler(wmi_handle,
536 					wmi_twt_nudge_dialog_complete_event_id);
537 	if (QDF_IS_STATUS_ERROR(status)) {
538 		target_if_err("Failed to deregister twt nudge dialog event cb");
539 		return status;
540 	}
541 
542 	status = wmi_unified_unregister_event_handler(wmi_handle,
543 					wmi_twt_notify_event_id);
544 	if (QDF_IS_STATUS_ERROR(status)) {
545 		target_if_err("Failed to deregister twt notify event cb");
546 		return status;
547 	}
548 
549 	status = wmi_unified_unregister_event_handler(wmi_handle,
550 					wmi_twt_ack_complete_event_id);
551 	if (QDF_IS_STATUS_ERROR(status)) {
552 		target_if_err("Failed to deregister twt ack complete event cb");
553 		return status;
554 	}
555 
556 	return status;
557 }
558 
559