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