Hmm ... I just noticed that the swsusp code path (PM_SUSPEND_DISK) is ignoring the new suspend_prepare() mechanism. That doesn't seem like a good thing ... Linus, is there a reason you did it that way? Why is there no sibling resume_complete()? ISTR that Ben was the advocate of a suspend_prepare(), but the use cases for this call are unclear to me ... - Dave This makes the prepare_suspend() phase apply to all suspend modes, instead of ignoring it for swsusp. Potential changes: - Add a sibling bus.resume_complete() to allow cleanup. - Remove the pm_message_t parameter bus.suspend_early() since there appears to be no useful way for it to be used with any value other than PMSG_SUSPEND ... and the intent of calling this while userspace and other tasks is still active seems to be to allow userspace notification about the desired state change. - Provide a sys/power/sleep_state file so that userspace can know if the upcoming sleep state is "standby", STR/"mem", STD/"disk", or "on" (whenever it's not suspending). Index: g26/kernel/power/main.c =================================================================== --- g26.orig/kernel/power/main.c 2006-07-15 18:15:21.000000000 -0700 +++ g26/kernel/power/main.c 2006-07-25 10:59:38.000000000 -0700 @@ -54,13 +54,6 @@ static int suspend_prepare(suspend_state int error = 0; unsigned int free_pages; - if (!pm_ops || !pm_ops->enter) - return -EPERM; - - error = device_prepare_suspend(PMSG_SUSPEND); - if (error) - return error; - pm_prepare_console(); disable_nonboot_cpus(); @@ -187,9 +180,20 @@ static int enter_state(suspend_state_t s if (!valid_state(state)) return -ENODEV; + if (state != PM_SUSPEND_DISK && (!pm_ops || !pm_ops->enter)) + return -EPERM; + if (down_trylock(&pm_sem)) return -EBUSY; + error = device_prepare_suspend(PMSG_SUSPEND); + if (error) { + /* FIXME don't we need a bus.resume_complete() mechanism, if + * only to reverse the effect of bus.suspend_prepare() ?? + */ + goto Unlock; + } + if (state == PM_SUSPEND_DISK) { error = pm_suspend_disk(); goto Unlock;