Bluetooth: Remove unneeded commands for suspend
authorAbhishek Pandit-Subedi <abhishekpandit@chromium.org>
Wed, 3 Mar 2021 16:34:04 +0000 (08:34 -0800)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 3 Mar 2021 16:49:29 +0000 (17:49 +0100)
During suspend, there are a few scan enable and set event filter
commands that don't need to be sent unless there are actual BR/EDR
devices capable of waking the system. Check the HCI_PSCAN bit before
writing scan enable and use a new dev flag, HCI_EVENT_FILTER_CONFIGURED
to control whether to clear the event filter.

Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Reviewed-by: Archie Pusaka <apusaka@chromium.org>
Reviewed-by: Alain Michaud <alainm@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci.h
net/bluetooth/hci_event.c
net/bluetooth/hci_request.c

index ba2f439bc04d346ae5c738b48093e6d8873248ae..ea4ae551c426872b1ac2ce6b8a0d0a375d8b8225 100644 (file)
@@ -320,6 +320,7 @@ enum {
        HCI_BREDR_ENABLED,
        HCI_LE_SCAN_INTERRUPTED,
        HCI_WIDEBAND_SPEECH_ENABLED,
+       HCI_EVENT_FILTER_CONFIGURED,
 
        HCI_DUT_MODE,
        HCI_VENDOR_DIAG,
index 67668be3461e93e0917f9fdd3c25d08b191d0cda..f4a734f8a9ac8831237ff8b86edc0d24723e7cc0 100644 (file)
@@ -395,6 +395,29 @@ done:
        hci_dev_unlock(hdev);
 }
 
+static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       __u8 status = *((__u8 *)skb->data);
+       struct hci_cp_set_event_filter *cp;
+       void *sent;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       if (status)
+               return;
+
+       sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT);
+       if (!sent)
+               return;
+
+       cp = (struct hci_cp_set_event_filter *)sent;
+
+       if (cp->flt_type == HCI_FLT_CLEAR_ALL)
+               hci_dev_clear_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
+       else
+               hci_dev_set_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
+}
+
 static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
@@ -3328,6 +3351,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
                hci_cc_write_scan_enable(hdev, skb);
                break;
 
+       case HCI_OP_SET_EVENT_FLT:
+               hci_cc_set_event_filter(hdev, skb);
+               break;
+
        case HCI_OP_READ_CLASS_OF_DEV:
                hci_cc_read_class_of_dev(hdev, skb);
                break;
index e55976db4403e7ad742d2721f6b8d9a3d91160bc..75a42178c82d9bb5e035abb4600b7e5f8e668b39 100644 (file)
@@ -1131,14 +1131,14 @@ static void hci_req_clear_event_filter(struct hci_request *req)
 {
        struct hci_cp_set_event_filter f;
 
-       memset(&f, 0, sizeof(f));
-       f.flt_type = HCI_FLT_CLEAR_ALL;
-       hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &f);
+       if (!hci_dev_test_flag(req->hdev, HCI_BREDR_ENABLED))
+               return;
 
-       /* Update page scan state (since we may have modified it when setting
-        * the event filter).
-        */
-       __hci_req_update_scan(req);
+       if (hci_dev_test_flag(req->hdev, HCI_EVENT_FILTER_CONFIGURED)) {
+               memset(&f, 0, sizeof(f));
+               f.flt_type = HCI_FLT_CLEAR_ALL;
+               hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &f);
+       }
 }
 
 static void hci_req_set_event_filter(struct hci_request *req)
@@ -1147,6 +1147,10 @@ static void hci_req_set_event_filter(struct hci_request *req)
        struct hci_cp_set_event_filter f;
        struct hci_dev *hdev = req->hdev;
        u8 scan = SCAN_DISABLED;
+       bool scanning = test_bit(HCI_PSCAN, &hdev->flags);
+
+       if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
+               return;
 
        /* Always clear event filter when starting */
        hci_req_clear_event_filter(req);
@@ -1167,12 +1171,13 @@ static void hci_req_set_event_filter(struct hci_request *req)
                scan = SCAN_PAGE;
        }
 
-       if (scan)
+       if (scan && !scanning) {
                set_bit(SUSPEND_SCAN_ENABLE, hdev->suspend_tasks);
-       else
+               hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+       } else if (!scan && scanning) {
                set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
-
-       hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+               hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+       }
 }
 
 static void cancel_adv_timeout(struct hci_dev *hdev)
@@ -1315,9 +1320,14 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
 
                hdev->advertising_paused = true;
                hdev->advertising_old_state = old_state;
-               /* Disable page scan */
-               page_scan = SCAN_DISABLED;
-               hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &page_scan);
+
+               /* Disable page scan if enabled */
+               if (test_bit(HCI_PSCAN, &hdev->flags)) {
+                       page_scan = SCAN_DISABLED;
+                       hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1,
+                                   &page_scan);
+                       set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
+               }
 
                /* Disable LE passive scan if enabled */
                if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
@@ -1328,9 +1338,6 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
                /* Disable advertisement filters */
                hci_req_add_set_adv_filter_enable(&req, false);
 
-               /* Mark task needing completion */
-               set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
-
                /* Prevent disconnects from causing scanning to be re-enabled */
                hdev->scanning_paused = true;
 
@@ -1364,7 +1371,10 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
                hdev->suspended = false;
                hdev->scanning_paused = false;
 
+               /* Clear any event filters and restore scan state */
                hci_req_clear_event_filter(&req);
+               __hci_req_update_scan(&req);
+
                /* Reset passive/background scanning to normal */
                __hci_update_background_scan(&req);
                /* Enable all of the advertisement filters */