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 #include "include/wlan_mlme_cmn.h"
19 #include <wlan_objmgr_psoc_obj.h>
20 #include <wlan_objmgr_peer_obj.h>
21 #include <wlan_twt_api.h>
22 #include <wlan_utility.h>
23 #include <wlan_mlme_api.h>
24 #include <wlan_mlme_main.h>
25 #include "twt/core/src/wlan_twt_priv.h"
26 #include "twt/core/src/wlan_twt_common.h"
27 #include <wlan_twt_tgt_if_ext_tx_api.h>
28 #include <wlan_serialization_api.h>
29 #include "wlan_twt_main.h"
30
31 /**
32 * wlan_twt_add_session() - Add TWT session entry in the TWT context
33 * @psoc: Pointer to global psoc object
34 * @peer_mac: Global peer mac address
35 * @dialog_id: Dialog ID
36 * @context: request context
37 *
38 * Return: QDF_STATUS
39 */
40 static QDF_STATUS
wlan_twt_add_session(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,void * context)41 wlan_twt_add_session(struct wlan_objmgr_psoc *psoc,
42 struct qdf_mac_addr *peer_mac,
43 uint8_t dialog_id,
44 void *context)
45 {
46 struct twt_peer_priv_obj *peer_priv;
47 struct wlan_objmgr_peer *peer;
48 uint8_t i;
49
50 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
51 WLAN_TWT_ID);
52 if (!peer) {
53 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
54 QDF_MAC_ADDR_REF(peer_mac->bytes));
55 return QDF_STATUS_E_FAILURE;
56 }
57
58 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
59 WLAN_UMAC_COMP_TWT);
60 if (!peer_priv) {
61 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
62 twt_err("peer twt component object is NULL");
63 return QDF_STATUS_E_FAILURE;
64 }
65
66 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
67
68 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
69 if (peer_priv->session_info[i].dialog_id ==
70 TWT_ALL_SESSIONS_DIALOG_ID) {
71 peer_priv->session_info[i].dialog_id = dialog_id;
72 peer_priv->session_info[i].twt_ack_ctx = context;
73 break;
74 }
75 }
76 qdf_mutex_release(&peer_priv->twt_peer_lock);
77
78 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
79 return QDF_STATUS_SUCCESS;
80 }
81
82 QDF_STATUS
wlan_twt_set_command_in_progress(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,enum wlan_twt_commands cmd)83 wlan_twt_set_command_in_progress(struct wlan_objmgr_psoc *psoc,
84 struct qdf_mac_addr *peer_mac,
85 uint8_t dialog_id,
86 enum wlan_twt_commands cmd)
87 {
88 struct wlan_objmgr_peer *peer;
89 struct twt_peer_priv_obj *peer_priv;
90 uint8_t i = 0;
91
92 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
93 WLAN_TWT_ID);
94 if (!peer) {
95 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
96 QDF_MAC_ADDR_REF(peer_mac->bytes));
97 return QDF_STATUS_E_FAILURE;
98 }
99
100 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
101 WLAN_UMAC_COMP_TWT);
102 if (!peer_priv) {
103 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
104 twt_err(" peer twt component object is NULL");
105 return QDF_STATUS_E_FAILURE;
106 }
107
108 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
109 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
110 if (peer_priv->session_info[i].dialog_id == dialog_id ||
111 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
112 peer_priv->session_info[i].active_cmd = cmd;
113 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID)
114 break;
115 }
116 }
117 qdf_mutex_release(&peer_priv->twt_peer_lock);
118
119 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
120
121 return QDF_STATUS_SUCCESS;
122 }
123
124 QDF_STATUS
wlan_twt_init_context(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)125 wlan_twt_init_context(struct wlan_objmgr_psoc *psoc,
126 struct qdf_mac_addr *peer_mac,
127 uint8_t dialog_id)
128 {
129 struct twt_peer_priv_obj *peer_priv;
130 struct wlan_objmgr_peer *peer;
131 uint8_t i;
132
133 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
134 WLAN_TWT_ID);
135 if (!peer) {
136 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
137 QDF_MAC_ADDR_REF(peer_mac->bytes));
138 return QDF_STATUS_E_FAILURE;
139 }
140
141 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
142 WLAN_UMAC_COMP_TWT);
143 if (!peer_priv) {
144 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
145 twt_err("peer twt component object is NULL");
146 return QDF_STATUS_E_FAILURE;
147 }
148
149 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
150 peer_priv->num_twt_sessions = WLAN_MAX_TWT_SESSIONS_PER_PEER;
151 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
152 if (peer_priv->session_info[i].dialog_id == dialog_id ||
153 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
154 peer_priv->session_info[i].setup_done = false;
155 peer_priv->session_info[i].dialog_id =
156 TWT_ALL_SESSIONS_DIALOG_ID;
157 peer_priv->session_info[i].active_cmd =
158 WLAN_TWT_NONE;
159 }
160 }
161 qdf_mutex_release(&peer_priv->twt_peer_lock);
162
163 twt_debug("init done");
164
165 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
166
167 return QDF_STATUS_SUCCESS;
168 }
169
170 /**
171 * wlan_is_twt_notify_in_progress() - is TWT notify in progress
172 * @psoc: Pointer to psoc object
173 * @vdev_id: VDEV identifier
174 *
175 * Return: True if twt_notify is in progress.
176 */
177 static bool
wlan_is_twt_notify_in_progress(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id)178 wlan_is_twt_notify_in_progress(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id)
179 {
180 struct wlan_objmgr_vdev *vdev;
181 struct twt_vdev_priv_obj *twt_vdev_priv;
182 bool is_twt_notify_in_progress;
183
184 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
185 WLAN_TWT_ID);
186 if (!vdev) {
187 twt_err("vdev object not found");
188 return false;
189 }
190
191 twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(vdev,
192 WLAN_UMAC_COMP_TWT);
193 if (!twt_vdev_priv) {
194 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
195 twt_err("twt vdev private object is NULL");
196 return false;
197 }
198
199 is_twt_notify_in_progress = twt_vdev_priv->twt_wait_for_notify;
200 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
201
202 twt_debug("is_twt_notify_in_progress: %d", is_twt_notify_in_progress);
203 return is_twt_notify_in_progress;
204 }
205
206 /**
207 * wlan_twt_set_wait_for_notify() - Set wait for notify flag
208 * @psoc: Pointer to psoc object
209 * @vdev_id: VDEV identifier
210 * @is_set: Set or clear notify flag
211 *
212 * Return: QDF_STATUS
213 */
214 static QDF_STATUS
wlan_twt_set_wait_for_notify(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,bool is_set)215 wlan_twt_set_wait_for_notify(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id,
216 bool is_set)
217 {
218 struct wlan_objmgr_vdev *vdev;
219 struct twt_vdev_priv_obj *twt_vdev_priv;
220
221 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
222 WLAN_TWT_ID);
223 if (!vdev) {
224 twt_err("vdev object not found");
225 return QDF_STATUS_E_INVAL;
226 }
227
228 twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(vdev,
229 WLAN_UMAC_COMP_TWT);
230 if (!twt_vdev_priv) {
231 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
232 twt_err("twt vdev private object is NULL");
233 return QDF_STATUS_E_INVAL;
234 }
235
236 twt_vdev_priv->twt_wait_for_notify = is_set;
237 twt_debug("twt_wait_for_notify: %d", is_set);
238 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
239 return QDF_STATUS_SUCCESS;
240 }
241
242 static QDF_STATUS
wlan_twt_update_peer_twt_required_bit(struct wlan_objmgr_psoc * psoc,struct twt_notify_event_param * event)243 wlan_twt_update_peer_twt_required_bit(struct wlan_objmgr_psoc *psoc,
244 struct twt_notify_event_param *event)
245 {
246 struct wlan_objmgr_vdev *vdev;
247 struct qdf_mac_addr peer_mac;
248 uint8_t peer_cap = 0;
249 QDF_STATUS status;
250
251 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id,
252 WLAN_TWT_ID);
253
254 if (!vdev) {
255 twt_err("vdev object not found");
256 return QDF_STATUS_E_INVAL;
257 }
258
259 status = wlan_vdev_get_bss_peer_mac(vdev, &peer_mac);
260 if (QDF_IS_STATUS_ERROR(status)) {
261 twt_err("Failed to get bssid");
262 goto exit;
263 }
264
265 status = wlan_twt_get_peer_capabilities(psoc, &peer_mac, &peer_cap);
266
267 if (QDF_IS_STATUS_ERROR(status)) {
268 twt_err("twt failed to get peer capabilities");
269 goto exit;
270 }
271
272 if ((peer_cap & WLAN_TWT_CAPA_REQUIRED) &&
273 event->status == HOST_TWT_NOTIFY_EVENT_AP_TWT_REQ_BIT_CLEAR) {
274 /* set TWT required bit as 0 */
275 peer_cap &= ~WLAN_TWT_CAPA_REQUIRED;
276 } else if (!(peer_cap & WLAN_TWT_CAPA_REQUIRED) &&
277 event->status == HOST_TWT_NOTIFY_EVENT_AP_TWT_REQ_BIT_SET) {
278 /* set TWT required bit as 1 */
279 peer_cap |= WLAN_TWT_CAPA_REQUIRED;
280 }
281
282 status = wlan_twt_set_peer_capabilities(psoc, &peer_mac, peer_cap);
283 twt_debug("Update Peer TWT capabilities: %d", peer_cap);
284
285 exit:
286 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
287
288 return status;
289 }
290
291 /**
292 * wlan_twt_util_cmd_in_progress() - for a given peer_priv, check if the
293 * given command is in progress
294 * @peer_priv: peer priv object
295 * @dialog_id: Dialog id
296 * @cmd: command
297 *
298 * Return: true if command is in progress, false otherwise
299 */
300 static bool
wlan_twt_util_cmd_in_progress(struct twt_peer_priv_obj * peer_priv,uint8_t dialog_id,enum wlan_twt_commands cmd)301 wlan_twt_util_cmd_in_progress(struct twt_peer_priv_obj *peer_priv,
302 uint8_t dialog_id,
303 enum wlan_twt_commands cmd)
304 {
305 bool cmd_in_progress = false;
306 uint8_t i;
307 uint8_t num_sessions = peer_priv->num_twt_sessions;
308
309 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
310 for (i = 0; i < num_sessions; i++) {
311 enum wlan_twt_commands active_cmd;
312 uint8_t existing_dialog_id;
313
314 active_cmd = peer_priv->session_info[i].active_cmd;
315 existing_dialog_id = peer_priv->session_info[i].dialog_id;
316
317 if (existing_dialog_id == dialog_id ||
318 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
319 cmd_in_progress = (active_cmd == cmd);
320
321 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID ||
322 cmd_in_progress) {
323 qdf_mutex_release(&peer_priv->twt_peer_lock);
324 return cmd_in_progress;
325 }
326 }
327 }
328 qdf_mutex_release(&peer_priv->twt_peer_lock);
329
330 return cmd_in_progress;
331 }
332
333 /**
334 * wlan_twt_any_peer_cmd_in_progress() - Iterate through the list of peers
335 * and check if the given command is in progress
336 * @psoc: Pointer to psoc object
337 * @vdev_id: Vdev id
338 * @dialog_id: Dialog id
339 * @cmd: command
340 *
341 * This API is used to check for the given @dialog_id if the
342 * @cmd command is in progress for any of the peers.
343 *
344 * Return: true if command is in progress, false otherwise
345 */
346 static bool
wlan_twt_any_peer_cmd_in_progress(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,uint8_t dialog_id,enum wlan_twt_commands cmd)347 wlan_twt_any_peer_cmd_in_progress(struct wlan_objmgr_psoc *psoc,
348 uint8_t vdev_id,
349 uint8_t dialog_id,
350 enum wlan_twt_commands cmd)
351 {
352 qdf_list_t *peer_list;
353 struct wlan_objmgr_peer *peer, *peer_next;
354 struct wlan_objmgr_vdev *vdev;
355 struct twt_peer_priv_obj *peer_priv;
356 bool cmd_in_progress = false;
357
358 if (!psoc) {
359 twt_err("psoc is NULL, dialog_id: %d", dialog_id);
360 return false;
361 }
362
363 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
364 WLAN_TWT_ID);
365 if (!vdev) {
366 twt_err("vdev is NULL, vdev_id: %d dialog_id: %d",
367 vdev_id, dialog_id);
368 return false;
369 }
370
371 peer_list = &vdev->vdev_objmgr.wlan_peer_list;
372 if (!peer_list) {
373 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
374 twt_err("Peer list for vdev obj is NULL");
375 return false;
376 }
377
378 peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list,
379 WLAN_TWT_ID);
380 while (peer) {
381 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
382 WLAN_UMAC_COMP_TWT);
383 if (peer_priv) {
384 cmd_in_progress =
385 wlan_twt_util_cmd_in_progress(peer_priv,
386 dialog_id, cmd);
387
388 if (cmd_in_progress) {
389 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
390 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
391 return cmd_in_progress;
392 }
393 }
394
395 peer_next =
396 wlan_peer_get_next_active_peer_of_vdev(vdev,
397 peer_list,
398 peer,
399 WLAN_TWT_ID);
400
401 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
402 peer = peer_next;
403 }
404
405 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
406 return cmd_in_progress;
407 }
408
409 /**
410 * wlan_twt_sap_peer_is_cmd_in_progress() - For a given peer_mac check if
411 * the given command is in progress
412 * @psoc: Pointer to psoc object
413 * @peer_mac: Pointer to peer mac address
414 * @dialog_id: Dialog id
415 * @cmd: TWT command
416 *
417 * Return: True if given command is in progress.
418 */
419 static bool
wlan_twt_sap_peer_is_cmd_in_progress(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,enum wlan_twt_commands cmd)420 wlan_twt_sap_peer_is_cmd_in_progress(struct wlan_objmgr_psoc *psoc,
421 struct qdf_mac_addr *peer_mac,
422 uint8_t dialog_id,
423 enum wlan_twt_commands cmd)
424 {
425 struct wlan_objmgr_peer *peer;
426 struct twt_peer_priv_obj *peer_priv;
427 uint8_t i;
428 bool cmd_in_progress = false;
429
430 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
431 WLAN_TWT_ID);
432 if (!peer) {
433 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
434 QDF_MAC_ADDR_REF(peer_mac->bytes));
435 return false;
436 }
437
438 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
439 WLAN_UMAC_COMP_TWT);
440 if (!peer_priv) {
441 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
442 twt_err("twt peer component object is NULL");
443 return false;
444 }
445
446 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
447 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
448 enum wlan_twt_commands active_cmd;
449 uint8_t existing_dialog_id;
450
451 active_cmd =
452 peer_priv->session_info[i].active_cmd;
453 existing_dialog_id =
454 peer_priv->session_info[i].dialog_id;
455
456 if (existing_dialog_id == dialog_id ||
457 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID ||
458 existing_dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
459 cmd_in_progress = (active_cmd == cmd);
460
461 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID ||
462 cmd_in_progress) {
463 break;
464 }
465 }
466 }
467 qdf_mutex_release(&peer_priv->twt_peer_lock);
468
469 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
470 return cmd_in_progress;
471 }
472
473 /**
474 * wlan_twt_sap_is_command_in_progress() - Based on the input peer mac address
475 * invoke the appropriate function to check if the given command is in progress
476 * @psoc: Pointer to psoc object
477 * @vdev_id: Vdev id
478 * @peer_mac: Peer MAC address
479 * @dialog_id: Dialog id
480 * @cmd: command
481 *
482 * If the input @peer_mac is a broadcast MAC address then the expectation is
483 * to iterate through the list of all peers and check for any given @dialog_id
484 * if the command @cmd is in progress.
485 * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
486 * be TWT_ALL_SESSIONS_DIALOG_ID.
487 * For ex: If TWT teardown command is issued on a particular @dialog_id and
488 * non-broadcast peer mac and FW response is not yet received then for that
489 * particular @dialog_id and @peer_mac, TWT teardown is the active command,
490 * then if the driver receives another TWT teardown request with broadcast
491 * peer mac, then API wlan_twt_any_peer_cmd_in_progress() shall iterate
492 * through the list of all peers and returns command in progress as true.
493 *
494 * If the input @peer_mac is a non-broadcast MAC address then
495 * wlan_twt_sap_peer_is_cmd_in_progress() shall check only for that
496 * particular @peer_mac and @dialog_id.
497 *
498 * Return: true if command is in progress, false otherwise
499 */
500 static bool
wlan_twt_sap_is_command_in_progress(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,enum wlan_twt_commands cmd)501 wlan_twt_sap_is_command_in_progress(struct wlan_objmgr_psoc *psoc,
502 uint32_t vdev_id,
503 struct qdf_mac_addr *peer_mac,
504 uint8_t dialog_id,
505 enum wlan_twt_commands cmd)
506 {
507 if (qdf_is_macaddr_broadcast(peer_mac)) {
508 return wlan_twt_any_peer_cmd_in_progress(psoc, vdev_id,
509 dialog_id, cmd);
510 } else {
511 return wlan_twt_sap_peer_is_cmd_in_progress(psoc, peer_mac,
512 dialog_id, cmd);
513 }
514 }
515
516 /**
517 * wlan_twt_sap_add_session() - Based on the input peer mac address
518 * invoke the appropriate function to add dialog_id to the TWT session context
519 * @psoc: Pointer to psoc object
520 * @vdev_id: Vdev id
521 * @peer_mac: Peer MAC address
522 * @dialog_id: Dialog id
523 *
524 * If the input @peer_mac is a broadcast MAC address then there is nothing
525 * to do, because the initialized structure is already in the expected format
526 * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
527 * be TWT_ALL_SESSIONS_DIALOG_ID.
528 *
529 * If the input @peer_mac is a non-broadcast MAC address then
530 * wlan_twt_add_session() shall add the @dialog_id to the @peer_mac
531 * TWT session context.
532 *
533 * Return: None
534 */
535 static void
wlan_twt_sap_add_session(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)536 wlan_twt_sap_add_session(struct wlan_objmgr_psoc *psoc,
537 uint8_t vdev_id,
538 struct qdf_mac_addr *peer_mac,
539 uint8_t dialog_id)
540 {
541 if (!qdf_is_macaddr_broadcast(peer_mac))
542 wlan_twt_add_session(psoc, peer_mac, dialog_id, NULL);
543 }
544
545 /**
546 * wlan_twt_sap_set_all_peers_cmd_in_progress() - Iterate through the list
547 * of peers and set the command in the TWT session entry in the TWT context
548 * @psoc: Pointer to global psoc object
549 * @vdev_id: Vdev id
550 * @dialog_id: Dialog ID
551 * @cmd: Command
552 *
553 * This API iterates through the list of peers and updates the active
554 * command to @cmd for the given dialog_id.
555 *
556 * Return: QDF_STATUS
557 */
558 static QDF_STATUS
wlan_twt_sap_set_all_peers_cmd_in_progress(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,uint8_t dialog_id,enum wlan_twt_commands cmd)559 wlan_twt_sap_set_all_peers_cmd_in_progress(struct wlan_objmgr_psoc *psoc,
560 uint8_t vdev_id,
561 uint8_t dialog_id,
562 enum wlan_twt_commands cmd)
563 {
564 qdf_list_t *peer_list;
565 struct wlan_objmgr_peer *peer, *peer_next;
566 struct wlan_objmgr_vdev *vdev;
567 struct twt_peer_priv_obj *peer_priv;
568
569 if (!psoc) {
570 twt_err("psoc is NULL, dialog_id: %d", dialog_id);
571 return QDF_STATUS_E_NULL_VALUE;
572 }
573
574 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
575 WLAN_TWT_ID);
576 if (!vdev) {
577 twt_err("vdev is NULL, vdev_id: %d dialog_id: %d",
578 vdev_id, dialog_id);
579 return QDF_STATUS_E_NULL_VALUE;
580 }
581
582 peer_list = &vdev->vdev_objmgr.wlan_peer_list;
583 if (!peer_list) {
584 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
585 twt_err("Peer list for vdev obj is NULL");
586 return QDF_STATUS_E_NULL_VALUE;
587 }
588
589 peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list,
590 WLAN_TWT_ID);
591 while (peer) {
592 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
593 WLAN_UMAC_COMP_TWT);
594 if (peer_priv) {
595 uint8_t i;
596 uint8_t num_sessions = peer_priv->num_twt_sessions;
597
598 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
599 for (i = 0; i < num_sessions; i++) {
600 uint8_t eid =
601 peer_priv->session_info[i].dialog_id;
602
603 if (eid == dialog_id ||
604 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
605 peer_priv->session_info[i].active_cmd =
606 cmd;
607
608 if (dialog_id !=
609 TWT_ALL_SESSIONS_DIALOG_ID) {
610 break;
611 }
612 }
613 }
614 qdf_mutex_release(&peer_priv->twt_peer_lock);
615 }
616
617 peer_next =
618 wlan_peer_get_next_active_peer_of_vdev(vdev,
619 peer_list,
620 peer,
621 WLAN_TWT_ID);
622
623 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
624 peer = peer_next;
625 }
626
627 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
628 return QDF_STATUS_SUCCESS;
629 }
630
631 /**
632 * wlan_twt_sap_set_command_in_progress() - Based on the input peer mac address
633 * invoke the appropriate function to set the command is in progress
634 * @psoc: Pointer to psoc object
635 * @vdev_id: Vdev id
636 * @peer_mac: Peer MAC address
637 * @dialog_id: Dialog id
638 * @cmd: command
639 *
640 * If the input @peer_mac is a broadcast MAC address then the expectation is
641 * to iterate through the list of all peers and set the active command to @cmd
642 * for the given @dialog_id
643 * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
644 * be TWT_ALL_SESSIONS_DIALOG_ID.
645 * For ex: If TWT teardown command is issued on broadcast @peer_mac, then
646 * it is same as issuing TWT teardown for all the peers (all TWT sessions).
647 * Invoking wlan_twt_sap_set_all_peers_cmd_in_progress() shall iterate through
648 * all the peers and set the active command to @cmd.
649 *
650 * If the input @peer_mac is a non-broadcast MAC address then
651 * wlan_twt_set_command_in_progress() shall set the active command to @cmd
652 * only for that particular @peer_mac and @dialog_id.
653 *
654 * Return: QDF_STATUS
655 */
656 static QDF_STATUS
wlan_twt_sap_set_command_in_progress(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,enum wlan_twt_commands cmd)657 wlan_twt_sap_set_command_in_progress(struct wlan_objmgr_psoc *psoc,
658 uint8_t vdev_id,
659 struct qdf_mac_addr *peer_mac,
660 uint8_t dialog_id,
661 enum wlan_twt_commands cmd)
662 {
663 if (qdf_is_macaddr_broadcast(peer_mac)) {
664 return wlan_twt_sap_set_all_peers_cmd_in_progress(psoc,
665 vdev_id,
666 dialog_id,
667 cmd);
668 } else {
669 return wlan_twt_set_command_in_progress(psoc, peer_mac,
670 dialog_id, cmd);
671 }
672 }
673
674 /**
675 * wlan_twt_init_all_peers_context() - Iterate through the list
676 * of peers and initialize the TWT context structure
677 * @psoc: Pointer to global psoc object
678 * @vdev_id: Vdev id
679 * @dialog_id: Dialog ID
680 *
681 * This API iterates through the list of peers and initializes
682 * the TWT context structure
683 *
684 * Return: QDF_STATUS
685 */
686 static QDF_STATUS
wlan_twt_init_all_peers_context(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,uint8_t dialog_id)687 wlan_twt_init_all_peers_context(struct wlan_objmgr_psoc *psoc,
688 uint8_t vdev_id,
689 uint8_t dialog_id)
690 {
691 qdf_list_t *peer_list;
692 struct wlan_objmgr_peer *peer, *peer_next;
693 struct wlan_objmgr_vdev *vdev;
694 struct twt_peer_priv_obj *peer_priv;
695
696 if (!psoc) {
697 twt_err("psoc is NULL, dialog_id: %d", dialog_id);
698 return QDF_STATUS_E_NULL_VALUE;
699 }
700
701 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
702 WLAN_TWT_ID);
703 if (!vdev) {
704 twt_err("vdev is NULL, vdev_id: %d dialog_id: %d",
705 vdev_id, dialog_id);
706 return QDF_STATUS_E_NULL_VALUE;
707 }
708
709 peer_list = &vdev->vdev_objmgr.wlan_peer_list;
710 if (!peer_list) {
711 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
712 twt_err("Peer list for vdev obj is NULL");
713 return QDF_STATUS_E_NULL_VALUE;
714 }
715
716 peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list,
717 WLAN_TWT_ID);
718 while (peer) {
719 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
720 WLAN_UMAC_COMP_TWT);
721 if (peer_priv) {
722 uint8_t i = 0;
723 uint8_t num_sessions = WLAN_MAX_TWT_SESSIONS_PER_PEER;
724
725 peer_priv->num_twt_sessions = num_sessions;
726 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
727 for (i = 0; i < num_sessions; i++) {
728 uint8_t eid =
729 peer_priv->session_info[i].dialog_id;
730
731 if (eid == dialog_id ||
732 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
733 peer_priv->session_info[i].setup_done =
734 false;
735 peer_priv->session_info[i].dialog_id =
736 TWT_ALL_SESSIONS_DIALOG_ID;
737 }
738 }
739 qdf_mutex_release(&peer_priv->twt_peer_lock);
740 }
741
742 peer_next =
743 wlan_peer_get_next_active_peer_of_vdev(vdev,
744 peer_list,
745 peer,
746 WLAN_TWT_ID);
747
748 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
749 peer = peer_next;
750 }
751
752 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
753 twt_debug("init done");
754 return QDF_STATUS_SUCCESS;
755 }
756
757 /**
758 * wlan_twt_sap_init_context() - Based on the input peer mac address
759 * invoke the appropriate function to initialize the TWT session context
760 * @psoc: Pointer to psoc object
761 * @vdev_id: Vdev id
762 * @peer_mac: Peer MAC address
763 * @dialog_id: Dialog id
764 *
765 * If the input @peer_mac is a broadcast MAC address then the expectation is
766 * to iterate through the list of all peers and initialize the TWT session
767 * context
768 * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
769 * be TWT_ALL_SESSIONS_DIALOG_ID.
770 * For ex: If TWT teardown command is issued on broadcast @peer_mac, then
771 * it is same as issuing TWT teardown for all the peers (all TWT sessions).
772 * Then active command for all the peers is set to @WLAN_TWT_TERMINATE.
773 * Upon receiving the TWT teardown WMI event, wlan_twt_init_all_peers_context()
774 * shall iterate through the list of all peers and initializes the TWT session
775 * context back to its initial state.
776 *
777 * If the input @peer_mac is a non-broadcast MAC address then
778 * wlan_twt_init_context() shall initialize the TWT session context
779 * only for that particular @peer_mac and @dialog_id.
780 *
781 * Return: QDF_STATUS
782 */
783 static QDF_STATUS
wlan_twt_sap_init_context(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)784 wlan_twt_sap_init_context(struct wlan_objmgr_psoc *psoc,
785 uint8_t vdev_id,
786 struct qdf_mac_addr *peer_mac,
787 uint8_t dialog_id)
788 {
789 if (!qdf_is_macaddr_broadcast(peer_mac))
790 return wlan_twt_init_context(psoc, peer_mac, dialog_id);
791
792 return wlan_twt_init_all_peers_context(psoc, vdev_id, dialog_id);
793 }
794
795 /**
796 * wlan_is_vdev_connected_to_peer() - find if peer exists in the vdev peer list
797 * @psoc: Pointer to global psoc object
798 * @vdev_id: Vdev id
799 * @peer_macaddr: peer mac address
800 *
801 * This API finds if for the given vdev there exists a peer with the given
802 * @peer_macaddr
803 *
804 * Return: true if exists, false otherwise
805 */
806 static bool
wlan_is_vdev_connected_to_peer(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,struct qdf_mac_addr * peer_macaddr)807 wlan_is_vdev_connected_to_peer(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id,
808 struct qdf_mac_addr *peer_macaddr)
809 {
810 uint8_t pdev_id;
811 struct wlan_objmgr_pdev *pdev;
812 struct wlan_objmgr_vdev *vdev;
813 struct wlan_objmgr_peer *peer;
814 bool connection_exists = false;
815
816 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, vdev_id,
817 WLAN_TWT_ID);
818 if (pdev_id == WLAN_INVALID_PDEV_ID) {
819 twt_err("Invalid pdev id");
820 return connection_exists;
821 }
822
823 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_TWT_ID);
824 if (!pdev) {
825 twt_err("Invalid pdev");
826 return connection_exists;
827 }
828
829 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
830 WLAN_TWT_ID);
831 if (!vdev) {
832 twt_err("vdev object is NULL");
833 goto end;
834 }
835
836 peer = wlan_objmgr_vdev_find_peer_by_mac(vdev, peer_macaddr->bytes,
837 WLAN_TWT_ID);
838 if (peer) {
839 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
840 connection_exists = true;
841 }
842
843 wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
844 end:
845 wlan_objmgr_pdev_release_ref(pdev, WLAN_TWT_ID);
846 return connection_exists;
847 }
848
849 /**
850 * wlan_twt_is_setup_done() - Get if TWT session is established for given
851 * dialog id.
852 * @psoc: Pointer to psoc object
853 * @peer_mac: Pointer to peer mac address
854 * @dialog_id: Dialog id
855 *
856 * Return: Return true if TWT session exists for given dialog ID.
857 */
wlan_twt_is_setup_done(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)858 bool wlan_twt_is_setup_done(struct wlan_objmgr_psoc *psoc,
859 struct qdf_mac_addr *peer_mac, uint8_t dialog_id)
860 {
861 struct twt_peer_priv_obj *peer_priv;
862 struct wlan_objmgr_peer *peer;
863 bool is_setup_done = false;
864 uint8_t i;
865
866 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
867 WLAN_TWT_ID);
868 if (!peer) {
869 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
870 QDF_MAC_ADDR_REF(peer_mac->bytes));
871 return false;
872 }
873
874 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
875 WLAN_UMAC_COMP_TWT);
876 if (!peer_priv) {
877 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
878 twt_err("peer mlme component object is NULL");
879 return false;
880 }
881
882 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
883 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
884 if (peer_priv->session_info[i].dialog_id == dialog_id ||
885 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
886 is_setup_done = peer_priv->session_info[i].setup_done;
887
888 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID ||
889 is_setup_done)
890 break;
891 }
892 }
893 qdf_mutex_release(&peer_priv->twt_peer_lock);
894
895 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
896
897 return is_setup_done;
898 }
899
wlan_twt_is_max_sessions_reached(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)900 bool wlan_twt_is_max_sessions_reached(struct wlan_objmgr_psoc *psoc,
901 struct qdf_mac_addr *peer_mac,
902 uint8_t dialog_id)
903 {
904 struct twt_peer_priv_obj *peer_priv;
905 struct wlan_objmgr_peer *peer;
906 uint8_t i, num_twt_sessions = 0, max_twt_sessions;
907
908 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
909 WLAN_TWT_ID);
910 if (!peer) {
911 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
912 QDF_MAC_ADDR_REF(peer_mac->bytes));
913 return true;
914 }
915
916 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
917 WLAN_UMAC_COMP_TWT);
918 if (!peer_priv) {
919 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
920 twt_err("peer twt component object is NULL");
921 return true;
922 }
923
924 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
925
926 max_twt_sessions = peer_priv->num_twt_sessions;
927 for (i = 0; i < max_twt_sessions; i++) {
928 uint8_t existing_session_dialog_id =
929 peer_priv->session_info[i].dialog_id;
930
931 if (existing_session_dialog_id != TWT_ALL_SESSIONS_DIALOG_ID &&
932 existing_session_dialog_id != dialog_id)
933 num_twt_sessions++;
934 }
935
936 qdf_mutex_release(&peer_priv->twt_peer_lock);
937 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
938
939 twt_debug("num_twt_sessions:%d max_twt_sessions:%d",
940 num_twt_sessions, max_twt_sessions);
941 return num_twt_sessions == max_twt_sessions;
942 }
943
wlan_twt_is_setup_in_progress(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)944 bool wlan_twt_is_setup_in_progress(struct wlan_objmgr_psoc *psoc,
945 struct qdf_mac_addr *peer_mac,
946 uint8_t dialog_id)
947 {
948 struct twt_peer_priv_obj *peer_priv;
949 struct wlan_objmgr_peer *peer;
950 uint8_t i;
951
952 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
953 WLAN_TWT_ID);
954 if (!peer) {
955 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
956 QDF_MAC_ADDR_REF(peer_mac->bytes));
957 return false;
958 }
959
960 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
961 WLAN_UMAC_COMP_TWT);
962 if (!peer_priv) {
963 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
964 twt_err("peer twt component object is NULL");
965 return false;
966 }
967
968 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
969
970 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
971 bool setup_done = peer_priv->session_info[i].setup_done;
972 uint8_t existing_session_dialog_id;
973
974 existing_session_dialog_id =
975 peer_priv->session_info[i].dialog_id;
976 if (existing_session_dialog_id == dialog_id &&
977 existing_session_dialog_id != TWT_ALL_SESSIONS_DIALOG_ID &&
978 !setup_done) {
979 qdf_mutex_release(&peer_priv->twt_peer_lock);
980 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
981 return true;
982 }
983 }
984 qdf_mutex_release(&peer_priv->twt_peer_lock);
985
986 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
987
988 return false;
989 }
990
991 /**
992 * wlan_twt_set_ack_context() - set twt ack context
993 * for given dialog id
994 * @psoc: Pointer to global psoc object
995 * @peer_mac: Global peer mac address
996 * @dialog_id: Dialog ID
997 * @context: TWT context
998 *
999 * Return: QDF_STATUS
1000 */
1001 static QDF_STATUS
wlan_twt_set_ack_context(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,void * context)1002 wlan_twt_set_ack_context(struct wlan_objmgr_psoc *psoc,
1003 struct qdf_mac_addr *peer_mac,
1004 uint8_t dialog_id,
1005 void *context)
1006 {
1007 struct twt_peer_priv_obj *peer_priv;
1008 struct wlan_objmgr_peer *peer;
1009 uint8_t i;
1010
1011 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1012 WLAN_TWT_ID);
1013 if (!peer) {
1014 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1015 QDF_MAC_ADDR_REF(peer_mac->bytes));
1016 return QDF_STATUS_E_FAILURE;
1017 }
1018
1019 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1020 WLAN_UMAC_COMP_TWT);
1021 if (!peer_priv) {
1022 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1023 twt_err("peer twt component object is NULL");
1024 return QDF_STATUS_E_FAILURE;
1025 }
1026
1027 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1028
1029 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1030 uint8_t existing_session_dialog_id;
1031
1032 existing_session_dialog_id =
1033 peer_priv->session_info[i].dialog_id;
1034 if (existing_session_dialog_id == dialog_id ||
1035 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
1036 peer_priv->session_info[i].twt_ack_ctx = context;
1037
1038 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID)
1039 break;
1040 }
1041 }
1042 qdf_mutex_release(&peer_priv->twt_peer_lock);
1043
1044 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1045 return QDF_STATUS_SUCCESS;
1046 }
1047
1048 /**
1049 * wlan_twt_get_ack_context() - get twt ack context
1050 * for given dialog id
1051 * @psoc: Pointer to global psoc object
1052 * @peer_mac: Global peer mac address
1053 * @dialog_id: Dialog ID
1054 * @context: TWT context
1055 *
1056 * Return: QDF_STATUS
1057 */
1058 static QDF_STATUS
wlan_twt_get_ack_context(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,void ** context)1059 wlan_twt_get_ack_context(struct wlan_objmgr_psoc *psoc,
1060 struct qdf_mac_addr *peer_mac,
1061 uint8_t dialog_id,
1062 void **context)
1063 {
1064 struct twt_peer_priv_obj *peer_priv;
1065 struct wlan_objmgr_peer *peer;
1066 uint8_t i;
1067
1068 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1069 WLAN_TWT_ID);
1070 if (!peer) {
1071 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1072 QDF_MAC_ADDR_REF(peer_mac->bytes));
1073 goto err;
1074 }
1075
1076 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1077 WLAN_UMAC_COMP_TWT);
1078 if (!peer_priv) {
1079 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1080 twt_err("peer twt component object is NULL");
1081 goto err;
1082 }
1083
1084 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1085 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1086 uint8_t existing_session_dialog_id;
1087
1088 existing_session_dialog_id =
1089 peer_priv->session_info[i].dialog_id;
1090 if (existing_session_dialog_id == dialog_id ||
1091 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
1092 *context = peer_priv->session_info[i].twt_ack_ctx;
1093 break;
1094 }
1095 }
1096
1097 qdf_mutex_release(&peer_priv->twt_peer_lock);
1098
1099 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1100 return QDF_STATUS_SUCCESS;
1101
1102 err:
1103 *context = NULL;
1104 return QDF_STATUS_E_FAILURE;
1105 }
1106
wlan_twt_is_command_in_progress(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,enum wlan_twt_commands cmd,enum wlan_twt_commands * pactive_cmd)1107 bool wlan_twt_is_command_in_progress(struct wlan_objmgr_psoc *psoc,
1108 struct qdf_mac_addr *peer_mac,
1109 uint8_t dialog_id,
1110 enum wlan_twt_commands cmd,
1111 enum wlan_twt_commands *pactive_cmd)
1112 {
1113 struct wlan_objmgr_peer *peer;
1114 struct twt_peer_priv_obj *peer_priv;
1115 enum wlan_twt_commands active_cmd;
1116 uint8_t i = 0;
1117 bool is_command_in_progress = false;
1118
1119 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1120 WLAN_TWT_ID);
1121 if (!peer) {
1122 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1123 QDF_MAC_ADDR_REF(peer_mac->bytes));
1124 return false;
1125 }
1126
1127 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1128 WLAN_UMAC_COMP_TWT);
1129 if (!peer_priv) {
1130 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1131 twt_err(" peer twt component object is NULL");
1132 return false;
1133 }
1134
1135 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1136 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1137 active_cmd = peer_priv->session_info[i].active_cmd;
1138
1139 if (pactive_cmd)
1140 *pactive_cmd = active_cmd;
1141
1142 if (peer_priv->session_info[i].dialog_id == dialog_id ||
1143 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
1144 if (cmd == WLAN_TWT_ANY) {
1145 is_command_in_progress =
1146 (active_cmd != WLAN_TWT_NONE);
1147
1148 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID ||
1149 is_command_in_progress)
1150 break;
1151 } else {
1152 is_command_in_progress = (active_cmd == cmd);
1153
1154 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID ||
1155 is_command_in_progress)
1156 break;
1157 }
1158 }
1159 }
1160 qdf_mutex_release(&peer_priv->twt_peer_lock);
1161
1162 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1163
1164 return is_command_in_progress;
1165 }
1166
wlan_twt_setup_req(struct wlan_objmgr_psoc * psoc,struct twt_add_dialog_param * req,void * context)1167 QDF_STATUS wlan_twt_setup_req(struct wlan_objmgr_psoc *psoc,
1168 struct twt_add_dialog_param *req,
1169 void *context)
1170 {
1171 QDF_STATUS status;
1172 bool cmd_in_progress, notify_in_progress;
1173 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
1174
1175 if (wlan_twt_is_max_sessions_reached(psoc, &req->peer_macaddr,
1176 req->dialog_id)) {
1177 twt_err("TWT add failed(dialog_id:%d), another TWT already exists (max reached)",
1178 req->dialog_id);
1179 return QDF_STATUS_E_AGAIN;
1180 }
1181
1182 if (wlan_twt_is_setup_in_progress(psoc, &req->peer_macaddr,
1183 req->dialog_id)) {
1184 twt_err("TWT setup is in progress for dialog_id:%d",
1185 req->dialog_id);
1186 return QDF_STATUS_E_ALREADY;
1187 }
1188
1189 if (!mlme_get_user_ps(psoc, req->vdev_id)) {
1190 twt_warn("Power save mode disable");
1191 return QDF_STATUS_E_AGAIN;
1192 }
1193
1194 notify_in_progress = wlan_is_twt_notify_in_progress(psoc, req->vdev_id);
1195 if (notify_in_progress) {
1196 twt_warn("Waiting for TWT Notify");
1197 return QDF_STATUS_E_BUSY;
1198 }
1199
1200 cmd_in_progress = wlan_twt_is_command_in_progress(
1201 psoc, &req->peer_macaddr, req->dialog_id,
1202 WLAN_TWT_ANY, &active_cmd);
1203 if (cmd_in_progress) {
1204 twt_debug("Already TWT command:%d is in progress", active_cmd);
1205 return QDF_STATUS_E_PENDING;
1206 }
1207
1208 /*
1209 * Add the dialog id to TWT context to drop back to back
1210 * commands
1211 */
1212 wlan_twt_add_session(psoc, &req->peer_macaddr, req->dialog_id, context);
1213 wlan_twt_set_ack_context(psoc, &req->peer_macaddr, req->dialog_id,
1214 context);
1215 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1216 req->dialog_id, WLAN_TWT_SETUP);
1217
1218 status = tgt_twt_setup_req_send(psoc, req);
1219 if (QDF_IS_STATUS_ERROR(status)) {
1220 twt_err("tgt_twt_setup_req_send failed (status=%d)", status);
1221 wlan_twt_init_context(psoc, &req->peer_macaddr, req->dialog_id);
1222 }
1223
1224 return status;
1225 }
1226
1227 /**
1228 * wlan_twt_sta_teardown_req() - station TWT teardown request
1229 * @psoc: Pointer to psoc object
1230 * @req: TWT del dialog parameters
1231 * @context: TWT context
1232 *
1233 * Return: QDF Status
1234 */
1235 static QDF_STATUS
wlan_twt_sta_teardown_req(struct wlan_objmgr_psoc * psoc,struct twt_del_dialog_param * req,void * context)1236 wlan_twt_sta_teardown_req(struct wlan_objmgr_psoc *psoc,
1237 struct twt_del_dialog_param *req,
1238 void *context)
1239 {
1240 bool cmd_in_progress;
1241 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
1242 QDF_STATUS status;
1243
1244 if (!wlan_twt_is_setup_done(psoc, &req->peer_macaddr, req->dialog_id)) {
1245 twt_err("vdev%d: TWT session %d setup incomplete",
1246 req->vdev_id, req->dialog_id);
1247 return QDF_STATUS_E_AGAIN;
1248 }
1249
1250 cmd_in_progress =
1251 wlan_twt_is_command_in_progress(psoc, &req->peer_macaddr,
1252 req->dialog_id, WLAN_TWT_SETUP, &active_cmd) ||
1253 wlan_twt_is_command_in_progress(
1254 psoc, &req->peer_macaddr, req->dialog_id,
1255 WLAN_TWT_TERMINATE, &active_cmd);
1256 if (cmd_in_progress) {
1257 twt_debug("Already TWT command:%d is in progress", active_cmd);
1258 return QDF_STATUS_E_PENDING;
1259 }
1260
1261 wlan_twt_set_ack_context(psoc, &req->peer_macaddr,
1262 req->dialog_id, context);
1263 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1264 req->dialog_id, WLAN_TWT_TERMINATE);
1265
1266 status = tgt_twt_teardown_req_send(psoc, req);
1267 if (QDF_IS_STATUS_ERROR(status)) {
1268 twt_err("tgt_twt_teardown_req_send failed (status=%d)", status);
1269 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1270 req->dialog_id, WLAN_TWT_NONE);
1271 }
1272
1273 return status;
1274 }
1275
wlan_twt_pause_req(struct wlan_objmgr_psoc * psoc,struct twt_pause_dialog_cmd_param * req,void * context)1276 QDF_STATUS wlan_twt_pause_req(struct wlan_objmgr_psoc *psoc,
1277 struct twt_pause_dialog_cmd_param *req,
1278 void *context)
1279 {
1280 QDF_STATUS status;
1281 bool cmd_in_progress;
1282 bool is_twt_setup_done;
1283 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
1284
1285 status = wlan_twt_check_all_twt_support(psoc, req->dialog_id);
1286 if (QDF_IS_STATUS_ERROR(status)) {
1287 twt_err("All TWT sessions not supported by target");
1288 return status;
1289 }
1290
1291 is_twt_setup_done = wlan_twt_is_setup_done(psoc, &req->peer_macaddr,
1292 req->dialog_id);
1293 if (!is_twt_setup_done) {
1294 twt_err("TWT setup is not complete for dialog_id:%d",
1295 req->dialog_id);
1296 return QDF_STATUS_E_AGAIN;
1297 }
1298
1299 cmd_in_progress = wlan_twt_is_command_in_progress(psoc,
1300 &req->peer_macaddr, req->dialog_id,
1301 WLAN_TWT_ANY, &active_cmd);
1302 if (cmd_in_progress) {
1303 twt_debug("Already TWT command:%d is in progress", active_cmd);
1304 return QDF_STATUS_E_PENDING;
1305 }
1306
1307 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1308 req->dialog_id, WLAN_TWT_SUSPEND);
1309 wlan_twt_set_ack_context(psoc, &req->peer_macaddr,
1310 req->dialog_id, context);
1311
1312 status = tgt_twt_pause_req_send(psoc, req);
1313 if (QDF_IS_STATUS_ERROR(status)) {
1314 twt_err("tgt_twt_pause_req_send failed (status=%d)", status);
1315 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1316 req->dialog_id, WLAN_TWT_NONE);
1317 }
1318
1319 return status;
1320 }
1321
wlan_twt_resume_req(struct wlan_objmgr_psoc * psoc,struct twt_resume_dialog_cmd_param * req,void * context)1322 QDF_STATUS wlan_twt_resume_req(struct wlan_objmgr_psoc *psoc,
1323 struct twt_resume_dialog_cmd_param *req,
1324 void *context)
1325 {
1326 QDF_STATUS status;
1327 bool cmd_in_progress;
1328 bool is_twt_setup_done;
1329 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
1330
1331 status = wlan_twt_check_all_twt_support(psoc, req->dialog_id);
1332 if (QDF_IS_STATUS_ERROR(status)) {
1333 twt_err("All TWT sessions not supported by target");
1334 return status;
1335 }
1336
1337 is_twt_setup_done = wlan_twt_is_setup_done(psoc, &req->peer_macaddr,
1338 req->dialog_id);
1339 if (!is_twt_setup_done) {
1340 twt_err("TWT setup is not complete for dialog_id:%d",
1341 req->dialog_id);
1342 return QDF_STATUS_E_AGAIN;
1343 }
1344
1345 cmd_in_progress = wlan_twt_is_command_in_progress(psoc,
1346 &req->peer_macaddr,
1347 req->dialog_id, WLAN_TWT_ANY,
1348 &active_cmd);
1349 if (cmd_in_progress) {
1350 twt_debug("Already TWT command:%d is in progress", active_cmd);
1351 return QDF_STATUS_E_PENDING;
1352 }
1353
1354 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1355 req->dialog_id, WLAN_TWT_RESUME);
1356 wlan_twt_set_ack_context(psoc, &req->peer_macaddr,
1357 req->dialog_id, context);
1358
1359 status = tgt_twt_resume_req_send(psoc, req);
1360 if (QDF_IS_STATUS_ERROR(status)) {
1361 twt_err("tgt_twt_resume_req_send failed (status=%d)", status);
1362 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1363 req->dialog_id, WLAN_TWT_NONE);
1364 }
1365
1366 return status;
1367 }
1368
wlan_twt_nudge_req(struct wlan_objmgr_psoc * psoc,struct twt_nudge_dialog_cmd_param * req,void * context)1369 QDF_STATUS wlan_twt_nudge_req(struct wlan_objmgr_psoc *psoc,
1370 struct twt_nudge_dialog_cmd_param *req,
1371 void *context)
1372 {
1373 QDF_STATUS status;
1374 bool cmd_in_progress;
1375 bool setup_done;
1376 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
1377
1378 status = wlan_twt_check_all_twt_support(psoc, req->dialog_id);
1379 if (QDF_IS_STATUS_ERROR(status)) {
1380 twt_err("All TWT sessions not supported by target");
1381 return status;
1382 }
1383
1384 setup_done = wlan_twt_is_setup_done(psoc, &req->peer_macaddr,
1385 req->dialog_id);
1386 if (!setup_done) {
1387 twt_err("TWT setup is not complete for dialog_id:%d",
1388 req->dialog_id);
1389 return QDF_STATUS_E_AGAIN;
1390 }
1391
1392 cmd_in_progress = wlan_twt_is_command_in_progress(psoc,
1393 &req->peer_macaddr, req->dialog_id,
1394 WLAN_TWT_ANY, &active_cmd);
1395 if (cmd_in_progress) {
1396 twt_debug("Already TWT command:%d is in progress", active_cmd);
1397 return QDF_STATUS_E_PENDING;
1398 }
1399
1400 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1401 req->dialog_id, WLAN_TWT_NUDGE);
1402 wlan_twt_set_ack_context(psoc, &req->peer_macaddr, req->dialog_id,
1403 context);
1404
1405 status = tgt_twt_nudge_req_send(psoc, req);
1406 if (QDF_IS_STATUS_ERROR(status)) {
1407 twt_err("tgt_twt_nudge_req_send failed (status=%d)", status);
1408 wlan_twt_set_command_in_progress(psoc, &req->peer_macaddr,
1409 req->dialog_id, WLAN_TWT_NONE);
1410 }
1411
1412 return status;
1413 }
1414
wlan_twt_ac_pdev_param_send(struct wlan_objmgr_psoc * psoc,enum twt_traffic_ac twt_ac)1415 QDF_STATUS wlan_twt_ac_pdev_param_send(struct wlan_objmgr_psoc *psoc,
1416 enum twt_traffic_ac twt_ac)
1417 {
1418 QDF_STATUS status;
1419
1420 status = tgt_twt_ac_pdev_param_send(psoc, twt_ac);
1421 if (QDF_IS_STATUS_ERROR(status))
1422 twt_err("failed (status=%d)", status);
1423
1424 return status;
1425 }
1426
1427 /**
1428 * wlan_twt_sap_teardown_req() - sap TWT teardown request
1429 * @psoc: Pointer to psoc object
1430 * @req: TWT del dialog parameters
1431 *
1432 * Return: QDF Status
1433 */
1434 static QDF_STATUS
wlan_twt_sap_teardown_req(struct wlan_objmgr_psoc * psoc,struct twt_del_dialog_param * req)1435 wlan_twt_sap_teardown_req(struct wlan_objmgr_psoc *psoc,
1436 struct twt_del_dialog_param *req)
1437 {
1438 bool is_twt_cmd_in_progress;
1439 QDF_STATUS status;
1440 bool connection_exists;
1441
1442 if (!qdf_is_macaddr_broadcast(&req->peer_macaddr)) {
1443 connection_exists = wlan_is_vdev_connected_to_peer(psoc,
1444 req->vdev_id,
1445 &req->peer_macaddr);
1446 if (!connection_exists) {
1447 twt_warn("SAP doesn't have connection with this peer("QDF_MAC_ADDR_FMT")",
1448 QDF_MAC_ADDR_REF(req->peer_macaddr.bytes));
1449 /*
1450 * Return success, since STA is not associated and
1451 * there is no TWT session.
1452 */
1453 return QDF_STATUS_SUCCESS;
1454 }
1455 }
1456
1457 is_twt_cmd_in_progress =
1458 wlan_twt_sap_is_command_in_progress(
1459 psoc, req->vdev_id, &req->peer_macaddr,
1460 req->dialog_id, WLAN_TWT_TERMINATE);
1461 if (is_twt_cmd_in_progress) {
1462 twt_debug("Already TWT teardown command is in progress");
1463 return QDF_STATUS_E_PENDING;
1464 }
1465
1466 /*
1467 * Add the dialog id to TWT context to drop back to back
1468 * commands
1469 */
1470 wlan_twt_sap_add_session(psoc, req->vdev_id, &req->peer_macaddr,
1471 req->dialog_id);
1472
1473 wlan_twt_sap_set_command_in_progress(psoc, req->vdev_id,
1474 &req->peer_macaddr, req->dialog_id,
1475 WLAN_TWT_TERMINATE);
1476
1477 status = tgt_twt_teardown_req_send(psoc, req);
1478 if (QDF_IS_STATUS_ERROR(status)) {
1479 twt_err("tgt_twt_teardown_req_send failed (status=%d)", status);
1480 wlan_twt_sap_set_command_in_progress(psoc, req->vdev_id,
1481 &req->peer_macaddr, req->dialog_id,
1482 WLAN_TWT_NONE);
1483 wlan_twt_sap_init_context(psoc, req->vdev_id,
1484 &req->peer_macaddr, req->dialog_id);
1485 }
1486
1487 return status;
1488 }
1489
1490 QDF_STATUS
wlan_twt_teardown_req(struct wlan_objmgr_psoc * psoc,struct twt_del_dialog_param * req,void * context)1491 wlan_twt_teardown_req(struct wlan_objmgr_psoc *psoc,
1492 struct twt_del_dialog_param *req,
1493 void *context)
1494 {
1495 enum QDF_OPMODE opmode;
1496 uint32_t pdev_id;
1497 struct wlan_objmgr_pdev *pdev;
1498 QDF_STATUS status;
1499
1500 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, req->vdev_id,
1501 WLAN_TWT_ID);
1502 if (pdev_id == WLAN_INVALID_PDEV_ID) {
1503 twt_err("Invalid pdev id");
1504 return QDF_STATUS_E_INVAL;
1505 }
1506
1507 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_TWT_ID);
1508 if (!pdev) {
1509 twt_err("Invalid pdev");
1510 return QDF_STATUS_E_INVAL;
1511 }
1512
1513 status = wlan_twt_check_all_twt_support(psoc, req->dialog_id);
1514 if (QDF_IS_STATUS_ERROR(status)) {
1515 twt_err("All TWT sessions not supported by target");
1516 return status;
1517 }
1518
1519 opmode = wlan_get_opmode_from_vdev_id(pdev, req->vdev_id);
1520
1521 switch (opmode) {
1522 case QDF_SAP_MODE:
1523 status = wlan_twt_sap_teardown_req(psoc, req);
1524 break;
1525 case QDF_STA_MODE:
1526 status = wlan_twt_sta_teardown_req(psoc, req, context);
1527 break;
1528 default:
1529 twt_err("TWT teardown not supported in mode: %d", opmode);
1530 status = QDF_STATUS_E_INVAL;
1531 break;
1532 }
1533
1534 wlan_objmgr_pdev_release_ref(pdev, WLAN_TWT_ID);
1535 return status;
1536 }
1537
1538 QDF_STATUS
wlan_twt_ack_event_handler(struct wlan_objmgr_psoc * psoc,struct twt_ack_complete_event_param * event)1539 wlan_twt_ack_event_handler(struct wlan_objmgr_psoc *psoc,
1540 struct twt_ack_complete_event_param *event)
1541 {
1542 void *ack_context = NULL;
1543 QDF_STATUS qdf_status;
1544
1545 twt_debug("TWT ack status: %d", event->status);
1546 /* If the ack status is other than 0 (SUCCESS) then its a error.
1547 * that means there won't be following TWT add/del/pause/resume/nudge
1548 * event, hence clear the command in progress to NONE
1549 */
1550 if (event->status) {
1551 qdf_status = wlan_twt_set_command_in_progress(psoc,
1552 &event->peer_macaddr,
1553 event->dialog_id, WLAN_TWT_NONE);
1554 if (QDF_IS_STATUS_ERROR(qdf_status))
1555 return qdf_status;
1556 }
1557 qdf_status = wlan_twt_get_ack_context(psoc, &event->peer_macaddr,
1558 event->dialog_id, &ack_context);
1559 if (QDF_IS_STATUS_ERROR(qdf_status))
1560 return qdf_status;
1561
1562 qdf_status = mlme_twt_osif_ack_complete_ind(psoc, event, ack_context);
1563
1564 return qdf_status;
1565 }
1566
1567 /**
1568 * wlan_twt_set_setup_done() - Set TWT setup complete for given dialog ID
1569 * @psoc: Pointer to psoc object
1570 * @peer_mac: Pointer to peer mac address
1571 * @dialog_id: Dialog id
1572 * @is_set: Set or clear the setup done flag
1573 *
1574 * Return: None
1575 */
1576 static void
wlan_twt_set_setup_done(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,bool is_set)1577 wlan_twt_set_setup_done(struct wlan_objmgr_psoc *psoc,
1578 struct qdf_mac_addr *peer_mac,
1579 uint8_t dialog_id, bool is_set)
1580 {
1581 struct twt_peer_priv_obj *peer_priv;
1582 struct wlan_objmgr_peer *peer;
1583 uint8_t i;
1584
1585 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1586 WLAN_TWT_ID);
1587 if (!peer) {
1588 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1589 QDF_MAC_ADDR_REF(peer_mac->bytes));
1590 return;
1591 }
1592
1593 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1594 WLAN_UMAC_COMP_TWT);
1595 if (!peer_priv) {
1596 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1597 twt_err(" peer twt component object is NULL");
1598 return;
1599 }
1600
1601 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1602
1603 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1604 if (peer_priv->session_info[i].dialog_id == dialog_id) {
1605 peer_priv->session_info[i].setup_done = is_set;
1606 twt_debug("setup done:%d dialog:%d", is_set, dialog_id);
1607 break;
1608 }
1609 }
1610 qdf_mutex_release(&peer_priv->twt_peer_lock);
1611
1612 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1613 }
1614
1615 /**
1616 * wlan_twt_set_session_state() - Set the TWT session state for the given dialog
1617 * id in TWT context
1618 * @psoc: Pointer to psoc object
1619 * @peer_mac: Pointer to peer mac address
1620 * @dialog_id: Dialog id
1621 * @state: TWT session state
1622 *
1623 * Return: None
1624 */
1625 static void
wlan_twt_set_session_state(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,enum wlan_twt_session_state state)1626 wlan_twt_set_session_state(struct wlan_objmgr_psoc *psoc,
1627 struct qdf_mac_addr *peer_mac,
1628 uint8_t dialog_id,
1629 enum wlan_twt_session_state state)
1630 {
1631 struct wlan_objmgr_peer *peer;
1632 struct twt_peer_priv_obj *peer_priv;
1633 uint8_t i;
1634
1635 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1636 WLAN_TWT_ID);
1637 if (!peer) {
1638 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1639 QDF_MAC_ADDR_REF(peer_mac->bytes));
1640 return;
1641 }
1642
1643 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1644 WLAN_UMAC_COMP_TWT);
1645 if (!peer_priv) {
1646 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1647 twt_err(" peer twt component object is NULL");
1648 return;
1649 }
1650
1651 twt_debug("set_state:%d for dialog_id:%d", state, dialog_id);
1652 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1653 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1654 if (peer_priv->session_info[i].dialog_id == dialog_id ||
1655 dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
1656 peer_priv->session_info[i].state = state;
1657 break;
1658 }
1659 }
1660 qdf_mutex_release(&peer_priv->twt_peer_lock);
1661
1662 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1663 }
1664
1665 enum wlan_twt_session_state
wlan_twt_get_session_state(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)1666 wlan_twt_get_session_state(struct wlan_objmgr_psoc *psoc,
1667 struct qdf_mac_addr *peer_mac, uint8_t dialog_id)
1668 {
1669 struct wlan_objmgr_peer *peer;
1670 struct twt_peer_priv_obj *peer_priv;
1671 uint8_t i;
1672
1673 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1674 WLAN_TWT_ID);
1675
1676 if (!peer) {
1677 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1678 QDF_MAC_ADDR_REF(peer_mac->bytes));
1679 return WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED;
1680 }
1681
1682 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1683 WLAN_UMAC_COMP_TWT);
1684
1685 if (!peer_priv) {
1686 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1687 twt_err(" peer twt component object is NULL");
1688 return WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED;
1689 }
1690
1691 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1692 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1693 if (peer_priv->session_info[i].dialog_id == dialog_id &&
1694 dialog_id != TWT_ALL_SESSIONS_DIALOG_ID) {
1695 qdf_mutex_release(&peer_priv->twt_peer_lock);
1696 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1697 return peer_priv->session_info[i].state;
1698 }
1699 }
1700
1701 qdf_mutex_release(&peer_priv->twt_peer_lock);
1702 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1703
1704 return WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED;
1705 }
1706
1707 /**
1708 * wlan_twt_process_renego_failure() - Process TWT re-negotiation failure
1709 * @psoc: psoc
1710 * @event: pointer to event buf containing twt response parameters
1711 *
1712 * Return: None
1713 */
1714 static void
wlan_twt_process_renego_failure(struct wlan_objmgr_psoc * psoc,struct twt_add_dialog_complete_event * event)1715 wlan_twt_process_renego_failure(struct wlan_objmgr_psoc *psoc,
1716 struct twt_add_dialog_complete_event *event)
1717 {
1718 /* Reset the active TWT command to none */
1719 wlan_twt_set_command_in_progress(psoc,
1720 &event->params.peer_macaddr,
1721 event->params.dialog_id,
1722 WLAN_TWT_NONE);
1723
1724 mlme_twt_osif_setup_complete_ind(psoc, event, true);
1725 }
1726
1727 /**
1728 * wlan_twt_process_add_initial_nego() - Process initial TWT setup or
1729 * re-negotiation successful setup
1730 * @psoc: psoc
1731 * @event: pointer to event buf containing twt response parameters
1732 *
1733 * Return: None
1734 */
1735 static void
wlan_twt_process_add_initial_nego(struct wlan_objmgr_psoc * psoc,struct twt_add_dialog_complete_event * event)1736 wlan_twt_process_add_initial_nego(struct wlan_objmgr_psoc *psoc,
1737 struct twt_add_dialog_complete_event *event)
1738 {
1739 mlme_twt_osif_setup_complete_ind(psoc, event, false);
1740
1741 /* Reset the active TWT command to none */
1742 wlan_twt_set_command_in_progress(psoc,
1743 &event->params.peer_macaddr,
1744 event->params.dialog_id,
1745 WLAN_TWT_NONE);
1746
1747 if (event->params.status) {
1748 /* Clear the stored TWT dialog ID as TWT setup failed */
1749 wlan_twt_init_context(psoc, &event->params.peer_macaddr,
1750 event->params.dialog_id);
1751 return;
1752 }
1753
1754 wlan_twt_set_setup_done(psoc, &event->params.peer_macaddr,
1755 event->params.dialog_id, true);
1756
1757 wlan_twt_set_session_state(psoc, &event->params.peer_macaddr,
1758 event->params.dialog_id,
1759 WLAN_TWT_SETUP_STATE_ACTIVE);
1760 }
1761
1762 /*
1763 * wlan_twt_clear_wake_dur_and_interval() - Clear cached TWT wake duration and
1764 * wake interval of peer.
1765 * @psoc: Pointer to psoc object
1766 * @vdev_id: Vdev Id
1767 * @peer_mac: Peer mac address
1768 * @dialog_id: Dialog Id
1769 *
1770 * Return: QDF_STATUS
1771 */
1772 static void
wlan_twt_clear_wake_dur_and_interval(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct qdf_mac_addr * peer_mac,uint8_t dialog_id)1773 wlan_twt_clear_wake_dur_and_interval(struct wlan_objmgr_psoc *psoc,
1774 uint8_t vdev_id,
1775 struct qdf_mac_addr *peer_mac,
1776 uint8_t dialog_id)
1777 {
1778 struct twt_peer_priv_obj *peer_priv;
1779 struct wlan_objmgr_peer *peer;
1780 uint8_t i;
1781
1782 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1783 WLAN_TWT_ID);
1784 if (!peer) {
1785 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1786 QDF_MAC_ADDR_REF(peer_mac->bytes));
1787 return;
1788 }
1789 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1790 WLAN_UMAC_COMP_TWT);
1791 if (!peer_priv) {
1792 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1793 twt_err(" peer twt component object is NULL");
1794 return;
1795 }
1796
1797 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1798
1799 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1800 if (peer_priv->session_info[i].dialog_id == dialog_id) {
1801 peer_priv->session_info[i].dialog_id = TWT_ALL_SESSIONS_DIALOG_ID;
1802 peer_priv->session_info[i].wake_dur = 0;
1803 peer_priv->session_info[i].wake_interval = 0;
1804 break;
1805 }
1806 }
1807
1808 twt_debug("vdev:%d peer:" QDF_MAC_ADDR_FMT " dialog_id:%d wake_dur:%d wake_interval:%d",
1809 vdev_id,
1810 QDF_MAC_ADDR_REF(peer_mac->bytes),
1811 peer_priv->session_info[i].dialog_id,
1812 peer_priv->session_info[i].wake_dur,
1813 peer_priv->session_info[i].wake_interval);
1814
1815 qdf_mutex_release(&peer_priv->twt_peer_lock);
1816 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1817 }
1818
1819 /*
1820 * wlan_twt_set_wake_dur_and_interval() - Set TWT wake duration and wake
1821 * interval of peer.
1822 * @psoc: Pointer to psoc object
1823 * @vdev_id: Vdev Id
1824 * @peer_mac: Peer mac address
1825 * @dialog_id: Dialog Id
1826 * @wake_dur: TWT wake duration
1827 * @wake_interval: TWT wake interval
1828 *
1829 * Return: QDF_STATUS
1830 */
1831 static void
wlan_twt_set_wake_dur_and_interval(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,uint32_t wake_dur,uint32_t wake_interval)1832 wlan_twt_set_wake_dur_and_interval(struct wlan_objmgr_psoc *psoc,
1833 uint8_t vdev_id,
1834 struct qdf_mac_addr *peer_mac,
1835 uint8_t dialog_id,
1836 uint32_t wake_dur,
1837 uint32_t wake_interval)
1838 {
1839 struct twt_peer_priv_obj *peer_priv;
1840 struct wlan_objmgr_peer *peer;
1841 uint8_t i;
1842
1843 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes,
1844 WLAN_TWT_ID);
1845 if (!peer) {
1846 twt_err("Peer object not found "QDF_MAC_ADDR_FMT,
1847 QDF_MAC_ADDR_REF(peer_mac->bytes));
1848 return;
1849 }
1850
1851 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1852 WLAN_UMAC_COMP_TWT);
1853 if (!peer_priv) {
1854 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1855 twt_err(" peer twt component object is NULL");
1856 return;
1857 }
1858
1859 qdf_mutex_acquire(&peer_priv->twt_peer_lock);
1860
1861 for (i = 0; i < peer_priv->num_twt_sessions; i++) {
1862 if (peer_priv->session_info[i].dialog_id == dialog_id) {
1863 peer_priv->session_info[i].wake_dur = wake_dur;
1864 peer_priv->session_info[i].wake_interval = wake_interval;
1865 break;
1866 } else {
1867 if (peer_priv->session_info[i].dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) {
1868 peer_priv->session_info[i].dialog_id = dialog_id;
1869 peer_priv->session_info[i].wake_dur = wake_dur;
1870 peer_priv->session_info[i].wake_interval = wake_interval;
1871 break;
1872 }
1873 }
1874 }
1875
1876 twt_debug("vdev:%d peer:" QDF_MAC_ADDR_FMT " dialog_id:%d wake_dur:%d wake_interval:%d",
1877 vdev_id,
1878 QDF_MAC_ADDR_REF(peer_mac->bytes),
1879 peer_priv->session_info[i].dialog_id,
1880 peer_priv->session_info[i].wake_dur,
1881 peer_priv->session_info[i].wake_interval);
1882
1883 qdf_mutex_release(&peer_priv->twt_peer_lock);
1884 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID);
1885 }
1886
1887 QDF_STATUS
wlan_twt_setup_complete_event_handler(struct wlan_objmgr_psoc * psoc,struct twt_add_dialog_complete_event * event)1888 wlan_twt_setup_complete_event_handler(struct wlan_objmgr_psoc *psoc,
1889 struct twt_add_dialog_complete_event *event)
1890 {
1891 bool is_evt_allowed;
1892 bool setup_done;
1893 enum HOST_TWT_ADD_STATUS status = event->params.status;
1894 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
1895 enum QDF_OPMODE opmode;
1896 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
1897 uint32_t pdev_id, vdev_id;
1898 struct wlan_objmgr_pdev *pdev;
1899
1900 vdev_id = event->params.vdev_id;
1901 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, vdev_id, WLAN_TWT_ID);
1902 if (pdev_id == WLAN_INVALID_PDEV_ID) {
1903 twt_err("Invalid pdev id");
1904 return QDF_STATUS_E_INVAL;
1905 }
1906
1907 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_TWT_ID);
1908 if (!pdev) {
1909 twt_err("Invalid pdev");
1910 return QDF_STATUS_E_INVAL;
1911 }
1912
1913 opmode = wlan_get_opmode_from_vdev_id(pdev, vdev_id);
1914
1915 switch (opmode) {
1916 case QDF_SAP_MODE:
1917 wlan_twt_set_wake_dur_and_interval(
1918 psoc, vdev_id,
1919 &event->params.peer_macaddr,
1920 event->params.dialog_id,
1921 event->additional_params.wake_dur_us,
1922 event->additional_params.wake_intvl_us);
1923 qdf_status = mlme_twt_osif_setup_complete_ind(psoc, event,
1924 false);
1925 break;
1926 case QDF_STA_MODE:
1927 is_evt_allowed = wlan_twt_is_command_in_progress(
1928 psoc,
1929 &event->params.peer_macaddr,
1930 event->params.dialog_id,
1931 WLAN_TWT_SETUP, &active_cmd);
1932
1933 if (!is_evt_allowed) {
1934 twt_debug("Drop TWT add dialog event for dialog_id:%d status:%d active_cmd:%d",
1935 event->params.dialog_id, status,
1936 active_cmd);
1937 qdf_status = QDF_STATUS_E_INVAL;
1938 goto cleanup;
1939 }
1940
1941 setup_done = wlan_twt_is_setup_done(psoc,
1942 &event->params.peer_macaddr,
1943 event->params.dialog_id);
1944 twt_debug("setup_done:%d status:%d", setup_done, status);
1945
1946 if (setup_done && status) {
1947 /*This is re-negotiation failure case */
1948 wlan_twt_process_renego_failure(psoc, event);
1949 } else {
1950 wlan_twt_process_add_initial_nego(psoc, event);
1951 }
1952
1953 qdf_status = QDF_STATUS_SUCCESS;
1954 break;
1955 default:
1956 twt_debug("TWT Setup is not supported on %s",
1957 qdf_opmode_str(opmode));
1958 break;
1959 }
1960
1961 cleanup:
1962 wlan_objmgr_pdev_release_ref(pdev, WLAN_TWT_ID);
1963 return qdf_status;
1964 }
1965
1966 static bool
wlan_is_twt_teardown_failed(enum HOST_TWT_DEL_STATUS teardown_status)1967 wlan_is_twt_teardown_failed(enum HOST_TWT_DEL_STATUS teardown_status)
1968 {
1969 switch (teardown_status) {
1970 case HOST_TWT_DEL_STATUS_DIALOG_ID_NOT_EXIST:
1971 case HOST_TWT_DEL_STATUS_INVALID_PARAM:
1972 case HOST_TWT_DEL_STATUS_DIALOG_ID_BUSY:
1973 case HOST_TWT_DEL_STATUS_NO_RESOURCE:
1974 case HOST_TWT_DEL_STATUS_NO_ACK:
1975 case HOST_TWT_DEL_STATUS_UNKNOWN_ERROR:
1976 return true;
1977 default:
1978 return false;
1979 }
1980
1981 return false;
1982 }
1983
1984 static void
wlan_twt_handle_sta_del_dialog_event(struct wlan_objmgr_psoc * psoc,struct twt_del_dialog_complete_event_param * event)1985 wlan_twt_handle_sta_del_dialog_event(struct wlan_objmgr_psoc *psoc,
1986 struct twt_del_dialog_complete_event_param *event)
1987 {
1988 bool is_evt_allowed, usr_cfg_ps_enable;
1989 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
1990
1991 is_evt_allowed = wlan_twt_is_command_in_progress(
1992 psoc, &event->peer_macaddr,
1993 event->dialog_id,
1994 WLAN_TWT_TERMINATE, &active_cmd);
1995 if (!is_evt_allowed &&
1996 event->dialog_id != TWT_ALL_SESSIONS_DIALOG_ID &&
1997 event->status != HOST_TWT_DEL_STATUS_ROAMING &&
1998 event->status != HOST_TWT_DEL_STATUS_PEER_INIT_TEARDOWN &&
1999 event->status != HOST_TWT_DEL_STATUS_CONCURRENCY) {
2000 twt_err("Drop TWT Del dialog event for dialog_id:%d status:%d active_cmd:%d",
2001 event->dialog_id, event->status, active_cmd);
2002
2003 return;
2004 }
2005
2006 usr_cfg_ps_enable = mlme_get_user_ps(psoc, event->vdev_id);
2007 if (!usr_cfg_ps_enable &&
2008 event->status == HOST_TWT_DEL_STATUS_OK)
2009 event->status = HOST_TWT_DEL_STATUS_PS_DISABLE_TEARDOWN;
2010
2011 mlme_twt_osif_teardown_complete_ind(psoc, event);
2012
2013 if (event->status == HOST_TWT_DEL_STATUS_ROAMING ||
2014 event->status == HOST_TWT_DEL_STATUS_CONCURRENCY)
2015 wlan_twt_set_wait_for_notify(psoc, event->vdev_id, true);
2016
2017 wlan_twt_set_command_in_progress(psoc, &event->peer_macaddr,
2018 event->dialog_id, WLAN_TWT_NONE);
2019
2020 if (wlan_is_twt_teardown_failed(event->status))
2021 return;
2022
2023 wlan_twt_set_setup_done(psoc, &event->peer_macaddr,
2024 event->dialog_id, false);
2025 wlan_twt_set_session_state(psoc, &event->peer_macaddr, event->dialog_id,
2026 WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED);
2027 wlan_twt_init_context(psoc, &event->peer_macaddr, event->dialog_id);
2028 }
2029
2030 QDF_STATUS
wlan_twt_teardown_complete_event_handler(struct wlan_objmgr_psoc * psoc,struct twt_del_dialog_complete_event_param * event)2031 wlan_twt_teardown_complete_event_handler(struct wlan_objmgr_psoc *psoc,
2032 struct twt_del_dialog_complete_event_param *event)
2033 {
2034 enum QDF_OPMODE opmode;
2035 uint32_t pdev_id, vdev_id;
2036 struct wlan_objmgr_pdev *pdev;
2037
2038 vdev_id = event->vdev_id;
2039 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, vdev_id, WLAN_TWT_ID);
2040 if (pdev_id == WLAN_INVALID_PDEV_ID) {
2041 twt_err("Invalid pdev id");
2042 return QDF_STATUS_E_INVAL;
2043 }
2044
2045 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_TWT_ID);
2046 if (!pdev) {
2047 twt_err("Invalid pdev");
2048 return QDF_STATUS_E_INVAL;
2049 }
2050
2051 opmode = wlan_get_opmode_from_vdev_id(pdev, vdev_id);
2052
2053 switch (opmode) {
2054 case QDF_SAP_MODE:
2055 mlme_twt_osif_teardown_complete_ind(psoc, event);
2056
2057 wlan_twt_clear_wake_dur_and_interval(psoc, vdev_id,
2058 &event->peer_macaddr,
2059 event->dialog_id);
2060
2061 /*
2062 * If this is an unsolicited TWT del event initiated from the
2063 * peer, then no need to clear the active command in progress
2064 */
2065 if (event->status != HOST_TWT_DEL_STATUS_PEER_INIT_TEARDOWN) {
2066 /* Reset the active TWT command to none */
2067 wlan_twt_sap_set_command_in_progress(psoc,
2068 event->vdev_id, &event->peer_macaddr,
2069 event->dialog_id, WLAN_TWT_NONE);
2070 wlan_twt_sap_init_context(psoc, event->vdev_id,
2071 &event->peer_macaddr, event->dialog_id);
2072 }
2073 break;
2074 case QDF_STA_MODE:
2075 wlan_twt_handle_sta_del_dialog_event(psoc, event);
2076 break;
2077 default:
2078 twt_debug("TWT Teardown is not supported on %s",
2079 qdf_opmode_str(opmode));
2080 break;
2081 }
2082
2083 wlan_objmgr_pdev_release_ref(pdev, WLAN_TWT_ID);
2084 return QDF_STATUS_SUCCESS;
2085 }
2086
2087 QDF_STATUS
wlan_twt_pause_complete_event_handler(struct wlan_objmgr_psoc * psoc,struct twt_pause_dialog_complete_event_param * event)2088 wlan_twt_pause_complete_event_handler(struct wlan_objmgr_psoc *psoc,
2089 struct twt_pause_dialog_complete_event_param *event)
2090 {
2091 enum QDF_OPMODE opmode;
2092 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
2093 uint32_t pdev_id, vdev_id;
2094 struct wlan_objmgr_pdev *pdev;
2095
2096 vdev_id = event->vdev_id;
2097 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, vdev_id, WLAN_TWT_ID);
2098 if (pdev_id == WLAN_INVALID_PDEV_ID) {
2099 twt_err("Invalid pdev id");
2100 return QDF_STATUS_E_INVAL;
2101 }
2102
2103 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_TWT_ID);
2104 if (!pdev) {
2105 twt_err("Invalid pdev");
2106 return QDF_STATUS_E_INVAL;
2107 }
2108
2109 opmode = wlan_get_opmode_from_vdev_id(pdev, vdev_id);
2110
2111 switch (opmode) {
2112 case QDF_SAP_MODE:
2113 qdf_status = mlme_twt_osif_pause_complete_ind(psoc, event);
2114 break;
2115 case QDF_STA_MODE:
2116 qdf_status = mlme_twt_osif_pause_complete_ind(psoc, event);
2117
2118 wlan_twt_set_session_state(psoc, &event->peer_macaddr,
2119 event->dialog_id,
2120 WLAN_TWT_SETUP_STATE_SUSPEND);
2121
2122 qdf_status = wlan_twt_set_command_in_progress(psoc,
2123 &event->peer_macaddr,
2124 event->dialog_id, WLAN_TWT_NONE);
2125 break;
2126 default:
2127 twt_debug("TWT Pause is not supported on %s",
2128 qdf_opmode_str(opmode));
2129 break;
2130 }
2131
2132 wlan_objmgr_pdev_release_ref(pdev, WLAN_TWT_ID);
2133 return qdf_status;
2134 }
2135
2136 QDF_STATUS
wlan_twt_resume_complete_event_handler(struct wlan_objmgr_psoc * psoc,struct twt_resume_dialog_complete_event_param * event)2137 wlan_twt_resume_complete_event_handler(struct wlan_objmgr_psoc *psoc,
2138 struct twt_resume_dialog_complete_event_param *event)
2139 {
2140 enum QDF_OPMODE opmode;
2141 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
2142 uint32_t pdev_id, vdev_id;
2143 struct wlan_objmgr_pdev *pdev;
2144
2145 vdev_id = event->vdev_id;
2146 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, vdev_id, WLAN_TWT_ID);
2147 if (pdev_id == WLAN_INVALID_PDEV_ID) {
2148 twt_err("Invalid pdev id");
2149 return QDF_STATUS_E_INVAL;
2150 }
2151
2152 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_TWT_ID);
2153 if (!pdev) {
2154 twt_err("Invalid pdev");
2155 return QDF_STATUS_E_INVAL;
2156 }
2157
2158 opmode = wlan_get_opmode_from_vdev_id(pdev, vdev_id);
2159
2160 switch (opmode) {
2161 case QDF_SAP_MODE:
2162 qdf_status = mlme_twt_osif_resume_complete_ind(psoc, event);
2163 break;
2164 case QDF_STA_MODE:
2165 qdf_status = mlme_twt_osif_resume_complete_ind(psoc, event);
2166
2167 wlan_twt_set_session_state(psoc, &event->peer_macaddr,
2168 event->dialog_id,
2169 WLAN_TWT_SETUP_STATE_ACTIVE);
2170
2171 qdf_status = wlan_twt_set_command_in_progress(psoc,
2172 &event->peer_macaddr,
2173 event->dialog_id,
2174 WLAN_TWT_NONE);
2175 break;
2176 default:
2177 twt_debug("TWT Resume is not supported on %s",
2178 qdf_opmode_str(opmode));
2179 break;
2180 }
2181
2182 wlan_objmgr_pdev_release_ref(pdev, WLAN_TWT_ID);
2183 return qdf_status;
2184 }
2185
2186 QDF_STATUS
wlan_twt_nudge_complete_event_handler(struct wlan_objmgr_psoc * psoc,struct twt_nudge_dialog_complete_event_param * event)2187 wlan_twt_nudge_complete_event_handler(struct wlan_objmgr_psoc *psoc,
2188 struct twt_nudge_dialog_complete_event_param *event)
2189 {
2190 bool is_evt_allowed;
2191 enum HOST_TWT_NUDGE_STATUS status = event->status;
2192 enum QDF_OPMODE opmode;
2193 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
2194 enum wlan_twt_commands active_cmd = WLAN_TWT_NONE;
2195 uint32_t pdev_id, vdev_id;
2196 struct wlan_objmgr_pdev *pdev;
2197
2198 vdev_id = event->vdev_id;
2199 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, vdev_id, WLAN_TWT_ID);
2200 if (pdev_id == WLAN_INVALID_PDEV_ID) {
2201 twt_err("Invalid pdev id");
2202 return QDF_STATUS_E_INVAL;
2203 }
2204
2205 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_TWT_ID);
2206 if (!pdev) {
2207 twt_err("Invalid pdev");
2208 return QDF_STATUS_E_INVAL;
2209 }
2210
2211 opmode = wlan_get_opmode_from_vdev_id(pdev, vdev_id);
2212
2213 switch (opmode) {
2214 case QDF_SAP_MODE:
2215 qdf_status = mlme_twt_osif_nudge_complete_ind(psoc, event);
2216 break;
2217 case QDF_STA_MODE:
2218 is_evt_allowed = wlan_twt_is_command_in_progress(
2219 psoc,
2220 &event->peer_macaddr,
2221 event->dialog_id,
2222 WLAN_TWT_NUDGE, &active_cmd);
2223
2224 if (!is_evt_allowed &&
2225 event->dialog_id != TWT_ALL_SESSIONS_DIALOG_ID) {
2226 twt_debug("Drop TWT nudge dialog event for dialog_id:%d status:%d active_cmd:%d",
2227 event->dialog_id, status,
2228 active_cmd);
2229 qdf_status = QDF_STATUS_E_INVAL;
2230 goto fail;
2231 }
2232
2233 mlme_twt_osif_nudge_complete_ind(psoc, event);
2234 qdf_status = wlan_twt_set_command_in_progress(psoc,
2235 &event->peer_macaddr,
2236 event->dialog_id, WLAN_TWT_NONE);
2237 break;
2238 default:
2239 twt_debug("TWT nudge is not supported on %s",
2240 qdf_opmode_str(opmode));
2241 break;
2242 }
2243
2244 fail:
2245 wlan_objmgr_pdev_release_ref(pdev, WLAN_TWT_ID);
2246 return qdf_status;
2247 }
2248
2249 QDF_STATUS
wlan_twt_notify_event_handler(struct wlan_objmgr_psoc * psoc,struct twt_notify_event_param * event)2250 wlan_twt_notify_event_handler(struct wlan_objmgr_psoc *psoc,
2251 struct twt_notify_event_param *event)
2252 {
2253 QDF_STATUS status;
2254
2255 if (event->status == HOST_TWT_NOTIFY_EVENT_READY)
2256 status = wlan_twt_set_wait_for_notify(psoc, event->vdev_id,
2257 false);
2258 else
2259 status = wlan_twt_update_peer_twt_required_bit(psoc, event);
2260
2261 if (QDF_IS_STATUS_ERROR(status)) {
2262 twt_err("failed to get status");
2263 return status;
2264 }
2265
2266 mlme_twt_osif_notify_complete_ind(psoc, event);
2267
2268 return QDF_STATUS_SUCCESS;
2269 }
2270
wlan_twt_update_beacon_template(void)2271 QDF_STATUS wlan_twt_update_beacon_template(void)
2272 {
2273 struct scheduler_msg msg = { 0 };
2274 QDF_STATUS status;
2275
2276 msg.type = SIR_LIM_UPDATE_BEACON;
2277 status = scheduler_post_message(QDF_MODULE_ID_TWT, QDF_MODULE_ID_PE,
2278 QDF_MODULE_ID_PE, &msg);
2279 if (QDF_IS_STATUS_ERROR(status))
2280 twt_err("scheduler_post_message failed, status = %u", status);
2281
2282 return status;
2283 }
2284
wlan_twt_set_work_params(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * peer_mac,uint8_t dialog_id,bool is_ps_disabled,uint32_t twt_next_action)2285 void wlan_twt_set_work_params(
2286 struct wlan_objmgr_vdev *vdev,
2287 struct qdf_mac_addr *peer_mac,
2288 uint8_t dialog_id,
2289 bool is_ps_disabled,
2290 uint32_t twt_next_action)
2291 {
2292 struct twt_vdev_priv_obj *twt_vdev_priv;
2293
2294 twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(
2295 vdev, WLAN_UMAC_COMP_TWT);
2296
2297 if (!twt_vdev_priv) {
2298 twt_err("twt vdev private obj is null");
2299 return;
2300 }
2301
2302 qdf_copy_macaddr(&twt_vdev_priv->peer_macaddr, peer_mac);
2303 twt_vdev_priv->dialog_id = dialog_id;
2304 twt_vdev_priv->is_ps_disabled = is_ps_disabled;
2305 twt_vdev_priv->next_action = twt_next_action;
2306
2307 twt_debug("TWT terminate: dialog_id:%d is_ps_disabled:%d next_action:%d peer mac_addr "
2308 QDF_MAC_ADDR_FMT, twt_vdev_priv->dialog_id,
2309 twt_vdev_priv->is_ps_disabled,
2310 twt_vdev_priv->next_action,
2311 QDF_MAC_ADDR_REF(twt_vdev_priv->peer_macaddr.bytes));
2312 }
2313
wlan_twt_get_work_params(struct wlan_objmgr_vdev * vdev,struct twt_work_params * params,uint32_t * next_action)2314 void wlan_twt_get_work_params(struct wlan_objmgr_vdev *vdev,
2315 struct twt_work_params *params,
2316 uint32_t *next_action)
2317 {
2318 struct twt_vdev_priv_obj *twt_vdev_priv;
2319
2320 twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(
2321 vdev, WLAN_UMAC_COMP_TWT);
2322 if (!twt_vdev_priv) {
2323 twt_err("twt vdev private obj is null");
2324 return;
2325 }
2326
2327 qdf_copy_macaddr(¶ms->peer_macaddr, &twt_vdev_priv->peer_macaddr);
2328 params->dialog_id = twt_vdev_priv->dialog_id;
2329 params->is_ps_disabled = twt_vdev_priv->is_ps_disabled;
2330 *next_action = twt_vdev_priv->next_action;
2331 }
2332