mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-18 16:26:54 +07:00
Bluetooth: Restore running state if suspend fails
If Bluetooth fails to enter the suspended state correctly, restore the state to running (re-enabling scans). PM_POST_SUSPEND is only sent to notifiers that successfully return from PM_PREPARE_SUSPEND notification so we should recover gracefully if it fails. Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
0d7043f355
commit
8731840a34
@ -3305,6 +3305,15 @@ static void hci_prepare_suspend(struct work_struct *work)
|
|||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hci_change_suspend_state(struct hci_dev *hdev,
|
||||||
|
enum suspended_state next)
|
||||||
|
{
|
||||||
|
hdev->suspend_state_next = next;
|
||||||
|
set_bit(SUSPEND_PREPARE_NOTIFIER, hdev->suspend_tasks);
|
||||||
|
queue_work(hdev->req_workqueue, &hdev->suspend_prepare);
|
||||||
|
return hci_suspend_wait_event(hdev);
|
||||||
|
}
|
||||||
|
|
||||||
static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
|
static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
@ -3330,32 +3339,24 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
|
|||||||
* connectable (disabling scanning)
|
* connectable (disabling scanning)
|
||||||
* - Second, program event filter/whitelist and enable scan
|
* - Second, program event filter/whitelist and enable scan
|
||||||
*/
|
*/
|
||||||
hdev->suspend_state_next = BT_SUSPEND_DISCONNECT;
|
ret = hci_change_suspend_state(hdev, BT_SUSPEND_DISCONNECT);
|
||||||
set_bit(SUSPEND_PREPARE_NOTIFIER, hdev->suspend_tasks);
|
|
||||||
queue_work(hdev->req_workqueue, &hdev->suspend_prepare);
|
|
||||||
ret = hci_suspend_wait_event(hdev);
|
|
||||||
|
|
||||||
/* If the disconnect portion failed, don't attempt to complete
|
/* Only configure whitelist if disconnect succeeded */
|
||||||
* by configuring the whitelist. The suspend notifier will
|
if (!ret)
|
||||||
* follow a cancelled suspend with a PM_POST_SUSPEND
|
ret = hci_change_suspend_state(hdev,
|
||||||
* notification.
|
BT_SUSPEND_COMPLETE);
|
||||||
*/
|
|
||||||
if (!ret) {
|
|
||||||
hdev->suspend_state_next = BT_SUSPEND_COMPLETE;
|
|
||||||
set_bit(SUSPEND_PREPARE_NOTIFIER, hdev->suspend_tasks);
|
|
||||||
queue_work(hdev->req_workqueue, &hdev->suspend_prepare);
|
|
||||||
ret = hci_suspend_wait_event(hdev);
|
|
||||||
}
|
|
||||||
} else if (action == PM_POST_SUSPEND) {
|
} else if (action == PM_POST_SUSPEND) {
|
||||||
hdev->suspend_state_next = BT_RUNNING;
|
ret = hci_change_suspend_state(hdev, BT_RUNNING);
|
||||||
set_bit(SUSPEND_PREPARE_NOTIFIER, hdev->suspend_tasks);
|
|
||||||
queue_work(hdev->req_workqueue, &hdev->suspend_prepare);
|
|
||||||
ret = hci_suspend_wait_event(hdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If suspend failed, restore it to running */
|
||||||
|
if (ret && action == PM_SUSPEND_PREPARE)
|
||||||
|
hci_change_suspend_state(hdev, BT_RUNNING);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return ret ? notifier_from_errno(-EBUSY) : NOTIFY_STOP;
|
return ret ? notifier_from_errno(-EBUSY) : NOTIFY_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Alloc HCI device */
|
/* Alloc HCI device */
|
||||||
struct hci_dev *hci_alloc_dev(void)
|
struct hci_dev *hci_alloc_dev(void)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user