xref: /wlan-dirver/qca-wifi-host-cmn/umac/twt/core/src/wlan_twt_common.c (revision 8cfe6b10058a04cafb17eed051f2ddf11bee8931)
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: wlan_twt_common.c
19  */
20 #include "include/wlan_mlme_cmn.h"
21 #include "wlan_twt_common.h"
22 #include "wlan_twt_priv.h"
23 #include <wlan_twt_public_structs.h>
24 #include <wlan_objmgr_peer_obj.h>
25 #include <wlan_twt_tgt_if_tx_api.h>
26 #include "twt/core/src/wlan_twt_cfg.h"
27 
28 QDF_STATUS
29 wlan_twt_tgt_caps_get_responder(struct wlan_objmgr_psoc *psoc, bool *val)
30 {
31 	struct twt_psoc_priv_obj *twt_psoc;
32 
33 	if (!psoc) {
34 		twt_err("null psoc");
35 		return QDF_STATUS_E_FAILURE;
36 	}
37 
38 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
39 							 WLAN_UMAC_COMP_TWT);
40 	if (!twt_psoc) {
41 		twt_err("null twt psoc priv obj");
42 		return QDF_STATUS_E_FAILURE;
43 	}
44 
45 	*val = twt_psoc->twt_caps.twt_responder;
46 	return QDF_STATUS_SUCCESS;
47 }
48 
49 QDF_STATUS
50 wlan_twt_tgt_caps_get_legacy_bcast_support(struct wlan_objmgr_psoc *psoc,
51 					   bool *val)
52 {
53 	struct twt_psoc_priv_obj *twt_psoc;
54 
55 	if (!psoc) {
56 		twt_err("null psoc");
57 		return QDF_STATUS_E_FAILURE;
58 	}
59 
60 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
61 							 WLAN_UMAC_COMP_TWT);
62 	if (!twt_psoc) {
63 		twt_err("null twt psoc priv obj");
64 		return QDF_STATUS_E_FAILURE;
65 	}
66 
67 	*val = twt_psoc->twt_caps.legacy_bcast_twt_support;
68 	return QDF_STATUS_SUCCESS;
69 }
70 
71 QDF_STATUS
72 wlan_twt_tgt_caps_get_nudge_enabled(struct wlan_objmgr_psoc *psoc,
73 				    bool *val)
74 {
75 	struct twt_psoc_priv_obj *twt_psoc;
76 
77 	if (!psoc) {
78 		twt_err("null psoc");
79 		return QDF_STATUS_E_FAILURE;
80 	}
81 
82 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
83 							 WLAN_UMAC_COMP_TWT);
84 	if (!twt_psoc) {
85 		twt_err("null twt psoc priv obj");
86 		return QDF_STATUS_E_FAILURE;
87 	}
88 
89 	*val = twt_psoc->twt_caps.twt_nudge_enabled;
90 	return QDF_STATUS_SUCCESS;
91 }
92 
93 QDF_STATUS
94 wlan_twt_tgt_caps_get_all_twt_enabled(struct wlan_objmgr_psoc *psoc,
95 				      bool *val)
96 {
97 	struct twt_psoc_priv_obj *twt_psoc;
98 
99 	if (!psoc) {
100 		twt_err("null psoc");
101 		return QDF_STATUS_E_FAILURE;
102 	}
103 
104 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
105 							 WLAN_UMAC_COMP_TWT);
106 	if (!twt_psoc) {
107 		twt_err("null twt psoc priv obj");
108 		return QDF_STATUS_E_FAILURE;
109 	}
110 
111 	*val = twt_psoc->twt_caps.all_twt_enabled;
112 	return QDF_STATUS_SUCCESS;
113 }
114 
115 QDF_STATUS
116 wlan_twt_tgt_caps_get_stats_enabled(struct wlan_objmgr_psoc *psoc,
117 					bool *val)
118 {
119 	struct twt_psoc_priv_obj *twt_psoc;
120 
121 	if (!psoc) {
122 		twt_err("null psoc");
123 		return QDF_STATUS_E_FAILURE;
124 	}
125 
126 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
127 							 WLAN_UMAC_COMP_TWT);
128 	if (!twt_psoc) {
129 		twt_err("null twt psoc priv obj");
130 		return QDF_STATUS_E_FAILURE;
131 	}
132 
133 	*val = twt_psoc->twt_caps.twt_stats_enabled;
134 	return QDF_STATUS_SUCCESS;
135 }
136 
137 QDF_STATUS wlan_twt_check_all_twt_support(struct wlan_objmgr_psoc *psoc,
138 					  uint32_t dialog_id)
139 {
140 	bool is_all_twt_enabled = false;
141 	QDF_STATUS status;
142 
143 	/* Cap check is check NOT required if id is for a single session */
144 	if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID)
145 		return QDF_STATUS_SUCCESS;
146 
147 	status = wlan_twt_tgt_caps_get_all_twt_enabled(psoc,
148 						       &is_all_twt_enabled);
149 	if (QDF_IS_STATUS_ERROR(status))
150 		return QDF_STATUS_E_INVAL;
151 
152 	if (!is_all_twt_enabled)
153 		return QDF_STATUS_E_NOSUPPORT;
154 
155 	return QDF_STATUS_SUCCESS;
156 }
157 
158 QDF_STATUS
159 wlan_twt_tgt_caps_get_ack_supported(struct wlan_objmgr_psoc *psoc,
160 				    bool *val)
161 {
162 	struct twt_psoc_priv_obj *twt_psoc;
163 
164 	if (!psoc) {
165 		twt_err("null psoc");
166 		*val = false;
167 		return QDF_STATUS_E_FAILURE;
168 	}
169 
170 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
171 							 WLAN_UMAC_COMP_TWT);
172 	if (!twt_psoc) {
173 		twt_err("null twt psoc priv obj");
174 		*val = false;
175 		return QDF_STATUS_E_FAILURE;
176 	}
177 
178 	*val = twt_psoc->twt_caps.twt_ack_supported;
179 	return QDF_STATUS_SUCCESS;
180 }
181 
182 QDF_STATUS
183 wlan_twt_requestor_disable(struct wlan_objmgr_psoc *psoc,
184 			   struct twt_disable_param *req,
185 			   void *context)
186 {
187 	struct twt_psoc_priv_obj *twt_psoc;
188 
189 	if (!psoc) {
190 		twt_err("null psoc");
191 		return QDF_STATUS_E_FAILURE;
192 	}
193 
194 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
195 							 WLAN_UMAC_COMP_TWT);
196 	if (!twt_psoc) {
197 		twt_err("null twt psoc priv obj");
198 		return QDF_STATUS_E_FAILURE;
199 	}
200 
201 	twt_psoc->disable_context.twt_role = TWT_ROLE_REQUESTOR;
202 	twt_psoc->disable_context.context = context;
203 
204 	req->twt_role = TWT_ROLE_REQUESTOR;
205 
206 	twt_debug("TWT req disable: pdev_id:%d role:%d ext:%d reason_code:%d",
207 		  req->pdev_id, req->twt_role, req->ext_conf_present,
208 		  req->dis_reason_code);
209 
210 	return tgt_twt_disable_req_send(psoc, req);
211 }
212 
213 QDF_STATUS
214 wlan_twt_responder_disable(struct wlan_objmgr_psoc *psoc,
215 			   struct twt_disable_param *req,
216 			   void *context)
217 {
218 	struct twt_psoc_priv_obj *twt_psoc;
219 
220 	if (!psoc) {
221 		twt_err("null psoc");
222 		return QDF_STATUS_E_FAILURE;
223 	}
224 
225 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
226 							 WLAN_UMAC_COMP_TWT);
227 	if (!twt_psoc) {
228 		twt_err("null twt psoc priv obj");
229 		return QDF_STATUS_E_FAILURE;
230 	}
231 
232 	twt_psoc->disable_context.twt_role = TWT_ROLE_RESPONDER;
233 	twt_psoc->disable_context.context = context;
234 
235 	req->twt_role = TWT_ROLE_RESPONDER;
236 
237 	twt_debug("TWT res disable: pdev_id:%d role:%d ext:%d reason_code:%d",
238 		  req->pdev_id, req->twt_role, req->ext_conf_present,
239 		  req->dis_reason_code);
240 
241 	return tgt_twt_disable_req_send(psoc, req);
242 }
243 
244 QDF_STATUS
245 wlan_twt_requestor_enable(struct wlan_objmgr_psoc *psoc,
246 			  struct twt_enable_param *req,
247 			  void *context)
248 {
249 	struct twt_psoc_priv_obj *twt_psoc;
250 	bool requestor_en = false, twt_bcast_requestor = false;
251 
252 	if (!psoc) {
253 		twt_err("null psoc");
254 		return QDF_STATUS_E_FAILURE;
255 	}
256 
257 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
258 							 WLAN_UMAC_COMP_TWT);
259 	if (!twt_psoc) {
260 		twt_err("null twt psoc priv obj");
261 		return QDF_STATUS_E_FAILURE;
262 	}
263 
264 	wlan_twt_cfg_get_requestor(psoc, &requestor_en);
265 	if (!requestor_en) {
266 		twt_warn("twt requestor ini is not enabled");
267 		return QDF_STATUS_E_FAILURE;
268 	}
269 
270 	twt_psoc->enable_context.twt_role = TWT_ROLE_REQUESTOR;
271 	twt_psoc->enable_context.context = context;
272 
273 	wlan_twt_cfg_get_congestion_timeout(psoc, &req->sta_cong_timer_ms);
274 	wlan_twt_cfg_get_bcast_requestor(psoc, &twt_bcast_requestor);
275 	req->b_twt_enable = twt_bcast_requestor;
276 	req->twt_role = TWT_ROLE_REQUESTOR;
277 	if (twt_bcast_requestor)
278 		req->twt_oper = TWT_OPERATION_BROADCAST;
279 	else
280 		req->twt_oper = TWT_OPERATION_INDIVIDUAL;
281 
282 	twt_debug("TWT req enable: pdev_id:%d cong:%d bcast:%d",
283 		  req->pdev_id, req->sta_cong_timer_ms, req->b_twt_enable);
284 	twt_debug("TWT req enable: role:%d ext:%d oper:%d",
285 		  req->twt_role, req->ext_conf_present, req->twt_oper);
286 
287 	return tgt_twt_enable_req_send(psoc, req);
288 }
289 
290 QDF_STATUS
291 wlan_twt_responder_enable(struct wlan_objmgr_psoc *psoc,
292 			  struct twt_enable_param *req,
293 			  void *context)
294 {
295 	struct twt_psoc_priv_obj *twt_psoc;
296 	bool responder_en = false, twt_bcast_responder = false;
297 
298 	if (!psoc) {
299 		twt_err("null psoc");
300 		return QDF_STATUS_E_FAILURE;
301 	}
302 
303 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
304 							 WLAN_UMAC_COMP_TWT);
305 	if (!twt_psoc) {
306 		twt_err("null twt psoc priv obj");
307 		return QDF_STATUS_E_FAILURE;
308 	}
309 
310 	wlan_twt_cfg_get_responder(psoc, &responder_en);
311 	if (!responder_en) {
312 		twt_warn("twt responder ini is not enabled");
313 		return QDF_STATUS_E_FAILURE;
314 	}
315 
316 	twt_psoc->enable_context.twt_role = TWT_ROLE_RESPONDER;
317 	twt_psoc->enable_context.context = context;
318 
319 	wlan_twt_cfg_get_bcast_responder(psoc, &twt_bcast_responder);
320 	req->b_twt_enable = twt_bcast_responder;
321 	req->twt_role = TWT_ROLE_RESPONDER;
322 	if (twt_bcast_responder)
323 		req->twt_oper = TWT_OPERATION_BROADCAST;
324 	else
325 		req->twt_oper = TWT_OPERATION_INDIVIDUAL;
326 
327 	twt_debug("TWT res enable: pdev_id:%d bcast:%d",
328 		  req->pdev_id, req->b_twt_enable);
329 	twt_debug("TWT res enable: role:%d ext:%d oper:%d",
330 		  req->twt_role, req->ext_conf_present, req->twt_oper);
331 
332 	return tgt_twt_enable_req_send(psoc, req);
333 }
334 
335 QDF_STATUS
336 wlan_twt_set_peer_capabilities(struct wlan_objmgr_psoc *psoc,
337 			       struct qdf_mac_addr *peer_mac,
338 			       uint8_t peer_cap)
339 {
340 	struct twt_peer_priv_obj *peer_priv;
341 	struct wlan_objmgr_peer *peer;
342 
343 	peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
344 					   WLAN_TWT_ID);
345 	if (!peer) {
346 		twt_debug("Peer object not found " QDF_MAC_ADDR_FMT,
347 			  QDF_MAC_ADDR_REF(peer_mac->bytes));
348 		return QDF_STATUS_E_FAILURE;
349 	}
350 
351 	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
352 							  WLAN_UMAC_COMP_TWT);
353 	if (!peer_priv) {
354 		wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
355 		twt_err("peer twt component object is NULL");
356 		return QDF_STATUS_E_FAILURE;
357 	}
358 
359 	twt_lock_acquire(&peer_priv->twt_peer_lock);
360 	peer_priv->peer_capability = peer_cap;
361 	twt_lock_release(&peer_priv->twt_peer_lock);
362 
363 	twt_debug("set peer cap: 0x%x", peer_cap);
364 	wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
365 	return QDF_STATUS_SUCCESS;
366 }
367 
368 QDF_STATUS
369 wlan_twt_get_peer_capabilities(struct wlan_objmgr_psoc *psoc,
370 			       struct qdf_mac_addr *peer_mac,
371 			       uint8_t *peer_cap)
372 {
373 	struct twt_peer_priv_obj *peer_priv;
374 	struct wlan_objmgr_peer *peer;
375 
376 	peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
377 					   WLAN_TWT_ID);
378 	if (!peer) {
379 		twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
380 			QDF_MAC_ADDR_REF(peer_mac->bytes));
381 		*peer_cap = 0;
382 		return QDF_STATUS_E_FAILURE;
383 	}
384 
385 	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
386 							  WLAN_UMAC_COMP_TWT);
387 	if (!peer_priv) {
388 		wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
389 		*peer_cap = 0;
390 		twt_err("peer twt component object is NULL");
391 		return QDF_STATUS_E_FAILURE;
392 	}
393 
394 	twt_lock_acquire(&peer_priv->twt_peer_lock);
395 	*peer_cap = peer_priv->peer_capability;
396 	twt_lock_release(&peer_priv->twt_peer_lock);
397 
398 	twt_debug("get peer cap: 0x%x", *peer_cap);
399 	wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
400 	return QDF_STATUS_SUCCESS;
401 }
402 
403 QDF_STATUS
404 wlan_twt_enable_event_handler(struct wlan_objmgr_psoc *psoc,
405 			      struct twt_enable_complete_event_param *event)
406 {
407 	struct twt_psoc_priv_obj *twt_psoc;
408 	struct twt_en_dis_context *twt_context;
409 
410 	if (!psoc) {
411 		twt_err("null psoc");
412 		return QDF_STATUS_E_FAILURE;
413 	}
414 
415 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
416 							 WLAN_UMAC_COMP_TWT);
417 	if (!twt_psoc) {
418 		twt_err("null twt psoc priv obj");
419 		return QDF_STATUS_E_FAILURE;
420 	}
421 
422 	twt_context = &twt_psoc->enable_context;
423 
424 	twt_debug("pdev_id:%d status:%d twt_role:%d",
425 		  event->pdev_id, event->status, twt_context->twt_role);
426 	switch (event->status) {
427 	case HOST_TWT_ENABLE_STATUS_OK:
428 	case HOST_TWT_ENABLE_STATUS_ALREADY_ENABLED:
429 		if (twt_context->twt_role == TWT_ROLE_REQUESTOR)
430 			wlan_twt_cfg_set_requestor_flag(psoc, true);
431 		else if (twt_context->twt_role == TWT_ROLE_RESPONDER)
432 			wlan_twt_cfg_set_responder_flag(psoc, true);
433 		else
434 			twt_err("Invalid role:%d", twt_context->twt_role);
435 
436 		break;
437 
438 	default:
439 		twt_err("twt enable status:%d", event->status);
440 		break;
441 	}
442 
443 	return mlme_twt_osif_enable_complete_ind(psoc, event,
444 						 twt_context->context);
445 }
446 
447 QDF_STATUS
448 wlan_twt_disable_event_handler(struct wlan_objmgr_psoc *psoc,
449 			       struct twt_disable_complete_event_param *event)
450 {
451 	struct twt_psoc_priv_obj *twt_psoc;
452 	struct twt_en_dis_context *twt_context;
453 
454 	if (!psoc) {
455 		twt_err("null psoc");
456 		return QDF_STATUS_E_FAILURE;
457 	}
458 
459 	twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
460 							 WLAN_UMAC_COMP_TWT);
461 	if (!twt_psoc) {
462 		twt_err("null twt psoc priv obj");
463 		return QDF_STATUS_E_FAILURE;
464 	}
465 
466 	twt_context = &twt_psoc->disable_context;
467 
468 	twt_debug("pdev_id:%d status:%d twt_role:%d",
469 		  event->pdev_id, event->status, twt_context->twt_role);
470 	switch (event->status) {
471 	case HOST_TWT_DISABLE_STATUS_OK:
472 		if (twt_context->twt_role == TWT_ROLE_REQUESTOR)
473 			wlan_twt_cfg_set_requestor_flag(psoc, false);
474 		else if (twt_context->twt_role == TWT_ROLE_RESPONDER)
475 			wlan_twt_cfg_set_responder_flag(psoc, false);
476 		else
477 			twt_err("Invalid role:%d", twt_context->twt_role);
478 
479 		break;
480 
481 	default:
482 		twt_err("twt disable status:%d", event->status);
483 		break;
484 	}
485 
486 	return mlme_twt_osif_disable_complete_ind(psoc, event,
487 						  twt_context->context);
488 }
489 
490