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 b825e9f53f43..8f28d643c880 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_twt_ucfg_api.h @@ -219,6 +219,21 @@ QDF_STATUS ucfg_mlme_set_twt_requestor_flag(struct wlan_objmgr_psoc *psoc, QDF_STATUS ucfg_mlme_set_twt_responder_flag(struct wlan_objmgr_psoc *psoc, bool val); +/** + * ucfg_mlme_reset_twt_init_context() - Reset twt init if ack fail + * This is to handle back to back command. If ack failed for previous + * command and again new commad comes then init context should reset to + * allow new command. + * @psoc: pointer to psoc object + * @peer_mac: peer mac address + * @dialog_id: dialog id + * + * Return: QDF Status + */ +QDF_STATUS ucfg_mlme_reset_twt_init_context(struct wlan_objmgr_psoc *psoc, + struct qdf_mac_addr *peer_mac, + uint8_t dialog_id); + /** * ucfg_mlme_is_twt_setup_in_progress() - Get TWT setup in progress for * given dialog id @@ -624,6 +639,14 @@ ucfg_mlme_set_twt_responder_flag(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_NOSUPPORT; } +static inline QDF_STATUS +ucfg_mlme_reset_twt_init_context(struct wlan_objmgr_psoc *psoc, + struct qdf_mac_addr *peer_mac, + uint8_t dialog_id) +{ + return QDF_STATUS_E_NOSUPPORT; +} + static inline bool ucfg_mlme_is_flexible_twt_enabled(struct wlan_objmgr_psoc *psoc) { diff --git a/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c b/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c index c9cdb29aec8b..57f6b9785a35 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_twt_ucfg_api.c @@ -117,6 +117,18 @@ ucfg_mlme_set_twt_responder_flag(struct wlan_objmgr_psoc *psoc, bool val) return QDF_STATUS_SUCCESS; } +QDF_STATUS +ucfg_mlme_reset_twt_init_context(struct wlan_objmgr_psoc *psoc, + struct qdf_mac_addr *peer_macaddr, + uint8_t dialog_id) +{ + mlme_set_twt_command_in_progress(psoc, peer_macaddr, dialog_id, + WLAN_TWT_NONE); + mlme_init_twt_context(psoc, peer_macaddr, dialog_id); + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS ucfg_mlme_get_twt_congestion_timeout(struct wlan_objmgr_psoc *psoc, uint32_t *val) diff --git a/core/hdd/inc/wlan_hdd_twt.h b/core/hdd/inc/wlan_hdd_twt.h index 857a87dd399f..f1035e8589b5 100644 --- a/core/hdd/inc/wlan_hdd_twt.h +++ b/core/hdd/inc/wlan_hdd_twt.h @@ -110,6 +110,22 @@ struct twt_conc_arg { struct hdd_context *hdd_ctx; }; +/** + * twt_ack_info_priv - twt ack private info + * @vdev_id: vdev id + * @peer_macaddr: peer mac address + * @dialog_id: dialog id + * @twt_cmd_ack: twt ack command + * @status: twt command status + */ +struct twt_ack_info_priv { + uint32_t vdev_id; + struct qdf_mac_addr peer_macaddr; + uint32_t dialog_id; + uint32_t twt_cmd_ack; + uint32_t status; +}; + /** * wlan_hdd_cfg80211_wifi_twt_config() - Wifi twt configuration * vendor command diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index 2b050eb2f24f..081388bd2490 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -41,6 +41,7 @@ #define TWT_DISABLE_COMPLETE_TIMEOUT 1000 #define TWT_ENABLE_COMPLETE_TIMEOUT 1000 +#define TWT_ACK_COMPLETE_TIMEOUT 1000 #define TWT_FLOW_TYPE_ANNOUNCED 0 #define TWT_FLOW_TYPE_UNANNOUNCED 1 @@ -1516,6 +1517,93 @@ hdd_twt_handle_renego_failure(struct hdd_adapter *adapter, hdd_send_twt_del_dialog_cmd(adapter->hdd_ctx, ¶ms); } +/** + * hdd_twt_ack_comp_cb() - TWT ack complete event callback + * @params: TWT parameters + * @context: Context + * + * Return: None + */ +static void +hdd_twt_ack_comp_cb(struct wmi_twt_ack_complete_event_param *params, + void *context) +{ + struct osif_request *request = NULL; + struct twt_ack_info_priv *status_priv; + + request = osif_request_get(context); + if (!request) { + hdd_err("obsolete request"); + return; + } + + status_priv = osif_request_priv(request); + if (!status_priv) { + hdd_err("obsolete status_priv"); + return; + } + + if (status_priv->twt_cmd_ack == params->twt_cmd_ack) { + status_priv->vdev_id = params->vdev_id; + qdf_copy_macaddr(&status_priv->peer_macaddr, + ¶ms->peer_macaddr); + status_priv->dialog_id = params->dialog_id; + status_priv->status = params->status; + osif_request_complete(request); + } else { + hdd_err("Invalid ack for twt command"); + } + + osif_request_put(request); +} + +/** + * hdd_twt_ack_wait_response: TWT wait for ack event if it's supported + * @hdd_ctx: HDD context + * @request: OSIF request cookie + * @twt_cmd: TWT command for which ack event come + * + * Return: None + */ +static QDF_STATUS +hdd_twt_ack_wait_response(struct hdd_context *hdd_ctx, + struct osif_request *request, int twt_cmd) +{ + struct target_psoc_info *tgt_hdl; + struct twt_ack_info_priv *ack_priv; + int ret = 0; + bool twt_ack_cap; + + tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc); + if (!tgt_hdl) { + hdd_err("tgt_hdl is NULL"); + return QDF_STATUS_E_FAILURE; + } + target_psoc_get_twt_ack_cap(tgt_hdl, &twt_ack_cap); + + if (!twt_ack_cap) { + hdd_err("TWT ack bit is not supported. No need to wait"); + return QDF_STATUS_SUCCESS; + } + + ack_priv = osif_request_priv(request); + ack_priv->twt_cmd_ack = twt_cmd; + + ret = osif_request_wait_for_response(request); + if (ret) { + hdd_err("TWT setup response timed out"); + return QDF_STATUS_E_FAILURE; + } + + ack_priv = osif_request_priv(request); + hdd_debug("TWT ack info: vdev_id %d dialog_id %d twt_cmd %d status %d peer_macaddr " + QDF_MAC_ADDR_FMT, ack_priv->vdev_id, ack_priv->dialog_id, + ack_priv->twt_cmd_ack, ack_priv->status, + QDF_MAC_ADDR_REF(ack_priv->peer_macaddr.bytes)); + + return QDF_STATUS_SUCCESS; +} + /** * hdd_twt_add_dialog_comp_cb() - HDD callback for twt add dialog * complete event @@ -1561,26 +1649,48 @@ static int hdd_send_twt_add_dialog_cmd(struct hdd_context *hdd_ctx, struct wmi_twt_add_dialog_param *twt_params) { - struct target_psoc_info *tgt_hdl; QDF_STATUS status; - int ret; - bool twt_ack_cap; + int ret = 0, twt_cmd; + struct osif_request *request; + struct twt_ack_info_priv *ack_priv; + void *context; + static const struct osif_request_params params = { + .priv_size = sizeof(*ack_priv), + .timeout_ms = TWT_ACK_COMPLETE_TIMEOUT, + }; - status = sme_add_dialog_cmd(hdd_ctx->mac_handle, - hdd_twt_add_dialog_comp_cb, - twt_params); - if (!QDF_IS_STATUS_SUCCESS(status)) - hdd_err("Failed to send add dialog command"); + hdd_enter(); - tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc); - if (!tgt_hdl) { - hdd_err("tgt_hdl is NULL"); + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); return -EINVAL; } - target_psoc_get_twt_ack_cap(tgt_hdl, &twt_ack_cap); + context = osif_request_cookie(request); + + status = sme_add_dialog_cmd(hdd_ctx->mac_handle, + hdd_twt_add_dialog_comp_cb, + twt_params, context); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to send add dialog command"); + ret = qdf_status_to_os_return(status); + goto cleanup; + } + + twt_cmd = WMI_HOST_TWT_ADD_DIALOG_CMDID; + + status = hdd_twt_ack_wait_response(hdd_ctx, request, twt_cmd); + + if (QDF_IS_STATUS_ERROR(status)) { + ret = qdf_status_to_os_return(status); + goto cleanup; + } ret = qdf_status_to_os_return(status); +cleanup: + osif_request_put(request); + hdd_exit(); return ret; } @@ -1892,27 +2002,49 @@ static int hdd_send_twt_del_dialog_cmd(struct hdd_context *hdd_ctx, struct wmi_twt_del_dialog_param *twt_params) { - struct target_psoc_info *tgt_hdl; QDF_STATUS status; - int ret = 0; - bool twt_ack_cap; + int ret = 0, twt_cmd; + struct osif_request *request; + struct twt_ack_info_priv *ack_priv; + void *context; + static const struct osif_request_params params = { + .priv_size = sizeof(*ack_priv), + .timeout_ms = TWT_ACK_COMPLETE_TIMEOUT, + }; + + hdd_enter(); + + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); + return -EINVAL; + } + + context = osif_request_cookie(request); status = sme_del_dialog_cmd(hdd_ctx->mac_handle, hdd_twt_del_dialog_comp_cb, - twt_params); + twt_params, context); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("Failed to send del dialog command"); ret = qdf_status_to_os_return(status); + goto cleanup; } - tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc); - if (!tgt_hdl) { - hdd_err("tgt_hdl is NULL"); - return -EINVAL; + twt_cmd = WMI_HOST_TWT_DEL_DIALOG_CMDID; + + status = hdd_twt_ack_wait_response(hdd_ctx, request, twt_cmd); + + if (QDF_IS_STATUS_ERROR(status)) { + ret = qdf_status_to_os_return(status); + goto cleanup; } - target_psoc_get_twt_ack_cap(tgt_hdl, &twt_ack_cap); + ret = qdf_status_to_os_return(status); +cleanup: + osif_request_put(request); + hdd_exit(); return ret; } @@ -2375,25 +2507,47 @@ static int hdd_send_twt_pause_dialog_cmd(struct hdd_context *hdd_ctx, struct wmi_twt_pause_dialog_cmd_param *twt_params) { - struct target_psoc_info *tgt_hdl; QDF_STATUS status; - int ret = 0; - bool twt_ack_cap; + int ret = 0, twt_cmd; + struct osif_request *request; + struct twt_ack_info_priv *ack_priv; + void *context; + static const struct osif_request_params params = { + .priv_size = sizeof(*ack_priv), + .timeout_ms = TWT_ACK_COMPLETE_TIMEOUT, + }; - status = sme_pause_dialog_cmd(hdd_ctx->mac_handle, - twt_params); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Failed to send pause dialog command"); - ret = qdf_status_to_os_return(status); - } + hdd_enter(); - tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc); - if (!tgt_hdl) { - hdd_err("tgt_hdl is NULL"); + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); return -EINVAL; } - target_psoc_get_twt_ack_cap(tgt_hdl, &twt_ack_cap); + context = osif_request_cookie(request); + + status = sme_pause_dialog_cmd(hdd_ctx->mac_handle, + twt_params, context); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to send pause dialog command"); + ret = qdf_status_to_os_return(status); + goto cleanup; + } + + twt_cmd = WMI_HOST_TWT_PAUSE_DIALOG_CMDID; + + status = hdd_twt_ack_wait_response(hdd_ctx, request, twt_cmd); + + if (QDF_IS_STATUS_ERROR(status)) { + ret = qdf_status_to_os_return(status); + goto cleanup; + } + + ret = qdf_status_to_os_return(status); +cleanup: + osif_request_put(request); + hdd_exit(); return ret; } @@ -2479,23 +2633,48 @@ static int hdd_send_twt_nudge_dialog_cmd(struct hdd_context *hdd_ctx, struct wmi_twt_nudge_dialog_cmd_param *twt_params) { - struct target_psoc_info *tgt_hdl; QDF_STATUS status; - bool twt_ack_cap; + int twt_cmd, ret = 0; + struct osif_request *request; + struct twt_ack_info_priv *ack_priv; + void *context; + static const struct osif_request_params params = { + .priv_size = sizeof(*ack_priv), + .timeout_ms = TWT_ACK_COMPLETE_TIMEOUT, + }; - status = sme_nudge_dialog_cmd(hdd_ctx->mac_handle, twt_params); - if (QDF_IS_STATUS_ERROR(status)) - hdd_err("Failed to send nudge dialog command"); + hdd_enter(); - tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc); - if (!tgt_hdl) { - hdd_err("tgt_hdl is NULL"); + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); return -EINVAL; } - target_psoc_get_twt_ack_cap(tgt_hdl, &twt_ack_cap); + context = osif_request_cookie(request); - return qdf_status_to_os_return(status); + status = sme_nudge_dialog_cmd(hdd_ctx->mac_handle, twt_params, context); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to send nudge dialog command"); + ret = qdf_status_to_os_return(status); + goto cleanup; + } + + twt_cmd = WMI_HOST_TWT_NUDGE_DIALOG_CMDID; + + status = hdd_twt_ack_wait_response(hdd_ctx, request, twt_cmd); + + if (QDF_IS_STATUS_ERROR(status)) { + ret = qdf_status_to_os_return(status); + goto cleanup; + } + + ret = qdf_status_to_os_return(status); +cleanup: + osif_request_put(request); + hdd_exit(); + + return ret; } /** @@ -2722,25 +2901,47 @@ static int hdd_send_twt_resume_dialog_cmd(struct hdd_context *hdd_ctx, struct wmi_twt_resume_dialog_cmd_param *twt_params) { - struct target_psoc_info *tgt_hdl; QDF_STATUS status; - int ret = 0; - bool twt_ack_cap; + int ret = 0, twt_cmd; + struct osif_request *request; + struct twt_ack_info_priv *ack_priv; + void *context; + static const struct osif_request_params params = { + .priv_size = sizeof(*ack_priv), + .timeout_ms = TWT_ACK_COMPLETE_TIMEOUT, + }; - status = sme_resume_dialog_cmd(hdd_ctx->mac_handle, - twt_params); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Failed to send resume dialog command"); - ret = qdf_status_to_os_return(status); - } + hdd_enter(); - tgt_hdl = wlan_psoc_get_tgt_if_handle(hdd_ctx->psoc); - if (!tgt_hdl) { - hdd_err("tgt_hdl is NULL"); + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); return -EINVAL; } - target_psoc_get_twt_ack_cap(tgt_hdl, &twt_ack_cap); + context = osif_request_cookie(request); + + status = sme_resume_dialog_cmd(hdd_ctx->mac_handle, + twt_params, context); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to send resume dialog command"); + ret = qdf_status_to_os_return(status); + goto cleanup; + } + + twt_cmd = WMI_HOST_TWT_RESUME_DIALOG_CMDID; + + status = hdd_twt_ack_wait_response(hdd_ctx, request, twt_cmd); + + if (QDF_IS_STATUS_ERROR(status)) { + ret = qdf_status_to_os_return(status); + goto cleanup; + } + + ret = qdf_status_to_os_return(status); +cleanup: + osif_request_put(request); + hdd_exit(); return ret; } @@ -4110,6 +4311,7 @@ void wlan_hdd_twt_init(struct hdd_context *hdd_ctx) twt_cb.twt_resume_dialog_cb = hdd_twt_resume_dialog_comp_cb; twt_cb.twt_notify_cb = hdd_twt_notify_cb; twt_cb.twt_nudge_dialog_cb = hdd_twt_nudge_dialog_comp_cb; + twt_cb.twt_ack_comp_cb = hdd_twt_ack_comp_cb; status = sme_register_twt_callbacks(hdd_ctx->mac_handle, &twt_cb); if (QDF_IS_STATUS_ERROR(status)) { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 97c7ecee9285..2ed97dd66622 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -3687,12 +3687,14 @@ QDF_STATUS sme_register_twt_callbacks(mac_handle_t mac_handle, * @mac_handle: MAC handle * @twt_add_dialog_cb: Function callback to handle add_dialog event * @twt_params: TWT add dialog parameters + * @context: TWT context * * Return: QDF Status */ QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle, twt_add_dialog_cb twt_add_dialog_cb, - struct wmi_twt_add_dialog_param *twt_params); + struct wmi_twt_add_dialog_param *twt_params, + void *context); /** * sme_del_dialog_cmd() - Register callback and send TWT del dialog @@ -3700,12 +3702,14 @@ QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle, * @mac_handle: MAC handle * @twt_del_dialog_cb: Function callback to handle del_dialog event * @twt_params: TWT del dialog parameters + * @context: TWT context * * Return: QDF Status */ QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle, twt_del_dialog_cb del_dialog_cb, - struct wmi_twt_del_dialog_param *twt_params); + struct wmi_twt_del_dialog_param *twt_params, + void *context); /** * sme_sap_del_dialog_cmd() - Register callback and send TWT del dialog @@ -3725,39 +3729,45 @@ QDF_STATUS sme_sap_del_dialog_cmd(mac_handle_t mac_handle, * command to firmware * @mac_handle: MAC handle * @twt_params: TWT pause dialog parameters + * @context: TWT context * * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes * on failure */ QDF_STATUS sme_pause_dialog_cmd(mac_handle_t mac_handle, - struct wmi_twt_pause_dialog_cmd_param *twt_params); + struct wmi_twt_pause_dialog_cmd_param *twt_params, + void *context); /** * sme_nudge_dialog_cmd() - Register callback and send TWT nudge dialog * command to firmware * @mac_handle: MAC handle * @twt_params: TWT nudge dialog parameters + * @context: TWT context * * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes * on failure */ QDF_STATUS sme_nudge_dialog_cmd(mac_handle_t mac_handle, - struct wmi_twt_nudge_dialog_cmd_param *twt_params); + struct wmi_twt_nudge_dialog_cmd_param *twt_params, + void *context); /** * sme_resume_dialog_cmd() - Register callback and send TWT resume dialog * command to firmware * @mac_handle: MAC handle * @twt_params: TWT resume dialog parameters + * @context: TWT context * * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes * on failure */ QDF_STATUS sme_resume_dialog_cmd(mac_handle_t mac_handle, - struct wmi_twt_resume_dialog_cmd_param *twt_params); + struct wmi_twt_resume_dialog_cmd_param *twt_params, + void *context); /** * sme_twt_update_beacon_template() - API to send beacon update to fw diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 48ee84f38122..af28a7e31963 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -215,6 +215,16 @@ void (*twt_resume_dialog_cb)(struct wlan_objmgr_psoc *psoc, typedef void (*twt_notify_cb)(struct wlan_objmgr_psoc *psoc, struct wmi_twt_notify_event_param *params); + +/** + * typedef twt_ack_comp_cb - TWT ack callback signature. + * @params: TWT ack complete event parameters. + * @context: TWT context + */ +typedef +void (*twt_ack_comp_cb)(struct wmi_twt_ack_complete_event_param *params, + void *context); + /** * struct twt_callbacks - TWT response callback pointers * @twt_enable_cb: TWT enable completion callback @@ -225,6 +235,7 @@ void (*twt_notify_cb)(struct wlan_objmgr_psoc *psoc, * @twt_resume_dialog_cb: TWT resume dialog completion callback * @twt_notify_cb: TWT notify event callback * @twt_nudge_dialog_cb: TWT nudge dialog completion callback + * @twt_ack_comp_cb: TWT ack completion callback */ struct twt_callbacks { void (*twt_enable_cb)(hdd_handle_t hdd_handle, @@ -243,6 +254,8 @@ struct twt_callbacks { struct wmi_twt_notify_event_param *params); void (*twt_nudge_dialog_cb)(struct wlan_objmgr_psoc *psoc, struct wmi_twt_nudge_dialog_complete_event_param *params); + void (*twt_ack_comp_cb)(struct wmi_twt_ack_complete_event_param *params, + void *context); }; #endif @@ -462,6 +475,8 @@ struct sme_context { twt_nudge_dialog_cb twt_nudge_dialog_cb; twt_resume_dialog_cb twt_resume_dialog_cb; twt_notify_cb twt_notify_cb; + twt_ack_comp_cb twt_ack_comp_cb; + void *twt_ack_context_cb; #endif #ifdef FEATURE_WLAN_APF apf_get_offload_cb apf_get_offload_cb; diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index bd48d1f2dce2..e2c5d189e38a 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14863,6 +14863,7 @@ QDF_STATUS sme_clear_twt_complete_cb(mac_handle_t mac_handle) mac->sme.twt_resume_dialog_cb = NULL; mac->sme.twt_notify_cb = NULL; mac->sme.twt_nudge_dialog_cb = NULL; + mac->sme.twt_ack_comp_cb = NULL; sme_release_global_lock(&mac->sme); sme_debug("TWT: callbacks Initialized"); @@ -14887,6 +14888,7 @@ QDF_STATUS sme_register_twt_callbacks(mac_handle_t mac_handle, mac->sme.twt_disable_cb = twt_cb->twt_disable_cb; mac->sme.twt_notify_cb = twt_cb->twt_notify_cb; mac->sme.twt_nudge_dialog_cb = twt_cb->twt_nudge_dialog_cb; + mac->sme.twt_ack_comp_cb = twt_cb->twt_ack_comp_cb; sme_release_global_lock(&mac->sme); sme_debug("TWT: callbacks registered"); } @@ -14896,7 +14898,8 @@ QDF_STATUS sme_register_twt_callbacks(mac_handle_t mac_handle, QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle, twt_add_dialog_cb twt_add_dialog_cb, - struct wmi_twt_add_dialog_param *twt_params) + struct wmi_twt_add_dialog_param *twt_params, + void *context) { struct mac_context *mac = MAC_CONTEXT(mac_handle); struct scheduler_msg twt_msg = {0}; @@ -14959,6 +14962,7 @@ QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle, /* Serialize the req through MC thread */ mac->sme.twt_add_dialog_cb = twt_add_dialog_cb; + mac->sme.twt_ack_context_cb = context; twt_msg.bodyptr = cmd_params; twt_msg.type = WMA_TWT_ADD_DIALOG_REQUEST; sme_release_global_lock(&mac->sme); @@ -14985,7 +14989,8 @@ QDF_STATUS sme_add_dialog_cmd(mac_handle_t mac_handle, QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle, twt_del_dialog_cb del_dialog_cb, - struct wmi_twt_del_dialog_param *twt_params) + struct wmi_twt_del_dialog_param *twt_params, + void *context) { struct mac_context *mac = MAC_CONTEXT(mac_handle); struct scheduler_msg twt_msg = {0}; @@ -15038,6 +15043,7 @@ QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle, /* Serialize the req through MC thread */ mac->sme.twt_del_dialog_cb = del_dialog_cb; + mac->sme.twt_ack_context_cb = context; twt_msg.bodyptr = cmd_params; twt_msg.type = WMA_TWT_DEL_DIALOG_REQUEST; sme_release_global_lock(&mac->sme); @@ -15144,7 +15150,8 @@ QDF_STATUS sme_sap_del_dialog_cmd(mac_handle_t mac_handle, QDF_STATUS sme_pause_dialog_cmd(mac_handle_t mac_handle, - struct wmi_twt_pause_dialog_cmd_param *twt_params) + struct wmi_twt_pause_dialog_cmd_param *twt_params, + void *context) { struct mac_context *mac = MAC_CONTEXT(mac_handle); struct wmi_twt_pause_dialog_cmd_param *cmd_params; @@ -15190,6 +15197,7 @@ sme_pause_dialog_cmd(mac_handle_t mac_handle, twt_params->dialog_id, WLAN_TWT_SUSPEND); /* Serialize the req through MC thread */ + mac->sme.twt_ack_context_cb = context; twt_msg.bodyptr = cmd_params; twt_msg.type = WMA_TWT_PAUSE_DIALOG_REQUEST; sme_release_global_lock(&mac->sme); @@ -15214,7 +15222,8 @@ sme_pause_dialog_cmd(mac_handle_t mac_handle, QDF_STATUS sme_nudge_dialog_cmd(mac_handle_t mac_handle, - struct wmi_twt_nudge_dialog_cmd_param *twt_params) + struct wmi_twt_nudge_dialog_cmd_param *twt_params, + void *context) { struct mac_context *mac = MAC_CONTEXT(mac_handle); struct wmi_twt_nudge_dialog_cmd_param *cmd_params; @@ -15260,6 +15269,7 @@ sme_nudge_dialog_cmd(mac_handle_t mac_handle, twt_params->dialog_id, WLAN_TWT_NUDGE); /* Serialize the req through MC thread */ + mac->sme.twt_ack_context_cb = context; twt_msg.bodyptr = cmd_params; twt_msg.type = WMA_TWT_NUDGE_DIALOG_REQUEST; sme_release_global_lock(&mac->sme); @@ -15284,7 +15294,8 @@ sme_nudge_dialog_cmd(mac_handle_t mac_handle, QDF_STATUS sme_resume_dialog_cmd(mac_handle_t mac_handle, - struct wmi_twt_resume_dialog_cmd_param *twt_params) + struct wmi_twt_resume_dialog_cmd_param *twt_params, + void *context) { struct mac_context *mac = MAC_CONTEXT(mac_handle); struct wmi_twt_resume_dialog_cmd_param *cmd_params; @@ -15330,6 +15341,7 @@ sme_resume_dialog_cmd(mac_handle_t mac_handle, twt_params->dialog_id, WLAN_TWT_RESUME); /* Serialize the req through MC thread */ + mac->sme.twt_ack_context_cb = context; twt_msg.bodyptr = cmd_params; twt_msg.type = WMA_TWT_RESUME_DIALOG_REQUEST; sme_release_global_lock(&mac->sme); diff --git a/core/wma/src/wma_twt.c b/core/wma/src/wma_twt.c index 427b47066778..04b507ddca44 100644 --- a/core/wma/src/wma_twt.c +++ b/core/wma/src/wma_twt.c @@ -596,6 +596,48 @@ int wma_twt_resume_dialog_complete_event_handler(void *handle, uint8_t *event, return status; } +static +int wma_twt_ack_complete_event_handler(void *handle, uint8_t *event, + uint32_t len) +{ + struct wmi_twt_ack_complete_event_param *param; + tp_wma_handle wma_handle = handle; + wmi_unified_t wmi_handle; + struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); + QDF_STATUS status; + + if (!mac) + return -EINVAL; + + if (wma_validate_handle(wma_handle)) + return -EINVAL; + + wmi_handle = (wmi_unified_t)wma_handle->wmi_handle; + if (!wmi_handle) { + wma_err("Invalid wmi handle for TWT ack complete"); + return -EINVAL; + } + + param = qdf_mem_malloc(sizeof(*param)); + if (!param) + return -ENOMEM; + + status = wmi_extract_twt_ack_comp_event(wmi_handle, event, + param); + + wma_debug("TWT: Received TWT ack comp event, status:%d", status); + + if (QDF_IS_STATUS_ERROR(status)) + goto exit; + + if (mac->sme.twt_ack_comp_cb) + mac->sme.twt_ack_comp_cb(param, mac->sme.twt_ack_context_cb); + +exit: + qdf_mem_free(param); + return qdf_status_to_os_return(status); +} + /** * wma_update_bcast_twt_support() - update bcost twt support * @wh: wma handle @@ -653,31 +695,36 @@ void wma_register_twt_events(tp_wma_handle wma_handle) (wma_handle->wmi_handle, wmi_twt_add_dialog_complete_event_id, wma_twt_add_dialog_complete_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler (wma_handle->wmi_handle, wmi_twt_del_dialog_complete_event_id, wma_twt_del_dialog_complete_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler (wma_handle->wmi_handle, wmi_twt_pause_dialog_complete_event_id, wma_twt_pause_dialog_complete_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler (wma_handle->wmi_handle, wmi_twt_resume_dialog_complete_event_id, wma_twt_resume_dialog_complete_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler (wma_handle->wmi_handle, wmi_twt_nudge_dialog_complete_event_id, wma_twt_nudge_dialog_complete_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler (wma_handle->wmi_handle, wmi_twt_notify_event_id, wma_twt_notify_event_handler, WMA_RX_SERIALIZER_CTX); + wmi_unified_register_event_handler + (wma_handle->wmi_handle, + wmi_twt_ack_complete_event_id, + wma_twt_ack_complete_event_handler, + WMA_RX_WORK_CTX); }