qcacld-3.0: Add support to handle twt_notify event

Add support to handle twt_notify event. Firmware can
terminate a TWT session without a Host trigger due to internal
reasons. In that case it sends an event to notify that it is
again ready for a TWT session setup.

Change-Id: I3508687cee93e16a26221a1bc7ad9c626a4f4523
CRs-Fixed: 2847158
This commit is contained in:
Rajasekaran Kalidoss
2020-12-19 13:31:44 +05:30
committed by snandini
parent ac5297a3df
commit 741def98ba
6 changed files with 187 additions and 5 deletions

View File

@@ -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");

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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

View File

@@ -72,6 +72,7 @@
#include "wlan_mlme_twt_api.h"
#include "parser_api.h"
#include <../../core/src/wlan_cm_vdev_api.h>
#include <wlan_mlme_twt_api.h>
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");
}

View File

@@ -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);
}