diff options
Diffstat (limited to 'kernel/power')
| -rw-r--r-- | kernel/power/disk.c | 195 | ||||
| -rw-r--r-- | kernel/power/main.c | 42 | ||||
| -rw-r--r-- | kernel/power/power.h | 7 | ||||
| -rw-r--r-- | kernel/power/snapshot.c | 2 | ||||
| -rw-r--r-- | kernel/power/user.c | 13 |
5 files changed, 132 insertions, 127 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 06331374d862..b5f0543ed84d 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
| @@ -30,30 +30,69 @@ char resume_file[256] = CONFIG_PM_STD_PARTITION; | |||
| 30 | dev_t swsusp_resume_device; | 30 | dev_t swsusp_resume_device; |
| 31 | sector_t swsusp_resume_block; | 31 | sector_t swsusp_resume_block; |
| 32 | 32 | ||
| 33 | enum { | ||
| 34 | HIBERNATION_INVALID, | ||
| 35 | HIBERNATION_PLATFORM, | ||
| 36 | HIBERNATION_TEST, | ||
| 37 | HIBERNATION_TESTPROC, | ||
| 38 | HIBERNATION_SHUTDOWN, | ||
| 39 | HIBERNATION_REBOOT, | ||
| 40 | /* keep last */ | ||
| 41 | __HIBERNATION_AFTER_LAST | ||
| 42 | }; | ||
| 43 | #define HIBERNATION_MAX (__HIBERNATION_AFTER_LAST-1) | ||
| 44 | #define HIBERNATION_FIRST (HIBERNATION_INVALID + 1) | ||
| 45 | |||
| 46 | static int hibernation_mode = HIBERNATION_SHUTDOWN; | ||
| 47 | |||
| 48 | struct hibernation_ops *hibernation_ops; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * hibernation_set_ops - set the global hibernate operations | ||
| 52 | * @ops: the hibernation operations to use in subsequent hibernation transitions | ||
| 53 | */ | ||
| 54 | |||
| 55 | void hibernation_set_ops(struct hibernation_ops *ops) | ||
| 56 | { | ||
| 57 | if (ops && !(ops->prepare && ops->enter && ops->finish)) { | ||
| 58 | WARN_ON(1); | ||
| 59 | return; | ||
| 60 | } | ||
| 61 | mutex_lock(&pm_mutex); | ||
| 62 | hibernation_ops = ops; | ||
| 63 | if (ops) | ||
| 64 | hibernation_mode = HIBERNATION_PLATFORM; | ||
| 65 | else if (hibernation_mode == HIBERNATION_PLATFORM) | ||
| 66 | hibernation_mode = HIBERNATION_SHUTDOWN; | ||
| 67 | |||
| 68 | mutex_unlock(&pm_mutex); | ||
| 69 | } | ||
| 70 | |||
| 71 | |||
| 33 | /** | 72 | /** |
| 34 | * platform_prepare - prepare the machine for hibernation using the | 73 | * platform_prepare - prepare the machine for hibernation using the |
| 35 | * platform driver if so configured and return an error code if it fails | 74 | * platform driver if so configured and return an error code if it fails |
| 36 | */ | 75 | */ |
| 37 | 76 | ||
| 38 | static inline int platform_prepare(void) | 77 | static int platform_prepare(void) |
| 39 | { | 78 | { |
| 40 | int error = 0; | 79 | return (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops) ? |
| 80 | hibernation_ops->prepare() : 0; | ||
| 81 | } | ||
| 41 | 82 | ||
| 42 | switch (pm_disk_mode) { | 83 | /** |
| 43 | case PM_DISK_TEST: | 84 | * platform_finish - switch the machine to the normal mode of operation |
| 44 | case PM_DISK_TESTPROC: | 85 | * using the platform driver (must be called after platform_prepare()) |
| 45 | case PM_DISK_SHUTDOWN: | 86 | */ |
| 46 | case PM_DISK_REBOOT: | 87 | |
| 47 | break; | 88 | static void platform_finish(void) |
| 48 | default: | 89 | { |
| 49 | if (pm_ops && pm_ops->prepare) | 90 | if (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops) |
| 50 | error = pm_ops->prepare(PM_SUSPEND_DISK); | 91 | hibernation_ops->finish(); |
| 51 | } | ||
| 52 | return error; | ||
| 53 | } | 92 | } |
| 54 | 93 | ||
| 55 | /** | 94 | /** |
| 56 | * power_down - Shut machine down for hibernate. | 95 | * power_down - Shut the machine down for hibernation. |
| 57 | * | 96 | * |
| 58 | * Use the platform driver, if configured so; otherwise try | 97 | * Use the platform driver, if configured so; otherwise try |
| 59 | * to power off or reboot. | 98 | * to power off or reboot. |
| @@ -61,20 +100,20 @@ static inline int platform_prepare(void) | |||
| 61 | 100 | ||
| 62 | static void power_down(void) | 101 | static void power_down(void) |
| 63 | { | 102 | { |
| 64 | switch (pm_disk_mode) { | 103 | switch (hibernation_mode) { |
| 65 | case PM_DISK_TEST: | 104 | case HIBERNATION_TEST: |
| 66 | case PM_DISK_TESTPROC: | 105 | case HIBERNATION_TESTPROC: |
| 67 | break; | 106 | break; |
| 68 | case PM_DISK_SHUTDOWN: | 107 | case HIBERNATION_SHUTDOWN: |
| 69 | kernel_power_off(); | 108 | kernel_power_off(); |
| 70 | break; | 109 | break; |
| 71 | case PM_DISK_REBOOT: | 110 | case HIBERNATION_REBOOT: |
| 72 | kernel_restart(NULL); | 111 | kernel_restart(NULL); |
| 73 | break; | 112 | break; |
| 74 | default: | 113 | case HIBERNATION_PLATFORM: |
| 75 | if (pm_ops && pm_ops->enter) { | 114 | if (hibernation_ops) { |
| 76 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); | 115 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); |
| 77 | pm_ops->enter(PM_SUSPEND_DISK); | 116 | hibernation_ops->enter(); |
| 78 | break; | 117 | break; |
| 79 | } | 118 | } |
| 80 | } | 119 | } |
| @@ -87,20 +126,6 @@ static void power_down(void) | |||
| 87 | while(1); | 126 | while(1); |
| 88 | } | 127 | } |
| 89 | 128 | ||
| 90 | static inline void platform_finish(void) | ||
| 91 | { | ||
| 92 | switch (pm_disk_mode) { | ||
| 93 | case PM_DISK_TEST: | ||
| 94 | case PM_DISK_TESTPROC: | ||
| 95 | case PM_DISK_SHUTDOWN: | ||
| 96 | case PM_DISK_REBOOT: | ||
| 97 | break; | ||
| 98 | default: | ||
| 99 | if (pm_ops && pm_ops->finish) | ||
| 100 | pm_ops->finish(PM_SUSPEND_DISK); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | static void unprepare_processes(void) | 129 | static void unprepare_processes(void) |
| 105 | { | 130 | { |
| 106 | thaw_processes(); | 131 | thaw_processes(); |
| @@ -120,13 +145,10 @@ static int prepare_processes(void) | |||
| 120 | } | 145 | } |
| 121 | 146 | ||
| 122 | /** | 147 | /** |
| 123 | * pm_suspend_disk - The granpappy of hibernation power management. | 148 | * hibernate - The granpappy of the built-in hibernation management |
| 124 | * | ||
| 125 | * If not, then call swsusp to do its thing, then figure out how | ||
| 126 | * to power down the system. | ||
| 127 | */ | 149 | */ |
| 128 | 150 | ||
| 129 | int pm_suspend_disk(void) | 151 | int hibernate(void) |
| 130 | { | 152 | { |
| 131 | int error; | 153 | int error; |
| 132 | 154 | ||
| @@ -143,7 +165,8 @@ int pm_suspend_disk(void) | |||
| 143 | if (error) | 165 | if (error) |
| 144 | goto Finish; | 166 | goto Finish; |
| 145 | 167 | ||
| 146 | if (pm_disk_mode == PM_DISK_TESTPROC) { | 168 | mutex_lock(&pm_mutex); |
| 169 | if (hibernation_mode == HIBERNATION_TESTPROC) { | ||
| 147 | printk("swsusp debug: Waiting for 5 seconds.\n"); | 170 | printk("swsusp debug: Waiting for 5 seconds.\n"); |
| 148 | mdelay(5000); | 171 | mdelay(5000); |
| 149 | goto Thaw; | 172 | goto Thaw; |
| @@ -168,7 +191,7 @@ int pm_suspend_disk(void) | |||
| 168 | if (error) | 191 | if (error) |
| 169 | goto Enable_cpus; | 192 | goto Enable_cpus; |
| 170 | 193 | ||
| 171 | if (pm_disk_mode == PM_DISK_TEST) { | 194 | if (hibernation_mode == HIBERNATION_TEST) { |
| 172 | printk("swsusp debug: Waiting for 5 seconds.\n"); | 195 | printk("swsusp debug: Waiting for 5 seconds.\n"); |
| 173 | mdelay(5000); | 196 | mdelay(5000); |
| 174 | goto Enable_cpus; | 197 | goto Enable_cpus; |
| @@ -205,6 +228,7 @@ int pm_suspend_disk(void) | |||
| 205 | device_resume(); | 228 | device_resume(); |
| 206 | resume_console(); | 229 | resume_console(); |
| 207 | Thaw: | 230 | Thaw: |
| 231 | mutex_unlock(&pm_mutex); | ||
| 208 | unprepare_processes(); | 232 | unprepare_processes(); |
| 209 | Finish: | 233 | Finish: |
| 210 | free_basic_memory_bitmaps(); | 234 | free_basic_memory_bitmaps(); |
| @@ -220,7 +244,7 @@ int pm_suspend_disk(void) | |||
| 220 | * Called as a late_initcall (so all devices are discovered and | 244 | * Called as a late_initcall (so all devices are discovered and |
| 221 | * initialized), we call swsusp to see if we have a saved image or not. | 245 | * initialized), we call swsusp to see if we have a saved image or not. |
| 222 | * If so, we quiesce devices, the restore the saved image. We will | 246 | * If so, we quiesce devices, the restore the saved image. We will |
| 223 | * return above (in pm_suspend_disk() ) if everything goes well. | 247 | * return above (in hibernate() ) if everything goes well. |
| 224 | * Otherwise, we fail gracefully and return to the normally | 248 | * Otherwise, we fail gracefully and return to the normally |
| 225 | * scheduled program. | 249 | * scheduled program. |
| 226 | * | 250 | * |
| @@ -315,25 +339,26 @@ static int software_resume(void) | |||
| 315 | late_initcall(software_resume); | 339 | late_initcall(software_resume); |
| 316 | 340 | ||
| 317 | 341 | ||
| 318 | static const char * const pm_disk_modes[] = { | 342 | static const char * const hibernation_modes[] = { |
| 319 | [PM_DISK_PLATFORM] = "platform", | 343 | [HIBERNATION_PLATFORM] = "platform", |
| 320 | [PM_DISK_SHUTDOWN] = "shutdown", | 344 | [HIBERNATION_SHUTDOWN] = "shutdown", |
| 321 | [PM_DISK_REBOOT] = "reboot", | 345 | [HIBERNATION_REBOOT] = "reboot", |
| 322 | [PM_DISK_TEST] = "test", | 346 | [HIBERNATION_TEST] = "test", |
| 323 | [PM_DISK_TESTPROC] = "testproc", | 347 | [HIBERNATION_TESTPROC] = "testproc", |
| 324 | }; | 348 | }; |
| 325 | 349 | ||
| 326 | /** | 350 | /** |
| 327 | * disk - Control suspend-to-disk mode | 351 | * disk - Control hibernation mode |
| 328 | * | 352 | * |
| 329 | * Suspend-to-disk can be handled in several ways. We have a few options | 353 | * Suspend-to-disk can be handled in several ways. We have a few options |
| 330 | * for putting the system to sleep - using the platform driver (e.g. ACPI | 354 | * for putting the system to sleep - using the platform driver (e.g. ACPI |
| 331 | * or other pm_ops), powering off the system or rebooting the system | 355 | * or other hibernation_ops), powering off the system or rebooting the |
| 332 | * (for testing) as well as the two test modes. | 356 | * system (for testing) as well as the two test modes. |
| 333 | * | 357 | * |
| 334 | * The system can support 'platform', and that is known a priori (and | 358 | * The system can support 'platform', and that is known a priori (and |
| 335 | * encoded in pm_ops). However, the user may choose 'shutdown' or 'reboot' | 359 | * encoded by the presence of hibernation_ops). However, the user may |
| 336 | * as alternatives, as well as the test modes 'test' and 'testproc'. | 360 | * choose 'shutdown' or 'reboot' as alternatives, as well as one fo the |
| 361 | * test modes, 'test' or 'testproc'. | ||
| 337 | * | 362 | * |
| 338 | * show() will display what the mode is currently set to. | 363 | * show() will display what the mode is currently set to. |
| 339 | * store() will accept one of | 364 | * store() will accept one of |
| @@ -345,7 +370,7 @@ static const char * const pm_disk_modes[] = { | |||
| 345 | * 'testproc' | 370 | * 'testproc' |
| 346 | * | 371 | * |
| 347 | * It will only change to 'platform' if the system | 372 | * It will only change to 'platform' if the system |
| 348 | * supports it (as determined from pm_ops->pm_disk_mode). | 373 | * supports it (as determined by having hibernation_ops). |
| 349 | */ | 374 | */ |
| 350 | 375 | ||
| 351 | static ssize_t disk_show(struct kset *kset, char *buf) | 376 | static ssize_t disk_show(struct kset *kset, char *buf) |
| @@ -353,28 +378,25 @@ static ssize_t disk_show(struct kset *kset, char *buf) | |||
| 353 | int i; | 378 | int i; |
| 354 | char *start = buf; | 379 | char *start = buf; |
| 355 | 380 | ||
| 356 | for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) { | 381 | for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { |
| 357 | if (!pm_disk_modes[i]) | 382 | if (!hibernation_modes[i]) |
| 358 | continue; | 383 | continue; |
| 359 | switch (i) { | 384 | switch (i) { |
| 360 | case PM_DISK_SHUTDOWN: | 385 | case HIBERNATION_SHUTDOWN: |
| 361 | case PM_DISK_REBOOT: | 386 | case HIBERNATION_REBOOT: |
| 362 | case PM_DISK_TEST: | 387 | case HIBERNATION_TEST: |
| 363 | case PM_DISK_TESTPROC: | 388 | case HIBERNATION_TESTPROC: |
| 364 | break; | 389 | break; |
| 365 | default: | 390 | case HIBERNATION_PLATFORM: |
| 366 | if (pm_ops && pm_ops->enter && | 391 | if (hibernation_ops) |
| 367 | (i == pm_ops->pm_disk_mode)) | ||
| 368 | break; | 392 | break; |
| 369 | /* not a valid mode, continue with loop */ | 393 | /* not a valid mode, continue with loop */ |
| 370 | continue; | 394 | continue; |
| 371 | } | 395 | } |
| 372 | if (i == pm_disk_mode) | 396 | if (i == hibernation_mode) |
| 373 | buf += sprintf(buf, "[%s]", pm_disk_modes[i]); | 397 | buf += sprintf(buf, "[%s] ", hibernation_modes[i]); |
| 374 | else | 398 | else |
| 375 | buf += sprintf(buf, "%s", pm_disk_modes[i]); | 399 | buf += sprintf(buf, "%s ", hibernation_modes[i]); |
| 376 | if (i+1 != PM_DISK_MAX) | ||
| 377 | buf += sprintf(buf, " "); | ||
| 378 | } | 400 | } |
| 379 | buf += sprintf(buf, "\n"); | 401 | buf += sprintf(buf, "\n"); |
| 380 | return buf-start; | 402 | return buf-start; |
| @@ -387,39 +409,38 @@ static ssize_t disk_store(struct kset *kset, const char *buf, size_t n) | |||
| 387 | int i; | 409 | int i; |
| 388 | int len; | 410 | int len; |
| 389 | char *p; | 411 | char *p; |
| 390 | suspend_disk_method_t mode = 0; | 412 | int mode = HIBERNATION_INVALID; |
| 391 | 413 | ||
| 392 | p = memchr(buf, '\n', n); | 414 | p = memchr(buf, '\n', n); |
| 393 | len = p ? p - buf : n; | 415 | len = p ? p - buf : n; |
| 394 | 416 | ||
| 395 | mutex_lock(&pm_mutex); | 417 | mutex_lock(&pm_mutex); |
| 396 | for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) { | 418 | for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { |
| 397 | if (!strncmp(buf, pm_disk_modes[i], len)) { | 419 | if (!strncmp(buf, hibernation_modes[i], len)) { |
| 398 | mode = i; | 420 | mode = i; |
| 399 | break; | 421 | break; |
| 400 | } | 422 | } |
| 401 | } | 423 | } |
| 402 | if (mode) { | 424 | if (mode != HIBERNATION_INVALID) { |
| 403 | switch (mode) { | 425 | switch (mode) { |
| 404 | case PM_DISK_SHUTDOWN: | 426 | case HIBERNATION_SHUTDOWN: |
| 405 | case PM_DISK_REBOOT: | 427 | case HIBERNATION_REBOOT: |
| 406 | case PM_DISK_TEST: | 428 | case HIBERNATION_TEST: |
| 407 | case PM_DISK_TESTPROC: | 429 | case HIBERNATION_TESTPROC: |
| 408 | pm_disk_mode = mode; | 430 | hibernation_mode = mode; |
| 409 | break; | 431 | break; |
| 410 | default: | 432 | case HIBERNATION_PLATFORM: |
| 411 | if (pm_ops && pm_ops->enter && | 433 | if (hibernation_ops) |
| 412 | (mode == pm_ops->pm_disk_mode)) | 434 | hibernation_mode = mode; |
| 413 | pm_disk_mode = mode; | ||
| 414 | else | 435 | else |
| 415 | error = -EINVAL; | 436 | error = -EINVAL; |
| 416 | } | 437 | } |
| 417 | } else { | 438 | } else |
| 418 | error = -EINVAL; | 439 | error = -EINVAL; |
| 419 | } | ||
| 420 | 440 | ||
| 421 | pr_debug("PM: suspend-to-disk mode set to '%s'\n", | 441 | if (!error) |
| 422 | pm_disk_modes[mode]); | 442 | pr_debug("PM: suspend-to-disk mode set to '%s'\n", |
| 443 | hibernation_modes[mode]); | ||
| 423 | mutex_unlock(&pm_mutex); | 444 | mutex_unlock(&pm_mutex); |
| 424 | return error ? error : n; | 445 | return error ? error : n; |
| 425 | } | 446 | } |
diff --git a/kernel/power/main.c b/kernel/power/main.c index f6dda685e7e2..40d56a31245e 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | DEFINE_MUTEX(pm_mutex); | 30 | DEFINE_MUTEX(pm_mutex); |
| 31 | 31 | ||
| 32 | struct pm_ops *pm_ops; | 32 | struct pm_ops *pm_ops; |
| 33 | suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN; | ||
| 34 | 33 | ||
| 35 | /** | 34 | /** |
| 36 | * pm_set_ops - Set the global power method table. | 35 | * pm_set_ops - Set the global power method table. |
| @@ -41,10 +40,6 @@ void pm_set_ops(struct pm_ops * ops) | |||
| 41 | { | 40 | { |
| 42 | mutex_lock(&pm_mutex); | 41 | mutex_lock(&pm_mutex); |
| 43 | pm_ops = ops; | 42 | pm_ops = ops; |
| 44 | if (ops && ops->pm_disk_mode != PM_DISK_INVALID) { | ||
| 45 | pm_disk_mode = ops->pm_disk_mode; | ||
| 46 | } else | ||
| 47 | pm_disk_mode = PM_DISK_SHUTDOWN; | ||
| 48 | mutex_unlock(&pm_mutex); | 43 | mutex_unlock(&pm_mutex); |
| 49 | } | 44 | } |
| 50 | 45 | ||
| @@ -184,24 +179,12 @@ static void suspend_finish(suspend_state_t state) | |||
| 184 | static const char * const pm_states[PM_SUSPEND_MAX] = { | 179 | static const char * const pm_states[PM_SUSPEND_MAX] = { |
| 185 | [PM_SUSPEND_STANDBY] = "standby", | 180 | [PM_SUSPEND_STANDBY] = "standby", |
| 186 | [PM_SUSPEND_MEM] = "mem", | 181 | [PM_SUSPEND_MEM] = "mem", |
| 187 | [PM_SUSPEND_DISK] = "disk", | ||
| 188 | }; | 182 | }; |
| 189 | 183 | ||
| 190 | static inline int valid_state(suspend_state_t state) | 184 | static inline int valid_state(suspend_state_t state) |
| 191 | { | 185 | { |
| 192 | /* Suspend-to-disk does not really need low-level support. | 186 | /* All states need lowlevel support and need to be valid |
| 193 | * It can work with shutdown/reboot if needed. If it isn't | 187 | * to the lowlevel implementation, no valid callback |
| 194 | * configured, then it cannot be supported. | ||
| 195 | */ | ||
| 196 | if (state == PM_SUSPEND_DISK) | ||
| 197 | #ifdef CONFIG_SOFTWARE_SUSPEND | ||
| 198 | return 1; | ||
| 199 | #else | ||
| 200 | return 0; | ||
| 201 | #endif | ||
| 202 | |||
| 203 | /* all other states need lowlevel support and need to be | ||
| 204 | * valid to the lowlevel implementation, no valid callback | ||
| 205 | * implies that none are valid. */ | 188 | * implies that none are valid. */ |
| 206 | if (!pm_ops || !pm_ops->valid || !pm_ops->valid(state)) | 189 | if (!pm_ops || !pm_ops->valid || !pm_ops->valid(state)) |
| 207 | return 0; | 190 | return 0; |
| @@ -229,11 +212,6 @@ static int enter_state(suspend_state_t state) | |||
| 229 | if (!mutex_trylock(&pm_mutex)) | 212 | if (!mutex_trylock(&pm_mutex)) |
| 230 | return -EBUSY; | 213 | return -EBUSY; |
| 231 | 214 | ||
| 232 | if (state == PM_SUSPEND_DISK) { | ||
| 233 | error = pm_suspend_disk(); | ||
| 234 | goto Unlock; | ||
| 235 | } | ||
| 236 | |||
| 237 | pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); | 215 | pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); |
| 238 | if ((error = suspend_prepare(state))) | 216 | if ((error = suspend_prepare(state))) |
| 239 | goto Unlock; | 217 | goto Unlock; |
| @@ -251,7 +229,7 @@ static int enter_state(suspend_state_t state) | |||
| 251 | 229 | ||
| 252 | /** | 230 | /** |
| 253 | * pm_suspend - Externally visible function for suspending system. | 231 | * pm_suspend - Externally visible function for suspending system. |
| 254 | * @state: Enumarted value of state to enter. | 232 | * @state: Enumerated value of state to enter. |
| 255 | * | 233 | * |
| 256 | * Determine whether or not value is within range, get state | 234 | * Determine whether or not value is within range, get state |
| 257 | * structure, and enter (above). | 235 | * structure, and enter (above). |
| @@ -289,7 +267,13 @@ static ssize_t state_show(struct kset *kset, char *buf) | |||
| 289 | if (pm_states[i] && valid_state(i)) | 267 | if (pm_states[i] && valid_state(i)) |
| 290 | s += sprintf(s,"%s ", pm_states[i]); | 268 | s += sprintf(s,"%s ", pm_states[i]); |
| 291 | } | 269 | } |
| 292 | s += sprintf(s,"\n"); | 270 | #ifdef CONFIG_SOFTWARE_SUSPEND |
| 271 | s += sprintf(s, "%s\n", "disk"); | ||
| 272 | #else | ||
| 273 | if (s != buf) | ||
| 274 | /* convert the last space to a newline */ | ||
| 275 | *(s-1) = '\n'; | ||
| 276 | #endif | ||
| 293 | return (s - buf); | 277 | return (s - buf); |
| 294 | } | 278 | } |
| 295 | 279 | ||
| @@ -304,6 +288,12 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n) | |||
| 304 | p = memchr(buf, '\n', n); | 288 | p = memchr(buf, '\n', n); |
| 305 | len = p ? p - buf : n; | 289 | len = p ? p - buf : n; |
| 306 | 290 | ||
| 291 | /* First, check if we are requested to hibernate */ | ||
| 292 | if (!strncmp(buf, "disk", len)) { | ||
| 293 | error = hibernate(); | ||
| 294 | return error ? error : n; | ||
| 295 | } | ||
| 296 | |||
| 307 | for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { | 297 | for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { |
| 308 | if (*s && !strncmp(buf, *s, len)) | 298 | if (*s && !strncmp(buf, *s, len)) |
| 309 | break; | 299 | break; |
diff --git a/kernel/power/power.h b/kernel/power/power.h index 34b43542785a..51381487103f 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
| @@ -25,12 +25,7 @@ struct swsusp_info { | |||
| 25 | */ | 25 | */ |
| 26 | #define SPARE_PAGES ((1024 * 1024) >> PAGE_SHIFT) | 26 | #define SPARE_PAGES ((1024 * 1024) >> PAGE_SHIFT) |
| 27 | 27 | ||
| 28 | extern int pm_suspend_disk(void); | 28 | extern struct hibernation_ops *hibernation_ops; |
| 29 | #else | ||
| 30 | static inline int pm_suspend_disk(void) | ||
| 31 | { | ||
| 32 | return -EPERM; | ||
| 33 | } | ||
| 34 | #endif | 29 | #endif |
| 35 | 30 | ||
| 36 | extern int pfn_is_nosave(unsigned long); | 31 | extern int pfn_is_nosave(unsigned long); |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 59fb89ba9a4d..a3b7854b8f7c 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
| @@ -1233,7 +1233,7 @@ asmlinkage int swsusp_save(void) | |||
| 1233 | nr_copy_pages = nr_pages; | 1233 | nr_copy_pages = nr_pages; |
| 1234 | nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE); | 1234 | nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE); |
| 1235 | 1235 | ||
| 1236 | printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages); | 1236 | printk("swsusp: critical section: done (%d pages copied)\n", nr_pages); |
| 1237 | 1237 | ||
| 1238 | return 0; | 1238 | return 0; |
| 1239 | } | 1239 | } |
diff --git a/kernel/power/user.c b/kernel/power/user.c index 040560d9c312..24d7d78e6f42 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
| @@ -130,16 +130,16 @@ static inline int platform_prepare(void) | |||
| 130 | { | 130 | { |
| 131 | int error = 0; | 131 | int error = 0; |
| 132 | 132 | ||
| 133 | if (pm_ops && pm_ops->prepare) | 133 | if (hibernation_ops) |
| 134 | error = pm_ops->prepare(PM_SUSPEND_DISK); | 134 | error = hibernation_ops->prepare(); |
| 135 | 135 | ||
| 136 | return error; | 136 | return error; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | static inline void platform_finish(void) | 139 | static inline void platform_finish(void) |
| 140 | { | 140 | { |
| 141 | if (pm_ops && pm_ops->finish) | 141 | if (hibernation_ops) |
| 142 | pm_ops->finish(PM_SUSPEND_DISK); | 142 | hibernation_ops->finish(); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static inline int snapshot_suspend(int platform_suspend) | 145 | static inline int snapshot_suspend(int platform_suspend) |
| @@ -384,7 +384,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
| 384 | switch (arg) { | 384 | switch (arg) { |
| 385 | 385 | ||
| 386 | case PMOPS_PREPARE: | 386 | case PMOPS_PREPARE: |
| 387 | if (pm_ops && pm_ops->enter) { | 387 | if (hibernation_ops) { |
| 388 | data->platform_suspend = 1; | 388 | data->platform_suspend = 1; |
| 389 | error = 0; | 389 | error = 0; |
| 390 | } else { | 390 | } else { |
| @@ -395,8 +395,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
| 395 | case PMOPS_ENTER: | 395 | case PMOPS_ENTER: |
| 396 | if (data->platform_suspend) { | 396 | if (data->platform_suspend) { |
| 397 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); | 397 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); |
| 398 | error = pm_ops->enter(PM_SUSPEND_DISK); | 398 | error = hibernation_ops->enter(); |
| 399 | error = 0; | ||
| 400 | } | 399 | } |
| 401 | break; | 400 | break; |
| 402 | 401 | ||
