Skip to content

Commit 3b42055

Browse files
Vudentzholtmann
authored andcommitted
Bluetooth: hci_sync: Fix attempting to suspend with unfiltered passive scan
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 for hdev->suspended && HCI_CONN_FLAG_REMOTE_WAKEUP first, since the MGMT_OP_SET_DEVICE_FLAGS will reject any attempt to set HCI_CONN_FLAG_REMOTE_WAKEUP when it cannot be programmed in the acceptlist, so it can return success causing the proper filter_policy to be used. Link: https://bugzilla.kernel.org/show_bug.cgi?id=215768 Signed-off-by: Luiz Augusto von Dentz <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent a9a3476 commit 3b42055

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

net/bluetooth/hci_sync.c

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,20 +1664,19 @@ static int hci_le_add_accept_list_sync(struct hci_dev *hdev,
16641664
struct hci_cp_le_add_to_accept_list cp;
16651665
int err;
16661666

1667+
/* During suspend, only wakeable devices can be in acceptlist */
1668+
if (hdev->suspended &&
1669+
!test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
1670+
return 0;
1671+
16671672
/* Select filter policy to accept all advertising */
16681673
if (*num_entries >= hdev->le_accept_list_size)
16691674
return -ENOSPC;
16701675

16711676
/* Accept list can not be used with RPAs */
16721677
if (!use_ll_privacy(hdev) &&
1673-
hci_find_irk_by_addr(hdev, &params->addr, params->addr_type)) {
1678+
hci_find_irk_by_addr(hdev, &params->addr, params->addr_type))
16741679
return -EINVAL;
1675-
}
1676-
1677-
/* During suspend, only wakeable devices can be in acceptlist */
1678-
if (hdev->suspended &&
1679-
!test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
1680-
return 0;
16811680

16821681
/* Attempt to program the device in the resolving list first to avoid
16831682
* having to rollback in case it fails since the resolving list is
@@ -4913,10 +4912,28 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev)
49134912
return 0;
49144913
}
49154914

4915+
/* This function disables scan (BR and LE) and mark it as paused */
4916+
static int hci_pause_scan_sync(struct hci_dev *hdev)
4917+
{
4918+
if (hdev->scanning_paused)
4919+
return 0;
4920+
4921+
/* Disable page scan if enabled */
4922+
if (test_bit(HCI_PSCAN, &hdev->flags))
4923+
hci_write_scan_enable_sync(hdev, SCAN_DISABLED);
4924+
4925+
hci_scan_disable_sync(hdev);
4926+
4927+
hdev->scanning_paused = true;
4928+
4929+
return 0;
4930+
}
4931+
49164932
/* This function performs the HCI suspend procedures in the follow order:
49174933
*
49184934
* Pause discovery (active scanning/inquiry)
49194935
* Pause Directed Advertising/Advertising
4936+
* Pause Scanning (passive scanning in case discovery was not active)
49204937
* Disconnect all connections
49214938
* Set suspend_status to BT_SUSPEND_DISCONNECT if hdev cannot wakeup
49224939
* otherwise:
@@ -4942,15 +4959,11 @@ int hci_suspend_sync(struct hci_dev *hdev)
49424959
/* Pause other advertisements */
49434960
hci_pause_advertising_sync(hdev);
49444961

4945-
/* Disable page scan if enabled */
4946-
if (test_bit(HCI_PSCAN, &hdev->flags))
4947-
hci_write_scan_enable_sync(hdev, SCAN_DISABLED);
4948-
49494962
/* Suspend monitor filters */
49504963
hci_suspend_monitor_sync(hdev);
49514964

49524965
/* Prevent disconnects from causing scanning to be re-enabled */
4953-
hdev->scanning_paused = true;
4966+
hci_pause_scan_sync(hdev);
49544967

49554968
/* Soft disconnect everything (power off) */
49564969
err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
@@ -5021,6 +5034,22 @@ static void hci_resume_monitor_sync(struct hci_dev *hdev)
50215034
}
50225035
}
50235036

5037+
/* This function resume scan and reset paused flag */
5038+
static int hci_resume_scan_sync(struct hci_dev *hdev)
5039+
{
5040+
if (!hdev->scanning_paused)
5041+
return 0;
5042+
5043+
hci_update_scan_sync(hdev);
5044+
5045+
/* Reset passive scanning to normal */
5046+
hci_update_passive_scan_sync(hdev);
5047+
5048+
hdev->scanning_paused = false;
5049+
5050+
return 0;
5051+
}
5052+
50245053
/* This function performs the HCI suspend procedures in the follow order:
50255054
*
50265055
* Restore event mask
@@ -5043,10 +5072,9 @@ int hci_resume_sync(struct hci_dev *hdev)
50435072

50445073
/* Clear any event filters and restore scan state */
50455074
hci_clear_event_filter_sync(hdev);
5046-
hci_update_scan_sync(hdev);
50475075

5048-
/* Reset passive scanning to normal */
5049-
hci_update_passive_scan_sync(hdev);
5076+
/* Resume scanning */
5077+
hci_resume_scan_sync(hdev);
50505078

50515079
/* Resume monitor filters */
50525080
hci_resume_monitor_sync(hdev);

0 commit comments

Comments
 (0)