diff --git a/Kbuild b/Kbuild index ef00a964398e..f292fa7a4c69 100644 --- a/Kbuild +++ b/Kbuild @@ -245,6 +245,10 @@ ifeq ($(CONFIG_WLAN_BCN_RECV_FEATURE), y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_bcn_recv.o endif +ifeq ($(CONFIG_QCACLD_FEATURE_HW_CAPABILITY), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_hw_capability.o +endif + ###### OSIF_SYNC ######## SYNC_DIR := os_if/sync SYNC_INC_DIR := $(SYNC_DIR)/inc @@ -2607,6 +2611,9 @@ cppflags-$(CONFIG_QCACLD_FEATURE_COEX_CONFIG) += -DFEATURE_COEX_CONFIG #Flag to enable MPTA helper feature cppflags-$(CONFIG_QCACLD_FEATURE_MPTA_HELPER) += -DFEATURE_MPTA_HELPER +#Flag to enable get hw capability +cppflags-$(CONFIG_QCACLD_FEATURE_HW_CAPABILITY) += -DFEATURE_HW_CAPABILITY + cppflags-$(CONFIG_DATA_CE_SW_INDEX_NO_INLINE_UPDATE) += -DDATA_CE_SW_INDEX_NO_INLINE_UPDATE #Flag to enable Multi page memory allocation for RX descriptor pool diff --git a/configs/default_defconfig b/configs/default_defconfig index 36b847b99859..a8cf80820011 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -129,6 +129,11 @@ CONFIG_QCACLD_FEATURE_FW_STATE := y #Flag to enable set coex configuration CONFIG_QCACLD_FEATURE_COEX_CONFIG := n +#Flag to enable get hw capability +ifeq ($(CONFIG_ARCH_QCS405), y) +CONFIG_QCACLD_FEATURE_HW_CAPABILITY := y +endif + ifeq ($(CONFIG_ARCH_MSM8998), y) CONFIG_QCACLD_FEATURE_METERING := y endif diff --git a/configs/qcs40x.snoc.perf_defconfig b/configs/qcs40x.snoc.perf_defconfig index d03795e28f35..82b50fdf917b 100644 --- a/configs/qcs40x.snoc.perf_defconfig +++ b/configs/qcs40x.snoc.perf_defconfig @@ -102,6 +102,7 @@ CONFIG_PTT_SOCK_SVC_ENABLE := y CONFIG_WMI_INTERFACE_EVENT_LOGGING := y CONFIG_WLAN_FEATURE_LINK_LAYER_STATS := y CONFIG_DP_TRACE := n +CONFIG_QCACLD_FEATURE_HW_CAPABILITY := y CONFIG_WLAN_LOG_FATAL := y CONFIG_WLAN_LOG_ERROR := y diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index b42417feff90..244721793769 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -237,6 +237,8 @@ enum hdd_driver_flags { #define WLAN_WAIT_TIME_FW_ROAM_STATS 1000 +#define WLAN_WAIT_TIME_ANTENNA_ISOLATION 8000 + /* Maximum time(ms) to wait for RSO CMD status event */ #define WAIT_TIME_RSO_CMD_STATUS 2000 diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 1258b3a46fa7..7c7bcbbca323 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -142,6 +142,7 @@ #include "wlan_hdd_coex_config.h" #include "wlan_hdd_bcn_recv.h" #include "wlan_blm_ucfg_api.h" +#include "wlan_hdd_hw_capability.h" #define g_mode_rates_size (12) #define a_mode_rates_size (8) @@ -13139,6 +13140,7 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { FEATURE_FW_STATE_COMMANDS FEATURE_COEX_CONFIG_COMMANDS FEATURE_MPTA_HELPER_COMMANDS + FEATURE_HW_CAPABILITY_COMMANDS }; struct hdd_context *hdd_cfg80211_wiphy_alloc(void) diff --git a/core/hdd/src/wlan_hdd_hw_capability.c b/core/hdd/src/wlan_hdd_hw_capability.c new file mode 100644 index 000000000000..9898c6a6e491 --- /dev/null +++ b/core/hdd/src/wlan_hdd_hw_capability.c @@ -0,0 +1,212 @@ +/* + * 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_hdd_hw_capability.c + * + * The implementation of get hw capability + * + */ + +#include "wlan_hdd_main.h" +#include "wmi_unified_param.h" +#include "wlan_hdd_hw_capability.h" +#include "qca_vendor.h" +#include "wlan_osif_request_manager.h" +#include "osif_sync.h" + +/** + * hdd_get_isolation_cb - Callback function to get isolation information + * @context: opaque context originally passed to SME. HDD always passes + * a cookie for the request context + * @isolation: pointer of isolation information + * + * This function will fill isolation information to isolation priv adapter + * + * Return: None + */ +static void hdd_get_isolation_cb(struct sir_isolation_resp *isolation, + void *context) +{ + struct osif_request *request; + struct sir_isolation_resp *priv; + + if (!isolation) { + hdd_err("Bad param"); + return; + } + + request = osif_request_get(context); + if (!request) { + hdd_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + priv->isolation_chain0 = isolation->isolation_chain0; + priv->isolation_chain1 = isolation->isolation_chain1; + priv->isolation_chain2 = isolation->isolation_chain2; + priv->isolation_chain3 = isolation->isolation_chain3; + + osif_request_complete(request); + osif_request_put(request); +} + +/** + * hdd_post_isolation - send rsp to user space + * @hdd_ctx: pointer to hdd context + * @isolation: antenna isolation information + * + * Return: 0 for success, non-zero for failure + */ +static int hdd_post_isolation(struct hdd_context *hdd_ctx, + struct sir_isolation_resp *isolation) +{ + struct sk_buff *skb; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, + (sizeof(u8) + NLA_HDRLEN) + + (sizeof(u8) + NLA_HDRLEN) + + (sizeof(u8) + NLA_HDRLEN) + + (sizeof(u8) + NLA_HDRLEN) + + NLMSG_HDRLEN); + + if (!skb) { + hdd_err("cfg80211_vendor_event_alloc failed"); + return -ENOMEM; + } + + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION, + isolation->isolation_chain0)) { + hdd_err("put fail"); + goto nla_put_failure; + } + + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION, + isolation->isolation_chain1)) { + hdd_err("put fail"); + goto nla_put_failure; + } + + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION, + isolation->isolation_chain2)) { + hdd_err("put fail"); + goto nla_put_failure; + } + + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION, + isolation->isolation_chain3)) { + hdd_err("put fail"); + goto nla_put_failure; + } + + cfg80211_vendor_cmd_reply(skb); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +/** + * __wlan_hdd_cfg80211_get_hw_capability() - get hw capability + * @wiphy: wiphy device pointer + * @wdev: wireless device pointer + * @data: Vendor command data buffer + * @data_len: Buffer length + * + * Return: 0 on success; error number otherwise. + * + */ +static int __wlan_hdd_cfg80211_get_hw_capability(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + struct osif_request *request; + struct sir_isolation_resp *priv; + mac_handle_t mac_handle; + void *cookie; + QDF_STATUS status; + int ret; + static const struct osif_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_ANTENNA_ISOLATION, + }; + + hdd_enter(); + + if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); + return -ENOMEM; + } + + cookie = osif_request_cookie(request); + + mac_handle = hdd_ctx->mac_handle; + status = sme_get_isolation(mac_handle, + cookie, + hdd_get_isolation_cb); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Unable to retrieve isolation"); + ret = -EFAULT; + } else { + ret = osif_request_wait_for_response(request); + if (ret) { + hdd_err("SME timed out while retrieving isolation"); + ret = -ETIMEDOUT; + } else { + priv = osif_request_priv(request); + hdd_post_isolation(hdd_ctx, priv); + ret = 0; + } + } + osif_request_put(request); + + return ret; +} + +int wlan_hdd_cfg80211_get_hw_capability(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int errno; + struct osif_vdev_sync *vdev_sync; + + errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); + if (errno) + return errno; + + errno = __wlan_hdd_cfg80211_get_hw_capability(wiphy, wdev, + data, data_len); + + osif_vdev_sync_op_stop(vdev_sync); + + return errno; +} diff --git a/core/hdd/src/wlan_hdd_hw_capability.h b/core/hdd/src/wlan_hdd_hw_capability.h new file mode 100644 index 000000000000..0cbdc071a54a --- /dev/null +++ b/core/hdd/src/wlan_hdd_hw_capability.h @@ -0,0 +1,58 @@ +/* + * 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_hdd_hw_capability.h + * + * Add Vendor subcommand QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY + */ + +#ifndef __WLAN_HDD_HW_CAPABILITY_H +#define __WLAN_HDD_HW_CAPABILITY_H + +#ifdef FEATURE_HW_CAPABILITY +#include + +/** + * wlan_hdd_cfg80211_get_hw_capability() - get hardware capability + * @wiphy: wiphy device pointer + * @wdev: wireless device pointer + * @data: Vendor command data buffer + * @data_len: Buffer length + * + * Return: 0 on success; error number otherwise. + */ +int wlan_hdd_cfg80211_get_hw_capability(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +#define FEATURE_HW_CAPABILITY_COMMANDS \ +{ \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY,\ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ + WIPHY_VENDOR_CMD_NEED_NETDEV | \ + WIPHY_VENDOR_CMD_NEED_RUNNING, \ + .doit = wlan_hdd_cfg80211_get_hw_capability \ +}, +#else /* FEATURE_HW_CAPABILITY */ +#define FEATURE_HW_CAPABILITY_COMMANDS +#endif /* FEATURE_HW_CAPABILITY */ + +#endif /* __WLAN_HDD_HW_CAPABILITY_H */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 34fc7e46cc53..970440e0a7e7 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2712,6 +2712,20 @@ struct sir_peer_sta_ext_info { struct sir_peer_info_ext info[MAX_PEER_STA]; }; +/** + * struct sir_isolation_resp - isolation info related structure + * @isolation_chain0: isolation value for chain 0 + * @isolation_chain1: isolation value for chain 1 + * @isolation_chain2: isolation value for chain 2 + * @isolation_chain3: isolation value for chain 3 + */ +struct sir_isolation_resp { + uint32_t isolation_chain0:8, + isolation_chain1:8, + isolation_chain2:8, + isolation_chain3:8; +}; + typedef struct sSirAddPeriodicTxPtrn { /* MAC Address for the adapter */ struct qdf_mac_addr mac_address; diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index a31ae81fc496..2789f493edb0 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -238,7 +238,8 @@ enum eWniMsgTypes { eWNI_SME_FW_STATUS_IND = SIR_SME_MSG_TYPES_BEGIN + 152, eWNI_SME_STA_CSA_CONTINUE_REQ = SIR_SME_MSG_TYPES_BEGIN + 153, WNI_SME_REGISTER_BCN_REPORT_SEND_CB = SIR_SME_MSG_TYPES_BEGIN + 154, - eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 155 + eWNI_SME_ANTENNA_ISOLATION_RSP = SIR_SME_MSG_TYPES_BEGIN + 155, + eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 156 }; typedef struct sAniCfgTxRateCtrs { diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 07569e8c90c3..d5bdd1fcf93a 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -663,6 +663,8 @@ struct sir_cfg_action_frm_tb_ppdu { #define SIR_HAL_SEND_PEER_UNMAP_CONF (SIR_HAL_ITC_MSG_TYPES_BEGIN + 411) +#define SIR_HAL_GET_ISOLATION (SIR_HAL_ITC_MSG_TYPES_BEGIN + 412) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* LIM message types */ 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 71fe945836ca..43b56d29c6f6 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 @@ -370,6 +370,7 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg) CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END); CASE_RETURN_STRING(eWNI_SME_HIDDEN_SSID_RESTART_RSP); CASE_RETURN_STRING(eWNI_SME_STA_CSA_CONTINUE_REQ); + CASE_RETURN_STRING(eWNI_SME_ANTENNA_ISOLATION_RSP); default: return (uint8_t *) "UNKNOWN"; break; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 8e2d860550dd..25cade9ae04f 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -2271,6 +2271,20 @@ QDF_STATUS sme_get_chain_rssi(mac_handle_t mac_handle, get_chain_rssi_callback callback, void *context); +/** + * sme_get_isolation() - sme api to get antenna isolation + * @mac_handle: hal handle for getting global mac struct + * @context: context of callback function + * @callbackfn: hdd callback function when receive response + * + * This function will send WMA_GET_ISOLATION to WMA + * + * Return: QDF_STATUS_SUCCESS or non-zero on failure + */ +QDF_STATUS sme_get_isolation(mac_handle_t mac_handle, + void *context, + sme_get_isolation_cb callbackfn); + #ifdef FEATURE_FW_STATE /** * sme_get_fw_state() - Get fw state diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 59fbb1c055a2..7f8f150af9df 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -277,6 +277,15 @@ typedef void (*beacon_pause_cb)(hdd_handle_t hdd_handle, enum scan_event_type type, bool is_disconnected); +/** + * typedef sme_get_isolation_cb - get isolation callback fun + * @param: isolation result reported by firmware + * @pcontext: Opaque context that the client can use to associate the + * callback with the request + */ +typedef void (*sme_get_isolation_cb)(struct sir_isolation_resp *param, + void *pcontext); + #ifdef WLAN_FEATURE_MOTION_DETECTION typedef QDF_STATUS (*md_host_evt_cb)(void *hdd_ctx, struct sir_md_evt *event); #endif /* WLAN_FEATURE_MOTION_DETECTION */ @@ -325,6 +334,8 @@ struct sme_context { void (*pget_peer_info_ext_ind_cb)(struct sir_peer_info_ext_resp *param, void *pcontext); void *pget_peer_info_ext_cb_context; + sme_get_isolation_cb get_isolation_cb; + void *get_isolation_cb_context; #ifdef FEATURE_WLAN_EXTSCAN ext_scan_ind_cb ext_scan_ind_cb; #endif /* FEATURE_WLAN_EXTSCAN */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 8392012c8bf7..8613c9ff5c16 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -2264,6 +2264,17 @@ QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg) else sme_err("callback is NULL"); break; + case eWNI_SME_ANTENNA_ISOLATION_RSP: + if (pMsg->bodyptr) { + if (mac->sme.get_isolation_cb) + mac->sme.get_isolation_cb( + (struct sir_isolation_resp *)pMsg->bodyptr, + mac->sme.get_isolation_cb_context); + qdf_mem_free(pMsg->bodyptr); + } else { + sme_err("Empty message for: %d", pMsg->type); + } + break; default: if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) @@ -7567,6 +7578,36 @@ QDF_STATUS sme_get_peer_info_ext(mac_handle_t mac_handle, return status; } +QDF_STATUS sme_get_isolation(mac_handle_t mac_handle, void *context, + sme_get_isolation_cb callbackfn) +{ + QDF_STATUS status; + struct mac_context *mac = MAC_CONTEXT(mac_handle); + struct scheduler_msg message = {0}; + + if (!callbackfn) { + sme_err("Indication Call back is NULL"); + return QDF_STATUS_E_FAILURE; + } + status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_ERROR(status)) + return status; + mac->sme.get_isolation_cb = callbackfn; + mac->sme.get_isolation_cb_context = context; + message.bodyptr = NULL; + message.type = WMA_GET_ISOLATION; + status = scheduler_post_message(QDF_MODULE_ID_SME, + QDF_MODULE_ID_WMA, + QDF_MODULE_ID_WMA, + &message); + if (!QDF_IS_STATUS_SUCCESS(status)) { + sme_err("failed to post WMA_GET_ISOLATION"); + status = QDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + return status; +} + /*convert the ini value to the ENUM used in csr and MAC for CB state*/ ePhyChanBondState sme_get_cb_phy_state_from_cb_ini_value(uint32_t cb_ini_value) { diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 0e37064f5346..bad0b9577444 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1060,6 +1060,16 @@ QDF_STATUS wma_get_peer_info(WMA_HANDLE handle, QDF_STATUS wma_get_peer_info_ext(WMA_HANDLE handle, struct sir_peer_info_ext_req *peer_info_req); +/** + * wma_get_isolation() - get antenna isolation + * @handle: wma interface + * + * This function will send WMI_COEX_GET_ANTENNA_ISOLATION_CMDID to FW + * + * Return: 0 on success, otherwise error value + */ +QDF_STATUS wma_get_isolation(tp_wma_handle wma); + /** * wma_peer_info_event_handler() - Handler for WMI_PEER_STATS_INFO_EVENTID * @handle: WMA global handle diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index c8fc52e3215d..7a620ddc09cc 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -336,6 +336,8 @@ #define WMA_GET_PEER_INFO SIR_HAL_GET_PEER_INFO #define WMA_GET_PEER_INFO_EXT SIR_HAL_GET_PEER_INFO_EXT +#define WMA_GET_ISOLATION SIR_HAL_GET_ISOLATION + #define WMA_MODEM_POWER_STATE_IND SIR_HAL_MODEM_POWER_STATE_IND #ifdef WLAN_FEATURE_STATS_EXT diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index ad0e6d6b4ff2..79b45f6d52c0 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -901,6 +901,46 @@ QDF_STATUS wma_get_peer_info_ext(WMA_HANDLE handle, return QDF_STATUS_SUCCESS; } +QDF_STATUS wma_get_isolation(tp_wma_handle wma) +{ + wmi_coex_get_antenna_isolation_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + uint8_t *buf_ptr; + + WMA_LOGD("%s: get isolation", __func__); + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue get isolation", + __func__); + return QDF_STATUS_E_INVAL; + } + + len = sizeof(wmi_coex_get_antenna_isolation_cmd_fixed_param); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf); + + cmd = (wmi_coex_get_antenna_isolation_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR( + &cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_coex_get_antenna_isolation_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_coex_get_antenna_isolation_cmd_fixed_param)); + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_COEX_GET_ANTENNA_ISOLATION_CMDID)) { + WMA_LOGE("Failed to get isolation request from fw"); + wmi_buf_free(wmi_buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + /** * wma_add_beacon_filter() - Issue WMI command to set beacon filter * @wma: wma handler diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 295a9946d346..82a0bbb3b691 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1818,6 +1818,69 @@ int wma_process_fw_event_handler(ol_scn_t scn_handle, void *evt_buf, return err; } +/** + * wma_antenna_isolation_event_handler() - antenna isolation event handler + * @handle: wma handle + * @param: event data + * @len: length + * + * Return: 0 for success or error code + */ +static int wma_antenna_isolation_event_handler(void *handle, + u8 *param, + u32 len) +{ + struct scheduler_msg cds_msg = {0}; + wmi_coex_report_isolation_event_fixed_param *event; + WMI_COEX_REPORT_ANTENNA_ISOLATION_EVENTID_param_tlvs *param_buf; + struct sir_isolation_resp *pisolation; + struct mac_context *mac = NULL; + + WMA_LOGD("%s: handle %pK param %pK len %d", __func__, + handle, param, len); + + mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); + if (!mac) { + WMA_LOGE("%s: Invalid mac context", __func__); + return -EINVAL; + } + + pisolation = qdf_mem_malloc(sizeof(*pisolation)); + if (!pisolation) + return 0; + + param_buf = + (WMI_COEX_REPORT_ANTENNA_ISOLATION_EVENTID_param_tlvs *)param; + if (!param_buf) { + WMA_LOGE("%s: Invalid isolation event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + pisolation->isolation_chain0 = event->isolation_chain0; + pisolation->isolation_chain1 = event->isolation_chain1; + pisolation->isolation_chain2 = event->isolation_chain2; + pisolation->isolation_chain3 = event->isolation_chain3; + + WMA_LOGD("%s: chain1 %d chain2 %d chain3 %d chain4 %d", __func__, + pisolation->isolation_chain0, pisolation->isolation_chain1, + pisolation->isolation_chain2, pisolation->isolation_chain3); + + cds_msg.type = eWNI_SME_ANTENNA_ISOLATION_RSP; + cds_msg.bodyptr = pisolation; + cds_msg.bodyval = 0; + if (QDF_STATUS_SUCCESS != + scheduler_post_message(QDF_MODULE_ID_WMA, + QDF_MODULE_ID_SME, + QDF_MODULE_ID_SME, &cds_msg)) { + WMA_LOGE("%s: could not post peer info rsp msg to SME", + __func__); + /* free the mem and return */ + qdf_mem_free(pisolation); + } + + return 0; +} + /** * wma_init_max_no_of_peers - API to initialize wma configuration params * @wma_handle: WMA Handle @@ -3632,6 +3695,12 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, wma_rx_aggr_failure_event_handler, WMA_RX_SERIALIZER_CTX); + wmi_unified_register_event_handler( + wma_handle->wmi_handle, + wmi_coex_report_antenna_isolation_event_id, + wma_antenna_isolation_event_handler, + WMA_RX_SERIALIZER_CTX); + wma_handle->ito_repeat_count = cds_cfg->ito_repeat_count; wma_handle->bandcapability = cds_cfg->bandcapability; @@ -8726,6 +8795,9 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg) wma_get_peer_info_ext(wma_handle, msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case WMA_GET_ISOLATION: + wma_get_isolation(wma_handle); + break; case WMA_MODEM_POWER_STATE_IND: wma_notify_modem_power_state(wma_handle, (tSirModemPowerStateInd *) msg->bodyptr);