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