.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * sleep.c - ACPI sleep support. |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * Copyright (c) 2004 David Shaohua Li <shaohua.li@intel.com> |
---|
6 | 7 | * Copyright (c) 2000-2003 Patrick Mochel |
---|
7 | 8 | * Copyright (c) 2003 Open Source Development Lab |
---|
8 | | - * |
---|
9 | | - * This file is released under the GPLv2. |
---|
10 | | - * |
---|
11 | 9 | */ |
---|
12 | 10 | |
---|
13 | 11 | #include <linux/delay.h> |
---|
.. | .. |
---|
63 | 61 | static int acpi_sleep_prepare(u32 acpi_state) |
---|
64 | 62 | { |
---|
65 | 63 | #ifdef CONFIG_ACPI_SLEEP |
---|
| 64 | + unsigned long acpi_wakeup_address; |
---|
| 65 | + |
---|
66 | 66 | /* do we have a wakeup address for S2 and S3? */ |
---|
67 | 67 | if (acpi_state == ACPI_STATE_S3) { |
---|
| 68 | + acpi_wakeup_address = acpi_get_wakeup_address(); |
---|
68 | 69 | if (!acpi_wakeup_address) |
---|
69 | 70 | return -EFAULT; |
---|
70 | 71 | acpi_set_waking_vector(acpi_wakeup_address); |
---|
.. | .. |
---|
79 | 80 | return 0; |
---|
80 | 81 | } |
---|
81 | 82 | |
---|
82 | | -static bool acpi_sleep_state_supported(u8 sleep_state) |
---|
| 83 | +bool acpi_sleep_state_supported(u8 sleep_state) |
---|
83 | 84 | { |
---|
84 | 85 | acpi_status status; |
---|
85 | 86 | u8 type_a, type_b; |
---|
.. | .. |
---|
91 | 92 | } |
---|
92 | 93 | |
---|
93 | 94 | #ifdef CONFIG_ACPI_SLEEP |
---|
| 95 | +static bool sleep_no_lps0 __read_mostly; |
---|
| 96 | +module_param(sleep_no_lps0, bool, 0644); |
---|
| 97 | +MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface"); |
---|
| 98 | + |
---|
94 | 99 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
---|
95 | 100 | |
---|
96 | 101 | u32 acpi_target_system_state(void) |
---|
.. | .. |
---|
160 | 165 | return 0; |
---|
161 | 166 | } |
---|
162 | 167 | |
---|
163 | | -static bool acpi_sleep_no_lps0; |
---|
| 168 | +static bool acpi_sleep_default_s3; |
---|
164 | 169 | |
---|
165 | | -static int __init init_no_lps0(const struct dmi_system_id *d) |
---|
| 170 | +static int __init init_default_s3(const struct dmi_system_id *d) |
---|
166 | 171 | { |
---|
167 | | - acpi_sleep_no_lps0 = true; |
---|
| 172 | + acpi_sleep_default_s3 = true; |
---|
168 | 173 | return 0; |
---|
169 | 174 | } |
---|
170 | 175 | |
---|
.. | .. |
---|
359 | 364 | DMI_MATCH(DMI_PRODUCT_NAME, "80E3"), |
---|
360 | 365 | }, |
---|
361 | 366 | }, |
---|
362 | | - /* |
---|
363 | | - * https://bugzilla.kernel.org/show_bug.cgi?id=196907 |
---|
364 | | - * Some Dell XPS13 9360 cannot do suspend-to-idle using the Low Power |
---|
365 | | - * S0 Idle firmware interface. |
---|
366 | | - */ |
---|
367 | 367 | { |
---|
368 | | - .callback = init_no_lps0, |
---|
369 | | - .ident = "Dell XPS13 9360", |
---|
| 368 | + .callback = init_nvs_save_s3, |
---|
| 369 | + .ident = "Lenovo G40-45", |
---|
370 | 370 | .matches = { |
---|
371 | | - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
---|
372 | | - DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"), |
---|
| 371 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
---|
| 372 | + DMI_MATCH(DMI_PRODUCT_NAME, "80E1"), |
---|
373 | 373 | }, |
---|
374 | 374 | }, |
---|
375 | 375 | /* |
---|
.. | .. |
---|
378 | 378 | * https://bugzilla.kernel.org/show_bug.cgi?id=199057). |
---|
379 | 379 | */ |
---|
380 | 380 | { |
---|
381 | | - .callback = init_no_lps0, |
---|
| 381 | + .callback = init_default_s3, |
---|
382 | 382 | .ident = "ThinkPad X1 Tablet(2016)", |
---|
383 | 383 | .matches = { |
---|
384 | 384 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
---|
385 | 385 | DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"), |
---|
| 386 | + }, |
---|
| 387 | + }, |
---|
| 388 | + /* |
---|
| 389 | + * ASUS B1400CEAE hangs on resume from suspend (see |
---|
| 390 | + * https://bugzilla.kernel.org/show_bug.cgi?id=215742). |
---|
| 391 | + */ |
---|
| 392 | + { |
---|
| 393 | + .callback = init_default_s3, |
---|
| 394 | + .ident = "ASUS B1400CEAE", |
---|
| 395 | + .matches = { |
---|
| 396 | + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
---|
| 397 | + DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK B1400CEAE"), |
---|
386 | 398 | }, |
---|
387 | 399 | }, |
---|
388 | 400 | {}, |
---|
.. | .. |
---|
454 | 466 | return error; |
---|
455 | 467 | } |
---|
456 | 468 | |
---|
457 | | -static int find_powerf_dev(struct device *dev, void *data) |
---|
458 | | -{ |
---|
459 | | - struct acpi_device *device = to_acpi_device(dev); |
---|
460 | | - const char *hid = acpi_device_hid(device); |
---|
461 | | - |
---|
462 | | - return !strcmp(hid, ACPI_BUTTON_HID_POWERF); |
---|
463 | | -} |
---|
464 | | - |
---|
465 | 469 | /** |
---|
466 | 470 | * acpi_pm_finish - Instruct the platform to leave a sleep state. |
---|
467 | 471 | * |
---|
.. | .. |
---|
470 | 474 | */ |
---|
471 | 475 | static void acpi_pm_finish(void) |
---|
472 | 476 | { |
---|
473 | | - struct device *pwr_btn_dev; |
---|
| 477 | + struct acpi_device *pwr_btn_adev; |
---|
474 | 478 | u32 acpi_state = acpi_target_sleep_state; |
---|
475 | 479 | |
---|
476 | 480 | acpi_ec_unblock_transactions(); |
---|
.. | .. |
---|
501 | 505 | return; |
---|
502 | 506 | |
---|
503 | 507 | pwr_btn_event_pending = false; |
---|
504 | | - pwr_btn_dev = bus_find_device(&acpi_bus_type, NULL, NULL, |
---|
505 | | - find_powerf_dev); |
---|
506 | | - if (pwr_btn_dev) { |
---|
507 | | - pm_wakeup_event(pwr_btn_dev, 0); |
---|
508 | | - put_device(pwr_btn_dev); |
---|
| 508 | + pwr_btn_adev = acpi_dev_get_first_match_dev(ACPI_BUTTON_HID_POWERF, |
---|
| 509 | + NULL, -1); |
---|
| 510 | + if (pwr_btn_adev) { |
---|
| 511 | + pm_wakeup_event(&pwr_btn_adev->dev, 0); |
---|
| 512 | + acpi_dev_put(pwr_btn_adev); |
---|
509 | 513 | } |
---|
510 | 514 | } |
---|
511 | 515 | |
---|
.. | .. |
---|
534 | 538 | acpi_sleep_tts_switch(acpi_target_sleep_state); |
---|
535 | 539 | } |
---|
536 | 540 | #else /* !CONFIG_ACPI_SLEEP */ |
---|
| 541 | +#define sleep_no_lps0 (1) |
---|
537 | 542 | #define acpi_target_sleep_state ACPI_STATE_S0 |
---|
538 | | -#define acpi_sleep_no_lps0 (false) |
---|
| 543 | +#define acpi_sleep_default_s3 (1) |
---|
539 | 544 | static inline void acpi_sleep_dmi_check(void) {} |
---|
540 | 545 | #endif /* CONFIG_ACPI_SLEEP */ |
---|
541 | 546 | |
---|
.. | .. |
---|
701 | 706 | .recover = acpi_pm_finish, |
---|
702 | 707 | }; |
---|
703 | 708 | |
---|
704 | | -static bool s2idle_in_progress; |
---|
705 | 709 | static bool s2idle_wakeup; |
---|
706 | 710 | |
---|
707 | 711 | /* |
---|
.. | .. |
---|
914 | 918 | if (lps0_device_handle) |
---|
915 | 919 | return 0; |
---|
916 | 920 | |
---|
917 | | - if (acpi_sleep_no_lps0) { |
---|
918 | | - acpi_handle_info(adev->handle, |
---|
919 | | - "Low Power S0 Idle interface disabled\n"); |
---|
920 | | - return 0; |
---|
921 | | - } |
---|
922 | | - |
---|
923 | 921 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) |
---|
924 | 922 | return 0; |
---|
925 | 923 | |
---|
926 | 924 | guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid); |
---|
927 | 925 | /* Check if the _DSM is present and as expected. */ |
---|
928 | 926 | out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL); |
---|
929 | | - if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { |
---|
930 | | - char bitmask = *(char *)out_obj->buffer.pointer; |
---|
931 | | - |
---|
932 | | - lps0_dsm_func_mask = bitmask; |
---|
933 | | - lps0_device_handle = adev->handle; |
---|
934 | | - /* |
---|
935 | | - * Use suspend-to-idle by default if the default |
---|
936 | | - * suspend mode was not set from the command line. |
---|
937 | | - */ |
---|
938 | | - if (mem_sleep_default > PM_SUSPEND_MEM) |
---|
939 | | - mem_sleep_current = PM_SUSPEND_TO_IDLE; |
---|
940 | | - |
---|
941 | | - acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", |
---|
942 | | - bitmask); |
---|
943 | | - |
---|
944 | | - acpi_ec_mark_gpe_for_wake(); |
---|
945 | | - } else { |
---|
| 927 | + if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) { |
---|
946 | 928 | acpi_handle_debug(adev->handle, |
---|
947 | 929 | "_DSM function 0 evaluation failed\n"); |
---|
| 930 | + return 0; |
---|
948 | 931 | } |
---|
| 932 | + |
---|
| 933 | + lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer; |
---|
| 934 | + |
---|
949 | 935 | ACPI_FREE(out_obj); |
---|
950 | 936 | |
---|
| 937 | + acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", |
---|
| 938 | + lps0_dsm_func_mask); |
---|
| 939 | + |
---|
| 940 | + lps0_device_handle = adev->handle; |
---|
| 941 | + |
---|
951 | 942 | lpi_device_get_constraints(); |
---|
| 943 | + |
---|
| 944 | + /* |
---|
| 945 | + * Use suspend-to-idle by default if the default suspend mode was not |
---|
| 946 | + * set from the command line. |
---|
| 947 | + */ |
---|
| 948 | + if (mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3) |
---|
| 949 | + mem_sleep_current = PM_SUSPEND_TO_IDLE; |
---|
| 950 | + |
---|
| 951 | + /* |
---|
| 952 | + * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the |
---|
| 953 | + * EC GPE to be enabled while suspended for certain wakeup devices to |
---|
| 954 | + * work, so mark it as wakeup-capable. |
---|
| 955 | + */ |
---|
| 956 | + acpi_ec_mark_gpe_for_wake(); |
---|
952 | 957 | |
---|
953 | 958 | return 0; |
---|
954 | 959 | } |
---|
.. | .. |
---|
961 | 966 | static int acpi_s2idle_begin(void) |
---|
962 | 967 | { |
---|
963 | 968 | acpi_scan_lock_acquire(); |
---|
964 | | - s2idle_in_progress = true; |
---|
965 | 969 | return 0; |
---|
966 | 970 | } |
---|
967 | 971 | |
---|
968 | 972 | static int acpi_s2idle_prepare(void) |
---|
969 | 973 | { |
---|
970 | | - if (lps0_device_handle) { |
---|
971 | | - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); |
---|
972 | | - acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); |
---|
973 | | - |
---|
| 974 | + if (acpi_sci_irq_valid()) { |
---|
| 975 | + enable_irq_wake(acpi_sci_irq); |
---|
974 | 976 | acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); |
---|
975 | 977 | } |
---|
976 | | - |
---|
977 | | - if (acpi_sci_irq_valid()) |
---|
978 | | - enable_irq_wake(acpi_sci_irq); |
---|
979 | 978 | |
---|
980 | 979 | acpi_enable_wakeup_devices(ACPI_STATE_S0); |
---|
981 | 980 | |
---|
982 | 981 | /* Change the configuration of GPEs to avoid spurious wakeup. */ |
---|
983 | 982 | acpi_enable_all_wakeup_gpes(); |
---|
984 | 983 | acpi_os_wait_events_complete(); |
---|
| 984 | + |
---|
| 985 | + s2idle_wakeup = true; |
---|
985 | 986 | return 0; |
---|
986 | 987 | } |
---|
987 | 988 | |
---|
988 | | -static void acpi_s2idle_wake(void) |
---|
| 989 | +static int acpi_s2idle_prepare_late(void) |
---|
989 | 990 | { |
---|
| 991 | + if (!lps0_device_handle || sleep_no_lps0) |
---|
| 992 | + return 0; |
---|
990 | 993 | |
---|
991 | 994 | if (pm_debug_messages_on) |
---|
992 | 995 | lpi_check_constraints(); |
---|
993 | 996 | |
---|
994 | | - /* |
---|
995 | | - * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means |
---|
996 | | - * that the SCI has triggered while suspended, so cancel the wakeup in |
---|
997 | | - * case it has not been a wakeup event (the GPEs will be checked later). |
---|
998 | | - */ |
---|
999 | | - if (acpi_sci_irq_valid() && |
---|
1000 | | - !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { |
---|
1001 | | - pm_system_cancel_wakeup(); |
---|
1002 | | - s2idle_wakeup = true; |
---|
1003 | | - /* |
---|
1004 | | - * On some platforms with the LPS0 _DSM device noirq resume |
---|
1005 | | - * takes too much time for EC wakeup events to survive, so look |
---|
1006 | | - * for them now. |
---|
1007 | | - */ |
---|
1008 | | - if (lps0_device_handle) |
---|
1009 | | - acpi_ec_dispatch_gpe(); |
---|
1010 | | - } |
---|
| 997 | + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); |
---|
| 998 | + acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); |
---|
| 999 | + |
---|
| 1000 | + return 0; |
---|
1011 | 1001 | } |
---|
1012 | 1002 | |
---|
1013 | | -static void acpi_s2idle_sync(void) |
---|
| 1003 | +static bool acpi_s2idle_wake(void) |
---|
1014 | 1004 | { |
---|
1015 | | - /* |
---|
1016 | | - * Process all pending events in case there are any wakeup ones. |
---|
1017 | | - * |
---|
1018 | | - * The EC driver uses the system workqueue and an additional special |
---|
1019 | | - * one, so those need to be flushed too. |
---|
1020 | | - */ |
---|
1021 | | - acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */ |
---|
1022 | | - acpi_ec_flush_work(); |
---|
1023 | | - acpi_os_wait_events_complete(); /* synchronize Notify handling */ |
---|
1024 | | - s2idle_wakeup = false; |
---|
| 1005 | + if (!acpi_sci_irq_valid()) |
---|
| 1006 | + return pm_wakeup_pending(); |
---|
| 1007 | + |
---|
| 1008 | + while (pm_wakeup_pending()) { |
---|
| 1009 | + /* |
---|
| 1010 | + * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the |
---|
| 1011 | + * SCI has not triggered while suspended, so bail out (the |
---|
| 1012 | + * wakeup is pending anyway and the SCI is not the source of |
---|
| 1013 | + * it). |
---|
| 1014 | + */ |
---|
| 1015 | + if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { |
---|
| 1016 | + pm_pr_dbg("Wakeup unrelated to ACPI SCI\n"); |
---|
| 1017 | + return true; |
---|
| 1018 | + } |
---|
| 1019 | + |
---|
| 1020 | + /* |
---|
| 1021 | + * If the status bit of any enabled fixed event is set, the |
---|
| 1022 | + * wakeup is regarded as valid. |
---|
| 1023 | + */ |
---|
| 1024 | + if (acpi_any_fixed_event_status_set()) { |
---|
| 1025 | + pm_pr_dbg("ACPI fixed event wakeup\n"); |
---|
| 1026 | + return true; |
---|
| 1027 | + } |
---|
| 1028 | + |
---|
| 1029 | + /* Check wakeups from drivers sharing the SCI. */ |
---|
| 1030 | + if (acpi_check_wakeup_handlers()) { |
---|
| 1031 | + pm_pr_dbg("ACPI custom handler wakeup\n"); |
---|
| 1032 | + return true; |
---|
| 1033 | + } |
---|
| 1034 | + |
---|
| 1035 | + /* Check non-EC GPE wakeups and dispatch the EC GPE. */ |
---|
| 1036 | + if (acpi_ec_dispatch_gpe()) { |
---|
| 1037 | + pm_pr_dbg("ACPI non-EC GPE wakeup\n"); |
---|
| 1038 | + return true; |
---|
| 1039 | + } |
---|
| 1040 | + |
---|
| 1041 | + /* |
---|
| 1042 | + * Cancel the SCI wakeup and process all pending events in case |
---|
| 1043 | + * there are any wakeup ones in there. |
---|
| 1044 | + * |
---|
| 1045 | + * Note that if any non-EC GPEs are active at this point, the |
---|
| 1046 | + * SCI will retrigger after the rearming below, so no events |
---|
| 1047 | + * should be missed by canceling the wakeup here. |
---|
| 1048 | + */ |
---|
| 1049 | + pm_system_cancel_wakeup(); |
---|
| 1050 | + acpi_os_wait_events_complete(); |
---|
| 1051 | + |
---|
| 1052 | + /* |
---|
| 1053 | + * The SCI is in the "suspended" state now and it cannot produce |
---|
| 1054 | + * new wakeup events till the rearming below, so if any of them |
---|
| 1055 | + * are pending here, they must be resulting from the processing |
---|
| 1056 | + * of EC events above or coming from somewhere else. |
---|
| 1057 | + */ |
---|
| 1058 | + if (pm_wakeup_pending()) { |
---|
| 1059 | + pm_pr_dbg("Wakeup after ACPI Notify sync\n"); |
---|
| 1060 | + return true; |
---|
| 1061 | + } |
---|
| 1062 | + |
---|
| 1063 | + pm_wakeup_clear(acpi_sci_irq); |
---|
| 1064 | + rearm_wake_irq(acpi_sci_irq); |
---|
| 1065 | + } |
---|
| 1066 | + |
---|
| 1067 | + return false; |
---|
| 1068 | +} |
---|
| 1069 | + |
---|
| 1070 | +static void acpi_s2idle_restore_early(void) |
---|
| 1071 | +{ |
---|
| 1072 | + if (!lps0_device_handle || sleep_no_lps0) |
---|
| 1073 | + return; |
---|
| 1074 | + |
---|
| 1075 | + acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); |
---|
| 1076 | + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); |
---|
1025 | 1077 | } |
---|
1026 | 1078 | |
---|
1027 | 1079 | static void acpi_s2idle_restore(void) |
---|
1028 | 1080 | { |
---|
| 1081 | + /* |
---|
| 1082 | + * Drain pending events before restoring the working-state configuration |
---|
| 1083 | + * of GPEs. |
---|
| 1084 | + */ |
---|
| 1085 | + acpi_os_wait_events_complete(); /* synchronize GPE processing */ |
---|
| 1086 | + acpi_ec_flush_work(); /* flush the EC driver's workqueues */ |
---|
| 1087 | + acpi_os_wait_events_complete(); /* synchronize Notify handling */ |
---|
| 1088 | + |
---|
| 1089 | + s2idle_wakeup = false; |
---|
| 1090 | + |
---|
1029 | 1091 | acpi_enable_all_runtime_gpes(); |
---|
1030 | 1092 | |
---|
1031 | 1093 | acpi_disable_wakeup_devices(ACPI_STATE_S0); |
---|
1032 | 1094 | |
---|
1033 | | - if (acpi_sci_irq_valid()) |
---|
1034 | | - disable_irq_wake(acpi_sci_irq); |
---|
1035 | | - |
---|
1036 | | - if (lps0_device_handle) { |
---|
| 1095 | + if (acpi_sci_irq_valid()) { |
---|
1037 | 1096 | acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); |
---|
1038 | | - |
---|
1039 | | - acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); |
---|
1040 | | - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); |
---|
| 1097 | + disable_irq_wake(acpi_sci_irq); |
---|
1041 | 1098 | } |
---|
1042 | 1099 | } |
---|
1043 | 1100 | |
---|
1044 | 1101 | static void acpi_s2idle_end(void) |
---|
1045 | 1102 | { |
---|
1046 | | - s2idle_in_progress = false; |
---|
1047 | 1103 | acpi_scan_lock_release(); |
---|
1048 | 1104 | } |
---|
1049 | 1105 | |
---|
1050 | 1106 | static const struct platform_s2idle_ops acpi_s2idle_ops = { |
---|
1051 | 1107 | .begin = acpi_s2idle_begin, |
---|
1052 | 1108 | .prepare = acpi_s2idle_prepare, |
---|
| 1109 | + .prepare_late = acpi_s2idle_prepare_late, |
---|
1053 | 1110 | .wake = acpi_s2idle_wake, |
---|
1054 | | - .sync = acpi_s2idle_sync, |
---|
| 1111 | + .restore_early = acpi_s2idle_restore_early, |
---|
1055 | 1112 | .restore = acpi_s2idle_restore, |
---|
1056 | 1113 | .end = acpi_s2idle_end, |
---|
1057 | 1114 | }; |
---|
.. | .. |
---|
1072 | 1129 | } |
---|
1073 | 1130 | |
---|
1074 | 1131 | #else /* !CONFIG_SUSPEND */ |
---|
1075 | | -#define s2idle_in_progress (false) |
---|
1076 | 1132 | #define s2idle_wakeup (false) |
---|
1077 | 1133 | #define lps0_device_handle (NULL) |
---|
1078 | 1134 | static inline void acpi_sleep_suspend_setup(void) {} |
---|
.. | .. |
---|
1081 | 1137 | bool acpi_s2idle_wakeup(void) |
---|
1082 | 1138 | { |
---|
1083 | 1139 | return s2idle_wakeup; |
---|
1084 | | -} |
---|
1085 | | - |
---|
1086 | | -bool acpi_sleep_no_ec_events(void) |
---|
1087 | | -{ |
---|
1088 | | - return !s2idle_in_progress || !lps0_device_handle; |
---|
1089 | 1140 | } |
---|
1090 | 1141 | |
---|
1091 | 1142 | #ifdef CONFIG_PM_SLEEP |
---|
.. | .. |
---|
1131 | 1182 | nosigcheck = true; |
---|
1132 | 1183 | } |
---|
1133 | 1184 | |
---|
1134 | | -static int acpi_hibernation_begin(void) |
---|
| 1185 | +static int acpi_hibernation_begin(pm_message_t stage) |
---|
1135 | 1186 | { |
---|
1136 | | - int error; |
---|
| 1187 | + if (!nvs_nosave) { |
---|
| 1188 | + int error = suspend_nvs_alloc(); |
---|
| 1189 | + if (error) |
---|
| 1190 | + return error; |
---|
| 1191 | + } |
---|
1137 | 1192 | |
---|
1138 | | - error = nvs_nosave ? 0 : suspend_nvs_alloc(); |
---|
1139 | | - if (!error) |
---|
1140 | | - acpi_pm_start(ACPI_STATE_S4); |
---|
| 1193 | + if (stage.event == PM_EVENT_HIBERNATE) |
---|
| 1194 | + pm_set_suspend_via_firmware(); |
---|
1141 | 1195 | |
---|
1142 | | - return error; |
---|
| 1196 | + acpi_pm_start(ACPI_STATE_S4); |
---|
| 1197 | + return 0; |
---|
1143 | 1198 | } |
---|
1144 | 1199 | |
---|
1145 | 1200 | static int acpi_hibernation_enter(void) |
---|
.. | .. |
---|
1199 | 1254 | * function is used if the pre-ACPI 2.0 suspend ordering has been |
---|
1200 | 1255 | * requested. |
---|
1201 | 1256 | */ |
---|
1202 | | -static int acpi_hibernation_begin_old(void) |
---|
| 1257 | +static int acpi_hibernation_begin_old(pm_message_t stage) |
---|
1203 | 1258 | { |
---|
1204 | 1259 | int error; |
---|
1205 | 1260 | /* |
---|
.. | .. |
---|
1210 | 1265 | acpi_sleep_tts_switch(ACPI_STATE_S4); |
---|
1211 | 1266 | |
---|
1212 | 1267 | error = acpi_sleep_prepare(ACPI_STATE_S4); |
---|
| 1268 | + if (error) |
---|
| 1269 | + return error; |
---|
1213 | 1270 | |
---|
1214 | | - if (!error) { |
---|
1215 | | - if (!nvs_nosave) |
---|
1216 | | - error = suspend_nvs_alloc(); |
---|
1217 | | - if (!error) { |
---|
1218 | | - acpi_target_sleep_state = ACPI_STATE_S4; |
---|
1219 | | - acpi_scan_lock_acquire(); |
---|
1220 | | - } |
---|
| 1271 | + if (!nvs_nosave) { |
---|
| 1272 | + error = suspend_nvs_alloc(); |
---|
| 1273 | + if (error) |
---|
| 1274 | + return error; |
---|
1221 | 1275 | } |
---|
1222 | | - return error; |
---|
| 1276 | + |
---|
| 1277 | + if (stage.event == PM_EVENT_HIBERNATE) |
---|
| 1278 | + pm_set_suspend_via_firmware(); |
---|
| 1279 | + |
---|
| 1280 | + acpi_target_sleep_state = ACPI_STATE_S4; |
---|
| 1281 | + acpi_scan_lock_acquire(); |
---|
| 1282 | + return 0; |
---|
1223 | 1283 | } |
---|
1224 | 1284 | |
---|
1225 | 1285 | /* |
---|