Ver Fonte

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
Jeff Johnson há 6 anos atrás
pai
commit
0187c628e3

+ 2 - 0
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

+ 1 - 0
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)

+ 18 - 0
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__ */

+ 10 - 0
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:

+ 110 - 1
core/hdd/src/wlan_hdd_wext.c

@@ -197,8 +197,14 @@
  * </ioctl>
  */
 #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
+
 /*
  * <ioctl>
  * 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,