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