| 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 |
| |