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