diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index 1341040d27..3c1c5cbe60 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -2310,6 +2310,79 @@ static int hdd_twt_resume_session(struct hdd_adapter *adapter, return ret; } +/** + * hdd_twt_notify_pack_nlmsg() - pack the skb with + * twt notify event from firmware + * @reply_skb: skb to store the response + * + * Return: QDF_STATUS_SUCCESS on Success, QDF_STATUS_E_FAILURE + * on failure + */ +static QDF_STATUS +hdd_twt_notify_pack_nlmsg(struct sk_buff *reply_skb) +{ + if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION, + QCA_WLAN_TWT_SETUP_READY_NOTIFY)) { + hdd_err("Failed to put TWT notify operation"); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * hdd_twt_notify_cb() - callback function + * to get twt notify event + * @psoc: Pointer to global psoc + * @params: Pointer to notify param event buffer + * + * Return: None + */ +static void +hdd_twt_notify_cb(struct wlan_objmgr_psoc *psoc, + struct wmi_twt_notify_event_param *params) +{ + struct hdd_adapter *adapter = + wlan_hdd_get_adapter_from_vdev(psoc, params->vdev_id); + struct wireless_dev *wdev; + struct sk_buff *twt_vendor_event; + size_t data_len; + QDF_STATUS status; + + hdd_enter(); + + if (hdd_validate_adapter(adapter)) + return; + + wdev = adapter->dev->ieee80211_ptr; + + data_len = NLA_HDRLEN; + data_len += nla_total_size(sizeof(u8)); + + twt_vendor_event = wlan_cfg80211_vendor_event_alloc( + adapter->wdev.wiphy, wdev, + data_len, + QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX, + GFP_KERNEL); + if (!twt_vendor_event) { + hdd_err("Notify skb alloc failed"); + return; + } + + hdd_debug("Notify vdev_id %d", params->vdev_id); + + status = hdd_twt_notify_pack_nlmsg(twt_vendor_event); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to pack nl notify event"); + wlan_cfg80211_vendor_free_skb(twt_vendor_event); + return; + } + + wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL); + + hdd_exit(); +} + /** * hdd_twt_configure - Process the TWT * operation in the received vendor command @@ -2720,6 +2793,7 @@ void wlan_hdd_twt_init(struct hdd_context *hdd_ctx) twt_cb.twt_del_dialog_cb = hdd_twt_del_dialog_comp_cb; twt_cb.twt_pause_dialog_cb = hdd_twt_pause_dialog_comp_cb; twt_cb.twt_resume_dialog_cb = hdd_twt_resume_dialog_comp_cb; + twt_cb.twt_notify_cb = hdd_twt_notify_cb; status = sme_register_twt_callbacks(hdd_ctx->mac_handle, &twt_cb); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("Register twt enable complete failed"); diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index 310f8593d1..2bbf321922 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021 The Linux Foundation. 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 @@ -250,7 +250,8 @@ enum eWniMsgTypes { eWNI_SME_TWT_PAUSE_DIALOG_EVENT = SIR_SME_MSG_TYPES_BEGIN + 167, eWNI_SME_TWT_RESUME_DIALOG_EVENT = SIR_SME_MSG_TYPES_BEGIN + 168, eWNI_SME_TWT_NUDGE_DIALOG_EVENT = SIR_SME_MSG_TYPES_BEGIN + 169, - eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 170 + eWNI_SME_TWT_NOTIFY_EVENT = SIR_SME_MSG_TYPES_BEGIN + 170, + eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 171 }; typedef struct sAniCfgTxRateCtrs { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 231e9627a9..437ef90175 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -3675,7 +3675,8 @@ QDF_STATUS sme_clear_twt_complete_cb(mac_handle_t mac_handle); * @mac_handle: MAC handle * @twt_cb: TWT callbacks * - * Return: QDF Status + * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes + * on failure */ QDF_STATUS sme_register_twt_callbacks(mac_handle_t mac_handle, struct twt_callbacks *twt_cb); diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 556fa60060..c13c8d846a 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -207,13 +207,22 @@ void (*twt_resume_dialog_cb)(struct wlan_objmgr_psoc *psoc, struct wmi_twt_resume_dialog_complete_event_param *params); /** - * struct twt_callbacks - TWT response callback pointers + * typedef twt_notify_cb - TWT notify callback signature. + * @psoc: Pointer to global psoc + * @params: TWT twt notify event parameters. + */ +typedef +void (*twt_notify_cb)(struct wlan_objmgr_psoc *psoc, + struct wmi_twt_notify_event_param *params); +/** + * struct twt_callbacks - TWT response callback pointers * @twt_enable_cb: TWT enable completion callback * @twt_disable_cb: TWT disable completion callback * @twt_add_dialog_cb: TWT add dialog completion callback * @twt_del_dialog_cb: TWT delete dialog completion callback * @twt_pause_dialog_cb: TWT pause dialog completion callback * @twt_resume_dialog_cb: TWT resume dialog completion callback + * @twt_notify_cb: TWT notify event callback */ struct twt_callbacks { void (*twt_enable_cb)(hdd_handle_t hdd_handle, @@ -227,6 +236,8 @@ struct twt_callbacks { struct wmi_twt_pause_dialog_complete_event_param *params); void (*twt_resume_dialog_cb)(struct wlan_objmgr_psoc *psoc, struct wmi_twt_resume_dialog_complete_event_param *params); + void (*twt_notify_cb)(struct wlan_objmgr_psoc *psoc, + struct wmi_twt_notify_event_param *params); }; #endif @@ -442,6 +453,7 @@ struct sme_context { twt_pause_dialog_cb twt_pause_dialog_cb; twt_nudge_dialog_cb twt_nudge_dialog_cb; twt_resume_dialog_cb twt_resume_dialog_cb; + twt_notify_cb twt_notify_cb; void *twt_nudge_dialog_context; #endif #ifdef FEATURE_WLAN_APF diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index f8889327b8..a49e93ec0f 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -72,6 +72,7 @@ #include "wlan_mlme_twt_api.h" #include "parser_api.h" #include <../../core/src/wlan_cm_vdev_api.h> +#include static QDF_STATUS init_sme_cmd_list(struct mac_context *mac); @@ -2263,6 +2264,30 @@ sme_process_twt_resume_dialog_event(struct mac_context *mac, mac->psoc, (struct qdf_mac_addr *)param->peer_macaddr, param->dialog_id, WLAN_TWT_NONE); } + +/** + * sme_process_twt_notify_event() - Process twt ready for setup notification + * event from firmware + * @mac: Global MAC pointer + * @twt_notify_event: pointer to event buf containing twt notify parameters + * + * Return: None + */ +static void +sme_process_twt_notify_event(struct mac_context *mac, + struct wmi_twt_notify_event_param *notify_event) +{ + twt_notify_cb callback; + struct csr_roam_session *session; + + session = CSR_GET_SESSION(mac, notify_event->vdev_id); + mlme_twt_set_wait_for_notify(mac->psoc, + &session->connectedProfile.bssid, + FALSE); + callback = mac->sme.twt_notify_cb; + if (callback) + callback(mac->psoc, notify_event); +} #else static void sme_process_twt_add_dialog_event(struct mac_context *mac, @@ -2293,6 +2318,12 @@ sme_process_twt_nudge_dialog_event(struct mac_context *mac, struct wmi_twt_nudge_dialog_complete_event_param *param) { } + +static void +sme_process_twt_notify_event(struct mac_context *mac, + struct wmi_twt_notify_event_param *notify_event) +{ +} #endif QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg) @@ -2618,6 +2649,10 @@ QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg) sme_process_twt_nudge_dialog_event(mac, pMsg->bodyptr); qdf_mem_free(pMsg->bodyptr); break; + case eWNI_SME_TWT_NOTIFY_EVENT: + sme_process_twt_notify_event(mac, pMsg->bodyptr); + qdf_mem_free(pMsg->bodyptr); + break; default: if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) @@ -13954,6 +13989,7 @@ QDF_STATUS sme_clear_twt_complete_cb(mac_handle_t mac_handle) mac->sme.twt_del_dialog_cb = NULL; mac->sme.twt_pause_dialog_cb = NULL; mac->sme.twt_resume_dialog_cb = NULL; + mac->sme.twt_notify_cb = NULL; sme_release_global_lock(&mac->sme); sme_debug("TWT: callbacks Initialized"); @@ -13976,6 +14012,7 @@ QDF_STATUS sme_register_twt_callbacks(mac_handle_t mac_handle, mac->sme.twt_pause_dialog_cb = twt_cb->twt_pause_dialog_cb; mac->sme.twt_resume_dialog_cb = twt_cb->twt_resume_dialog_cb; mac->sme.twt_disable_cb = twt_cb->twt_disable_cb; + mac->sme.twt_notify_cb = twt_cb->twt_notify_cb; sme_release_global_lock(&mac->sme); sme_debug("TWT: callbacks registered"); } diff --git a/core/wma/src/wma_twt.c b/core/wma/src/wma_twt.c index 44459834bd..d5cd58eb12 100644 --- a/core/wma/src/wma_twt.c +++ b/core/wma/src/wma_twt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 The Linux Foundation. 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 @@ -442,6 +442,58 @@ wma_twt_process_resume_dialog(t_wma_handle *wma_handle, return wmi_unified_twt_resume_dialog_cmd(wmi_handle, params); } +/** + * wma_twt_notify_event_handler - TWT notify event handler + * @handle: wma handle + * @event: buffer with event + * @len: buffer length + * + * Return: 0 on success, negative value on failure + */ +static +int wma_twt_notify_event_handler(void *handle, uint8_t *event, uint32_t len) +{ + struct wmi_twt_notify_event_param *param; + struct scheduler_msg sme_msg = {0}; + tp_wma_handle wma_handle = handle; + wmi_unified_t wmi_handle; + struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); + int status = -EINVAL; + + if (!mac) + return status; + + if (wma_validate_handle(wma_handle)) + return status; + + wmi_handle = (wmi_unified_t)wma_handle->wmi_handle; + if (!wmi_handle) { + wma_err("Invalid wmi handle for TWT notify event"); + return status; + } + + param = qdf_mem_malloc(sizeof(*param)); + if (!param) + return -ENOMEM; + + if (wmi_handle->ops->extract_twt_notify_event) + status = wmi_handle->ops->extract_twt_notify_event(wmi_handle, + event, + param); + wma_debug("Extract Notify event status:%d", status); + + sme_msg.type = eWNI_SME_TWT_NOTIFY_EVENT; + sme_msg.bodyptr = param; + sme_msg.bodyval = 0; + status = scheduler_post_message(QDF_MODULE_ID_WMA, + QDF_MODULE_ID_SME, + QDF_MODULE_ID_SME, &sme_msg); + if (QDF_IS_STATUS_ERROR(status)) + return -EINVAL; + + return 0; +} + /** * wma_twt_resume_dialog_complete_event_handler - TWT resume dlg complete evt * handler @@ -561,4 +613,9 @@ void wma_register_twt_events(tp_wma_handle wma_handle) wmi_twt_nudge_dialog_complete_event_id, wma_twt_nudge_dialog_complete_event_handler, WMA_RX_SERIALIZER_CTX); + wmi_unified_register_event_handler + (wma_handle->wmi_handle, + wmi_twt_notify_event_id, + wma_twt_notify_event_handler, + WMA_RX_SERIALIZER_CTX); }