@@ -682,47 +682,74 @@ static void acpi_pm_notify_work_func(struct acpi_device_wakeup_context *context)
682682 }
683683}
684684
685+ static DEFINE_MUTEX (acpi_wakeup_lock );
686+
685687/**
686- * acpi_device_wakeup - Enable/disable wakeup functionality for device.
687- * @adev: ACPI device to enable/disable wakeup functionality for.
688+ * acpi_device_wakeup_enable - Enable wakeup functionality for device.
689+ * @adev: ACPI device to enable wakeup functionality for.
688690 * @target_state: State the system is transitioning into.
689- * @enable: Whether to enable or disable the wakeup functionality.
690691 *
691- * Enable/disable the GPE associated with @adev so that it can generate
692- * wakeup signals for the device in response to external (remote) events and
693- * enable/disable device wakeup power .
692+ * Enable the GPE associated with @adev so that it can generate wakeup signals
693+ * for the device in response to external (remote) events and enable wakeup
694+ * power for it .
694695 *
695696 * Callers must ensure that @adev is a valid ACPI device node before executing
696697 * this function.
697698 */
698- static int acpi_device_wakeup (struct acpi_device * adev , u32 target_state ,
699- bool enable )
699+ static int acpi_device_wakeup_enable (struct acpi_device * adev , u32 target_state )
700700{
701701 struct acpi_device_wakeup * wakeup = & adev -> wakeup ;
702+ acpi_status status ;
703+ int error = 0 ;
702704
703- if (enable ) {
704- acpi_status res ;
705- int error ;
705+ mutex_lock (& acpi_wakeup_lock );
706706
707- if (adev -> wakeup . flags . enabled )
708- return 0 ;
707+ if (wakeup -> enable_count > 0 )
708+ goto out ;
709709
710- error = acpi_enable_wakeup_device_power (adev , target_state );
711- if (error )
712- return error ;
710+ error = acpi_enable_wakeup_device_power (adev , target_state );
711+ if (error )
712+ goto out ;
713713
714- res = acpi_enable_gpe (wakeup -> gpe_device , wakeup -> gpe_number );
715- if (ACPI_FAILURE (res )) {
716- acpi_disable_wakeup_device_power (adev );
717- return - EIO ;
718- }
719- adev -> wakeup .flags .enabled = 1 ;
720- } else if (adev -> wakeup .flags .enabled ) {
721- acpi_disable_gpe (wakeup -> gpe_device , wakeup -> gpe_number );
714+ status = acpi_enable_gpe (wakeup -> gpe_device , wakeup -> gpe_number );
715+ if (ACPI_FAILURE (status )) {
722716 acpi_disable_wakeup_device_power (adev );
723- adev -> wakeup .flags .enabled = 0 ;
717+ error = - EIO ;
718+ goto out ;
724719 }
725- return 0 ;
720+
721+ wakeup -> enable_count ++ ;
722+
723+ out :
724+ mutex_unlock (& acpi_wakeup_lock );
725+ return error ;
726+ }
727+
728+ /**
729+ * acpi_device_wakeup_disable - Disable wakeup functionality for device.
730+ * @adev: ACPI device to disable wakeup functionality for.
731+ *
732+ * Disable the GPE associated with @adev and disable wakeup power for it.
733+ *
734+ * Callers must ensure that @adev is a valid ACPI device node before executing
735+ * this function.
736+ */
737+ static void acpi_device_wakeup_disable (struct acpi_device * adev )
738+ {
739+ struct acpi_device_wakeup * wakeup = & adev -> wakeup ;
740+
741+ mutex_lock (& acpi_wakeup_lock );
742+
743+ if (!wakeup -> enable_count )
744+ goto out ;
745+
746+ acpi_disable_gpe (wakeup -> gpe_device , wakeup -> gpe_number );
747+ acpi_disable_wakeup_device_power (adev );
748+
749+ wakeup -> enable_count -- ;
750+
751+ out :
752+ mutex_unlock (& acpi_wakeup_lock );
726753}
727754
728755/**
@@ -744,9 +771,15 @@ int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
744771 if (!acpi_device_can_wakeup (adev ))
745772 return - EINVAL ;
746773
747- error = acpi_device_wakeup (adev , acpi_target_system_state (), enable );
774+ if (!enable ) {
775+ acpi_device_wakeup_disable (adev );
776+ dev_dbg (dev , "Wakeup disabled by ACPI\n" );
777+ return 0 ;
778+ }
779+
780+ error = acpi_device_wakeup_enable (adev , acpi_target_system_state ());
748781 if (!error )
749- dev_dbg (dev , "Wakeup %s by ACPI\n" , enable ? "enabled" : "disabled " );
782+ dev_dbg (dev , "Wakeup enabled by ACPI\n" );
750783
751784 return error ;
752785}
@@ -800,13 +833,15 @@ int acpi_dev_runtime_suspend(struct device *dev)
800833
801834 remote_wakeup = dev_pm_qos_flags (dev , PM_QOS_FLAG_REMOTE_WAKEUP ) >
802835 PM_QOS_FLAGS_NONE ;
803- error = acpi_device_wakeup (adev , ACPI_STATE_S0 , remote_wakeup );
804- if (remote_wakeup && error )
805- return - EAGAIN ;
836+ if (remote_wakeup ) {
837+ error = acpi_device_wakeup_enable (adev , ACPI_STATE_S0 );
838+ if (error )
839+ return - EAGAIN ;
840+ }
806841
807842 error = acpi_dev_pm_low_power (dev , adev , ACPI_STATE_S0 );
808- if (error )
809- acpi_device_wakeup (adev , ACPI_STATE_S0 , false );
843+ if (error && remote_wakeup )
844+ acpi_device_wakeup_disable (adev );
810845
811846 return error ;
812847}
@@ -829,7 +864,7 @@ int acpi_dev_runtime_resume(struct device *dev)
829864 return 0 ;
830865
831866 error = acpi_dev_pm_full_power (adev );
832- acpi_device_wakeup (adev , ACPI_STATE_S0 , false );
867+ acpi_device_wakeup_disable (adev );
833868 return error ;
834869}
835870EXPORT_SYMBOL_GPL (acpi_dev_runtime_resume );
@@ -884,13 +919,15 @@ int acpi_dev_suspend_late(struct device *dev)
884919
885920 target_state = acpi_target_system_state ();
886921 wakeup = device_may_wakeup (dev ) && acpi_device_can_wakeup (adev );
887- error = acpi_device_wakeup (adev , target_state , wakeup );
888- if (wakeup && error )
889- return error ;
922+ if (wakeup ) {
923+ error = acpi_device_wakeup_enable (adev , target_state );
924+ if (error )
925+ return error ;
926+ }
890927
891928 error = acpi_dev_pm_low_power (dev , adev , target_state );
892- if (error )
893- acpi_device_wakeup (adev , ACPI_STATE_UNKNOWN , false );
929+ if (error && wakeup )
930+ acpi_device_wakeup_disable (adev );
894931
895932 return error ;
896933}
@@ -913,7 +950,7 @@ int acpi_dev_resume_early(struct device *dev)
913950 return 0 ;
914951
915952 error = acpi_dev_pm_full_power (adev );
916- acpi_device_wakeup (adev , ACPI_STATE_UNKNOWN , false );
953+ acpi_device_wakeup_disable (adev );
917954 return error ;
918955}
919956EXPORT_SYMBOL_GPL (acpi_dev_resume_early );
@@ -1056,7 +1093,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off)
10561093 */
10571094 dev_pm_qos_hide_latency_limit (dev );
10581095 dev_pm_qos_hide_flags (dev );
1059- acpi_device_wakeup (adev , ACPI_STATE_S0 , false );
1096+ acpi_device_wakeup_disable (adev );
10601097 acpi_dev_pm_low_power (dev , adev , ACPI_STATE_S0 );
10611098 }
10621099 }
@@ -1100,7 +1137,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
11001137 dev_pm_domain_set (dev , & acpi_general_pm_domain );
11011138 if (power_on ) {
11021139 acpi_dev_pm_full_power (adev );
1103- acpi_device_wakeup (adev , ACPI_STATE_S0 , false );
1140+ acpi_device_wakeup_disable (adev );
11041141 }
11051142
11061143 dev -> pm_domain -> detach = acpi_dev_pm_detach ;
0 commit comments