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