/* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * DOC: define internal APIs related to the mlme TWT functionality */ #include "cfg_mlme_twt.h" #include "cfg_ucfg_api.h" #include "wlan_mlme_main.h" #include "wlan_psoc_mlme_api.h" #include "wlan_vdev_mlme_api.h" #include "wlan_mlme_api.h" #include "wlan_mlme_twt_api.h" bool mlme_is_max_twt_sessions_reached(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id) { struct peer_mlme_priv_obj *peer_priv; struct wlan_objmgr_peer *peer; uint8_t i; uint8_t num_twt_sessions = 0, max_twt_sessions; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return true; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err("peer mlme component object is NULL"); return true; } max_twt_sessions = peer_priv->twt_ctx.num_twt_sessions; for (i = 0; i < max_twt_sessions; i++) { uint8_t existing_session_dialog_id = peer_priv->twt_ctx.session_info[i].dialog_id; if (existing_session_dialog_id != TWT_ALL_SESSIONS_DIALOG_ID && existing_session_dialog_id != dialog_id) num_twt_sessions++; } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_debug("num_twt_sessions:%d max_twt_sessions:%d", num_twt_sessions, max_twt_sessions); return num_twt_sessions == max_twt_sessions; } bool mlme_is_twt_setup_in_progress(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id) { struct peer_mlme_priv_obj *peer_priv; struct wlan_objmgr_peer *peer; uint8_t existing_session_dialog_id; uint8_t i; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return false; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err("peer mlme component object is NULL"); return false; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { bool setup_done = peer_priv->twt_ctx.session_info[i].setup_done; existing_session_dialog_id = peer_priv->twt_ctx.session_info[i].dialog_id; if (existing_session_dialog_id == dialog_id && existing_session_dialog_id != TWT_ALL_SESSIONS_DIALOG_ID && !setup_done) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return true; } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return false; } void mlme_add_twt_session(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id) { struct peer_mlme_priv_obj *peer_priv; struct wlan_objmgr_peer *peer; uint8_t i; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err("peer mlme component object is NULL"); return; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { if (peer_priv->twt_ctx.session_info[i].dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { peer_priv->twt_ctx.session_info[i].dialog_id = dialog_id; break; } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); } void mlme_set_twt_setup_done(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id, bool is_set) { struct peer_mlme_priv_obj *peer_priv; struct wlan_objmgr_peer *peer; uint8_t i; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err(" peer mlme component object is NULL"); return; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id) { peer_priv->twt_ctx.session_info[i].setup_done = is_set; mlme_legacy_debug("setup done:%d dialog:%d", is_set, dialog_id); break; } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); } QDF_STATUS mlme_init_twt_context(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id) { struct peer_mlme_priv_obj *peer_priv; struct wlan_objmgr_peer *peer; uint8_t i; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_debug("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return QDF_STATUS_E_FAILURE; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_debug("peer mlme component object is NULL"); return QDF_STATUS_E_FAILURE; } peer_priv->twt_ctx.num_twt_sessions = WLAN_MAX_TWT_SESSIONS_PER_PEER; for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { peer_priv->twt_ctx.session_info[i].setup_done = false; peer_priv->twt_ctx.session_info[i].dialog_id = TWT_ALL_SESSIONS_DIALOG_ID; mlme_set_twt_command_in_progress( psoc, peer_mac, peer_priv->twt_ctx.session_info[i].dialog_id, WLAN_TWT_NONE); } } mlme_legacy_debug("init done"); wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return QDF_STATUS_SUCCESS; } QDF_STATUS mlme_init_all_peers_twt_context(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t dialog_id) { qdf_list_t *peer_list; struct wlan_objmgr_peer *peer, *peer_next; struct wlan_objmgr_vdev *vdev; struct peer_mlme_priv_obj *peer_priv; if (!psoc) { mlme_legacy_err("psoc is NULL, dialog_id: %d", dialog_id); return QDF_STATUS_E_NULL_VALUE; } vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_MLME_NB_ID); if (!vdev) { mlme_legacy_err("vdev is NULL, vdev_id: %d dialog_id: %d", vdev_id, dialog_id); return QDF_STATUS_E_NULL_VALUE; } peer_list = &vdev->vdev_objmgr.wlan_peer_list; if (!peer_list) { wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); mlme_legacy_err("Peer list for vdev obj is NULL"); return QDF_STATUS_E_NULL_VALUE; } peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list, WLAN_MLME_NB_ID); while (peer) { peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (peer_priv) { uint8_t i = 0; uint8_t num_twt_sessions = WLAN_MAX_TWT_SESSIONS_PER_PEER; peer_priv->twt_ctx.num_twt_sessions = num_twt_sessions; for (i = 0; i < num_twt_sessions; i++) { uint8_t existing_dialog_id = peer_priv->twt_ctx.session_info[i].dialog_id; if (existing_dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { peer_priv->twt_ctx.session_info[i].setup_done = false; peer_priv->twt_ctx.session_info[i].dialog_id = TWT_ALL_SESSIONS_DIALOG_ID; } } } peer_next = wlan_peer_get_next_active_peer_of_vdev(vdev, peer_list, peer, WLAN_MLME_NB_ID); wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); peer = peer_next; } wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); mlme_legacy_debug("init done"); return QDF_STATUS_SUCCESS; } bool mlme_is_twt_setup_done(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id) { struct peer_mlme_priv_obj *peer_priv; struct wlan_objmgr_peer *peer; bool is_setup_done = false; uint8_t i; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return false; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err("peer mlme component object is NULL"); return false; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { is_setup_done = peer_priv->twt_ctx.session_info[i].setup_done; if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID || is_setup_done) break; } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return is_setup_done; } void mlme_twt_set_wait_for_notify(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id, bool is_set) { struct wlan_objmgr_vdev *vdev; struct mlme_legacy_priv *mlme_priv; vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_MLME_NB_ID); if (!vdev) { mlme_legacy_err("vdev object not found"); return; } mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); if (!mlme_priv) { wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); mlme_legacy_err("vdev legacy private object is NULL"); return; } mlme_priv->twt_wait_for_notify = is_set; wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); } void mlme_set_twt_session_state(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id, enum wlan_twt_session_state state) { struct wlan_objmgr_peer *peer; struct peer_mlme_priv_obj *peer_priv; uint8_t i; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_err(" peer mlme component object is NULL"); return; } mlme_debug("set_state:%d for dialog_id:%d", state, dialog_id); for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { peer_priv->twt_ctx.session_info[i].state = state; break; } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); } enum wlan_twt_session_state mlme_get_twt_session_state(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id) { struct wlan_objmgr_peer *peer; struct peer_mlme_priv_obj *peer_priv; uint8_t i; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err(" peer mlme object is NULL"); return WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id && dialog_id != TWT_ALL_SESSIONS_DIALOG_ID) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return peer_priv->twt_ctx.session_info[i].state; } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED; } uint8_t mlme_get_twt_peer_capabilities(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac) { struct peer_mlme_priv_obj *peer_priv; struct wlan_objmgr_peer *peer; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return false; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); if (!peer_priv) { mlme_legacy_err("peer mlme object is NULL"); return 0; } return peer_priv->twt_ctx.peer_capability; } void mlme_set_twt_peer_capabilities(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t caps) { struct wlan_objmgr_peer *peer; struct peer_mlme_priv_obj *peer_priv; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_debug("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_debug("peer mlme object is NULL"); return; } peer_priv->twt_ctx.peer_capability = caps; wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); } bool mlme_is_twt_enabled(struct wlan_objmgr_psoc *psoc) { struct wlan_mlme_psoc_ext_obj *mlme_obj; mlme_obj = mlme_get_psoc_ext_obj(psoc); if (!mlme_obj) return cfg_default(CFG_ENABLE_TWT); return mlme_obj->cfg.twt_cfg.is_twt_enabled; } #if defined(WLAN_FEATURE_11AX) && defined(WLAN_SUPPORT_TWT) bool mlme_is_flexible_twt_enabled(struct wlan_objmgr_psoc *psoc) { struct wlan_mlme_psoc_ext_obj *mlme_obj; mlme_obj = mlme_get_psoc_ext_obj(psoc); if (!mlme_obj) return false; return mlme_obj->cfg.he_caps.dot11_he_cap.flex_twt_sched; } #endif QDF_STATUS mlme_sap_set_twt_all_peers_cmd_in_progress(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t dialog_id, enum wlan_twt_commands cmd) { qdf_list_t *peer_list; struct wlan_objmgr_peer *peer, *peer_next; struct wlan_objmgr_vdev *vdev; struct peer_mlme_priv_obj *peer_priv; if (!psoc) { mlme_legacy_err("psoc is NULL, dialog_id: %d", dialog_id); return QDF_STATUS_E_NULL_VALUE; } vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_MLME_NB_ID); if (!vdev) { mlme_legacy_err("vdev is NULL, vdev_id: %d dialog_id: %d", vdev_id, dialog_id); return QDF_STATUS_E_NULL_VALUE; } peer_list = &vdev->vdev_objmgr.wlan_peer_list; if (!peer_list) { wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); mlme_legacy_err("Peer list for vdev obj is NULL"); return QDF_STATUS_E_NULL_VALUE; } peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list, WLAN_MLME_NB_ID); while (peer) { peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (peer_priv) { uint8_t i = 0; uint8_t num_twt_sessions = peer_priv->twt_ctx.num_twt_sessions; for (i = 0; i < num_twt_sessions; i++) { uint8_t existing_dialog_id = peer_priv->twt_ctx.session_info[i].dialog_id; if (existing_dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { peer_priv->twt_ctx.session_info[i].active_cmd = cmd; if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID) { break; } } } } peer_next = wlan_peer_get_next_active_peer_of_vdev(vdev, peer_list, peer, WLAN_MLME_NB_ID); wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); peer = peer_next; } wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); return QDF_STATUS_SUCCESS; } bool mlme_twt_any_peer_cmd_in_progress(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t dialog_id, enum wlan_twt_commands cmd) { qdf_list_t *peer_list; struct wlan_objmgr_peer *peer, *peer_next; struct wlan_objmgr_vdev *vdev; struct peer_mlme_priv_obj *peer_priv; bool cmd_in_progress = false; if (!psoc) { mlme_legacy_err("psoc is NULL, dialog_id: %d", dialog_id); return false; } vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_MLME_NB_ID); if (!vdev) { mlme_legacy_err("vdev is NULL, vdev_id: %d dialog_id: %d", vdev_id, dialog_id); return false; } peer_list = &vdev->vdev_objmgr.wlan_peer_list; if (!peer_list) { wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); mlme_legacy_err("Peer list for vdev obj is NULL"); return false; } peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list, WLAN_MLME_NB_ID); while (peer) { peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (peer_priv) { uint8_t i = 0; uint8_t num_twt_sessions = peer_priv->twt_ctx.num_twt_sessions; for (i = 0; i < num_twt_sessions; i++) { enum wlan_twt_commands active_cmd; uint8_t existing_dialog_id; active_cmd = peer_priv->twt_ctx.session_info[i].active_cmd; existing_dialog_id = peer_priv->twt_ctx.session_info[i].dialog_id; if (existing_dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { cmd_in_progress = (active_cmd == cmd); if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID || cmd_in_progress) { wlan_objmgr_peer_release_ref( peer, WLAN_MLME_NB_ID); wlan_objmgr_vdev_release_ref( vdev, WLAN_MLME_NB_ID); return cmd_in_progress; } } } } peer_next = wlan_peer_get_next_active_peer_of_vdev(vdev, peer_list, peer, WLAN_MLME_NB_ID); wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); peer = peer_next; } wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); return cmd_in_progress; } bool mlme_sap_twt_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) { struct wlan_objmgr_peer *peer; struct peer_mlme_priv_obj *peer_priv; uint8_t i = 0; bool cmd_in_progress = false; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return false; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err(" peer mlme component object is NULL"); return false; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { enum wlan_twt_commands active_cmd; uint8_t existing_dialog_id; active_cmd = peer_priv->twt_ctx.session_info[i].active_cmd; existing_dialog_id = peer_priv->twt_ctx.session_info[i].dialog_id; if (existing_dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID || existing_dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { cmd_in_progress = (active_cmd == cmd); if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID || cmd_in_progress) { break; } } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return cmd_in_progress; } QDF_STATUS mlme_set_twt_command_in_progress(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id, enum wlan_twt_commands cmd) { struct wlan_objmgr_peer *peer; struct peer_mlme_priv_obj *peer_priv; uint8_t i = 0; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return QDF_STATUS_E_FAILURE; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err(" peer mlme component object is NULL"); return QDF_STATUS_E_FAILURE; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { peer_priv->twt_ctx.session_info[i].active_cmd = cmd; if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID) break; } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return QDF_STATUS_SUCCESS; } bool mlme_is_twt_notify_in_progress(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id) { struct wlan_objmgr_vdev *vdev; struct mlme_legacy_priv *mlme_priv; bool is_twt_notify_in_progress; vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_MLME_NB_ID); if (!vdev) { mlme_legacy_err("vdev object not found"); return false; } mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); if (!mlme_priv) { wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); mlme_legacy_err("vdev legacy private object is NULL"); return false; } is_twt_notify_in_progress = mlme_priv->twt_wait_for_notify; wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); return is_twt_notify_in_progress; } bool mlme_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) { struct wlan_objmgr_peer *peer; struct peer_mlme_priv_obj *peer_priv; enum wlan_twt_commands active_cmd; uint8_t i = 0; bool is_command_in_progress = false; peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, WLAN_MLME_NB_ID); if (!peer) { mlme_legacy_err("Peer object not found "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(peer_mac->bytes)); return false; } peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); mlme_legacy_err(" peer mlme component object is NULL"); return false; } for (i = 0; i < peer_priv->twt_ctx.num_twt_sessions; i++) { active_cmd = peer_priv->twt_ctx.session_info[i].active_cmd; if (pactive_cmd) *pactive_cmd = active_cmd; if (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id || dialog_id == TWT_ALL_SESSIONS_DIALOG_ID) { if (cmd == WLAN_TWT_ANY) { is_command_in_progress = (active_cmd != WLAN_TWT_NONE); if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID || is_command_in_progress) break; } else { is_command_in_progress = (active_cmd == cmd); if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID || is_command_in_progress) break; } } } wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); return is_command_in_progress; } bool mlme_is_24ghz_twt_enabled(struct wlan_objmgr_psoc *psoc) { struct wlan_mlme_psoc_ext_obj *mlme_obj; mlme_obj = mlme_get_psoc_ext_obj(psoc); if (!mlme_obj) return cfg_default(CFG_ENABLE_TWT_24GHZ); return mlme_obj->cfg.twt_cfg.enable_twt_24ghz; } #if defined(WLAN_SUPPORT_TWT) && defined(WLAN_TWT_CONV_SUPPORTED) bool mlme_is_twt_disable_info_frame(struct wlan_objmgr_psoc *psoc) { struct wlan_mlme_psoc_ext_obj *mlme_obj; mlme_obj = mlme_get_psoc_ext_obj(psoc); if (!mlme_obj) return cfg_default(CFG_DISABLE_TWT_INFO_FRAME); return mlme_obj->cfg.twt_cfg.disable_twt_info_frame; } #endif