From 1f58cbbf369061d222a9ec607af58063d43df591 Mon Sep 17 00:00:00 2001 From: Arif Hussain Date: Thu, 14 Mar 2019 17:06:56 -0700 Subject: [PATCH] qcacld-3.0: Add support to process twt qca vendor command Add support to process twt qca vendor command. Change-Id: I2691ce7d1cc50798d99104389fe2213791ebdf78 CRs-Fixed: 2328891 --- core/hdd/src/wlan_hdd_cfg80211.c | 178 +++++++++++++++++++++++++++++++ core/sme/inc/sme_api.h | 19 ++++ core/sme/src/common/sme_api.c | 19 ++++ core/wma/inc/wma_twt.h | 36 ++++++- core/wma/src/wma_twt.c | 42 +++++++- 5 files changed, 292 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 7f6b4f991601..4c7cdef33b2a 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -59,6 +59,7 @@ #include "wlan_hdd_wmm.h" #include "wma_types.h" #include "wma.h" +#include "wma_twt.h" #include "wlan_hdd_misc.h" #include "wlan_hdd_nan.h" #include "wlan_logging_sock_svc.h" @@ -5301,6 +5302,20 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = { }; +static const struct nla_policy qca_wlan_vendor_twt_add_dialog_policy[ + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA] = { + .type = NLA_U32 }, +}; + static const struct nla_policy qca_wlan_vendor_attr_he_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] = {.type = NLA_U8 }, @@ -5367,6 +5382,12 @@ wlan_hdd_wifi_test_config_policy[ = {.type = NLA_U8}, [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = { .type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = { + .type = NLA_NESTED}, + [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = { + .type = NLA_NESTED}, + [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = { + .type = NLA_U8}, }; /** @@ -7178,6 +7199,163 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy, adapter->vdev_id, cfg_val); } + if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) { + struct wmi_twt_add_dialog_param params = {0}; + struct hdd_station_ctx *hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + uint32_t wake_intvl_exp = 0, result = 0; + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1]; + struct nlattr *twt_session; + int tmp, rc; + + if ((adapter->device_mode != QDF_STA_MODE && + adapter->device_mode != QDF_P2P_CLIENT_MODE) || + hdd_sta_ctx->conn_info.conn_state != + eConnectionState_Associated) { + hdd_err("Invalid state, vdev %d mode %d state %d", + adapter->vdev_id, adapter->device_mode, + hdd_sta_ctx->conn_info.conn_state); + goto send_err; + } + + qdf_mem_copy(params.peer_macaddr, + hdd_sta_ctx->conn_info.bssid.bytes, + QDF_MAC_ADDR_SIZE); + params.vdev_id = adapter->vdev_id; + params.dialog_id = 0; + + cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP; + nla_for_each_nested(twt_session, tb[cmd_id], tmp) { + rc = wlan_cfg80211_nla_parse( + tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX, + nla_data(twt_session), + nla_len(twt_session), + qca_wlan_vendor_twt_add_dialog_policy); + if (rc) { + hdd_err("Invalid twt ATTR"); + goto send_err; + } + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP; + if (tb2[cmd_id]) + wake_intvl_exp = nla_get_u8(tb2[cmd_id]); + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST; + if (tb2[cmd_id]) + params.flag_bcast = nla_get_u8(tb2[cmd_id]); + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE; + if (tb2[cmd_id]) + params.twt_cmd = nla_get_u8(tb2[cmd_id]); + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER; + if (tb2[cmd_id]) + params.flag_trigger = nla_get_u8(tb2[cmd_id]); + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE; + if (tb2[cmd_id]) + params.flag_flow_type = nla_get_u8(tb2[cmd_id]); + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION; + if (tb2[cmd_id]) + params.flag_protection = + nla_get_u8(tb2[cmd_id]); + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME; + if (tb2[cmd_id]) + params.sp_offset_us = nla_get_u32(tb2[cmd_id]); + + cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION; + if (tb2[cmd_id]) + params.wake_dura_us = + 256 * nla_get_u32(tb2[cmd_id]); + + cmd_id = + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA; + if (tb2[cmd_id]) + params.wake_intvl_mantis = + nla_get_u32(tb2[cmd_id]); + + if (wake_intvl_exp) { + if (((sizeof(UINT_MAX) / 8) - 2) < + (wake_intvl_exp - 1)) { + hdd_err("Invalid wake_intvl_exp %d", + wake_intvl_exp); + goto send_err; + } + result = 2 << (wake_intvl_exp - 1); + if (result > + (UINT_MAX / params.wake_intvl_mantis)) { + hdd_err("Invalid exp %d mantissa %d", + wake_intvl_exp, + params.wake_intvl_mantis); + goto send_err; + } + params.wake_intvl_us = + params.wake_intvl_mantis * result; + } else { + params.wake_intvl_us = params.wake_intvl_mantis; + } + + if (params.wake_dura_us > 0xFFFF) { + hdd_err("Invalid wake_dura_us %d", + params.wake_dura_us); + goto send_err; + } + + hdd_debug("twt: vdev %d, intvl_us %d, mantis %d", + params.vdev_id, params.wake_intvl_us, + params.wake_intvl_mantis); + hdd_debug("twt: dura %d, offset %d, cmd %d", + params.wake_dura_us, params.sp_offset_us, + params.twt_cmd); + hdd_debug("twt: bcast %d, trigger %d, type %d, prot %d", + params.flag_bcast, params.flag_trigger, + params.flag_flow_type, + params.flag_protection); + + ret_val = qdf_status_to_os_return( + wma_twt_process_add_dialog(¶ms)); + if (ret_val) + goto send_err; + } + } + + if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) { + struct wmi_twt_del_dialog_param params = {0}; + struct hdd_station_ctx *hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + if ((adapter->device_mode != QDF_STA_MODE && + adapter->device_mode != QDF_P2P_CLIENT_MODE) || + hdd_sta_ctx->conn_info.conn_state != + eConnectionState_Associated) { + hdd_err("Invalid state, vdev %d mode %d state %d", + adapter->vdev_id, adapter->device_mode, + hdd_sta_ctx->conn_info.conn_state); + goto send_err; + } + qdf_mem_copy(params.peer_macaddr, + hdd_sta_ctx->conn_info.bssid.bytes, + QDF_MAC_ADDR_SIZE); + params.vdev_id = adapter->vdev_id; + params.dialog_id = 0; + hdd_debug("twt_terminate: vdev_id %d", params.vdev_id); + ret_val = qdf_status_to_os_return( + wma_twt_process_del_dialog(¶ms)); + if (ret_val) + goto send_err; + } + + cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT; + if (tb[cmd_id]) { + cfg_val = nla_get_u8(tb[cmd_id]); + hdd_debug("twt_request: val %d", cfg_val); + ret_val = sme_update_he_twt_req_support(hdd_ctx->mac_handle, + adapter->vdev_id, + cfg_val); + } + if (update_sme_cfg) sme_update_config(mac_handle, sme_config); diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index a824dda377e0..69f5e96aaa76 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -2829,6 +2829,17 @@ int sme_update_he_frag_supp(mac_handle_t mac_handle, uint8_t session_id, */ int sme_update_he_ldpc_supp(mac_handle_t mac_handle, uint8_t session_id, uint16_t he_ldpc); + +/** + * sme_update_he_twt_req_support() - Sets twt request capability + * @mac_handle: Opaque handle to the global MAC context + * @session_id: SME session id + * @value: set value + * + * Return: 0 on success else err code + */ +int sme_update_he_twt_req_support(mac_handle_t mac_handle, uint8_t session_id, + uint8_t cfg_val); #else static inline void sme_update_tgt_he_cap(mac_handle_t mac_handle, struct wma_tgt_cfg *cfg, @@ -2952,6 +2963,14 @@ static inline void sme_set_he_tx_bf_cbf_rates(uint8_t session_id) static inline void sme_config_su_ppdu_queue(uint8_t session_id, bool enable) { } + +static inline int sme_update_he_twt_req_support(mac_handle_t mac_handle, + uint8_t session_id, + uint8_t cfg_val) +{ + return 0; +} + #endif /** diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 1fcf1b8ebe9e..137ab08574df 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -11743,6 +11743,25 @@ int sme_update_he_ldpc_supp(mac_handle_t mac_handle, uint8_t session_id, return 0; } + +int sme_update_he_twt_req_support(mac_handle_t mac_handle, uint8_t session_id, + uint8_t cfg_val) +{ + struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle); + struct csr_roam_session *session; + + session = CSR_GET_SESSION(mac_ctx, session_id); + + if (!session) { + sme_err("No session for id %d", session_id); + return -EINVAL; + } + mac_ctx->mlme_cfg->he_caps.dot11_he_cap.twt_request = cfg_val; + + csr_update_session_he_cap(mac_ctx, session); + + return 0; +} #endif /** diff --git a/core/wma/inc/wma_twt.h b/core/wma/inc/wma_twt.h index 8efec5baa5c0..5f081bad2922 100644 --- a/core/wma/inc/wma_twt.h +++ b/core/wma/inc/wma_twt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2019 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 @@ -20,6 +20,7 @@ #define __WMA_TWT_H #include "wma.h" +#include "wmi_unified_twt_param.h" #ifdef WLAN_SUPPORT_TWT /** @@ -40,6 +41,23 @@ void wma_send_twt_enable_cmd(uint32_t pdev_id, uint32_t congestion_timeout); */ void wma_set_twt_peer_caps(tpAddStaParams params, struct peer_assoc_params *cmd); + +/** + * wma_twt_process_add_dialog() - Process twt add dialog command + * @params: add dialog configuration param + * + * Return: QDF_STATUS + */ +QDF_STATUS wma_twt_process_add_dialog(struct wmi_twt_add_dialog_param *params); + +/** + * wma_twt_process_del_dialog() - Process del dialog command + * @params: del dialog configuration param + * + * Return: QDF_STATUS + */ +QDF_STATUS wma_twt_process_del_dialog(struct wmi_twt_del_dialog_param *params); + #else static inline void wma_send_twt_enable_cmd(uint32_t pdev_id, uint32_t congestion_timeout) @@ -51,6 +69,22 @@ static inline void wma_set_twt_peer_caps(tpAddStaParams params, struct peer_assoc_params *cmd) { } + +static inline QDF_STATUS wma_twt_process_add_dialog( + struct wmi_twt_add_dialog_param *params) +{ + WMA_LOGD(FL("TWT not supported as WLAN_SUPPORT_TWT is disabled")); + + return QDF_STATUS_E_INVAL; +} + +static inline QDF_STATUS wma_twt_process_del_dialog( + struct wmi_twt_del_dialog_param *params) +{ + WMA_LOGD(FL("TWT not supported as WLAN_SUPPORT_TWT is disabled")); + + return QDF_STATUS_E_INVAL; +} #endif #endif /* __WMA_HE_H */ diff --git a/core/wma/src/wma_twt.c b/core/wma/src/wma_twt.c index 928f0bd2d9be..97869423c4aa 100644 --- a/core/wma/src/wma_twt.c +++ b/core/wma/src/wma_twt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2019 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 @@ -88,3 +88,43 @@ void wma_set_twt_peer_caps(tpAddStaParams params, struct peer_assoc_params *cmd) cmd->peer_flags |= WMI_PEER_TWT_RESP; } +QDF_STATUS wma_twt_process_add_dialog( + struct wmi_twt_add_dialog_param *params) +{ + t_wma_handle *wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + wmi_unified_t wmi_handle; + + if (!wma_handle) { + WMA_LOGE("Invalid WMA context, twt add dialog failed"); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = (wmi_unified_t)wma_handle->wmi_handle; + if (!wmi_handle) { + WMA_LOGE("Invalid wmi handle, twt add dialog failed"); + return QDF_STATUS_E_INVAL; + } + + return wmi_unified_twt_add_dialog_cmd(wmi_handle, params); +} + +QDF_STATUS wma_twt_process_del_dialog( + struct wmi_twt_del_dialog_param *params) +{ + t_wma_handle *wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + wmi_unified_t wmi_handle; + + if (!wma_handle) { + WMA_LOGE("Invalid WMA context, twt del dialog failed"); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = (wmi_unified_t)wma_handle->wmi_handle; + if (!wmi_handle) { + WMA_LOGE("Invalid wmi handle, twt del dialog failed"); + return QDF_STATUS_E_INVAL; + } + + return wmi_unified_twt_del_dialog_cmd(wmi_handle, params); +} +