Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 61541
b: refs/heads/master
c: a634cc1
h: refs/heads/master
i:
  61539: 64a81ed
v: v3
  • Loading branch information
Rafael J. Wysocki authored and Linus Torvalds committed Jul 19, 2007
1 parent ada380f commit 5a73c97
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7777fab989b5d006903188c966058ebcd2d6342a
refs/heads/master: a634cc10164d1c229fbeca33923e6a0ed939e894
16 changes: 16 additions & 0 deletions trunk/drivers/acpi/sleep/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,26 @@ static void acpi_hibernation_finish(void)
}
}

static int acpi_hibernation_pre_restore(void)
{
acpi_status status;

status = acpi_hw_disable_all_gpes();

return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}

static void acpi_hibernation_restore_cleanup(void)
{
acpi_hw_enable_all_runtime_gpes();
}

static struct hibernation_ops acpi_hibernation_ops = {
.prepare = acpi_hibernation_prepare,
.enter = acpi_hibernation_enter,
.finish = acpi_hibernation_finish,
.pre_restore = acpi_hibernation_pre_restore,
.restore_cleanup = acpi_hibernation_restore_cleanup,
};
#endif /* CONFIG_SOFTWARE_SUSPEND */

Expand Down
4 changes: 4 additions & 0 deletions trunk/include/linux/suspend.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ static inline void pm_restore_console(void) {}
* @prepare: prepare system for hibernation
* @enter: shut down system after state has been saved to disk
* @finish: finish/clean up after state has been reloaded
* @pre_restore: prepare system for the restoration from a hibernation image
* @restore_cleanup: clean up after a failing image restoration
*/
struct hibernation_ops {
int (*prepare)(void);
int (*enter)(void);
void (*finish)(void);
int (*pre_restore)(void);
void (*restore_cleanup)(void);
};

#if defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND)
Expand Down
56 changes: 46 additions & 10 deletions trunk/kernel/power/disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ static struct hibernation_ops *hibernation_ops;

