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
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  * DOC: wlan_twt_api.c
20  * This file defines the APIs of TWT component.
21  */
22 #include <wlan_twt_api.h>
23 #include "twt/core/src/wlan_twt_objmgr_handler.h"
24 #include "twt/core/src/wlan_twt_common.h"
25 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
26 #include <wlan_pmo_obj_mgmt_api.h>
27 #endif
28 
29 struct wlan_lmac_if_twt_tx_ops *
wlan_twt_get_tx_ops(struct wlan_objmgr_psoc * psoc)30 wlan_twt_get_tx_ops(struct wlan_objmgr_psoc *psoc)
31 {
32 	struct wlan_lmac_if_tx_ops *tx_ops;
33 
34 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
35 	if (!tx_ops) {
36 		twt_err("tx_ops is NULL");
37 		return NULL;
38 	}
39 
40 	return &tx_ops->twt_tx_ops;
41 }
42 
43 struct wlan_lmac_if_twt_rx_ops *
wlan_twt_get_rx_ops(struct wlan_objmgr_psoc * psoc)44 wlan_twt_get_rx_ops(struct wlan_objmgr_psoc *psoc)
45 {
46 	struct wlan_lmac_if_rx_ops *rx_ops;
47 
48 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
49 	if (!rx_ops) {
50 		twt_err("rx_ops is NULL");
51 		return NULL;
52 	}
53 
54 	return &rx_ops->twt_rx_ops;
55 }
56 
57 struct twt_psoc_priv_obj*
wlan_twt_psoc_get_comp_private_obj(struct wlan_objmgr_psoc * psoc)58 wlan_twt_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc)
59 {
60 	struct twt_psoc_priv_obj *twt_psoc;
61 
62 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
63 							WLAN_UMAC_COMP_TWT);
64 	if (!twt_psoc) {
65 		twt_err("TWT PSOC component object is NULL");
66 		return NULL;
67 	}
68 
69 	return twt_psoc;
70 }
71 
72 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
73 static QDF_STATUS
wlan_twt_suspend_handler(struct wlan_objmgr_psoc * psoc,void * arg)74 wlan_twt_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg)
75 {
76 	wlan_twt_psoc_set_pmo_disable(psoc, REASON_PMO_SUSPEND);
77 	return QDF_STATUS_SUCCESS;
78 }
79 
80 static QDF_STATUS
wlan_twt_resume_handler(struct wlan_objmgr_psoc * psoc,void * arg)81 wlan_twt_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg)
82 {
83 	wlan_twt_psoc_set_pmo_enable(psoc, REASON_PMO_SUSPEND);
84 	return QDF_STATUS_SUCCESS;
85 }
86 
87 static void
wlan_twt_register_pmo_handler(void)88 wlan_twt_register_pmo_handler(void)
89 {
90 	pmo_register_suspend_handler(WLAN_UMAC_COMP_TWT,
91 				     wlan_twt_suspend_handler, NULL);
92 	pmo_register_resume_handler(WLAN_UMAC_COMP_TWT,
93 				    wlan_twt_resume_handler, NULL);
94 }
95 
96 static inline void
wlan_twt_unregister_pmo_handler(void)97 wlan_twt_unregister_pmo_handler(void)
98 {
99 	pmo_unregister_suspend_handler(WLAN_UMAC_COMP_TWT,
100 				       wlan_twt_suspend_handler);
101 	pmo_unregister_resume_handler(WLAN_UMAC_COMP_TWT,
102 				      wlan_twt_resume_handler);
103 }
104 
105 #else
106 static void
wlan_twt_register_pmo_handler(void)107 wlan_twt_register_pmo_handler(void)
108 {
109 }
110 
111 static inline void
wlan_twt_unregister_pmo_handler(void)112 wlan_twt_unregister_pmo_handler(void)
113 {
114 }
115 
116 #endif
117 
wlan_twt_init(void)118 QDF_STATUS wlan_twt_init(void)
119 {
120 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
121 
122 	status = wlan_objmgr_register_psoc_create_handler
123 				(WLAN_UMAC_COMP_TWT,
124 				 wlan_twt_psoc_obj_create_handler,
125 				 NULL);
126 	if (QDF_IS_STATUS_ERROR(status)) {
127 		twt_err("Failed to register psoc create handler");
128 		goto wlan_twt_psoc_init_fail1;
129 	}
130 
131 	status = wlan_objmgr_register_psoc_destroy_handler
132 				(WLAN_UMAC_COMP_TWT,
133 				 wlan_twt_psoc_obj_destroy_handler,
134 				 NULL);
135 	if (QDF_IS_STATUS_ERROR(status)) {
136 		twt_err("Failed to register psoc destroy handler");
137 		goto wlan_twt_psoc_init_fail2;
138 	}
139 
140 	status = wlan_objmgr_register_vdev_create_handler
141 				(WLAN_UMAC_COMP_TWT,
142 				 wlan_twt_vdev_obj_create_handler,
143 				 NULL);
144 	if (QDF_IS_STATUS_ERROR(status)) {
145 		twt_err("Failed to register vdev create handler");
146 		goto wlan_twt_vdev_init_fail1;
147 	}
148 
149 	status = wlan_objmgr_register_vdev_destroy_handler
150 				(WLAN_UMAC_COMP_TWT,
151 				 wlan_twt_vdev_obj_destroy_handler,
152 				 NULL);
153 	if (QDF_IS_STATUS_ERROR(status)) {
154 		twt_err("Failed to register vdev destroy handler");
155 		goto wlan_twt_vdev_init_fail2;
156 	}
157 
158 	status = wlan_objmgr_register_peer_create_handler
159 				(WLAN_UMAC_COMP_TWT,
160 				 wlan_twt_peer_obj_create_handler,
161 				 NULL);
162 	if (QDF_IS_STATUS_ERROR(status)) {
163 		twt_err("Failed to register peer create handler");
164 		goto wlan_twt_peer_init_fail1;
165 	}
166 
167 	status = wlan_objmgr_register_peer_destroy_handler
168 				(WLAN_UMAC_COMP_TWT,
169 				 wlan_twt_peer_obj_destroy_handler,
170 				 NULL);
171 	if (QDF_IS_STATUS_ERROR(status)) {
172 		twt_err("Failed to register peer destroy handler");
173 		goto wlan_twt_peer_init_fail2;
174 	}
175 
176 	return QDF_STATUS_SUCCESS;
177 
178 wlan_twt_peer_init_fail2:
179 	wlan_objmgr_unregister_peer_create_handler
180 		(WLAN_UMAC_COMP_TWT,
181 		 wlan_twt_peer_obj_create_handler,
182 		 NULL);
183 wlan_twt_peer_init_fail1:
184 	wlan_objmgr_unregister_vdev_destroy_handler
185 		(WLAN_UMAC_COMP_TWT,
186 		wlan_twt_vdev_obj_destroy_handler,
187 		NULL);
188 wlan_twt_vdev_init_fail2:
189 	wlan_objmgr_unregister_vdev_create_handler
190 		(WLAN_UMAC_COMP_TWT,
191 		wlan_twt_vdev_obj_create_handler,
192 		NULL);
193 wlan_twt_vdev_init_fail1:
194 	wlan_objmgr_unregister_psoc_destroy_handler
195 		(WLAN_UMAC_COMP_TWT,
196 		 wlan_twt_psoc_obj_destroy_handler,
197 		 NULL);
198 wlan_twt_psoc_init_fail2:
199 	wlan_objmgr_unregister_psoc_create_handler
200 		(WLAN_UMAC_COMP_TWT,
201 		 wlan_twt_psoc_obj_create_handler,
202 		 NULL);
203 wlan_twt_psoc_init_fail1:
204 	return status;
205 }
206 
wlan_twt_deinit(void)207 QDF_STATUS wlan_twt_deinit(void)
208 {
209 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
210 
211 	status = wlan_objmgr_unregister_psoc_create_handler
212 				(WLAN_UMAC_COMP_TWT,
213 				 wlan_twt_psoc_obj_create_handler,
214 				 NULL);
215 	if (QDF_IS_STATUS_ERROR(status))
216 		twt_err("Failed to unregister psoc create handler");
217 
218 	status = wlan_objmgr_unregister_psoc_destroy_handler
219 				(WLAN_UMAC_COMP_TWT,
220 				 wlan_twt_psoc_obj_destroy_handler,
221 				 NULL);
222 	if (QDF_IS_STATUS_ERROR(status))
223 		twt_err("Failed to unregister psoc destroy handler");
224 
225 	status = wlan_objmgr_unregister_vdev_create_handler
226 				(WLAN_UMAC_COMP_TWT,
227 				 wlan_twt_vdev_obj_create_handler,
228 				 NULL);
229 	if (QDF_IS_STATUS_ERROR(status))
230 		twt_err("Failed to unregister vdev create handler");
231 
232 	status = wlan_objmgr_unregister_vdev_destroy_handler
233 				(WLAN_UMAC_COMP_TWT,
234 				 wlan_twt_vdev_obj_destroy_handler,
235 				 NULL);
236 	if (QDF_IS_STATUS_ERROR(status))
237 		twt_err("Failed to unregister vdev destroy handler");
238 
239 	status = wlan_objmgr_unregister_peer_create_handler
240 				(WLAN_UMAC_COMP_TWT,
241 				 wlan_twt_peer_obj_create_handler,
242 				 NULL);
243 	if (QDF_IS_STATUS_ERROR(status))
244 		twt_err("Failed to unregister peer create handler");
245 
246 	status = wlan_objmgr_unregister_peer_destroy_handler
247 				(WLAN_UMAC_COMP_TWT,
248 				 wlan_twt_peer_obj_destroy_handler,
249 				 NULL);
250 	if (QDF_IS_STATUS_ERROR(status))
251 		twt_err("Failed to unregister peer destroy handler");
252 
253 	return status;
254 }
255 
twt_psoc_enable(struct wlan_objmgr_psoc * psoc)256 QDF_STATUS twt_psoc_enable(struct wlan_objmgr_psoc *psoc)
257 {
258 	QDF_STATUS status = QDF_STATUS_E_NULL_VALUE;
259 	struct wlan_lmac_if_twt_tx_ops *tx_ops;
260 
261 	tx_ops = wlan_twt_get_tx_ops(psoc);
262 	if (!tx_ops || !tx_ops->register_events) {
263 		twt_err("%s is null", !tx_ops ? "tx_ops" : "register_events");
264 		return QDF_STATUS_E_NULL_VALUE;
265 	}
266 
267 	status = tx_ops->register_events(psoc);
268 	if (QDF_IS_STATUS_ERROR(status))
269 		twt_err("twt_register_events failed (status=%d)", status);
270 
271 	wlan_twt_register_pmo_handler();
272 
273 	return status;
274 }
275 
twt_psoc_disable(struct wlan_objmgr_psoc * psoc)276 QDF_STATUS twt_psoc_disable(struct wlan_objmgr_psoc *psoc)
277 {
278 	QDF_STATUS status = QDF_STATUS_E_NULL_VALUE;
279 	struct wlan_lmac_if_twt_tx_ops *tx_ops;
280 
281 	tx_ops = wlan_twt_get_tx_ops(psoc);
282 	if (!tx_ops || !tx_ops->deregister_events) {
283 		twt_err("%s is null", !tx_ops ? "tx_ops" : "deregister_events");
284 		return QDF_STATUS_E_NULL_VALUE;
285 	}
286 
287 	status = tx_ops->deregister_events(psoc);
288 	if (QDF_IS_STATUS_ERROR(status))
289 		twt_err("twt_deregister_events failed (status=%d)",
290 			status);
291 
292 	wlan_twt_unregister_pmo_handler();
293 
294 	return status;
295 }
296 
297 QDF_STATUS
wlan_set_peer_twt_capabilities(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t peer_cap)298 wlan_set_peer_twt_capabilities(struct wlan_objmgr_psoc *psoc,
299 			       struct qdf_mac_addr *peer_mac,
300 			       uint8_t peer_cap)
301 {
302 	return wlan_twt_set_peer_capabilities(psoc, peer_mac, peer_cap);
303 }
304 
305