diff options
Diffstat (limited to 'drivers/acpi/sleep.c')
| -rw-r--r-- | drivers/acpi/sleep.c | 70 | 
1 files changed, 40 insertions, 30 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 14df30580e1..b3e3cc73ba7 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -18,11 +18,8 @@  #include <linux/reboot.h>  #include <linux/acpi.h>  #include <linux/module.h> -  #include <asm/io.h> - -#include <acpi/acpi_bus.h> -#include <acpi/acpi_drivers.h> +#include <trace/events/power.h>  #include "internal.h"  #include "sleep.h" @@ -75,6 +72,17 @@ static int acpi_sleep_prepare(u32 acpi_state)  	return 0;  } +static bool acpi_sleep_state_supported(u8 sleep_state) +{ +	acpi_status status; +	u8 type_a, type_b; + +	status = acpi_get_sleep_type_data(sleep_state, &type_a, &type_b); +	return ACPI_SUCCESS(status) && (!acpi_gbl_reduced_hardware +		|| (acpi_gbl_FADT.sleep_control.address +			&& acpi_gbl_FADT.sleep_status.address)); +} +  #ifdef CONFIG_ACPI_SLEEP  static u32 acpi_target_sleep_state = ACPI_STATE_S0; @@ -82,6 +90,7 @@ u32 acpi_target_system_state(void)  {  	return acpi_target_sleep_state;  } +EXPORT_SYMBOL_GPL(acpi_target_system_state);  static bool pwr_btn_event_pending; @@ -493,6 +502,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)  	ACPI_FLUSH_CPU_CACHE(); +	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true);  	switch (acpi_state) {  	case ACPI_STATE_S1:  		barrier(); @@ -508,6 +518,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)  		pr_info(PREFIX "Low-level resume complete\n");  		break;  	} +	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, false);  	/* This violates the spec but is required for bug compatibility. */  	acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); @@ -525,7 +536,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)  	 * generate wakeup events.  	 */  	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) { -		acpi_event_status pwr_btn_status; +		acpi_event_status pwr_btn_status = ACPI_EVENT_FLAG_DISABLED;  		acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status); @@ -604,23 +615,35 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = {  	.recover = acpi_pm_finish,  }; +static int acpi_freeze_begin(void) +{ +	acpi_scan_lock_acquire(); +	return 0; +} + +static void acpi_freeze_end(void) +{ +	acpi_scan_lock_release(); +} + +static const struct platform_freeze_ops acpi_freeze_ops = { +	.begin = acpi_freeze_begin, +	.end = acpi_freeze_end, +}; +  static void acpi_sleep_suspend_setup(void)  {  	int i; -	for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { -		acpi_status status; -		u8 type_a, type_b; - -		status = acpi_get_sleep_type_data(i, &type_a, &type_b); -		if (ACPI_SUCCESS(status)) { +	for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) +		if (acpi_sleep_state_supported(i))  			sleep_states[i] = 1; -		} -	}  	suspend_set_ops(old_suspend_ordering ?  		&acpi_suspend_ops_old : &acpi_suspend_ops); +	freeze_set_ops(&acpi_freeze_ops);  } +  #else /* !CONFIG_SUSPEND */  static inline void acpi_sleep_suspend_setup(void) {}  #endif /* !CONFIG_SUSPEND */ @@ -670,11 +693,8 @@ static void acpi_hibernation_leave(void)  	/* Reprogram control registers */  	acpi_leave_sleep_state_prep(ACPI_STATE_S4);  	/* Check the hardware signature */ -	if (facs && s4_hardware_signature != facs->hardware_signature) { -		printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " -			"cannot resume!\n"); -		panic("ACPI S4 hardware signature mismatch"); -	} +	if (facs && s4_hardware_signature != facs->hardware_signature) +		pr_crit("ACPI: Hardware changed while hibernated, success doubtful!\n");  	/* Restore the NVS memory area */  	suspend_nvs_restore();  	/* Allow EC transactions to happen. */ @@ -747,11 +767,7 @@ static const struct platform_hibernation_ops acpi_hibernation_ops_old = {  static void acpi_sleep_hibernate_setup(void)  { -	acpi_status status; -	u8 type_a, type_b; - -	status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); -	if (ACPI_FAILURE(status)) +	if (!acpi_sleep_state_supported(ACPI_STATE_S4))  		return;  	hibernation_set_ops(old_suspend_ordering ? @@ -800,15 +816,10 @@ static void acpi_power_off(void)  int __init acpi_sleep_init(void)  { -	acpi_status status; -	u8 type_a, type_b;  	char supported[ACPI_S_STATE_COUNT * 3 + 1];  	char *pos = supported;  	int i; -	if (acpi_disabled) -		return 0; -  	acpi_sleep_dmi_check();  	sleep_states[ACPI_STATE_S0] = 1; @@ -816,8 +827,7 @@ int __init acpi_sleep_init(void)  	acpi_sleep_suspend_setup();  	acpi_sleep_hibernate_setup(); -	status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); -	if (ACPI_SUCCESS(status)) { +	if (acpi_sleep_state_supported(ACPI_STATE_S5)) {  		sleep_states[ACPI_STATE_S5] = 1;  		pm_power_off_prepare = acpi_power_off_prepare;  		pm_power_off = acpi_power_off;  | 
