ath10k: debugfs file to enable Bluetooth coexistence feature
authorYanbo Li <yanbol@qca.qualcomm.com>
Sat, 31 Oct 2015 09:07:21 +0000 (11:07 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Wed, 4 Nov 2015 17:37:32 +0000 (19:37 +0200)
As not all QCA98XX radios are not connected to Bluetooth modules, enabling the
BT coex feature in firmware will have side effects if the radio's GPIO are
connected with other (non-BT) HW modules. Add debugfs file to control the
firmware BT coex logic and set the feature as disable by default to avoid that
btcoex is accidentally enabled.

To enable this feature, execute:

echo 1 > /sys/kernel/debug/ieee80211/phyX/ath10k/btcoex

To disable:

echo 0 > /sys/kernel/debug/ieee80211/phyX/ath10k/btcoex

The firmware support this feature since 10.2.4.54 on 2G-only board, dual band
or 5G boards don't support this. The feature's name is WMI_SERVICE_COEX_GPIO
and the btcoex file is not created if firmware doesn't support it.

Signed-off-by: Yanbo Li <yanbol@qca.qualcomm.com>
[kvalo@qca.qualcomm.com: use btcoex filename and other smaller fixes]
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/wmi.c

index c26f84ee80ea72a746e122855011cdbaf4a7e445..c16f3484dc8a7313344585084257cfd39ea27c63 100644 (file)
@@ -538,6 +538,9 @@ enum ath10k_dev_flags {
 
        /* Disable HW crypto engine */
        ATH10K_FLAG_HW_CRYPTO_DISABLED,
+
+       /* Bluetooth coexistance enabled */
+       ATH10K_FLAG_BTCOEX,
 };
 
 enum ath10k_cal_mode {
index 6cc1aa3449c88640359ef716e3b300b692154d24..145c066b50870c84374430d7549a9239f78f6678 100644 (file)
@@ -2074,6 +2074,68 @@ static const struct file_operations fops_quiet_period = {
        .open = simple_open
 };
 
+static ssize_t ath10k_write_btcoex(struct file *file,
+                                  const char __user *ubuf,
+                                  size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       char buf[32];
+       size_t buf_size;
+       bool val;
+
+       buf_size = min(count, (sizeof(buf) - 1));
+       if (copy_from_user(buf, ubuf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+
+       if (strtobool(buf, &val) != 0)
+               return -EINVAL;
+
+       mutex_lock(&ar->conf_mutex);
+
+       if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
+               goto exit;
+
+       if (val)
+               set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
+       else
+               clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
+
+       if (ar->state != ATH10K_STATE_ON)
+               goto exit;
+
+       ath10k_info(ar, "restarting firmware due to btcoex change");
+
+       queue_work(ar->workqueue, &ar->restart_work);
+
+exit:
+       mutex_unlock(&ar->conf_mutex);
+
+       return count;
+}
+
+static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
+                                 size_t count, loff_t *ppos)
+{
+       char buf[32];
+       struct ath10k *ar = file->private_data;
+       int len = 0;
+
+       mutex_lock(&ar->conf_mutex);
+       len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+                       test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
+       mutex_unlock(&ar->conf_mutex);
+
+       return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_btcoex = {
+       .read = ath10k_read_btcoex,
+       .write = ath10k_write_btcoex,
+       .open = simple_open
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
        ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
@@ -2183,6 +2245,10 @@ int ath10k_debug_register(struct ath10k *ar)
        debugfs_create_file("tpc_stats", S_IRUSR,
                            ar->debug.debugfs_phy, ar, &fops_tpc_stats);
 
+       if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
+               debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
+                                   ar->debug.debugfs_phy, ar, &fops_btcoex);
+
        return 0;
 }
 
index e3ce8f09f1106c30783b5483a55893d6a3103395..56806d94e65e5870b9ef490793c4269bb74ca863 100644 (file)
@@ -5476,8 +5476,11 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
        cmd = (struct wmi_init_cmd_10_2 *)buf->data;
 
        features = WMI_10_2_RX_BATCH_MODE;
-       if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
+
+       if (test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) &&
+           test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
                features |= WMI_10_2_COEX_GPIO;
+
        cmd->resource_config.feature_mask = __cpu_to_le32(features);
 
        memcpy(&cmd->resource_config.common, &config, sizeof(config));