diff mbox series

Bluetooth: hci_sync: Fix attempting to suspend with unfiltered passive scan

Message ID 20220512205613.992901-1-luiz.dentz@gmail.com
State New
Headers show
Series Bluetooth: hci_sync: Fix attempting to suspend with unfiltered passive scan | expand

Commit Message

Luiz Augusto von Dentz May 12, 2022, 8:56 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

When suspending the passive scanning _must_ have its filter_policy set
to 0x01 to use the accept list otherwise _any_ advertise report would
end up waking up the system.

In order to fix the filter_policy the code now checks hdev->suspended
when attempting to program a device address using RPA into the accept
list, print a warning since the userspace shall not mark it as wakeable
when it doesn't enable LL privacy but proceed to return success so the
proper filter_policy is used.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=215768
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hci_sync.c | 64 ++++++++++++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 13 deletions(-)

Comments

bluez.test.bot@gmail.com May 12, 2022, 10 p.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=641155

---Test result---

Test Summary:
CheckPatch                    PASS      1.74 seconds
GitLint                       PASS      1.00 seconds
SubjectPrefix                 PASS      0.88 seconds
BuildKernel                   PASS      33.34 seconds
BuildKernel32                 PASS      28.56 seconds
Incremental Build with patchesPASS      37.85 seconds
TestRunner: Setup             PASS      466.89 seconds
TestRunner: l2cap-tester      PASS      18.60 seconds
TestRunner: bnep-tester       PASS      6.03 seconds
TestRunner: mgmt-tester       PASS      100.03 seconds
TestRunner: rfcomm-tester     PASS      9.71 seconds
TestRunner: sco-tester        PASS      9.86 seconds
TestRunner: smp-tester        PASS      9.80 seconds
TestRunner: userchan-tester   PASS      6.14 seconds



---
Regards,
Linux Bluetooth
diff mbox series

Patch

diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 7bdfdc6a91f5..894973dd045f 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -1664,6 +1664,11 @@  static int hci_le_add_accept_list_sync(struct hci_dev *hdev,
 	struct hci_cp_le_add_to_accept_list cp;
 	int err;
 
+	/* During suspend, only wakeable devices can be in acceptlist */
+	if (hdev->suspended &&
+	    !test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
+		return 0;
+
 	/* Select filter policy to accept all advertising */
 	if (*num_entries >= hdev->le_accept_list_size)
 		return -ENOSPC;
@@ -1671,14 +1676,18 @@  static int hci_le_add_accept_list_sync(struct hci_dev *hdev,
 	/* Accept list can not be used with RPAs */
 	if (!use_ll_privacy(hdev) &&
 	    hci_find_irk_by_addr(hdev, &params->addr, params->addr_type)) {
+		/* During suspend, only wakeable devices can be in acceptlist
+		 * which means that devices using RPAs without LL privacy cannot
+		 * be wakeable.
+		 */
+		if (hdev->suspended) {
+			bt_dev_warn(hdev,
+				    "Ignore wakeable but requires LL Privacy");
+			return 0;
+		}
 		return -EINVAL;
 	}
 
-	/* During suspend, only wakeable devices can be in acceptlist */
-	if (hdev->suspended &&
-	    !test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
-		return 0;
-
 	/* Attempt to program the device in the resolving list first to avoid
 	 * having to rollback in case it fails since the resolving list is
 	 * dynamic it can probably be smaller than the accept list.
@@ -4940,10 +4949,28 @@  static int hci_update_event_filter_sync(struct hci_dev *hdev)
 	return 0;
 }
 
+/* This function disables scan (BR and LE) and mark it as paused */
+static int hci_pause_scan_sync(struct hci_dev *hdev)
+{
+	if (hdev->scanning_paused)
+		return 0;
+
+	/* Disable page scan if enabled */
+	if (test_bit(HCI_PSCAN, &hdev->flags))
+		hci_write_scan_enable_sync(hdev, SCAN_DISABLED);
+
+	hci_scan_disable_sync(hdev);
+
+	hdev->scanning_paused = true;
+
+	return 0;
+}
+
 /* This function performs the HCI suspend procedures in the follow order:
  *
  * Pause discovery (active scanning/inquiry)
  * Pause Directed Advertising/Advertising
+ * Pause Scanning (passive scanning in case discovery was not active)
  * Disconnect all connections
  * Set suspend_status to BT_SUSPEND_DISCONNECT if hdev cannot wakeup
  * otherwise:
@@ -4969,15 +4996,11 @@  int hci_suspend_sync(struct hci_dev *hdev)
 	/* Pause other advertisements */
 	hci_pause_advertising_sync(hdev);
 
-	/* Disable page scan if enabled */
-	if (test_bit(HCI_PSCAN, &hdev->flags))
-		hci_write_scan_enable_sync(hdev, SCAN_DISABLED);
-
 	/* Suspend monitor filters */
 	hci_suspend_monitor_sync(hdev);
 
 	/* Prevent disconnects from causing scanning to be re-enabled */
-	hdev->scanning_paused = true;
+	hci_pause_scan_sync(hdev);
 
 	/* Soft disconnect everything (power off) */
 	err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
@@ -5048,6 +5071,22 @@  static void hci_resume_monitor_sync(struct hci_dev *hdev)
 	}
 }
 
+/* This function resume scan and reset paused flag */
+static int hci_resume_scan_sync(struct hci_dev *hdev)
+{
+	if (!hdev->scanning_paused)
+		return 0;
+
+	hci_update_scan_sync(hdev);
+
+	/* Reset passive scanning to normal */
+	hci_update_passive_scan_sync(hdev);
+
+	hdev->scanning_paused = false;
+
+	return 0;
+}
+
 /* This function performs the HCI suspend procedures in the follow order:
  *
  * Restore event mask
@@ -5070,10 +5109,9 @@  int hci_resume_sync(struct hci_dev *hdev)
 
 	/* Clear any event filters and restore scan state */
 	hci_clear_event_filter_sync(hdev);
-	hci_update_scan_sync(hdev);
 
-	/* Reset passive scanning to normal */
-	hci_update_passive_scan_sync(hdev);
+	/* Resume scanning */
+	hci_resume_scan_sync(hdev);
 
 	/* Resume monitor filters */
 	hci_resume_monitor_sync(hdev);