[PATCH v6 7/7] Bluetooth: disable advertisement filters during suspend

From: Archie Pusaka
Date: Fri Jan 22 2021 - 03:42:29 EST


From: Howard Chung <howardchung@xxxxxxxxxx>

This adds logic to disable and reenable advertisement filters during
suspend and resume. After this patch, we would only receive packets from
devices in allow list during suspend.

Signed-off-by: Howard Chung <howardchung@xxxxxxxxxx>
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@xxxxxxxxxxxx>
---

Changes in v6:
* New patch "disable advertisement filters during suspend"

include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_request.c | 29 +++++++++++++++++++++++++++++
net/bluetooth/msft.c | 17 ++++++++++++-----
net/bluetooth/msft.h | 3 +++
4 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 29cfc6a2d689..fd1d10fe2f11 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -105,6 +105,8 @@ enum suspend_tasks {
SUSPEND_POWERING_DOWN,

SUSPEND_PREPARE_NOTIFIER,
+
+ SUSPEND_SET_ADV_FILTER,
__SUSPEND_NUM_TASKS
};

diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index d29a44d77b4e..e55976db4403 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -29,6 +29,7 @@

#include "smp.h"
#include "hci_request.h"
+#include "msft.h"

#define HCI_REQ_DONE 0
#define HCI_REQ_PEND 1
@@ -1242,6 +1243,29 @@ static void suspend_req_complete(struct hci_dev *hdev, u8 status, u16 opcode)
clear_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
wake_up(&hdev->suspend_wait_q);
}
+
+ if (test_bit(SUSPEND_SET_ADV_FILTER, hdev->suspend_tasks)) {
+ clear_bit(SUSPEND_SET_ADV_FILTER, hdev->suspend_tasks);
+ wake_up(&hdev->suspend_wait_q);
+ }
+}
+
+static void hci_req_add_set_adv_filter_enable(struct hci_request *req,
+ bool enable)
+{
+ struct hci_dev *hdev = req->hdev;
+
+ switch (hci_get_adv_monitor_offload_ext(hdev)) {
+ case HCI_ADV_MONITOR_EXT_MSFT:
+ msft_req_add_set_filter_enable(req, enable);
+ break;
+ default:
+ return;
+ }
+
+ /* No need to block when enabling since it's on resume path */
+ if (hdev->suspended && !enable)
+ set_bit(SUSPEND_SET_ADV_FILTER, hdev->suspend_tasks);
}

/* Call with hci_dev_lock */
@@ -1301,6 +1325,9 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
hci_req_add_le_scan_disable(&req, false);
}

+ /* Disable advertisement filters */
+ hci_req_add_set_adv_filter_enable(&req, false);
+
/* Mark task needing completion */
set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);

@@ -1340,6 +1367,8 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
hci_req_clear_event_filter(&req);
/* Reset passive/background scanning to normal */
__hci_update_background_scan(&req);
+ /* Enable all of the advertisement filters */
+ hci_req_add_set_adv_filter_enable(&req, true);

/* Unpause directed advertising */
hdev->advertising_paused = false;
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index b2ef654b1d3d..47b104f318e9 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -579,9 +579,19 @@ int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
return err;
}

-int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
+void msft_req_add_set_filter_enable(struct hci_request *req, bool enable)
{
+ struct hci_dev *hdev = req->hdev;
struct msft_cp_le_set_advertisement_filter_enable cp;
+
+ cp.sub_opcode = MSFT_OP_LE_SET_ADVERTISEMENT_FILTER_ENABLE;
+ cp.enable = enable;
+
+ hci_req_add(req, hdev->msft_opcode, sizeof(cp), &cp);
+}
+
+int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
+{
struct hci_request req;
struct msft_data *msft = hdev->msft_data;
int err;
@@ -589,11 +599,8 @@ int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
if (!msft)
return -EOPNOTSUPP;

- cp.sub_opcode = MSFT_OP_LE_SET_ADVERTISEMENT_FILTER_ENABLE;
- cp.enable = enable;
-
hci_req_init(&req, hdev);
- hci_req_add(&req, hdev->msft_opcode, sizeof(cp), &cp);
+ msft_req_add_set_filter_enable(&req, enable);
err = hci_req_run_skb(&req, msft_le_set_advertisement_filter_enable_cb);

return err;
diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h
index f8e4d3a6d641..88ed613dfa08 100644
--- a/net/bluetooth/msft.h
+++ b/net/bluetooth/msft.h
@@ -20,6 +20,7 @@ __u64 msft_get_features(struct hci_dev *hdev);
int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor);
int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
u16 handle);
+void msft_req_add_set_filter_enable(struct hci_request *req, bool enable);
int msft_set_filter_enable(struct hci_dev *hdev, bool enable);

#else
@@ -46,6 +47,8 @@ static inline int msft_remove_monitor(struct hci_dev *hdev,
return -EOPNOTSUPP;
}

+static inline void msft_req_add_set_filter_enable(struct hci_request *req,
+ bool enable) {}
static inline int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
{
return -EOPNOTSUPP;
--
2.30.0.280.ga3ce27912f-goog