diff -ur kernel.bak/power/disk.c kernel/power/disk.c --- kernel.bak/power/disk.c 2004-12-05 16:11:19.000000000 +0000 +++ kernel/power/disk.c 2004-12-05 20:28:32.000000000 +0000 @@ -26,9 +26,10 @@ extern int swsusp_suspend(void); extern int swsusp_write(void); extern int swsusp_read(void); +extern int swsusp_read_from(dev_t resume_device); extern int swsusp_resume(void); extern int swsusp_free(void); - +extern void swsusp_set_resume_device(dev_t resume_device); static int noresume = 0; char resume_file[256] = CONFIG_PM_STD_PARTITION; @@ -198,18 +199,15 @@ /** - * software_resume - Resume from a saved image. + * software_resume_from - Do the actual grunt work of resume * - * Called as a late_initcall (so all devices are discovered and - * initialized), we call pmdisk to see if we have a saved image or not. + * We call pmdisk to see if we have a saved image or not. * If so, we quiesce devices, the restore the saved image. We will * return above (in pm_suspend_disk() ) if everything goes well. - * Otherwise, we fail gracefully and return to the normally - * scheduled program. * */ -static int software_resume(void) +static int software_resume_from(dev_t resume_device) { int error; @@ -223,9 +221,13 @@ pr_debug("PM: Reading pmdisk image.\n"); - if ((error = swsusp_read())) - goto Done; - + if (resume_device) { + if ((error = swsusp_read_from(resume_device))) + goto Done; + } else { + if ((error = swsusp_read())) + goto Done; + } pr_debug("PM: Preparing system for restore.\n"); if ((error = prepare())) @@ -245,6 +247,23 @@ return 0; } +/** + * software_resume - Resume from a saved image. + * + * Called as a late_initcall (so all devices are discovered and + * initialized), we simply trigger software_resume_from without + * giving it an explicit resume device. This will then allow + * swsusp to parse the resume argument passed to the kernel. With + * luck, we end up in pm_suspend_disk(). Otherwise, we fail gracefully + * and return to the normally scheduled program. + * + */ + +static int software_resume(void) +{ + return software_resume_from(0); +} + late_initcall(software_resume); @@ -327,17 +346,54 @@ power_attr(disk); +static ssize_t resume_show(struct subsystem * subsys, char * buf) { + return sprintf(buf,"set resume\n"); +} + +static ssize_t resume_store(struct subsystem * s, const char * buf, size_t n) +{ + int error = 0; + int len; + char *p; + unsigned maj, min; + dev_t (res); + + p = memchr(buf, '\n', n); + len = p ? p - buf : n; + + if (sscanf(buf, "resume %u:%u", &maj, &min) == 2) { + res = MKDEV(maj, min); + if (maj == MAJOR(res) && min == MINOR(res)) { + error = software_resume_from(res); + } else { + error = EINVAL; + } + } else if (sscanf(buf, "set %u:%u", &maj, &min) == 2) { + res = MKDEV(maj, min); + if (maj == MAJOR(res) && min == MINOR(res)) { + swsusp_set_resume_device(res); + } else { + error = EINVAL; + } + } else { + error = EINVAL; + } + + return error ? error : n; +} + +power_attr(resume); + static struct attribute * g[] = { &disk_attr.attr, + &resume_attr.attr, NULL, }; - static struct attribute_group attr_group = { - .attrs = g, + .attrs = g, }; - static int __init pm_disk_init(void) { return sysfs_create_group(&power_subsys.kset.kobj,&attr_group); diff -ur kernel.bak/power/swsusp.c kernel/power/swsusp.c --- kernel.bak/power/swsusp.c 2004-12-05 18:31:40.000000000 +0000 +++ kernel/power/swsusp.c 2004-12-05 20:30:02.000000000 +0000 @@ -174,6 +174,11 @@ resume_device == MKDEV(imajor(inode), iminor(inode)); } +void swsusp_set_resume_device(dev_t device) +{ + resume_device = device; +} + int swsusp_swap_check(void) /* This is called before saving image */ { int i, len; @@ -1216,16 +1221,10 @@ * pmdisk_read - Read saved image from swap. */ -int swsusp_read(void) +int swsusp_read_from(dev_t resume_device) { int error; - if (!strlen(resume_file)) - return -ENOENT; - - resume_device = name_to_dev_t(resume_file); - pr_debug("swsusp: Resume From Partition: %s\n", resume_file); - resume_bdev = open_by_devnum(resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); @@ -1240,3 +1239,14 @@ pr_debug("pmdisk: Error %d resuming\n", error); return error; } + +int swsusp_read(void) +{ + if (!strlen(resume_file)) + return -ENOENT; + + resume_device = name_to_dev_t(resume_file); + pr_debug("swsusp: Resume From Partition: %s\n", resume_file); + return swsusp_read_from(resume_device); +} +