[PATCH] Bluetooth: msft: add a bluetooth parameter, msft_enable

From: Koba Ko
Date: Thu Aug 12 2021 - 00:23:32 EST


With Intel AC9560, follow this scenario and can't turn on bt since.
1. turn off BT
2. then suspend&resume multiple times
3. turn on BT

Get this error message after turn on bt.
[ 877.194032] Bluetooth: hci0: urb 0000000061b9a002 failed to resubmit (113)
[ 886.941327] Bluetooth: hci0: Failed to read MSFT supported features (-110)

Remove msft from compilation would be helpful.
Turn off msft would be also helpful.

Because msft is enabled as default and can't turn off without
compliation,
Introduce a bluetooth parameter, msft_enable, to control.

Signed-off-by: Koba Ko <koba.ko@xxxxxxxxxxxxx>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_core.c | 16 ++++++++++++++++
net/bluetooth/msft.c | 30 +++++++++++++++++++++++++++++-
3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a7d06d7da602..002753db936a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1229,6 +1229,7 @@ static inline void *hci_get_priv(struct hci_dev *hdev)
return (char *)hdev + sizeof(*hdev);
}

+void hci_set_msft(bool enable);
struct hci_dev *hci_dev_get(int index);
struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, u8 src_type);

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cb2e9e513907..9e1bdaea20a8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1045,6 +1045,22 @@ static int hci_linkpol_req(struct hci_request *req, unsigned long opt)
return 0;
}

+void hci_set_msft(bool enable)
+{
+ struct hci_dev *hdev = NULL, *d;
+
+ read_lock(&hci_dev_list_lock);
+ list_for_each_entry(d, &hci_dev_list, list) {
+ hdev = hci_dev_hold(d);
+ if (enable)
+ msft_do_open(hdev);
+ else
+ msft_do_close(hdev);
+ hci_dev_put(hdev);
+ }
+ read_unlock(&hci_dev_list_lock);
+}
+
/* Get HCI device by index.
* Device is held on return. */
struct hci_dev *hci_dev_get(int index)
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index b4bfae41e8a5..0bb50ee11bf8 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -97,6 +97,34 @@ struct msft_data {
__u8 filter_enabled;
};

+static bool msft_enable = true;
+
+static int msft_set_enable(const char *s, const struct kernel_param *kp)
+{
+ bool do_enable;
+ int ret;
+
+ if (!s)
+ return 0;
+
+ ret = strtobool(s, &do_enable);
+ if (ret || msft_enable == do_enable)
+ return ret;
+
+ hci_set_msft(do_enable);
+
+ msft_enable = do_enable;
+
+ return ret;
+}
+
+static const struct kernel_param_ops msft_enable_ops = {
+ .set = msft_set_enable,
+ .get = param_get_bool,
+};
+
+module_param_cb(msft_enable, &msft_enable_ops, &msft_enable, 0644);
+
static int __msft_add_monitor_pattern(struct hci_dev *hdev,
struct adv_monitor *monitor);

@@ -186,7 +214,7 @@ void msft_do_open(struct hci_dev *hdev)
{
struct msft_data *msft;

- if (hdev->msft_opcode == HCI_OP_NOP)
+ if (!msft_enable || hdev->msft_opcode == HCI_OP_NOP)
return;

bt_dev_dbg(hdev, "Initialize MSFT extension");
--
2.25.1