31
31
#include <linux/debugfs.h>
32
32
#include <linux/crypto.h>
33
33
#include <linux/property.h>
34
+ #include <linux/suspend.h>
35
+ #include <linux/wait.h>
34
36
#include <asm/unaligned.h>
35
37
36
38
#include <net/bluetooth/bluetooth.h>
@@ -1787,6 +1789,9 @@ int hci_dev_do_close(struct hci_dev *hdev)
1787
1789
clear_bit (HCI_RUNNING , & hdev -> flags );
1788
1790
hci_sock_dev_event (hdev , HCI_DEV_CLOSE );
1789
1791
1792
+ if (test_and_clear_bit (SUSPEND_POWERING_DOWN , hdev -> suspend_tasks ))
1793
+ wake_up (& hdev -> suspend_wait_q );
1794
+
1790
1795
/* After this point our queues are empty
1791
1796
* and no tasks are scheduled. */
1792
1797
hdev -> close (hdev );
@@ -3264,6 +3269,78 @@ void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
3264
3269
}
3265
3270
}
3266
3271
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
+ }
3267
3344
/* Alloc HCI device */
3268
3345
struct hci_dev * hci_alloc_dev (void )
3269
3346
{
@@ -3341,6 +3418,7 @@ struct hci_dev *hci_alloc_dev(void)
3341
3418
INIT_WORK (& hdev -> tx_work , hci_tx_work );
3342
3419
INIT_WORK (& hdev -> power_on , hci_power_on );
3343
3420
INIT_WORK (& hdev -> error_reset , hci_error_reset );
3421
+ INIT_WORK (& hdev -> suspend_prepare , hci_prepare_suspend );
3344
3422
3345
3423
INIT_DELAYED_WORK (& hdev -> power_off , hci_power_off );
3346
3424
@@ -3349,6 +3427,7 @@ struct hci_dev *hci_alloc_dev(void)
3349
3427
skb_queue_head_init (& hdev -> raw_q );
3350
3428
3351
3429
init_waitqueue_head (& hdev -> req_wait_q );
3430
+ init_waitqueue_head (& hdev -> suspend_wait_q );
3352
3431
3353
3432
INIT_DELAYED_WORK (& hdev -> cmd_timer , hci_cmd_timeout );
3354
3433
@@ -3460,6 +3539,11 @@ int hci_register_dev(struct hci_dev *hdev)
3460
3539
hci_sock_dev_event (hdev , HCI_DEV_REG );
3461
3540
hci_dev_hold (hdev );
3462
3541
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
+
3463
3547
queue_work (hdev -> req_workqueue , & hdev -> power_on );
3464
3548
3465
3549
return id ;
@@ -3493,6 +3577,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
3493
3577
3494
3578
hci_dev_do_close (hdev );
3495
3579
3580
+ unregister_pm_notifier (& hdev -> suspend_notifier );
3581
+
3496
3582
if (!test_bit (HCI_INIT , & hdev -> flags ) &&
3497
3583
!hci_dev_test_flag (hdev , HCI_SETUP ) &&
3498
3584
!hci_dev_test_flag (hdev , HCI_CONFIG )) {
0 commit comments