--- zzzz-none-000/linux-3.10.107/drivers/acpi/sleep.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/acpi/sleep.c 2021-02-04 17:41:59.000000000 +0000 @@ -14,15 +14,13 @@ #include #include #include +#include #include #include #include #include - #include - -#include -#include +#include #include "internal.h" #include "sleep.h" @@ -31,12 +29,9 @@ static void acpi_sleep_tts_switch(u32 acpi_state) { - union acpi_object in_arg = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &in_arg }; - acpi_status status = AE_OK; + acpi_status status; - in_arg.integer.value = acpi_state; - status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); + status = acpi_execute_simple_method(NULL, "\\_TTS", acpi_state); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { /* * OS can't evaluate the _TTS object correctly. Some warning @@ -96,6 +91,7 @@ { return acpi_target_sleep_state; } +EXPORT_SYMBOL_GPL(acpi_target_system_state); static bool pwr_btn_event_pending; @@ -152,7 +148,7 @@ return 0; } -static struct dmi_system_id __initdata acpisleep_dmi_table[] = { +static struct dmi_system_id acpisleep_dmi_table[] __initdata = { { .callback = init_old_suspend_ordering, .ident = "Abit KN9 (nForce4 variant)", @@ -325,8 +321,13 @@ {}, }; -static void acpi_sleep_dmi_check(void) +static void __init acpi_sleep_dmi_check(void) { + int year; + + if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012) + acpi_nvs_nosave_s3(); + dmi_check_system(acpisleep_dmi_table); } @@ -434,10 +435,21 @@ } /** - * acpi_pm_end - Finish up suspend sequence. + * acpi_pm_start - Start system PM transition. + */ +static void acpi_pm_start(u32 acpi_state) +{ + acpi_target_sleep_state = acpi_state; + acpi_sleep_tts_switch(acpi_target_sleep_state); + acpi_scan_lock_acquire(); +} + +/** + * acpi_pm_end - Finish up system PM transition. */ static void acpi_pm_end(void) { + acpi_scan_lock_release(); /* * This is necessary in case acpi_pm_finish() is not called during a * failing transition to a sleep state. @@ -465,21 +477,21 @@ static int acpi_suspend_begin(suspend_state_t pm_state) { u32 acpi_state = acpi_suspend_states[pm_state]; - int error = 0; + int error; error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc(); if (error) return error; - if (sleep_states[acpi_state]) { - acpi_target_sleep_state = acpi_state; - acpi_sleep_tts_switch(acpi_target_sleep_state); - } else { - printk(KERN_ERR "ACPI does not support this state: %d\n", - pm_state); - error = -ENOSYS; + if (!sleep_states[acpi_state]) { + pr_err("ACPI does not support sleep state S%u\n", acpi_state); + return -ENOSYS; } - return error; + if (acpi_state > ACPI_STATE_S1) + pm_set_suspend_via_firmware(); + + acpi_pm_start(acpi_state); + return 0; } /** @@ -498,6 +510,7 @@ ACPI_FLUSH_CPU_CACHE(); + trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true); switch (acpi_state) { case ACPI_STATE_S1: barrier(); @@ -505,12 +518,16 @@ break; case ACPI_STATE_S3: + if (!acpi_suspend_lowlevel) + return -ENOSYS; error = acpi_suspend_lowlevel(); if (error) return error; pr_info(PREFIX "Low-level resume complete\n"); + pm_set_resume_via_firmware(); 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); @@ -528,7 +545,7 @@ * 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); @@ -607,6 +624,42 @@ .recover = acpi_pm_finish, }; +static int acpi_freeze_begin(void) +{ + acpi_scan_lock_acquire(); + return 0; +} + +static int acpi_freeze_prepare(void) +{ + acpi_enable_wakeup_devices(ACPI_STATE_S0); + acpi_enable_all_wakeup_gpes(); + acpi_os_wait_events_complete(); + if (acpi_sci_irq_valid()) + enable_irq_wake(acpi_sci_irq); + return 0; +} + +static void acpi_freeze_restore(void) +{ + acpi_disable_wakeup_devices(ACPI_STATE_S0); + if (acpi_sci_irq_valid()) + disable_irq_wake(acpi_sci_irq); + acpi_enable_all_runtime_gpes(); +} + +static void acpi_freeze_end(void) +{ + acpi_scan_lock_release(); +} + +static const struct platform_freeze_ops acpi_freeze_ops = { + .begin = acpi_freeze_begin, + .prepare = acpi_freeze_prepare, + .restore = acpi_freeze_restore, + .end = acpi_freeze_end, +}; + static void acpi_sleep_suspend_setup(void) { int i; @@ -617,7 +670,9 @@ 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 */ @@ -637,10 +692,8 @@ int error; error = nvs_nosave ? 0 : suspend_nvs_alloc(); - if (!error) { - acpi_target_sleep_state = ACPI_STATE_S4; - acpi_sleep_tts_switch(acpi_target_sleep_state); - } + if (!error) + acpi_pm_start(ACPI_STATE_S4); return error; } @@ -661,6 +714,7 @@ static void acpi_hibernation_leave(void) { + pm_set_resume_via_firmware(); /* * If ACPI is not enabled by the BIOS and the boot kernel, we need to * enable it here. @@ -669,11 +723,8 @@ /* 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. */ @@ -719,8 +770,10 @@ if (!error) { if (!nvs_nosave) error = suspend_nvs_alloc(); - if (!error) + if (!error) { acpi_target_sleep_state = ACPI_STATE_S4; + acpi_scan_lock_acquire(); + } } return error; } @@ -761,26 +814,12 @@ static inline void acpi_sleep_hibernate_setup(void) {} #endif /* !CONFIG_HIBERNATION */ -int acpi_suspend(u32 acpi_state) -{ - suspend_state_t states[] = { - [1] = PM_SUSPEND_STANDBY, - [3] = PM_SUSPEND_MEM, - [5] = PM_SUSPEND_MAX - }; - - if (acpi_state < 6 && states[acpi_state]) - return pm_suspend(states[acpi_state]); - if (acpi_state == 4) - return hibernate(); - return -EINVAL; -} - static void acpi_power_off_prepare(void) { /* Prepare to power off the system */ acpi_sleep_prepare(ACPI_STATE_S5); acpi_disable_all_gpes(); + acpi_os_wait_events_complete(); } static void acpi_power_off(void) @@ -797,9 +836,6 @@ char *pos = supported; int i; - if (acpi_disabled) - return 0; - acpi_sleep_dmi_check(); sleep_states[ACPI_STATE_S0] = 1;