diff --git a/components/mlme/core/inc/wlan_mlme_twt_api.h b/components/mlme/core/inc/wlan_mlme_twt_api.h index d56234221b17..f0b5faacee83 100644 --- a/components/mlme/core/inc/wlan_mlme_twt_api.h +++ b/components/mlme/core/inc/wlan_mlme_twt_api.h @@ -178,6 +178,34 @@ bool mlme_is_flexible_twt_enabled(struct wlan_objmgr_psoc *psoc); * Return: True if tgt cap is advertised. */ bool mlme_get_twt_bcast_requestor_tgt_cap(struct wlan_objmgr_psoc *psoc); + +/** + * mlme_set_twt_command_in_progress() - Set TWT command is in progress. + * @psoc: Pointer to psoc object + * @peer_mac: Pointer to peer mac address + * @dialog_id: Dialog id + * @cmd: TWT command + * + * Return: QDF_STATUS + */ +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); + +/** + * mlme_twt_is_command_in_progress() - Get TWT command in progress. + * @psoc: Pointer to psoc object + * @peer_mac: Pointer to peer mac address + * @dialog_id: Dialog id + * @cmd: TWT command + * + * Return: True if given command is 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); #else static inline void mlme_set_twt_peer_capabilities(struct wlan_objmgr_psoc *psoc, diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index ea62ca9ed220..151e87350341 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -66,8 +66,8 @@ uint32_t mlme_get_vdev_he_ops(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev); if (!mlme_obj) { - mlme_legacy_err("Failed to get vdev MLME Obj"); wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); + mlme_legacy_err("Failed to get vdev MLME Obj"); return he_ops; } diff --git a/components/mlme/core/src/wlan_mlme_twt_api.c b/components/mlme/core/src/wlan_mlme_twt_api.c index c07f382cbe31..a184dded570c 100644 --- a/components/mlme/core/src/wlan_mlme_twt_api.c +++ b/components/mlme/core/src/wlan_mlme_twt_api.c @@ -45,8 +45,8 @@ bool mlme_is_twt_setup_in_progress(struct wlan_objmgr_psoc *psoc, peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_MLME); if (!peer_priv) { - mlme_legacy_err("peer mlme component object is NULL"); wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); + mlme_legacy_err("peer mlme component object is NULL"); return false; } @@ -164,6 +164,10 @@ QDF_STATUS mlme_init_twt_context(struct wlan_objmgr_psoc *psoc, peer_priv->twt_ctx.session_info[i].setup_done = false; peer_priv->twt_ctx.session_info[i].dialog_id = WLAN_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); } } @@ -411,3 +415,86 @@ bool mlme_get_twt_bcast_requestor_tgt_cap(struct wlan_objmgr_psoc *psoc) return mlme_obj->cfg.twt_cfg.bcast_requestor_tgt_cap; } + +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"); + 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 == WLAN_ALL_SESSIONS_DIALOG_ID) { + peer_priv->twt_ctx.session_info[i].active_cmd = cmd; + if (dialog_id != WLAN_ALL_SESSIONS_DIALOG_ID) + break; + } + } + + wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); + + return QDF_STATUS_SUCCESS; +} + +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) +{ + 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"); + 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 (peer_priv->twt_ctx.session_info[i].dialog_id == dialog_id) { + if (cmd == WLAN_TWT_ANY) { + is_command_in_progress = + (active_cmd != WLAN_TWT_NONE); + break; + } else { + is_command_in_progress = (active_cmd == cmd); + break; + } + } + } + + wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID); + + return is_command_in_progress; +} diff --git a/components/mlme/dispatcher/inc/wlan_mlme_twt_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_twt_public_struct.h index 30a4279b3ab7..4acd371498c8 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_twt_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_twt_public_struct.h @@ -21,6 +21,26 @@ #ifndef _WLAN_MLME_TWT_STRUCT_H_ #define _WLAN_MLME_TWT_STRUCT_H_ +/** + * enum wlan_twt_commands - TWT commands + * @WLAN_TWT_NONE: Indicates none of the TWT commands are active. + * @WLAN_TWT_SETUP: TWT setup + * @WLAN_TWT_TERMINATE: TWT terminate + * @WLAN_TWT_SUSPEND: TWT suspend + * @WLAN_TWT_RESUME: TWT resume + * @WLAN_TWT_NUDGE: TWT nudge + * @WLAN_TWT_ANY: Indicates one of the commands is in progress. + */ +enum wlan_twt_commands { + WLAN_TWT_NONE = 0, + WLAN_TWT_SETUP = BIT(0), + WLAN_TWT_TERMINATE = BIT(1), + WLAN_TWT_SUSPEND = BIT(2), + WLAN_TWT_RESUME = BIT(3), + WLAN_TWT_NUDGE = BIT(4), + WLAN_TWT_ANY = 0xFF, +}; + /** * enum wlan_twt_capabilities - Represents the Bitmap of TWT capabilities * supported by device and peer. @@ -64,11 +84,14 @@ enum wlan_twt_session_state { * @dialog_id: TWT session dialog id * @state: TWT session state * @setup_done: TWT session setup is complete + * @active_cmd: bitmap to indicate which command is + * in progress. Bits are provided by enum wlan_twt_commands. */ struct twt_session_info { uint8_t dialog_id; uint8_t state; bool setup_done; + enum wlan_twt_commands active_cmd; }; /** diff --git a/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h index 5ff136a86027..b63bac3517e5 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h @@ -223,22 +223,6 @@ QDF_STATUS ucfg_mlme_set_twt_bcast_responder_tgt_cap(struct wlan_objmgr_psoc *psoc, bool val); -/** - * ucfg_mlme_add_twt_session() - Add the entry for the given dialog id in TWT - * context once TWT setup command is received - * @psoc: pointer to psoc object - * @peer_mac: Pointer to peer mac - * @dialog_id: TWT session dialog id - * - * Return: None - */ -static inline -void ucfg_mlme_add_twt_session(struct wlan_objmgr_psoc *psoc, - struct qdf_mac_addr *peer_mac, uint8_t dialog_id) -{ - mlme_add_twt_session(psoc, peer_mac, dialog_id); -} - /** * ucfg_mlme_is_twt_setup_in_progress() - Get TWT setup in progress for * given dialog id @@ -404,11 +388,6 @@ ucfg_mlme_set_enable_twt(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_NOSUPPORT; } -static inline -void ucfg_mlme_add_twt_session(struct wlan_objmgr_psoc *psoc, - struct qdf_mac_addr *peer_mac, uint8_t dialog_id) -{} - static inline bool ucfg_mlme_is_twt_setup_done(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id) diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index f0b0f7148ca9..dbe56b62fd96 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -1286,14 +1286,6 @@ static int hdd_twt_setup_session(struct hdd_adapter *adapter, if (ret < 0) return ret; - /* - * Add the dialog id to TWT context to drop back to back - * commands - */ - ucfg_mlme_add_twt_session(adapter->hdd_ctx->psoc, - &hdd_sta_ctx->conn_info.bssid, - params.dialog_id); - return ret; } diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 8e78f243cb2b..e4aedd988fbd 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -67,6 +67,9 @@ #include "mac_init_api.h" #include "wlan_cm_roam_api.h" #include "wlan_cm_tgt_if_tx_api.h" +#include "wlan_mlme_twt_public_struct.h" +#include "wlan_mlme_twt_api.h" +#include "parser_api.h" static QDF_STATUS init_sme_cmd_list(struct mac_context *mac); @@ -2062,10 +2065,24 @@ sme_process_twt_add_dialog_event(struct mac_context *mac, struct twt_add_dialog_complete_event *add_dialog_event) { twt_add_dialog_cb callback; + bool is_evt_allowed; + + is_evt_allowed = mlme_twt_is_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)add_dialog_event->params.peer_macaddr, + add_dialog_event->params.dialog_id, WLAN_TWT_SETUP); + if (!is_evt_allowed) + return; callback = mac->sme.twt_add_dialog_cb; if (callback) callback(mac->psoc, add_dialog_event); + + /* Reset the active TWT command to none */ + mlme_set_twt_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)add_dialog_event->params.peer_macaddr, + add_dialog_event->params.dialog_id, WLAN_TWT_NONE); } /** @@ -2081,10 +2098,30 @@ sme_process_twt_del_dialog_event(struct mac_context *mac, struct wmi_twt_del_dialog_complete_event_param *param) { twt_del_dialog_cb callback; + bool is_evt_allowed; + + is_evt_allowed = mlme_twt_is_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_TERMINATE); + if (!is_evt_allowed && + (param->status != WMI_HOST_DEL_TWT_STATUS_ROAMING || + param->status != WMI_HOST_DEL_TWT_STATUS_PEER_INIT_TEARDOWN)) + return; callback = mac->sme.twt_del_dialog_cb; if (callback) callback(mac->psoc, param); + + if (param->status == WMI_HOST_DEL_TWT_STATUS_ROAMING || + param->status == WMI_HOST_DEL_TWT_STATUS_PEER_INIT_TEARDOWN) + mlme_twt_set_wait_for_notify( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + true); + + /* Reset the active TWT command to none */ + mlme_set_twt_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_NONE); } /** @@ -2100,10 +2137,22 @@ sme_process_twt_pause_dialog_event(struct mac_context *mac, struct wmi_twt_pause_dialog_complete_event_param *param) { twt_pause_dialog_cb callback; + bool is_evt_allowed; + + is_evt_allowed = mlme_twt_is_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_SUSPEND); + if (!is_evt_allowed) + return; callback = mac->sme.twt_pause_dialog_cb; if (callback) callback(mac->psoc, param); + + /* Reset the active TWT command to none */ + mlme_set_twt_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_NONE); } /** @@ -2120,12 +2169,24 @@ sme_process_twt_nudge_dialog_event(struct mac_context *mac, { twt_nudge_dialog_cb callback; void *context; + bool is_evt_allowed; + + is_evt_allowed = mlme_twt_is_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_NUDGE); + if (!is_evt_allowed) + return; callback = mac->sme.twt_nudge_dialog_cb; context = mac->sme.twt_nudge_dialog_context; mac->sme.twt_nudge_dialog_cb = NULL; if (callback) callback(context, param); + + /* Reset the active TWT command to none */ + mlme_set_twt_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_NONE); } /** @@ -2141,13 +2202,24 @@ sme_process_twt_resume_dialog_event(struct mac_context *mac, struct wmi_twt_resume_dialog_complete_event_param *param) { twt_resume_dialog_cb callback; + bool is_evt_allowed; + + is_evt_allowed = mlme_twt_is_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_RESUME); + if (!is_evt_allowed) + return; callback = mac->sme.twt_resume_dialog_cb; if (callback) callback(mac->psoc, param); + + /* Reset the active TWT command to none */ + mlme_set_twt_command_in_progress( + mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, + param->dialog_id, WLAN_TWT_NONE); } #else - static void sme_process_twt_add_dialog_event(struct mac_context *mac, struct twt_add_dialog_complete_event *add_dialog_event) @@ -14529,11 +14601,22 @@ QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle, { struct mac_context *mac = MAC_CONTEXT(mac_handle); struct scheduler_msg twt_msg = {0}; + bool is_twt_cmd_in_progress; QDF_STATUS status; void *wma_handle; struct wmi_twt_add_dialog_param *cmd_params; SME_ENTER(); + + is_twt_cmd_in_progress = mlme_twt_is_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_ANY); + if (is_twt_cmd_in_progress) { + sme_debug("Already TWT command is in progress"); + return QDF_STATUS_E_AGAIN; + } + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); if (!wma_handle) { sme_err("wma_handle is NULL"); @@ -14568,6 +14651,20 @@ QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle, QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, FL("Post twt add dialog msg fail")); qdf_mem_free(cmd_params); + } else { + /* + * Add the dialog id to TWT context to drop back to back + * commands + */ + mlme_add_twt_session( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id); + + mlme_set_twt_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_SETUP); } SME_EXIT(); @@ -14580,11 +14677,27 @@ QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle, { struct mac_context *mac = MAC_CONTEXT(mac_handle); struct scheduler_msg twt_msg = {0}; + bool is_twt_cmd_in_progress; QDF_STATUS status; void *wma_handle; struct wmi_twt_del_dialog_param *cmd_params; SME_ENTER(); + + is_twt_cmd_in_progress = + mlme_twt_is_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_SETUP) || + mlme_twt_is_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_TERMINATE); + if (is_twt_cmd_in_progress) { + sme_debug("Already TWT command is in progress"); + return QDF_STATUS_E_AGAIN; + } + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); if (!wma_handle) { sme_err("wma_handle is NULL"); @@ -14619,6 +14732,11 @@ QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle, QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, FL("Post twt del dialog msg fail")); qdf_mem_free(cmd_params); + } else { + mlme_set_twt_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_TERMINATE); } SME_EXIT(); @@ -14632,10 +14750,21 @@ sme_pause_dialog_cmd(mac_handle_t mac_handle, struct mac_context *mac = MAC_CONTEXT(mac_handle); struct wmi_twt_pause_dialog_cmd_param *cmd_params; struct scheduler_msg twt_msg = {0}; + bool is_twt_cmd_in_progress; QDF_STATUS status; void *wma_handle; SME_ENTER(); + + is_twt_cmd_in_progress = mlme_twt_is_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_ANY); + if (is_twt_cmd_in_progress) { + sme_debug("Already TWT command is in progress"); + return QDF_STATUS_E_AGAIN; + } + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); if (!wma_handle) { sme_err("wma_handle is NULL"); @@ -14669,6 +14798,11 @@ sme_pause_dialog_cmd(mac_handle_t mac_handle, QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, FL("Post twt pause dialog msg fail")); qdf_mem_free(cmd_params); + } else { + mlme_set_twt_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_SUSPEND); } SME_EXIT(); @@ -14684,10 +14818,20 @@ sme_nudge_dialog_cmd(mac_handle_t mac_handle, struct mac_context *mac = MAC_CONTEXT(mac_handle); struct wmi_twt_nudge_dialog_cmd_param *cmd_params; struct scheduler_msg twt_msg = {0}; + bool is_twt_cmd_in_progress; QDF_STATUS status; void *wma_handle; SME_ENTER(); + + is_twt_cmd_in_progress = mlme_twt_is_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_ANY); + if (is_twt_cmd_in_progress) { + sme_debug("Already TWT command is in progress"); + return QDF_STATUS_E_AGAIN; + } wma_handle = cds_get_context(QDF_MODULE_ID_WMA); if (!wma_handle) { sme_err("wma_handle is NULL"); @@ -14730,6 +14874,11 @@ sme_nudge_dialog_cmd(mac_handle_t mac_handle, QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, FL("Post twt nudge dialog msg fail")); qdf_mem_free(cmd_params); + } else { + mlme_set_twt_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_NUDGE); } SME_EXIT(); @@ -14743,10 +14892,21 @@ sme_resume_dialog_cmd(mac_handle_t mac_handle, struct mac_context *mac = MAC_CONTEXT(mac_handle); struct wmi_twt_resume_dialog_cmd_param *cmd_params; struct scheduler_msg twt_msg = {0}; + bool is_twt_cmd_in_progress; QDF_STATUS status; void *wma_handle; SME_ENTER(); + + is_twt_cmd_in_progress = mlme_twt_is_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_ANY); + if (is_twt_cmd_in_progress) { + sme_debug("Already TWT command is in progress"); + return QDF_STATUS_E_AGAIN; + } + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); if (!wma_handle) { sme_err("wma_handle is NULL"); @@ -14775,11 +14935,14 @@ sme_resume_dialog_cmd(mac_handle_t mac_handle, status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_WMA, QDF_MODULE_ID_WMA, &twt_msg); - if (QDF_IS_STATUS_ERROR(status)) { - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - FL("Post twt resume dialog msg fail")); + sme_err("Post twt resume dialog msg fail"); qdf_mem_free(cmd_params); + } else { + mlme_set_twt_command_in_progress( + mac->psoc, + (struct qdf_mac_addr *)twt_params->peer_macaddr, + twt_params->dialog_id, WLAN_TWT_RESUME); } SME_EXIT();