From 0187c628e3837226cb5f63ffbb26046b4b1c722d Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Fri, 4 Jan 2019 06:39:44 -0800 Subject: [PATCH] qcacld-3.0: Implement temporary WAR for BT coex issue Implement a WAR to address a BT coex issue, along with a private ioctl which can be used to switch the WAR on or off dynamically. Change-Id: I9d29c141106db479039789d67c45a455e96a118b CRs-Fixed: 2383150 --- Kbuild | 2 + configs/default_defconfig | 1 + core/hdd/inc/wlan_hdd_wext.h | 18 ++++++ core/hdd/src/wlan_hdd_main.c | 10 ++++ core/hdd/src/wlan_hdd_wext.c | 111 ++++++++++++++++++++++++++++++++++- 5 files changed, 141 insertions(+), 1 deletion(-) diff --git a/Kbuild b/Kbuild index e5d76c40836a..36742bb597d8 100644 --- a/Kbuild +++ b/Kbuild @@ -2560,6 +2560,8 @@ ccflags-y += -DQDF_LOCK_STATS_LIST=1 ccflags-y += -DQDF_LOCK_STATS_LIST_SIZE=256 endif +ccflags-$(CONFIG_HASTINGS_BT_WAR) += -DHASTINGS_BT_WAR + KBUILD_CPPFLAGS += $(cppflags-y) # Currently, for versions of gcc which support it, the kernel Makefile diff --git a/configs/default_defconfig b/configs/default_defconfig index e85d0524208e..6ed4e9e8bde2 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -18,6 +18,7 @@ ifeq ($(CONFIG_CNSS_QCA6390), y) CONFIG_WLAN_FEATURE_DFS_OFFLOAD := y CONFIG_IPA3 := n CONFIG_SCALE_INCLUDES := y + CONFIG_HASTINGS_BT_WAR := y endif ifeq ($(CONFIG_CLD_HL_SDIO_CORE), y) diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index b7d952d9d2ab..96f8e2968aff 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -334,4 +334,22 @@ static inline void hdd_register_wext(struct net_device *dev) } #endif /* WLAN_WEXT_SUPPORT_ENABLE */ +#if defined(WLAN_WEXT_SUPPORT_ENABLE) && defined(HASTINGS_BT_WAR) +int hdd_hastings_bt_war_enable_fw(struct hdd_context *hdd_ctx); +int hdd_hastings_bt_war_disable_fw(struct hdd_context *hdd_ctx); +#else +static inline +int hdd_hastings_bt_war_enable_fw(struct hdd_context *hdd_ctx) +{ + return -ENOTSUPP; +} + +static inline +int hdd_hastings_bt_war_disable_fw(struct hdd_context *hdd_ctx) +{ + return -ENOTSUPP; +} + +#endif + #endif /* __WEXT_IW_H__ */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index d75119f48bbd..bde3239541c0 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -11145,6 +11145,14 @@ static void hdd_action_oui_send(struct hdd_context *hdd_ctx) hdd_err("Failed to send one or all action_ouis"); } +static void hdd_hastings_bt_war_initialize(struct hdd_context *hdd_ctx) +{ + if (hdd_ctx->config->iface_change_wait_time) + hdd_hastings_bt_war_disable_fw(hdd_ctx); + else + hdd_hastings_bt_war_enable_fw(hdd_ctx); +} + /** * hdd_configure_cds() - Configure cds modules * @hdd_ctx: HDD context @@ -11344,6 +11352,8 @@ int hdd_configure_cds(struct hdd_context *hdd_ctx) wma_cli_set_command(0, WMI_PDEV_PARAM_FAST_PWR_TRANSITION, enable_phy_reg_retention, PDEV_CMD); + hdd_hastings_bt_war_initialize(hdd_ctx); + return 0; cds_disable: diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 19e54eea3d0e..217de349e2bf 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -197,8 +197,14 @@ * */ #define WE_SET_MAX_TX_POWER 7 -/* 8 is unused */ + +#ifdef HASTINGS_BT_WAR +/* Temporary WAR for Hastings 1.1 only */ +#define WE_SET_HASTINGS_BT_WAR 8 +#endif + #define WE_SET_TM_LEVEL 9 + /* * * setphymode - Set the phymode dynamically @@ -4287,6 +4293,99 @@ static int hdd_we_set_max_tx_power_5_0(struct hdd_adapter *adapter, int power) return qdf_status_to_os_return(status); } +#ifdef HASTINGS_BT_WAR + +/* + * replicate logic: + * iwpriv wlan0 setUnitTestCmd 19 2 23 1 => enable WAR + * iwpriv wlan0 setUnitTestCmd 19 2 23 0 => disable WAR + */ + +#define HASTINGS_WAR_FW_PARAM_ID 23 + +static int hdd_hastings_bt_war_set_fw(struct hdd_context *hdd_ctx, + uint32_t value) +{ + uint32_t vdev_id = 0; /* not used */ + uint32_t module_id = WLAN_MODULE_WAL; + uint32_t arg_count = 2; + uint32_t arg[2] = {HASTINGS_WAR_FW_PARAM_ID, value}; + QDF_STATUS status; + + status = wma_form_unit_test_cmd_and_send(vdev_id, module_id, + arg_count, arg); + + return qdf_status_to_os_return(status); +} + +int hdd_hastings_bt_war_enable_fw(struct hdd_context *hdd_ctx) +{ + return hdd_hastings_bt_war_set_fw(hdd_ctx, 1); +} + +int hdd_hastings_bt_war_disable_fw(struct hdd_context *hdd_ctx) +{ + return hdd_hastings_bt_war_set_fw(hdd_ctx, 0); +} + +/* value to restore the config when the WAR is disabled */ +static uint32_t iface_change_wait_time_checkpoint; +static void checkpoint_iface_change_wait_time(struct hdd_context *hdd_ctx) +{ + struct hdd_config *config = hdd_ctx->config; + + /* did we already checkpoint a value ? */ + if (iface_change_wait_time_checkpoint) + return; + + /* checkpoint current value */ + iface_change_wait_time_checkpoint = config->iface_change_wait_time; + + /* was the timer enabled when we checkpointed? */ + if (iface_change_wait_time_checkpoint) + return; + + /* WAR was enabled at boot, use default when disable */ + iface_change_wait_time_checkpoint = + cfg_default(CFG_INTERFACE_CHANGE_WAIT); +} + +static int hdd_hastings_war_enable(struct hdd_context *hdd_ctx) +{ + struct hdd_config *config = hdd_ctx->config; + + config->iface_change_wait_time = 0; + + return hdd_hastings_bt_war_enable_fw(hdd_ctx); +} + +static int hdd_hastings_war_disable(struct hdd_context *hdd_ctx) +{ + struct hdd_config *config = hdd_ctx->config; + + config->iface_change_wait_time = iface_change_wait_time_checkpoint; + + return hdd_hastings_bt_war_disable_fw(hdd_ctx); +} + +static int hdd_we_set_hastings_bt_war(struct hdd_adapter *adapter, int enable) +{ + int errno; + struct hdd_context *hdd_ctx; + + errno = hdd_validate_adapter(adapter); + if (errno) + return errno; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + checkpoint_iface_change_wait_time(hdd_ctx); + + return enable ? + hdd_hastings_war_enable(hdd_ctx) : + hdd_hastings_war_disable(hdd_ctx); +} +#endif + static int hdd_we_set_tm_level(struct hdd_adapter *adapter, int level) { struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -5246,6 +5345,9 @@ static const setint_getnone_fn setint_getnone_cb[] = { [WE_SET_MAX_TX_POWER] = hdd_we_set_max_tx_power, [WE_SET_MAX_TX_POWER_2_4] = hdd_we_set_max_tx_power_2_4, [WE_SET_MAX_TX_POWER_5_0] = hdd_we_set_max_tx_power_5_0, +#ifdef HASTINGS_BT_WAR + [WE_SET_HASTINGS_BT_WAR] = hdd_we_set_hastings_bt_war, +#endif [WE_SET_TM_LEVEL] = hdd_we_set_tm_level, [WE_SET_PHYMODE] = wlan_hdd_update_phymode, [WE_SET_NSS] = hdd_we_set_nss, @@ -9597,6 +9699,13 @@ static const struct iw_priv_args we_private_args[] = { 0, "setTxMaxPower"}, +#ifdef HASTINGS_BT_WAR + {WE_SET_HASTINGS_BT_WAR, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "hastings_bt_war"}, +#endif + {WE_SET_TM_LEVEL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,