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