blob: 3ca09e8d17b339b2cc79e04992adb86c5d886a76 [file] [log] [blame]
From 0e730c93a36cc52e89143a3eaa3e47837e490d8f Mon Sep 17 00:00:00 2001
From: Archie Pusaka <apusaka@chromium.org>
Date: Fri, 22 Jan 2021 19:49:05 +0800
Subject: [PATCH] CHROMIUM: Bluetooth: updating controller reset handler
Since there is a logic change in msft_do_open and msft_do_close,
the handler to remove monitor mapping on controller reset needs
to be modifed.
BUG=b:153383808
TEST=Do the following test.
(1) Upon hci0 power on, all monitors would be registered to the
controller. This could be checked by powering off the controller,
then add some monitor, then power on the controller. The userspace
should not be notified when this happens.
(2) Upon hci0 power off, the currently registered monitor list is not
discarded. This could be checked by powering the controller back
on and see that the monitors would all be re-registered. The
userspace should not be notified when this happens.
(3) A monitor which is successfully added when the power is off might
have problems when it is actually presented to the controller when
the power is back on. These monitors should be removed on power on
and the userspace should be notified for the deletion. This could
be tested by adding monitors with invalid rssi when powered off,
then power the controller on.
Signed-off-by: Archie Pusaka <apusaka@chromium.org>
Signed-off-by: Yun-Hao Chung <howardchung@google.com>
Change-Id: Ifd445ff4a11d2f5bd6632bbb0964ff63a689de91
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2675380
Tested-by: Yun-Hao Chung <howardchung@google.com>
Reviewed-by: Archie Pusaka <apusaka@chromium.org>
Commit-Queue: Yun-Hao Chung <howardchung@google.com>
---
net/bluetooth/hci_core.c | 2 ++
net/bluetooth/msft.c | 35 +++++++++++++++++++++++++++--------
net/bluetooth/msft.h | 4 ++++
3 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9371bc7e0cfc..3620c339b80a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1588,6 +1588,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
msft_do_open(hdev);
aosp_do_open(hdev);
+ msft_power_on(hdev);
clear_bit(HCI_INIT, &hdev->flags);
@@ -1785,6 +1786,7 @@ int hci_dev_do_close(struct hci_dev *hdev)
hci_sock_dev_event(hdev, HCI_DEV_DOWN);
aosp_do_close(hdev);
+ msft_power_off(hdev);
if (hdev->flush)
hdev->flush(hdev);
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index efb429f2c768..a22ea64fd989 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -203,15 +203,38 @@ void msft_do_open(struct hci_dev *hdev)
INIT_LIST_HEAD(&msft->handle_map);
hdev->msft_data = msft;
+}
+
+void msft_do_close(struct hci_dev *hdev)
+{
+ struct msft_data *msft = hdev->msft_data;
+
+ if (!msft)
+ return;
+
+ bt_dev_dbg(hdev, "Cleanup of MSFT extension");
+
+ hdev->msft_data = NULL;
+
+ kfree(msft->evt_prefix);
+ kfree(msft);
+}
+
+void msft_power_on(struct hci_dev *hdev)
+{
+ struct msft_data *msft = hdev->msft_data;
if (msft_monitor_supported(hdev)) {
msft->reregistering = true;
msft_set_filter_enable(hdev, true);
+ /* Monitors get removed on power off, so we need to explicitly
+ * tell the controller to re-monitor.
+ */
reregister_monitor_on_restart(hdev, 0);
}
}
-void msft_do_close(struct hci_dev *hdev)
+void msft_power_off(struct hci_dev *hdev)
{
struct msft_data *msft = hdev->msft_data;
struct msft_monitor_advertisement_handle_data *handle_data, *tmp;
@@ -220,10 +243,9 @@ void msft_do_close(struct hci_dev *hdev)
if (!msft)
return;
- bt_dev_dbg(hdev, "Cleanup of MSFT extension");
-
- hdev->msft_data = NULL;
-
+ /* The controller will silently remove all monitors on power off.
+ * Therefore, remove handle_data mapping and reset monitor state.
+ */
list_for_each_entry_safe(handle_data, tmp, &msft->handle_map, list) {
monitor = idr_find(&hdev->adv_monitors_idr,
handle_data->mgmt_handle);
@@ -234,9 +256,6 @@ void msft_do_close(struct hci_dev *hdev)
list_del(&handle_data->list);
kfree(handle_data);
}
-
- kfree(msft->evt_prefix);
- kfree(msft);
}
void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h
index 6e56d94b88d8..9f178effda73 100644
--- a/net/bluetooth/msft.h
+++ b/net/bluetooth/msft.h
@@ -15,6 +15,8 @@
bool msft_monitor_supported(struct hci_dev *hdev);
void msft_do_open(struct hci_dev *hdev);
void msft_do_close(struct hci_dev *hdev);
+void msft_power_on(struct hci_dev *hdev);
+void msft_power_off(struct hci_dev *hdev);
void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb);
__u64 msft_get_features(struct hci_dev *hdev);
int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor);
@@ -33,6 +35,8 @@ static inline bool msft_monitor_supported(struct hci_dev *hdev)
static inline void msft_do_open(struct hci_dev *hdev) {}
static inline void msft_do_close(struct hci_dev *hdev) {}
+static inline void msft_power_on(struct hci_dev *hdev) {}
+static inline void msft_power_off(struct hci_dev *hdev) {}
static inline void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb) {}
static inline __u64 msft_get_features(struct hci_dev *hdev) { return 0; }
static inline int msft_add_monitor_pattern(struct hci_dev *hdev,
--
2.17.1