kernel/power/hibernate.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
Wake-up events that occur in the hibernation process's
hibernation_platform_enter() cannot wake up the system. Although the
current hibernation framework will execute part of the recovery process
after a wake-up event occurs, it ultimately performs a shutdown operation
because the system does not check the return value of
hibernation_platform_enter(). Moreover, when restoring the device before
system shutdown, the device's I/O and DMA capabilities will be turned on,
which can lead to data loss.
To solve this problem, check the return value of
hibernation_platform_enter(). When it returns -EAGAIN or -EBUSY, execute
the hibernation recovery process, discard the previously saved image, and
ultimately return to the working state.
Signed-off-by: Chris Feng <chris.feng@mediatek.com>
---
[PATCH v2]:
- Execute the hibernation recovery process and return to the working state
when the return value of the function hibernation_platform_enter() is
-EAGAIN or -EBUSY. Both of the two values may indicate the occurrence of
a wake-up event.
---
kernel/power/hibernate.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 8d35b9f9aaa3..7e39a9baca9e 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -642,9 +642,9 @@ int hibernation_platform_enter(void)
*/
static void power_down(void)
{
-#ifdef CONFIG_SUSPEND
int error;
+#ifdef CONFIG_SUSPEND
if (hibernation_mode == HIBERNATION_SUSPEND) {
error = suspend_devices_and_enter(mem_sleep_current);
if (error) {
@@ -667,7 +667,13 @@ static void power_down(void)
kernel_restart(NULL);
break;
case HIBERNATION_PLATFORM:
- hibernation_platform_enter();
+ error = hibernation_platform_enter();
+ if (error == -EAGAIN || error == -EBUSY) {
+ swsusp_unmark();
+ events_check_enabled = false;
+ pr_err("Hibernation Abort.\n");
+ return;
+ }
fallthrough;
case HIBERNATION_SHUTDOWN:
if (kernel_can_power_off())
--
2.17.0
Hi Chris,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.7-rc2 next-20231120]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chris-Feng/PM-hibernate-Fix-the-bug-where-wake-events-cannot-wake-system-during-hibernation/20231120-161752
base: linus/master
patch link: https://lore.kernel.org/r/20231120081516.55172-1-chris.feng%40mediatek.com
patch subject: [PATCH v2] PM: hibernate: Fix the bug where wake events cannot wake system during hibernation
config: arm-randconfig-003-20231120 (https://download.01.org/0day-ci/archive/20231120/202311202258.eqaMpEXc-lkp@intel.com/config)
compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231120/202311202258.eqaMpEXc-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311202258.eqaMpEXc-lkp@intel.com/
All errors (new ones prefixed by >>):
>> kernel/power/hibernate.c:672:4: error: call to undeclared function 'swsusp_unmark'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
swsusp_unmark();
^
1 error generated.
vim +/swsusp_unmark +672 kernel/power/hibernate.c
664
665 switch (hibernation_mode) {
666 case HIBERNATION_REBOOT:
667 kernel_restart(NULL);
668 break;
669 case HIBERNATION_PLATFORM:
670 error = hibernation_platform_enter();
671 if (error == -EAGAIN || error == -EBUSY) {
> 672 swsusp_unmark();
673 events_check_enabled = false;
674 pr_err("Hibernation Abort.\n");
675 return;
676 }
677 fallthrough;
678 case HIBERNATION_SHUTDOWN:
679 if (kernel_can_power_off())
680 kernel_power_off();
681 break;
682 }
683 kernel_halt();
684 /*
685 * Valid image is on the disk, if we continue we risk serious data
686 * corruption after resume.
687 */
688 pr_crit("Power down manually\n");
689 while (1)
690 cpu_relax();
691 }
692
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On Mon, Nov 20, 2023 at 9:15 AM Chris Feng <chris.feng@mediatek.com> wrote:
>
> Wake-up events that occur in the hibernation process's
> hibernation_platform_enter() cannot wake up the system. Although the
> current hibernation framework will execute part of the recovery process
> after a wake-up event occurs, it ultimately performs a shutdown operation
> because the system does not check the return value of
> hibernation_platform_enter(). Moreover, when restoring the device before
> system shutdown, the device's I/O and DMA capabilities will be turned on,
> which can lead to data loss.
This isn't correct, because devices are enabled to do IO and DMA
already before saving the hibernation image.
The problem really only is that if a wakeup event occurs before
putting the system into the final low-power state, it will be missed,
so the patch subject should be something like "Avoid missing wakeup
events during hibernation".
> To solve this problem, check the return value of
> hibernation_platform_enter(). When it returns -EAGAIN or -EBUSY, execute
> the hibernation recovery process, discard the previously saved image, and
> ultimately return to the working state.
>
> Signed-off-by: Chris Feng <chris.feng@mediatek.com>
> ---
> [PATCH v2]:
> - Execute the hibernation recovery process and return to the working state
> when the return value of the function hibernation_platform_enter() is
> -EAGAIN or -EBUSY. Both of the two values may indicate the occurrence of
> a wake-up event.
> ---
> kernel/power/hibernate.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index 8d35b9f9aaa3..7e39a9baca9e 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -642,9 +642,9 @@ int hibernation_platform_enter(void)
> */
> static void power_down(void)
> {
> -#ifdef CONFIG_SUSPEND
> int error;
>
> +#ifdef CONFIG_SUSPEND
> if (hibernation_mode == HIBERNATION_SUSPEND) {
> error = suspend_devices_and_enter(mem_sleep_current);
> if (error) {
> @@ -667,7 +667,13 @@ static void power_down(void)
> kernel_restart(NULL);
> break;
> case HIBERNATION_PLATFORM:
> - hibernation_platform_enter();
> + error = hibernation_platform_enter();
> + if (error == -EAGAIN || error == -EBUSY) {
> + swsusp_unmark();
> + events_check_enabled = false;
> + pr_err("Hibernation Abort.\n");
This is not an error condition, so pr_err() is not the right level.
pr_info() would suffice.
Also the message needs to be more precise, so whoever reads it will
know that this is about a (legitimate) wakeup event.
> + return;
> + }
> fallthrough;
> case HIBERNATION_SHUTDOWN:
> if (kernel_can_power_off())
> --
© 2016 - 2025 Red Hat, Inc.