blob: 6a1e56e07cfde7f97d03d65b8bf67aa600f0c79f [file] [log] [blame]
From 46d73c7a1313ceec9dce6f9e768f3560c5b896cc Mon Sep 17 00:00:00 2001
From: Joseph Hwang <josephsih@chromium.org>
Date: Thu, 7 Apr 2022 15:24:02 +0800
Subject: [PATCH] CHROMIUM: Bluetooth: let HCI_QUALITY_REPORT persist over
adapter power cycle
The quality report specifications, including AOSP Bluetooth Quality
Report and Intel Telemetry Event, do not define what happen when
the adapter is turned off and then on. To be consistent among
different specifications and vendors, the quality report feature is
turned off when the adapter is powered off and is turned on when
the adapter is powered on if the feature has been on before power
cycle.
BUG=b:228565358, b:242124116
TEST=After enabling BQR, turn off and then on the Bluetooth adapter.
The BQR feature should still be working.
Signed-off-by: Joseph Hwang <josephsih@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3583641
Reviewed-by: Archie Pusaka <apusaka@chromium.org>
Change-Id: I1c81ebb7e5db5c2659f15847e2705fe4f57c9450
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3823822
---
include/net/bluetooth/hci_core.h | 1 -
net/bluetooth/hci_sync.c | 37 +++++++++++++++++++++++++++++---
2 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 331bfced866c90badb51322a105e2afba3077831..fca2a4bd27dd8a87c5965f81925fc00d3e08f4d3 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -834,7 +834,6 @@ extern struct mutex hci_cb_list_lock;
hci_dev_clear_flag(hdev, HCI_LE_ADV); \
hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION);\
hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); \
- hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); \
} while (0)
#define hci_dev_le_state_simultaneous(hdev) \
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index c970b2d59ceb302d85ec154f49a9cc15e958cecc..bc4f8378dc736adfebc6fba5ca0d72eb68724e73 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -4474,6 +4474,22 @@ static int hci_init_sync(struct hci_dev *hdev)
return 0;
}
+static void set_quality_report(struct hci_dev *hdev, bool enable)
+{
+ int err;
+
+ if (hdev->set_quality_report)
+ err = hdev->set_quality_report(hdev, enable);
+ else
+ err = aosp_set_quality_report(hdev, enable);
+
+ if (err)
+ bt_dev_err(hdev, "set quality report error %d (enable %d)",
+ err, enable);
+ else
+ bt_dev_info(hdev, "set quality report (enable %d)", enable);
+}
+
#define HCI_QUIRK_BROKEN(_quirk, _desc) { HCI_QUIRK_BROKEN_##_quirk, _desc }
static const struct {
@@ -4627,6 +4643,9 @@ static int hci_dev_init_sync(struct hci_dev *hdev)
if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
msft_do_open(hdev);
aosp_do_open(hdev);
+
+ if (hci_dev_test_flag(hdev, HCI_QUALITY_REPORT))
+ set_quality_report(hdev, true);
}
clear_bit(HCI_INIT, &hdev->flags);
@@ -4795,6 +4814,17 @@ int hci_dev_close_sync(struct hci_dev *hdev)
hci_request_cancel_all(hdev);
+ /* Disable quality report and close aosp before shutdown()
+ * is called. Otherwise, some chips may panic.
+ */
+ if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
+ if (hci_dev_test_flag(hdev, HCI_QUALITY_REPORT))
+ set_quality_report(hdev, false);
+
+ aosp_do_close(hdev);
+ }
+
+
if (hdev->adv_instance_timeout) {
cancel_delayed_work_sync(&hdev->adv_instance_expire);
hdev->adv_instance_timeout = 0;
@@ -4856,10 +4886,11 @@ int hci_dev_close_sync(struct hci_dev *hdev)
hci_sock_dev_event(hdev, HCI_DEV_DOWN);
- if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
- aosp_do_close(hdev);
+ /* TODO: May be better to close msft early in the beginning of
+ * hci_dev_do_close before shutdown() is called.
+ */
+ if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
msft_do_close(hdev);
- }
if (hdev->flush)
hdev->flush(hdev);
--
2.38.1.584.g0f3c55d4c2-goog