3131#include <linux/debugfs.h>
3232#include <linux/crypto.h>
3333#include <linux/property.h>
34+ #include <linux/suspend.h>
35+ #include <linux/wait.h>
3436#include <asm/unaligned.h>
3537
3638#include <net/bluetooth/bluetooth.h>
@@ -1787,6 +1789,9 @@ int hci_dev_do_close(struct hci_dev *hdev)
17871789 clear_bit (HCI_RUNNING , & hdev -> flags );
17881790 hci_sock_dev_event (hdev , HCI_DEV_CLOSE );
17891791
1792+ if (test_and_clear_bit (SUSPEND_POWERING_DOWN , hdev -> suspend_tasks ))
1793+ wake_up (& hdev -> suspend_wait_q );
1794+
17901795 /* After this point our queues are empty
17911796 * and no tasks are scheduled. */
17921797 hdev -> close (hdev );
@@ -3264,6 +3269,78 @@ void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
32643269 }
32653270}
32663271
3272+ static int hci_suspend_wait_event (struct hci_dev * hdev )
3273+ {
3274+ #define WAKE_COND \
3275+ (find_first_bit(hdev->suspend_tasks, __SUSPEND_NUM_TASKS) == \
3276+ __SUSPEND_NUM_TASKS)
3277+
3278+ int i ;
3279+ int ret = wait_event_timeout (hdev -> suspend_wait_q ,
3280+ WAKE_COND , SUSPEND_NOTIFIER_TIMEOUT );
3281+
3282+ if (ret == 0 ) {
3283+ bt_dev_dbg (hdev , "Timed out waiting for suspend" );
3284+ for (i = 0 ; i < __SUSPEND_NUM_TASKS ; ++ i ) {
3285+ if (test_bit (i , hdev -> suspend_tasks ))
3286+ bt_dev_dbg (hdev , "Bit %d is set" , i );
3287+ clear_bit (i , hdev -> suspend_tasks );
3288+ }
3289+
3290+ ret = - ETIMEDOUT ;
3291+ } else {
3292+ ret = 0 ;
3293+ }
3294+
3295+ return ret ;
3296+ }
3297+
3298+ static void hci_prepare_suspend (struct work_struct * work )
3299+ {
3300+ struct hci_dev * hdev =
3301+ container_of (work , struct hci_dev , suspend_prepare );
3302+
3303+ hci_dev_lock (hdev );
3304+ hci_req_prepare_suspend (hdev , hdev -> suspend_state_next );
3305+ hci_dev_unlock (hdev );
3306+ }
3307+
3308+ static int hci_suspend_notifier (struct notifier_block * nb , unsigned long action ,
3309+ void * data )
3310+ {
3311+ struct hci_dev * hdev =
3312+ container_of (nb , struct hci_dev , suspend_notifier );
3313+ int ret = 0 ;
3314+
3315+ /* If powering down, wait for completion. */
3316+ if (mgmt_powering_down (hdev )) {
3317+ set_bit (SUSPEND_POWERING_DOWN , hdev -> suspend_tasks );
3318+ ret = hci_suspend_wait_event (hdev );
3319+ if (ret )
3320+ goto done ;
3321+ }
3322+
3323+ /* Suspend notifier should only act on events when powered. */
3324+ if (!hdev_is_powered (hdev ))
3325+ goto done ;
3326+
3327+ if (action == PM_SUSPEND_PREPARE ) {
3328+ hdev -> suspend_state_next = BT_SUSPENDED ;
3329+ set_bit (SUSPEND_PREPARE_NOTIFIER , hdev -> suspend_tasks );
3330+ queue_work (hdev -> req_workqueue , & hdev -> suspend_prepare );
3331+
3332+ ret = hci_suspend_wait_event (hdev );
3333+ } else if (action == PM_POST_SUSPEND ) {
3334+ hdev -> suspend_state_next = BT_RUNNING ;
3335+ set_bit (SUSPEND_PREPARE_NOTIFIER , hdev -> suspend_tasks );
3336+ queue_work (hdev -> req_workqueue , & hdev -> suspend_prepare );
3337+
3338+ ret = hci_suspend_wait_event (hdev );
3339+ }
3340+
3341+ done :
3342+ return ret ? notifier_from_errno (- EBUSY ) : NOTIFY_STOP ;
3343+ }
32673344/* Alloc HCI device */
32683345struct hci_dev * hci_alloc_dev (void )
32693346{
@@ -3341,6 +3418,7 @@ struct hci_dev *hci_alloc_dev(void)
33413418 INIT_WORK (& hdev -> tx_work , hci_tx_work );
33423419 INIT_WORK (& hdev -> power_on , hci_power_on );
33433420 INIT_WORK (& hdev -> error_reset , hci_error_reset );
3421+ INIT_WORK (& hdev -> suspend_prepare , hci_prepare_suspend );
33443422
33453423 INIT_DELAYED_WORK (& hdev -> power_off , hci_power_off );
33463424
@@ -3349,6 +3427,7 @@ struct hci_dev *hci_alloc_dev(void)
33493427 skb_queue_head_init (& hdev -> raw_q );
33503428
33513429 init_waitqueue_head (& hdev -> req_wait_q );
3430+ init_waitqueue_head (& hdev -> suspend_wait_q );
33523431
33533432 INIT_DELAYED_WORK (& hdev -> cmd_timer , hci_cmd_timeout );
33543433
@@ -3460,6 +3539,11 @@ int hci_register_dev(struct hci_dev *hdev)
34603539 hci_sock_dev_event (hdev , HCI_DEV_REG );
34613540 hci_dev_hold (hdev );
34623541
3542+ hdev -> suspend_notifier .notifier_call = hci_suspend_notifier ;
3543+ error = register_pm_notifier (& hdev -> suspend_notifier );
3544+ if (error )
3545+ goto err_wqueue ;
3546+
34633547 queue_work (hdev -> req_workqueue , & hdev -> power_on );
34643548
34653549 return id ;
@@ -3493,6 +3577,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
34933577
34943578 hci_dev_do_close (hdev );
34953579
3580+ unregister_pm_notifier (& hdev -> suspend_notifier );
3581+
34963582 if (!test_bit (HCI_INIT , & hdev -> flags ) &&
34973583 !hci_dev_test_flag (hdev , HCI_SETUP ) &&
34983584 !hci_dev_test_flag (hdev , HCI_CONFIG )) {
0 commit comments