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(&params->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