@@ -135,7 +135,6 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
135
135
136
136
static int acpi_button_add (struct acpi_device * device );
137
137
static void acpi_button_remove (struct acpi_device * device );
138
- static void acpi_button_notify (struct acpi_device * device , u32 event );
139
138
140
139
#ifdef CONFIG_PM_SLEEP
141
140
static int acpi_button_suspend (struct device * dev );
@@ -153,7 +152,6 @@ static struct acpi_driver acpi_button_driver = {
153
152
.ops = {
154
153
.add = acpi_button_add ,
155
154
.remove = acpi_button_remove ,
156
- .notify = acpi_button_notify ,
157
155
},
158
156
.drv .pm = & acpi_button_pm ,
159
157
};
@@ -409,45 +407,65 @@ static void acpi_lid_initialize_state(struct acpi_device *device)
409
407
button -> lid_state_initialized = true;
410
408
}
411
409
412
- static void acpi_button_notify ( struct acpi_device * device , u32 event )
410
+ static void acpi_lid_notify ( acpi_handle handle , u32 event , void * data )
413
411
{
414
- struct acpi_button * button = acpi_driver_data (device );
412
+ struct acpi_device * device = data ;
413
+ struct acpi_button * button ;
414
+
415
+ if (event != ACPI_BUTTON_NOTIFY_STATUS ) {
416
+ acpi_handle_debug (device -> handle , "Unsupported event [0x%x]\n" ,
417
+ event );
418
+ return ;
419
+ }
420
+
421
+ button = acpi_driver_data (device );
422
+ if (!button -> lid_state_initialized )
423
+ return ;
424
+
425
+ acpi_lid_update_state (device , true);
426
+ }
427
+
428
+ static void acpi_button_notify (acpi_handle handle , u32 event , void * data )
429
+ {
430
+ struct acpi_device * device = data ;
431
+ struct acpi_button * button ;
415
432
struct input_dev * input ;
433
+ int keycode ;
416
434
417
- switch (event ) {
418
- case ACPI_FIXED_HARDWARE_EVENT :
419
- event = ACPI_BUTTON_NOTIFY_STATUS ;
420
- fallthrough ;
421
- case ACPI_BUTTON_NOTIFY_STATUS :
422
- input = button -> input ;
423
- if (button -> type == ACPI_BUTTON_TYPE_LID ) {
424
- if (button -> lid_state_initialized )
425
- acpi_lid_update_state (device , true);
426
- } else {
427
- int keycode ;
428
-
429
- acpi_pm_wakeup_event (& device -> dev );
430
- if (button -> suspended )
431
- break ;
432
-
433
- keycode = test_bit (KEY_SLEEP , input -> keybit ) ?
434
- KEY_SLEEP : KEY_POWER ;
435
- input_report_key (input , keycode , 1 );
436
- input_sync (input );
437
- input_report_key (input , keycode , 0 );
438
- input_sync (input );
439
-
440
- acpi_bus_generate_netlink_event (
441
- device -> pnp .device_class ,
442
- dev_name (& device -> dev ),
443
- event , ++ button -> pushed );
444
- }
445
- break ;
446
- default :
435
+ if (event != ACPI_BUTTON_NOTIFY_STATUS ) {
447
436
acpi_handle_debug (device -> handle , "Unsupported event [0x%x]\n" ,
448
437
event );
449
- break ;
438
+ return ;
450
439
}
440
+
441
+ acpi_pm_wakeup_event (& device -> dev );
442
+
443
+ button = acpi_driver_data (device );
444
+ if (button -> suspended )
445
+ return ;
446
+
447
+ input = button -> input ;
448
+ keycode = test_bit (KEY_SLEEP , input -> keybit ) ? KEY_SLEEP : KEY_POWER ;
449
+
450
+ input_report_key (input , keycode , 1 );
451
+ input_sync (input );
452
+ input_report_key (input , keycode , 0 );
453
+ input_sync (input );
454
+
455
+ acpi_bus_generate_netlink_event (device -> pnp .device_class ,
456
+ dev_name (& device -> dev ),
457
+ event , ++ button -> pushed );
458
+ }
459
+
460
+ static void acpi_button_notify_run (void * data )
461
+ {
462
+ acpi_button_notify (NULL , ACPI_BUTTON_NOTIFY_STATUS , data );
463
+ }
464
+
465
+ static u32 acpi_button_event (void * data )
466
+ {
467
+ acpi_os_execute (OSL_NOTIFY_HANDLER , acpi_button_notify_run , data );
468
+ return ACPI_INTERRUPT_HANDLED ;
451
469
}
452
470
453
471
#ifdef CONFIG_PM_SLEEP
@@ -489,11 +507,13 @@ static int acpi_lid_input_open(struct input_dev *input)
489
507
490
508
static int acpi_button_add (struct acpi_device * device )
491
509
{
510
+ acpi_notify_handler handler ;
492
511
struct acpi_button * button ;
493
512
struct input_dev * input ;
494
513
const char * hid = acpi_device_hid (device );
514
+ acpi_status status ;
495
515
char * name , * class ;
496
- int error ;
516
+ int error = 0 ;
497
517
498
518
if (!strcmp (hid , ACPI_BUTTON_HID_LID ) &&
499
519
lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED )
@@ -517,30 +537,36 @@ static int acpi_button_add(struct acpi_device *device)
517
537
if (!strcmp (hid , ACPI_BUTTON_HID_POWER ) ||
518
538
!strcmp (hid , ACPI_BUTTON_HID_POWERF )) {
519
539
button -> type = ACPI_BUTTON_TYPE_POWER ;
540
+ handler = acpi_button_notify ;
520
541
strcpy (name , ACPI_BUTTON_DEVICE_NAME_POWER );
521
542
sprintf (class , "%s/%s" ,
522
543
ACPI_BUTTON_CLASS , ACPI_BUTTON_SUBCLASS_POWER );
523
544
} else if (!strcmp (hid , ACPI_BUTTON_HID_SLEEP ) ||
524
545
!strcmp (hid , ACPI_BUTTON_HID_SLEEPF )) {
525
546
button -> type = ACPI_BUTTON_TYPE_SLEEP ;
547
+ handler = acpi_button_notify ;
526
548
strcpy (name , ACPI_BUTTON_DEVICE_NAME_SLEEP );
527
549
sprintf (class , "%s/%s" ,
528
550
ACPI_BUTTON_CLASS , ACPI_BUTTON_SUBCLASS_SLEEP );
529
551
} else if (!strcmp (hid , ACPI_BUTTON_HID_LID )) {
530
552
button -> type = ACPI_BUTTON_TYPE_LID ;
553
+ handler = acpi_lid_notify ;
531
554
strcpy (name , ACPI_BUTTON_DEVICE_NAME_LID );
532
555
sprintf (class , "%s/%s" ,
533
556
ACPI_BUTTON_CLASS , ACPI_BUTTON_SUBCLASS_LID );
534
557
input -> open = acpi_lid_input_open ;
535
558
} else {
536
559
pr_info ("Unsupported hid [%s]\n" , hid );
537
560
error = - ENODEV ;
538
- goto err_free_input ;
539
561
}
540
562
541
- error = acpi_button_add_fs (device );
542
- if (error )
543
- goto err_free_input ;
563
+ if (!error )
564
+ error = acpi_button_add_fs (device );
565
+
566
+ if (error ) {
567
+ input_free_device (input );
568
+ goto err_free_button ;
569
+ }
544
570
545
571
snprintf (button -> phys , sizeof (button -> phys ), "%s/button/input0" , hid );
546
572
@@ -568,6 +594,29 @@ static int acpi_button_add(struct acpi_device *device)
568
594
error = input_register_device (input );
569
595
if (error )
570
596
goto err_remove_fs ;
597
+
598
+ switch (device -> device_type ) {
599
+ case ACPI_BUS_TYPE_POWER_BUTTON :
600
+ status = acpi_install_fixed_event_handler (ACPI_EVENT_POWER_BUTTON ,
601
+ acpi_button_event ,
602
+ device );
603
+ break ;
604
+ case ACPI_BUS_TYPE_SLEEP_BUTTON :
605
+ status = acpi_install_fixed_event_handler (ACPI_EVENT_SLEEP_BUTTON ,
606
+ acpi_button_event ,
607
+ device );
608
+ break ;
609
+ default :
610
+ status = acpi_install_notify_handler (device -> handle ,
611
+ ACPI_DEVICE_NOTIFY , handler ,
612
+ device );
613
+ break ;
614
+ }
615
+ if (ACPI_FAILURE (status )) {
616
+ error = - ENODEV ;
617
+ goto err_input_unregister ;
618
+ }
619
+
571
620
if (button -> type == ACPI_BUTTON_TYPE_LID ) {
572
621
/*
573
622
* This assumes there's only one lid device, or if there are
@@ -580,11 +629,11 @@ static int acpi_button_add(struct acpi_device *device)
580
629
pr_info ("%s [%s]\n" , name , acpi_device_bid (device ));
581
630
return 0 ;
582
631
583
- err_remove_fs :
632
+ err_input_unregister :
633
+ input_unregister_device (input );
634
+ err_remove_fs :
584
635
acpi_button_remove_fs (device );
585
- err_free_input :
586
- input_free_device (input );
587
- err_free_button :
636
+ err_free_button :
588
637
kfree (button );
589
638
return error ;
590
639
}
@@ -593,6 +642,24 @@ static void acpi_button_remove(struct acpi_device *device)
593
642
{
594
643
struct acpi_button * button = acpi_driver_data (device );
595
644
645
+ switch (device -> device_type ) {
646
+ case ACPI_BUS_TYPE_POWER_BUTTON :
647
+ acpi_remove_fixed_event_handler (ACPI_EVENT_POWER_BUTTON ,
648
+ acpi_button_event );
649
+ break ;
650
+ case ACPI_BUS_TYPE_SLEEP_BUTTON :
651
+ acpi_remove_fixed_event_handler (ACPI_EVENT_SLEEP_BUTTON ,
652
+ acpi_button_event );
653
+ break ;
654
+ default :
655
+ acpi_remove_notify_handler (device -> handle , ACPI_DEVICE_NOTIFY ,
656
+ button -> type == ACPI_BUTTON_TYPE_LID ?
657
+ acpi_lid_notify :
658
+ acpi_button_notify );
659
+ break ;
660
+ }
661
+ acpi_os_wait_events_complete ();
662
+
596
663
acpi_button_remove_fs (device );
597
664
input_unregister_device (button -> input );
598
665
kfree (button );
0 commit comments