mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
Bluetooth: hci_sync: Fix attempting to suspend with unfiltered passive scan
[ Upstream commit 3b42055388
]
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 <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
7ecdcf25a9
commit
c5bc2bdeed
1 changed files with 43 additions and 15 deletions
|
@ -1664,20 +1664,19 @@ 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;
|
||||
|
||||
/* Accept list can not be used with RPAs */
|
||||
if (!use_ll_privacy(hdev) &&
|
||||
hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type)) {
|
||||
hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type))
|
||||
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
|
||||
|
@ -4881,10 +4880,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:
|
||||
|
@ -4910,15 +4927,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);
|
||||
|
@ -4989,6 +5002,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
|
||||
|
@ -5011,10 +5040,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);
|
||||
|
|
Loading…
Reference in a new issue