Skip to content

Commit

Permalink
PM: hibernate: Add more logging on hibernation failure
Browse files Browse the repository at this point in the history
Hibernation fails when the kernel cannot allocate enough memory
to copy all pages of RAM in use.

Ensure that the failure reason is clearly logged, and clearly
attributable to the hibernation module.

Signed-off-by: Luigi Semenzato <semenzato@google.com>
[ rjw: Subject & changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Luigi Semenzato authored and Rafael J. Wysocki committed Jan 7, 2020
1 parent 809ed78 commit 7a7b99b
Showing 2 changed files with 27 additions and 20 deletions.
23 changes: 12 additions & 11 deletions kernel/power/hibernate.c
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
* Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com>
*/

#define pr_fmt(fmt) "PM: " fmt
#define pr_fmt(fmt) "PM: hibernation: " fmt

#include <linux/export.h>
#include <linux/suspend.h>
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(system_entering_hibernation);
#ifdef CONFIG_PM_DEBUG
static void hibernation_debug_sleep(void)
{
pr_info("hibernation debug: Waiting for 5 seconds.\n");
pr_info("debug: Waiting for 5 seconds.\n");
mdelay(5000);
}

@@ -277,7 +277,7 @@ static int create_image(int platform_mode)

error = dpm_suspend_end(PMSG_FREEZE);
if (error) {
pr_err("Some devices failed to power down, aborting hibernation\n");
pr_err("Some devices failed to power down, aborting\n");
return error;
}

@@ -295,7 +295,7 @@ static int create_image(int platform_mode)

error = syscore_suspend();
if (error) {
pr_err("Some system devices failed to power down, aborting hibernation\n");
pr_err("Some system devices failed to power down, aborting\n");
goto Enable_irqs;
}

@@ -310,7 +310,7 @@ static int create_image(int platform_mode)
restore_processor_state();
trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
if (error)
pr_err("Error %d creating hibernation image\n", error);
pr_err("Error %d creating image\n", error);

if (!in_suspend) {
events_check_enabled = false;
@@ -680,7 +680,7 @@ static int load_image_and_restore(void)
if (!error)
hibernation_restore(flags & SF_PLATFORM_MODE);

pr_err("Failed to load hibernation image, recovering.\n");
pr_err("Failed to load image, recovering.\n");
swsusp_free();
free_basic_memory_bitmaps();
Unlock:
@@ -743,7 +743,7 @@ int hibernate(void)
else
flags |= SF_CRC32_MODE;

pm_pr_dbg("Writing image.\n");
pm_pr_dbg("Writing hibernation image.\n");
error = swsusp_write(flags);
swsusp_free();
if (!error) {
@@ -755,7 +755,7 @@ int hibernate(void)
in_suspend = 0;
pm_restore_gfp_mask();
} else {
pm_pr_dbg("Image restored successfully.\n");
pm_pr_dbg("Hibernation image restored successfully.\n");
}

Free_bitmaps:
@@ -894,7 +894,7 @@ static int software_resume(void)
goto Close_Finish;
}

pm_pr_dbg("Preparing processes for restore.\n");
pm_pr_dbg("Preparing processes for hibernation restore.\n");
error = freeze_processes();
if (error)
goto Close_Finish;
@@ -903,7 +903,7 @@ static int software_resume(void)
Finish:
__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
pm_restore_console();
pr_info("resume from hibernation failed (%d)\n", error);
pr_info("resume failed (%d)\n", error);
atomic_inc(&snapshot_device_available);
/* For success case, the suspend path will release the lock */
Unlock:
@@ -1068,7 +1068,8 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
lock_system_sleep();
swsusp_resume_device = res;
unlock_system_sleep();
pm_pr_dbg("Configured resume from disk to %u\n", swsusp_resume_device);
pm_pr_dbg("Configured hibernation resume from disk to %u\n",
swsusp_resume_device);
noresume = 0;
software_resume();
return n;
24 changes: 15 additions & 9 deletions kernel/power/snapshot.c
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
* Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
*/

#define pr_fmt(fmt) "PM: " fmt
#define pr_fmt(fmt) "PM: hibernation: " fmt

#include <linux/version.h>
#include <linux/module.h>
@@ -1703,16 +1703,20 @@ int hibernate_preallocate_memory(void)
ktime_t start, stop;
int error;

pr_info("Preallocating image memory... ");
pr_info("Preallocating image memory\n");
start = ktime_get();

error = memory_bm_create(&orig_bm, GFP_IMAGE, PG_ANY);
if (error)
if (error) {
pr_err("Cannot allocate original bitmap\n");
goto err_out;
}

error = memory_bm_create(&copy_bm, GFP_IMAGE, PG_ANY);
if (error)
if (error) {
pr_err("Cannot allocate copy bitmap\n");
goto err_out;
}

alloc_normal = 0;
alloc_highmem = 0;
@@ -1802,8 +1806,11 @@ int hibernate_preallocate_memory(void)
alloc -= pages;
pages += pages_highmem;
pages_highmem = preallocate_image_highmem(alloc);
if (pages_highmem < alloc)
if (pages_highmem < alloc) {
pr_err("Image allocation is %lu pages short\n",
alloc - pages_highmem);
goto err_out;
}
pages += pages_highmem;
/*
* size is the desired number of saveable pages to leave in
@@ -1834,13 +1841,12 @@ int hibernate_preallocate_memory(void)

out:
stop = ktime_get();
pr_cont("done (allocated %lu pages)\n", pages);
pr_info("Allocated %lu pages for shapshot\n", pages);
swsusp_show_speed(start, stop, pages, "Allocated");

return 0;

err_out:
pr_cont("\n");
swsusp_free();
return -ENOMEM;
}
@@ -1974,7 +1980,7 @@ asmlinkage __visible int swsusp_save(void)
{
unsigned int nr_pages, nr_highmem;

pr_info("Creating hibernation image:\n");
pr_info("Creating image:\n");

drain_local_pages(NULL);
nr_pages = count_data_pages();
@@ -2008,7 +2014,7 @@ asmlinkage __visible int swsusp_save(void)
nr_copy_pages = nr_pages;
nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);

pr_info("Hibernation image created (%d pages copied)\n", nr_pages);
pr_info("Image created (%d pages copied)\n", nr_pages);

return 0;
}

0 comments on commit 7a7b99b

Please sign in to comment.