Commit bf6a4e30 authored by Howard Chung's avatar Howard Chung Committed by Marcel Holtmann

Bluetooth: disable advertisement filters during suspend

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: default avatarHoward Chung <howardchung@google.com>
Reviewed-by: default avatarAbhishek Pandit-Subedi <abhishekpandit@chromium.org>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 58ceb1e6
...@@ -105,6 +105,8 @@ enum suspend_tasks { ...@@ -105,6 +105,8 @@ enum suspend_tasks {
SUSPEND_POWERING_DOWN, SUSPEND_POWERING_DOWN,
SUSPEND_PREPARE_NOTIFIER, SUSPEND_PREPARE_NOTIFIER,
SUSPEND_SET_ADV_FILTER,
__SUSPEND_NUM_TASKS __SUSPEND_NUM_TASKS
}; };
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "smp.h" #include "smp.h"
#include "hci_request.h" #include "hci_request.h"
#include "msft.h"
#define HCI_REQ_DONE 0 #define HCI_REQ_DONE 0
#define HCI_REQ_PEND 1 #define HCI_REQ_PEND 1
...@@ -1242,6 +1243,29 @@ static void suspend_req_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -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); clear_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
wake_up(&hdev->suspend_wait_q); 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 */ /* Call with hci_dev_lock */
...@@ -1301,6 +1325,9 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next) ...@@ -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); hci_req_add_le_scan_disable(&req, false);
} }
/* Disable advertisement filters */
hci_req_add_set_adv_filter_enable(&req, false);
/* Mark task needing completion */ /* Mark task needing completion */
set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks); 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) ...@@ -1340,6 +1367,8 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
hci_req_clear_event_filter(&req); hci_req_clear_event_filter(&req);
/* Reset passive/background scanning to normal */ /* Reset passive/background scanning to normal */
__hci_update_background_scan(&req); __hci_update_background_scan(&req);
/* Enable all of the advertisement filters */
hci_req_add_set_adv_filter_enable(&req, true);
/* Unpause directed advertising */ /* Unpause directed advertising */
hdev->advertising_paused = false; hdev->advertising_paused = false;
......
...@@ -579,9 +579,19 @@ int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor, ...@@ -579,9 +579,19 @@ int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
return err; 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; 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 hci_request req;
struct msft_data *msft = hdev->msft_data; struct msft_data *msft = hdev->msft_data;
int err; int err;
...@@ -589,11 +599,8 @@ int msft_set_filter_enable(struct hci_dev *hdev, bool enable) ...@@ -589,11 +599,8 @@ int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
if (!msft) if (!msft)
return -EOPNOTSUPP; return -EOPNOTSUPP;
cp.sub_opcode = MSFT_OP_LE_SET_ADVERTISEMENT_FILTER_ENABLE;
cp.enable = enable;
hci_req_init(&req, hdev); 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); err = hci_req_run_skb(&req, msft_le_set_advertisement_filter_enable_cb);
return err; return err;
......
...@@ -20,6 +20,7 @@ __u64 msft_get_features(struct hci_dev *hdev); ...@@ -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_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor);
int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor, int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
u16 handle); 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); int msft_set_filter_enable(struct hci_dev *hdev, bool enable);
#else #else
...@@ -46,6 +47,8 @@ static inline int msft_remove_monitor(struct hci_dev *hdev, ...@@ -46,6 +47,8 @@ static inline int msft_remove_monitor(struct hci_dev *hdev,
return -EOPNOTSUPP; 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) static inline int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment