From c5c3bc6ce39f167d10bdb0e7d03a91fb81626aa3 Mon Sep 17 00:00:00 2001 From: Paul Zhang Date: Mon, 14 Dec 2020 13:54:24 +0800 Subject: [PATCH] qcacld-3.0: Add support op QCA_WLAN_TWT_NUDGE This is the new OP for vendor sub command QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT to set twt suspend/resume parameters. Change-Id: If4ec03364f41ca4960673fb7a13b91a929cfe567 CRs-Fixed: 2797664 --- core/hdd/src/wlan_hdd_twt.c | 282 ++++++++++++++++++ core/mac/inc/wni_api.h | 3 +- core/mac/src/include/sir_params.h | 1 + .../src/sys/legacy/src/utils/src/mac_trace.c | 1 + core/sme/inc/sme_api.h | 17 ++ core/sme/inc/sme_internal.h | 12 + core/sme/src/common/sme_api.c | 93 ++++++ core/wma/inc/wma_twt.h | 21 ++ core/wma/inc/wma_types.h | 1 + core/wma/src/wma_main.c | 4 + core/wma/src/wma_twt.c | 76 +++++ 11 files changed, 510 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index 9c68bb6a9765..78e8589c9757 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -40,6 +40,7 @@ #define TWT_DISABLE_COMPLETE_TIMEOUT 4000 #define TWT_TERMINATE_COMPLETE_TIMEOUT 4000 #define TWT_PAUSE_COMPLETE_TIMEOUT 4000 +#define TWT_NUDGE_COMPLETE_TIMEOUT 4000 #define TWT_RESUME_COMPLETE_TIMEOUT 4000 #define TWT_FLOW_TYPE_ANNOUNCED 0 @@ -62,6 +63,18 @@ struct twt_pause_dialog_comp_ev_priv { struct wmi_twt_pause_dialog_complete_event_param pause_dialog_comp_ev_buf; }; +/** + * struct twt_nudge_dialog_comp_ev_priv - private struct for twt nudge dialog + * @nudge_dialog_comp_ev_buf: buffer from TWT nudge dialog complete_event + * + * This TWT nudge dialog private structure is registered with os_if to + * retrieve the TWT nudge dialog response event buffer. + */ +struct twt_nudge_dialog_comp_ev_priv { + struct wmi_twt_nudge_dialog_complete_event_param + nudge_dialog_comp_ev_buf; +}; + /** * struct twt_resume_dialog_comp_ev_priv - private struct for twt resume dialog * @resume_dialog_comp_ev_buf: buffer from TWT resume dialog complete_event @@ -130,6 +143,14 @@ wlan_hdd_wifi_twt_config_policy[ .type = NLA_NESTED}, }; +static const struct nla_policy +qca_wlan_vendor_twt_nudge_dialog_policy[QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR] = VENDOR_NLA_POLICY_MAC_ADDR, +}; + /** * hdd_twt_setup_req_type_to_cmd() - Converts twt setup request type to twt cmd * @req_type: twt setup request type @@ -834,6 +855,37 @@ wmi_twt_pause_status_to_vendor_twt_status(enum WMI_HOST_PAUSE_TWT_STATUS status) } } +/** + * wmi_twt_nudge_status_to_vendor_twt_status() - convert from + * WMI_HOST_NUDGE_TWT_STATUS to qca_wlan_vendor_twt_status + * @status: WMI_HOST_NUDGE_TWT_STATUS value from firmware + * + * Return: qca_wlan_vendor_twt_status values corresponding + * to the firmware failure status + */ +static int +wmi_twt_nudge_status_to_vendor_twt_status(enum WMI_HOST_NUDGE_TWT_STATUS status) +{ + switch (status) { + case WMI_HOST_NUDGE_TWT_STATUS_OK: + return QCA_WLAN_VENDOR_TWT_STATUS_OK; + case WMI_HOST_NUDGE_TWT_STATUS_DIALOG_ID_NOT_EXIST: + return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST; + case WMI_HOST_NUDGE_TWT_STATUS_INVALID_PARAM: + return QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM; + case WMI_HOST_NUDGE_TWT_STATUS_DIALOG_ID_BUSY: + return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY; + case WMI_HOST_NUDGE_TWT_STATUS_NO_RESOURCE: + return QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE; + case WMI_HOST_NUDGE_TWT_STATUS_NO_ACK: + return QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK; + case WMI_HOST_NUDGE_TWT_STATUS_UNKNOWN_ERROR: + return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR; + default: + return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR; + } +} + /** * wmi_twt_add_cmd_to_vendor_twt_resp_type() - convert from * WMI_HOST_TWT_COMMAND to qca_wlan_vendor_twt_setup_resp_type @@ -1502,6 +1554,43 @@ hdd_twt_pause_dialog_comp_cb(void *context, hdd_exit(); } +/** + * hdd_twt_nudge_dialog_comp_cb() - callback function + * to get twt nudge command complete event + * @context: private context + * @params: Pointer to nudge dialog complete event buffer + * + * Return: None + */ +static void +hdd_twt_nudge_dialog_comp_cb(void *context, + struct wmi_twt_nudge_dialog_complete_event_param *params) +{ + struct osif_request *request; + struct twt_nudge_dialog_comp_ev_priv *priv; + + hdd_enter(); + + request = osif_request_get(context); + if (!request) { + hdd_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + + priv->nudge_dialog_comp_ev_buf = *params; + osif_request_complete(request); + osif_request_put(request); + + hdd_debug("TWT: nudge dialog_id:%d, status:%d vdev_id %d peer mac_addr " + QDF_MAC_ADDR_FMT, params->dialog_id, + params->status, params->vdev_id, + QDF_MAC_ADDR_REF(params->peer_macaddr)); + + hdd_exit(); +} + /** * hdd_twt_pause_pack_resp_nlmsg() - pack the skb with * firmware response for twt pause command @@ -1533,6 +1622,38 @@ hdd_twt_pause_pack_resp_nlmsg(struct sk_buff *reply_skb, return QDF_STATUS_SUCCESS; } +/** + * hdd_twt_nudge_pack_resp_nlmsg() - pack the skb with + * firmware response for twt nudge command + * @reply_skb: skb to store the response + * @params: Pointer to nudge dialog complete event buffer + * + * Return: QDF_STATUS_SUCCESS on Success, QDF_STATUS_E_FAILURE + * on failure + */ +static QDF_STATUS +hdd_twt_nudge_pack_resp_nlmsg(struct sk_buff *reply_skb, + struct wmi_twt_nudge_dialog_complete_event_param *params) +{ + int vendor_status; + + if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID, + params->dialog_id)) { + hdd_debug("TWT: Failed to put dialog_id"); + return QDF_STATUS_E_FAILURE; + } + + vendor_status = + wmi_twt_nudge_status_to_vendor_twt_status(params->status); + if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS, + vendor_status)) { + hdd_err("TWT: Failed to put QCA_WLAN_TWT_NUDGE status"); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + /** * hdd_send_twt_pause_dialog_cmd() - Send TWT pause dialog command to target * @hdd_ctx: HDD Context @@ -1672,6 +1793,164 @@ static int hdd_twt_pause_session(struct hdd_adapter *adapter, return ret; } +/** + * hdd_send_twt_nudge_dialog_cmd() - Send TWT nudge dialog command to target + * @hdd_ctx: HDD Context + * @twt_params: Pointer to nudge dialog cmd params structure + * + * Return: 0 on success, negative value on failure + */ +static +int hdd_send_twt_nudge_dialog_cmd(struct hdd_context *hdd_ctx, + struct wmi_twt_nudge_dialog_cmd_param *twt_params) +{ + struct wmi_twt_nudge_dialog_complete_event_param *comp_ev_params; + struct twt_nudge_dialog_comp_ev_priv *priv; + static const struct osif_request_params osif_req_params = { + .priv_size = sizeof(*priv), + .timeout_ms = TWT_NUDGE_COMPLETE_TIMEOUT, + .dealloc = NULL, + }; + struct osif_request *request; + struct sk_buff *reply_skb = NULL; + QDF_STATUS status; + void *cookie; + int skb_len; + int ret; + + request = osif_request_alloc(&osif_req_params); + if (!request) { + hdd_err("twt osif request allocation failure"); + ret = -ENOMEM; + goto err; + } + + cookie = osif_request_cookie(request); + + status = sme_nudge_dialog_cmd(hdd_ctx->mac_handle, + hdd_twt_nudge_dialog_comp_cb, + twt_params, cookie); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to send nudge dialog command"); + ret = qdf_status_to_os_return(status); + goto err; + } + + ret = osif_request_wait_for_response(request); + if (ret) { + hdd_err("twt: nudge dialog req timedout"); + ret = -ETIMEDOUT; + goto err; + } + + priv = osif_request_priv(request); + comp_ev_params = &priv->nudge_dialog_comp_ev_buf; + + skb_len = hdd_get_twt_event_len(); + reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, + skb_len); + if (!reply_skb) { + hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); + ret = -ENOMEM; + goto err; + } + + status = hdd_twt_nudge_pack_resp_nlmsg(reply_skb, comp_ev_params); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to pack nl nudge dialog response"); + ret = qdf_status_to_os_return(status); + goto err; + } + + ret = wlan_cfg80211_vendor_cmd_reply(reply_skb); + +err: + if (request) + osif_request_put(request); + if (ret && reply_skb) + kfree_skb(reply_skb); + return ret; +} + +/** + * hdd_twt_nudge_session - Process TWT nudge operation + * in the received vendor command and send it to firmware + * @adapter: adapter pointer + * @twt_param_attr: nl attributes + * + * Handles QCA_WLAN_TWT_NUDGE + * + * Return: 0 on success, negative value on failure + */ +static int hdd_twt_nudge_session(struct hdd_adapter *adapter, + struct nlattr *twt_param_attr) +{ + struct hdd_station_ctx *hdd_sta_ctx; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX + 1]; + struct wmi_twt_nudge_dialog_cmd_param params = {0}; + int id; + int ret; + + if (adapter->device_mode != QDF_STA_MODE && + adapter->device_mode != QDF_P2P_CLIENT_MODE) { + return -EOPNOTSUPP; + } + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (hdd_sta_ctx->conn_info.conn_state != eConnectionState_Associated) { + hdd_err_rl("Invalid state, vdev %d mode %d state %d", + adapter->vdev_id, adapter->device_mode, + hdd_sta_ctx->conn_info.conn_state); + return -EINVAL; + } + + params.vdev_id = adapter->vdev_id; + + ret = wlan_cfg80211_nla_parse_nested(tb, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX, + twt_param_attr, + qca_wlan_vendor_twt_nudge_dialog_policy); + if (ret) + return ret; + + id = QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR; + if (tb[id]) { + nla_memcpy(params.peer_macaddr, tb[id], QDF_MAC_ADDR_SIZE); + hdd_debug("peer mac_addr "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(params.peer_macaddr)); + } + + id = QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID; + if (!tb[id]) { + hdd_debug("TWT: FLOW_ID not specified."); + return -EINVAL; + } + params.dialog_id = nla_get_u8(tb[id]); + + id = QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME; + if (!tb[id]) { + hdd_debug("TWT: WAKE_TIME not specified."); + return -EINVAL; + } + params.suspend_duration = nla_get_u32(tb[id]); + + id = QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE; + if (!tb[id]) { + hdd_debug("TWT: NEXT_TWT_SIZE not specified."); + return -EINVAL; + } + params.next_twt_size = nla_get_u32(tb[id]); + + hdd_debug("twt_nudge: vdev_id %d dialog_id %d ", params.vdev_id, + params.dialog_id); + hdd_debug("twt_nudge: suspend_duration %d next_twt_size %d", + params.suspend_duration, params.next_twt_size); + + ret = hdd_send_twt_nudge_dialog_cmd(adapter->hdd_ctx, ¶ms); + + return ret; +} + /** * hdd_twt_resume_dialog_comp_cb() - callback function * to get twt resume command complete event @@ -1952,6 +2231,9 @@ static int hdd_twt_configure(struct hdd_adapter *adapter, case QCA_WLAN_TWT_RESUME: ret = hdd_twt_resume_session(adapter, twt_param_attr); break; + case QCA_WLAN_TWT_NUDGE: + ret = hdd_twt_nudge_session(adapter, twt_param_attr); + break; default: hdd_err("Invalid TWT Operation"); ret = -EINVAL; diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index 69ed5a0089ac..ee86eb1592d5 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -256,7 +256,8 @@ enum eWniMsgTypes { eWNI_SME_TWT_DEL_DIALOG_EVENT = SIR_SME_MSG_TYPES_BEGIN + 166, 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_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 169 + eWNI_SME_TWT_NUDGE_DIALOG_EVENT = SIR_SME_MSG_TYPES_BEGIN + 169, + eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 170 }; typedef struct sAniCfgTxRateCtrs { diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index bbd0e4efd282..21bb9668e10b 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -673,6 +673,7 @@ enum halmsgtype { SIR_HAL_TWT_PAUSE_DIALOG_REQUEST = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 419), SIR_HAL_TWT_RESUME_DIALOG_REQUEST = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 420), SIR_HAL_PEER_CREATE_REQ = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 421), + SIR_HAL_TWT_NUDGE_DIALOG_REQUEST = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 422), SIR_HAL_MSG_TYPES_END = (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF), diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index 8d3ee1636d91..97737e13e64a 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -565,6 +565,7 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg) CASE_RETURN_STRING(WMA_TWT_DEL_DIALOG_REQUEST); CASE_RETURN_STRING(WMA_TWT_PAUSE_DIALOG_REQUEST); CASE_RETURN_STRING(WMA_TWT_RESUME_DIALOG_REQUEST); + CASE_RETURN_STRING(WMA_TWT_NUDGE_DIALOG_REQUEST); #endif CASE_RETURN_STRING(WMA_RX_SCAN_EVENT); CASE_RETURN_STRING(WMA_RX_CHN_STATUS_EVENT); diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index b71c87c8704e..c7ed6b680002 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -3715,6 +3715,23 @@ sme_pause_dialog_cmd(mac_handle_t mac_handle, 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_nudge_dialog_cb: Function callback to handle nudge_dialog event + * @twt_params: TWT nudge dialog parameters + * @context: os_if_request cookie + * + * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes + * on failure + */ +QDF_STATUS +sme_nudge_dialog_cmd(mac_handle_t mac_handle, + twt_nudge_dialog_cb nudge_dialog_cb, + 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 diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index ef4548861eab..54727f1723e5 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -187,6 +187,16 @@ typedef void (*twt_pause_dialog_cb)(void *context, struct wmi_twt_pause_dialog_complete_event_param *params); +/** + * typedef twt_nudge_dialog_cb - TWT nudge dialog callback signature. + * @context: Opaque context that the client can use to associate the + * callback with the request. + * @params: TWT nudge dialog complete event parameters. + */ +typedef +void (*twt_nudge_dialog_cb)(void *context, + struct wmi_twt_nudge_dialog_complete_event_param *params); + /** * typedef twt_resume_dialog_cb - TWT resume dialog callback signature. * @context: Opaque context that the client can use to associate the @@ -431,9 +441,11 @@ struct sme_context { twt_add_dialog_cb twt_add_dialog_cb; twt_del_dialog_cb twt_del_dialog_cb; twt_pause_dialog_cb twt_pause_dialog_cb; + twt_nudge_dialog_cb twt_nudge_dialog_cb; twt_resume_dialog_cb twt_resume_dialog_cb; void *twt_del_dialog_context; void *twt_pause_dialog_context; + void *twt_nudge_dialog_context; void *twt_resume_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 3014c3251d45..5cf15ea41580 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -2111,6 +2111,28 @@ sme_process_twt_pause_dialog_event(struct mac_context *mac, callback(context, param); } +/** + * sme_process_twt_nudge_dialog_event() - Process twt nudge dialog event + * response from firmware + * @mac: Global MAC pointer + * @param: pointer to wmi_twt_nudge_dialog_complete_event_param buffer + * + * Return: None + */ +static void +sme_process_twt_nudge_dialog_event(struct mac_context *mac, + struct wmi_twt_nudge_dialog_complete_event_param *param) +{ + twt_nudge_dialog_cb callback; + void *context; + + 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); +} + /** * sme_process_twt_resume_dialog_event() - Process twt resume dialog event * response from firmware @@ -2156,6 +2178,12 @@ sme_process_twt_resume_dialog_event(struct mac_context *mac, struct wmi_twt_resume_dialog_complete_event_param *param) { } + +static void +sme_process_twt_nudge_dialog_event(struct mac_context *mac, + struct wmi_twt_nudge_dialog_complete_event_param *param) +{ +} #endif QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg) @@ -2477,6 +2505,10 @@ QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg) sme_process_twt_resume_dialog_event(mac, pMsg->bodyptr); qdf_mem_free(pMsg->bodyptr); break; + case eWNI_SME_TWT_NUDGE_DIALOG_EVENT: + sme_process_twt_nudge_dialog_event(mac, pMsg->bodyptr); + qdf_mem_free(pMsg->bodyptr); + break; default: if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) @@ -14657,6 +14689,67 @@ sme_pause_dialog_cmd(mac_handle_t mac_handle, return status; } +QDF_STATUS +sme_nudge_dialog_cmd(mac_handle_t mac_handle, + twt_nudge_dialog_cb nudge_dialog_cb, + 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; + struct scheduler_msg twt_msg = {0}; + QDF_STATUS status; + void *wma_handle; + + SME_ENTER(); + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + if (!wma_handle) { + sme_err("wma_handle is NULL"); + return QDF_STATUS_E_FAILURE; + } + + /*bodyptr should be freeable*/ + cmd_params = qdf_mem_malloc(sizeof(*cmd_params)); + if (!cmd_params) + return QDF_STATUS_E_NOMEM; + + qdf_mem_copy(cmd_params, twt_params, sizeof(*cmd_params)); + + status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("failed to register nudge dialog callback"); + qdf_mem_free(cmd_params); + return status; + } + + if (mac->sme.twt_nudge_dialog_cb) { + sme_release_global_lock(&mac->sme); + qdf_mem_free(cmd_params); + sme_err_rl("TWT: Command in progress - STATUS E_BUSY"); + return QDF_STATUS_E_BUSY; + } + + /* Serialize the req through MC thread */ + mac->sme.twt_nudge_dialog_cb = nudge_dialog_cb; + mac->sme.twt_nudge_dialog_context = context; + twt_msg.bodyptr = cmd_params; + twt_msg.type = WMA_TWT_NUDGE_DIALOG_REQUEST; + sme_release_global_lock(&mac->sme); + + 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 nudge dialog msg fail")); + qdf_mem_free(cmd_params); + } + + SME_EXIT(); + return status; +} + QDF_STATUS sme_resume_dialog_cmd(mac_handle_t mac_handle, twt_resume_dialog_cb resume_dialog_cb, diff --git a/core/wma/inc/wma_twt.h b/core/wma/inc/wma_twt.h index 5c274737dec8..dfb97a3784a5 100644 --- a/core/wma/inc/wma_twt.h +++ b/core/wma/inc/wma_twt.h @@ -117,6 +117,18 @@ QDF_STATUS wma_twt_process_pause_dialog(t_wma_handle *wma_handle, struct wmi_twt_pause_dialog_cmd_param *params); +/** + * wma_twt_process_nudge_dialog() - Process nudge dialog command + * @wma_handle: wma handle + * @params: nudge dialog configuration parameters + * + * Return: QDF_STATUS_SUCCESS on success, other QDF_STATUS error code + * on failure + */ +QDF_STATUS +wma_twt_process_nudge_dialog(t_wma_handle *wma_handle, + struct wmi_twt_nudge_dialog_cmd_param *params); + /** * wma_twt_process_resume_dialog() - Process resume dialog command * @wma_handle: wma handle @@ -195,6 +207,15 @@ wma_twt_process_pause_dialog(t_wma_handle *wma_handle, return QDF_STATUS_E_INVAL; } +static inline QDF_STATUS +wma_twt_process_nudge_dialog(t_wma_handle *wma_handle, + struct wmi_twt_nudge_dialog_cmd_param *params) +{ + wma_debug("TWT not supported as WLAN_SUPPORT_TWT is disabled"); + + return QDF_STATUS_E_INVAL; +} + static inline QDF_STATUS wma_twt_process_resume_dialog(t_wma_handle *wma_handle, struct wmi_twt_resume_dialog_cmd_param *params) diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index b43d60a5053e..12f4ad4afa5b 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -452,6 +452,7 @@ enum wmamsgtype { WMA_TWT_PAUSE_DIALOG_REQUEST = SIR_HAL_TWT_PAUSE_DIALOG_REQUEST, WMA_TWT_RESUME_DIALOG_REQUEST = SIR_HAL_TWT_RESUME_DIALOG_REQUEST, WMA_PEER_CREATE_REQ = SIR_HAL_PEER_CREATE_REQ, + WMA_TWT_NUDGE_DIALOG_REQUEST = SIR_HAL_TWT_NUDGE_DIALOG_REQUEST, }; #define WMA_DATA_STALL_TRIGGER 6 diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 7366752b5425..d5f4967fecba 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -9067,6 +9067,10 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg) wma_twt_process_resume_dialog(wma_handle, msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case WMA_TWT_NUDGE_DIALOG_REQUEST: + wma_twt_process_nudge_dialog(wma_handle, msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: wma_debug("Unhandled WMA message of type %d", msg->type); if (msg->bodyptr) diff --git a/core/wma/src/wma_twt.c b/core/wma/src/wma_twt.c index 742e1c7aae18..02bb84d02d6f 100644 --- a/core/wma/src/wma_twt.c +++ b/core/wma/src/wma_twt.c @@ -332,6 +332,24 @@ wma_twt_process_pause_dialog(t_wma_handle *wma_handle, return wmi_unified_twt_pause_dialog_cmd(wmi_handle, params); } +QDF_STATUS +wma_twt_process_nudge_dialog(t_wma_handle *wma_handle, + struct wmi_twt_nudge_dialog_cmd_param *params) +{ + wmi_unified_t wmi_handle; + + if (wma_validate_handle(wma_handle)) + return QDF_STATUS_E_INVAL; + + wmi_handle = (wmi_unified_t)wma_handle->wmi_handle; + if (!wmi_handle) { + wma_err("Invalid wmi handle, twt nudge dialog failed"); + return QDF_STATUS_E_INVAL; + } + + return wmi_unified_twt_nudge_dialog_cmd(wmi_handle, params); +} + /** * wma_twt_pause_dialog_complete_event_handler - TWT pause dlg complete evt * handler @@ -390,6 +408,59 @@ int wma_twt_pause_dialog_complete_event_handler(void *handle, uint8_t *event, return status; } +/** + * wma_twt_nudge_dialog_complete_event_handler - TWT nudge dlg complete evt + * handler + * @handle: wma handle + * @event: buffer with event + * @len: buffer length + * + * Return: 0 on success, negative value on failure + */ +static +int wma_twt_nudge_dialog_complete_event_handler(void *handle, uint8_t *event, + uint32_t len) +{ + struct wmi_twt_nudge_dialog_complete_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 nudge dialog complete"); + return status; + } + + param = qdf_mem_malloc(sizeof(*param)); + if (!param) + return -ENOMEM; + + if (wmi_handle->ops->extract_twt_nudge_dialog_comp_event) + status = wmi_handle->ops->extract_twt_nudge_dialog_comp_event( + wmi_handle, event, param); + + wma_debug("TWT: Extract nudge dialog comp event status:%d", status); + + sme_msg.type = eWNI_SME_TWT_NUDGE_DIALOG_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 status; +} QDF_STATUS wma_twt_process_resume_dialog(t_wma_handle *wma_handle, struct wmi_twt_resume_dialog_cmd_param *params) @@ -530,4 +601,9 @@ void wma_register_twt_events(tp_wma_handle wma_handle) wmi_twt_resume_dialog_complete_event_id, wma_twt_resume_dialog_complete_event_handler, WMA_RX_SERIALIZER_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); }