void hibernation_set_ops(struct hibernation_ops *ops)
{
if (ops && !(ops->prepare && ops->enter && ops->finish)) {
if (ops && !(ops->prepare && ops->enter && ops->finish
&& ops->pre_restore && ops->restore_cleanup)) {
WARN_ON(1);
return;
}
Expand Down Expand Up @@ -91,6 +92,31 @@ static void platform_finish(int platform_mode)
hibernation_ops->finish();
}

/**
* platform_pre_restore - prepare the platform for the restoration from a
* hibernation image. If the restore fails after this function has been
* called, platform_restore_cleanup() must be called.
*/

static int platform_pre_restore(int platform_mode)
{
return (platform_mode && hibernation_ops) ?
hibernation_ops->pre_restore() : 0;
}

/**
* platform_restore_cleanup - switch the platform to the normal mode of
* operation after a failing restore. If platform_pre_restore() has been
* called before the failing restore, this function must be called too,
* regardless of the result of platform_pre_restore().
*/

static void platform_restore_cleanup(int platform_mode)
{
if (platform_mode && hibernation_ops)
hibernation_ops->restore_cleanup();
}

/**
* hibernation_snapshot - quiesce devices and create the hibernation
* snapshot image.
Expand Down Expand Up @@ -141,11 +167,13 @@ int hibernation_snapshot(int platform_mode)
/**
* hibernation_restore - quiesce devices and restore the hibernation
* snapshot image. If successful, control returns in hibernation_snaphot()
* @platform_mode - if set, use the platform driver, if available, to
* prepare the platform frimware for the transition.
*
* Must be called with pm_mutex held
*/

int hibernation_restore(void)
int hibernation_restore(int platform_mode)
{
int error;

Expand All @@ -155,11 +183,14 @@ int hibernation_restore(void)
if (error)
goto Finish;

error = disable_nonboot_cpus();
if (!error)
error = swsusp_resume();

enable_nonboot_cpus();
error = platform_pre_restore(platform_mode);
if (!error) {
error = disable_nonboot_cpus();
if (!error)
error = swsusp_resume();
enable_nonboot_cpus();
}
platform_restore_cleanup(platform_mode);
Finish:
device_resume();
resume_console();
Expand Down Expand Up @@ -260,8 +291,12 @@ int hibernate(void)
}
error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
if (in_suspend && !error) {
unsigned int flags = 0;

if (hibernation_mode == HIBERNATION_PLATFORM)
flags |= SF_PLATFORM_MODE;
pr_debug("PM: writing image.\n");
error = swsusp_write();
error = swsusp_write(flags);
swsusp_free();
if (!error)
power_down();
Expand Down Expand Up @@ -295,6 +330,7 @@ int hibernate(void)
static int software_resume(void)
{
int error;
unsigned int flags;

mutex_lock(&pm_mutex);
if (!swsusp_resume_device) {
Expand Down Expand Up @@ -342,9 +378,9 @@ static int software_resume(void)

pr_debug("PM: Reading swsusp image.\n");

error = swsusp_read();
error = swsusp_read(&flags);
if (!error)
hibernation_restore();
hibernation_restore(flags & SF_PLATFORM_MODE);

printk(KERN_ERR "PM: Restore failed, recovering.\n");
swsusp_free();
Expand Down
13 changes: 10 additions & 3 deletions trunk/kernel/power/power.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct swsusp_info {

/* kernel/power/disk.c */
extern int hibernation_snapshot(int platform_mode);
extern int hibernation_restore(void);
extern int hibernation_restore(int platform_mode);
extern int hibernation_platform_enter(void);
#endif

Expand Down Expand Up @@ -155,13 +155,20 @@ extern sector_t alloc_swapdev_block(int swap);
extern void free_all_swap_pages(int swap);
extern int swsusp_swap_in_use(void);

/*
* Flags that can be passed from the hibernatig hernel to the "boot" kernel in
* the image header.
*/
#define SF_PLATFORM_MODE 1

/* kernel/power/disk.c */
extern int swsusp_check(void);
extern int swsusp_shrink_memory(void);
extern void swsusp_free(void);
extern int swsusp_suspend(void);
extern int swsusp_resume(void);
extern int swsusp_read(void);
extern int swsusp_write(void);
extern int swsusp_read(unsigned int *flags_p);
extern int swsusp_write(unsigned int flags);
extern void swsusp_close(void);
extern int suspend_enter(suspend_state_t state);

Expand Down
20 changes: 15 additions & 5 deletions trunk/kernel/power/swap.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ extern char resume_file[];
#define SWSUSP_SIG "S1SUSPEND"

struct swsusp_header {
char reserved[PAGE_SIZE - 20 - sizeof(sector_t)];
char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
sector_t image;
unsigned int flags; /* Flags to pass to the "boot" kernel */
char orig_sig[10];
char sig[10];
} __attribute__((packed));
Expand Down Expand Up @@ -138,7 +139,7 @@ static int wait_on_bio_chain(struct bio **bio_chain)
* Saving part
*/

static int mark_swapfiles(sector_t start)
static int mark_swapfiles(sector_t start, unsigned int flags)
{
int error;

Expand All @@ -148,6 +149,7 @@ static int mark_swapfiles(sector_t start)
memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
swsusp_header->image = start;
swsusp_header->flags = flags;
error = bio_write_page(swsusp_resume_block,
swsusp_header, NULL);
} else {
Expand Down Expand Up @@ -369,14 +371,15 @@ static int enough_swap(unsigned int nr_pages)

/**
* swsusp_write - Write entire image and metadata.
* @flags: flags to pass to the "boot" kernel in the image header
*
* It is important _NOT_ to umount filesystems at this point. We want
* them synced (in case something goes wrong) but we DO not want to mark
* filesystem clean: it is not. (And it does not matter, if we resume
* correctly, we'll mark system clean, anyway.)
*/

int swsusp_write(void)
int swsusp_write(unsigned int flags)
{
struct swap_map_handle handle;
struct snapshot_handle snapshot;
Expand Down Expand Up @@ -415,7 +418,7 @@ int swsusp_write(void)
if (!error) {
flush_swap_writer(&handle);
printk("S");
error = mark_swapfiles(start);
error = mark_swapfiles(start, flags);
printk("|\n");
}
}
Expand Down Expand Up @@ -540,13 +543,20 @@ static int load_image(struct swap_map_handle *handle,
return error;
}

int swsusp_read(void)
/**
* swsusp_read - read the hibernation image.
* @flags_p: flags passed by the "frozen" kernel in the image header should
* be written into this memeory location
*/

int swsusp_read(unsigned int *flags_p)
{
int error;
struct swap_map_handle handle;
struct snapshot_handle snapshot;
struct swsusp_info *header;

*flags_p = swsusp_header->flags;
if (IS_ERR(resume_bdev)) {
pr_debug("swsusp: block device not initialised\n");
return PTR_ERR(resume_bdev);
Expand Down
2 changes: 1 addition & 1 deletion trunk/kernel/power/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
error = -EPERM;
break;
}
error = hibernation_restore();
error = hibernation_restore(data->platform_suspend);
break;

case SNAPSHOT_FREE:
Expand Down

0 comments on commit 5a73c97

Please sign in to comment.