/** * hibernation_restore - Quiesce devices and restore from a hibernation image. * @platform_mode: If set, use platform driver to prepare for the transition. * * This routine must be called with pm_mutex held. If it is successful, control * reappears in the restored target kernel in hibernation_snapshot(). */ int hibernation_restore(int platform_mode) { int error; pm_prepare_console(); suspend_console(); ftrace_stop(); pm_restrict_gfp_mask(); error = dpm_suspend_start(PMSG_QUIESCE); if (!error) { error = resume_target_kernel(platform_mode); /* * The above should either succeed and jump to the new kernel, * or return with an error. Otherwise things are just * undefined, so let's be paranoid. */ BUG_ON(!error); } dpm_resume_end(PMSG_RECOVER); pm_restore_gfp_mask(); ftrace_start(); resume_console(); pm_restore_console(); return error; }
static int enter_state(suspend_state_t state) { int error; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; sys_sync(); pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&pm_mutex); return error; }
/** * hibernation_snapshot - Quiesce devices and create a hibernation image. * @platform_mode: If set, use platform driver to prepare for the transition. * * This routine must be called with pm_mutex held. */ int hibernation_snapshot(int platform_mode) { pm_message_t msg = PMSG_RECOVER; int error; error = platform_begin(platform_mode); if (error) goto Close; error = dpm_prepare(PMSG_FREEZE); if (error) goto Complete_devices; /* Preallocate image memory before shutting down devices. */ error = hibernate_preallocate_memory(); if (error) goto Complete_devices; suspend_console(); ftrace_stop(); pm_restrict_gfp_mask(); error = dpm_suspend(PMSG_FREEZE); if (error) goto Recover_platform; if (hibernation_test(TEST_DEVICES)) goto Recover_platform; error = create_image(platform_mode); /* * Control returns here (1) after the image has been created or the * image creation has failed and (2) after a successful restore. */ Resume_devices: /* We may need to release the preallocated image pages here. */ if (error || !in_suspend) swsusp_free(); msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE; dpm_resume(msg); if (error || !in_suspend) pm_restore_gfp_mask(); ftrace_start(); resume_console(); Complete_devices: dpm_complete(msg); Close: platform_end(platform_mode); return error; Recover_platform: platform_recover(platform_mode); goto Resume_devices; }
/** * enter_state - Do common work of entering low-power state. * @state: pm_state structure for state we're entering. * * Make sure we're the only ones trying to enter a sleep state. Fail * if someone has beat us to it, since we don't want anything weird to * happen when we wake up. * Then, do the setup for suspend, enter the state, and cleaup (after * we've woken up). */ int enter_state(suspend_state_t state) { int error; struct task_struct *cpu_task; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; /* * Assure that previous started thread is completed before * attempting to suspend again. */ error = wait_for_completion_timeout(&second_cpu_complete, msecs_to_jiffies(500)); WARN_ON(error == 0); #ifdef CONFIG_PM_SYNC_CTRL if (pm_sync_active) { ; sys_sync(); ; } #else ; sys_sync(); ; #endif pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: cpu_task = kthread_run(plug_secondary_cpus, NULL, "cpu-plug"); BUG_ON(IS_ERR(cpu_task)); mutex_unlock(&pm_mutex); return error; }
/** * enter_state - Do common work needed to enter system sleep state. * @state: System sleep state to enter. * * Make sure that no one else is trying to put the system into a sleep state. * Fail if that's not the case. Otherwise, prepare for system suspend, make the * system enter the given sleep state and clean up after wakeup. */ static int enter_state(suspend_state_t state) { int error; trace_suspend_resume(TPS("suspend_enter"), state, true); if (state == PM_SUSPEND_TO_IDLE) { #ifdef CONFIG_PM_DEBUG if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) { pr_warn("Unsupported test mode for suspend to idle, please choose none/freezer/devices/platform.\n"); return -EAGAIN; } #endif } else if (!valid_state(state)) { return -EINVAL; } if (!mutex_trylock(&system_transition_mutex)) return -EBUSY; if (state == PM_SUSPEND_TO_IDLE) s2idle_begin(); #ifndef CONFIG_SUSPEND_SKIP_SYNC trace_suspend_resume(TPS("sync_filesystems"), 0, true); pr_info("Syncing filesystems ... "); ksys_sync(); pr_cont("done.\n"); trace_suspend_resume(TPS("sync_filesystems"), 0, false); #endif pm_pr_dbg("Preparing system for sleep (%s)\n", mem_sleep_labels[state]); pm_suspend_clear_flags(); error = suspend_prepare(state); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; trace_suspend_resume(TPS("suspend_enter"), state, false); pm_pr_dbg("Suspending system (%s)\n", mem_sleep_labels[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: events_check_enabled = false; pm_pr_dbg("Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&system_transition_mutex); return error; }
/** * enter_state - Do common work needed to enter system sleep state. * @state: System sleep state to enter. * * Make sure that no one else is trying to put the system into a sleep state. * Fail if that's not the case. Otherwise, prepare for system suspend, make the * system enter the given sleep state and clean up after wakeup. */ static int enter_state(suspend_state_t state) { int error; if (state == PM_SUSPEND_FREEZE) { #ifdef CONFIG_PM_DEBUG if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) { pr_warning("PM: Unsupported test mode for freeze state," "please choose none/freezer/devices/platform.\n"); return -EAGAIN; } #endif } else if (!valid_state(state)) { return -EINVAL; } if (!mutex_trylock(&pm_mutex)) return -EBUSY; if (state == PM_SUSPEND_FREEZE) freeze_begin(); #ifdef CONFIG_HAS_EARLYSUSPEND if (suspendsync) suspend_sys_sync_queue(); #else if (suspendsync) { printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); } #endif pr_debug("PM: Preparing system for %s sleep\n", pm_states[state].label); error = suspend_prepare(state); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state].label); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&pm_mutex); return error; }
/** * enter_state - Do common work needed to enter system sleep state. * @state: System sleep state to enter. * * Make sure that no one else is trying to put the system into a sleep state. * Fail if that's not the case. Otherwise, prepare for system suspend, make the * system enter the given sleep state and clean up after wakeup. */ static int enter_state(suspend_state_t state) { int error; trace_suspend_resume(TPS("suspend_enter"), state, true); if (state == PM_SUSPEND_FREEZE) { #ifdef CONFIG_PM_DEBUG if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) { pr_warning("PM: Unsupported test mode for suspend to idle," "please choose none/freezer/devices/platform.\n"); return -EAGAIN; } #endif } else if (!valid_state(state)) { return -EINVAL; } if (!mutex_trylock(&pm_mutex)) return -EBUSY; if (state == PM_SUSPEND_FREEZE) freeze_begin(); trace_suspend_resume(TPS("sync_filesystems"), 0, true); printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); trace_suspend_resume(TPS("sync_filesystems"), 0, false); pr_debug("PM: Preparing system for sleep (%s)\n", pm_states[state]); error = suspend_prepare(state); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; trace_suspend_resume(TPS("suspend_enter"), state, false); pr_debug("PM: Suspending system (%s)\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&pm_mutex); return error; }
/** * hibernation_restore - Quiesce devices and restore from a hibernation image. * @platform_mode: If set, use platform driver to prepare for the transition. * * This routine must be called with pm_mutex held. If it is successful, control * reappears in the restored target kernel in hibernation_snapshot(). */ int hibernation_restore(int platform_mode) { int error; pm_prepare_console(); suspend_console(); pm_restrict_gfp_mask(); error = dpm_suspend_start(PMSG_QUIESCE); if (!error) { error = resume_target_kernel(platform_mode); dpm_resume_end(PMSG_RECOVER); } pm_restore_gfp_mask(); resume_console(); pm_restore_console(); return error; }
/** * suspend_devices_and_enter - suspend devices and enter the desired system * sleep state. * @state: state to enter */ int suspend_devices_and_enter(suspend_state_t state) { int error; if (!suspend_ops) return -ENOSYS; if (suspend_ops->begin) { error = suspend_ops->begin(state); if (error) goto Close; } suspend_console(); pm_restrict_gfp_mask(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); if (error) { printk(KERN_ERR "PM: Some devices failed to suspend\n"); goto Recover_platform; } suspend_test_finish("suspend devices"); if (suspend_test(TEST_DEVICES)) goto Recover_platform; suspend_enter(state); Resume_devices: suspend_test_start(); dpm_resume_end(PMSG_RESUME); ktime_resume_endtime=ktime_get(); printk(KERN_ERR "<POWER>resume6[peripheral resume]take %llu ns\n",ktime_to_ns(ktime_sub(ktime_resume_endtime, ktime_resume_fromtime))); ktime_resume_fromtime=ktime_resume_endtime; suspend_test_finish("resume devices"); pm_restore_gfp_mask(); resume_console(); Close: if (suspend_ops->end) suspend_ops->end(); return error; Recover_platform: if (suspend_ops->recover) suspend_ops->recover(); goto Resume_devices; }
/** * enter_state - Do common work needed to enter system sleep state. * @state: System sleep state to enter. * * Make sure that no one else is trying to put the system into a sleep state. * Fail if that's not the case. Otherwise, prepare for system suspend, make the * system enter the given sleep state and clean up after wakeup. */ static int enter_state(suspend_state_t state) { int error; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; if (state == PM_SUSPEND_FREEZE) freeze_begin(); #ifndef CONFIG_ARCH_HI3630 printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); #else hisi_sys_sync_queue(); #endif pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(state); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&pm_mutex); return error; }
/** * enter_state - Do common work needed to enter system sleep state. * @state: System sleep state to enter. * * Make sure that no one else is trying to put the system into a sleep state. * Fail if that's not the case. Otherwise, prepare for system suspend, make the * system enter the given sleep state and clean up after wakeup. */ static int enter_state(suspend_state_t state) { int error; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; if (state == PM_SUSPEND_FREEZE) freeze_begin(); printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(state); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); #ifdef CONFIG_MACH_LGE start_monitor_blocking(suspend_monitor_id, jiffies + usecs_to_jiffies(3000000)); #endif suspend_finish(); #ifdef CONFIG_MACH_LGE end_monitor_blocking(suspend_monitor_id); #endif Unlock: mutex_unlock(&pm_mutex); return error; }
/** * suspend_devices_and_enter - suspend devices and enter the desired system * sleep state. * @state: state to enter */ int suspend_devices_and_enter(suspend_state_t state) { int error; if (!suspend_ops) return -ENOSYS; trace_machine_suspend(state); if (suspend_ops->begin) { error = suspend_ops->begin(state); if (error) goto Close; } suspend_console(); pm_restrict_gfp_mask(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); if (error) { printk(KERN_ERR "PM: Some devices failed to suspend\n"); goto Recover_platform; } suspend_test_finish("suspend devices"); if (suspend_test(TEST_DEVICES)) goto Recover_platform; suspend_enter(state); Resume_devices: suspend_test_start(); dpm_resume_end(PMSG_RESUME); suspend_test_finish("resume devices"); pm_restore_gfp_mask(); resume_console(); Close: if (suspend_ops->end) suspend_ops->end(); trace_machine_suspend(PWR_EVENT_EXIT); return error; Recover_platform: if (suspend_ops->recover) suspend_ops->recover(); goto Resume_devices; }
/** * enter_state - Do common work of entering low-power state. * @state: pm_state structure for state we're entering. * * Make sure we're the only ones trying to enter a sleep state. Fail * if someone has beat us to it, since we don't want anything weird to * happen when we wake up. * Then, do the setup for suspend, enter the state, and cleaup (after * we've woken up). */ int enter_state(suspend_state_t state) { int error; struct timer_list timer; struct pm_wd_data data; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pm_wd_add_timer(&timer, &data, 15); pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); pm_wd_del_timer(&timer); Unlock: mutex_unlock(&pm_mutex); return error; }
/** * enter_state - Do common work of entering low-power state. * @state: pm_state structure for state we're entering. * * Make sure we're the only ones trying to enter a sleep state. Fail * if someone has beat us to it, since we don't want anything weird to * happen when we wake up. * Then, do the setup for suspend, enter the state, and cleaup (after * we've woken up). */ int enter_state(suspend_state_t state) { int error; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; #ifdef CONFIG_MSM_SM_EVENT sm_set_system_state (SM_STATE_SUSPEND); sm_add_event(SM_POWER_EVENT | SM_POWER_EVENT_SUSPEND, SM_EVENT_START, 0, NULL, 0); #endif suspend_sys_sync_queue(); pr_info("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_info("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_info("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&pm_mutex); #ifdef CONFIG_MSM_SM_EVENT sm_add_event(SM_POWER_EVENT | SM_POWER_EVENT_RESUME, SM_EVENT_END, 0, NULL, 0); #endif return error; }
/** * toi_end_atomic - post atomic copy/restore routines * @stage: What step to start at. * @suspend_time: Whether we're suspending or resuming. * @error: Whether we're recovering from an error. **/ void toi_end_atomic(int stage, int suspend_time, int error) { pm_message_t msg = suspend_time ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE; switch (stage) { case ATOMIC_ALL_STEPS: if (!suspend_time) { events_check_enabled = false; platform_leave(1); } case ATOMIC_STEP_SYSCORE_RESUME: syscore_resume(); case ATOMIC_STEP_IRQS: local_irq_enable(); case ATOMIC_STEP_CPU_HOTPLUG: if (test_action_state(TOI_LATE_CPU_HOTPLUG)) enable_nonboot_cpus(); case ATOMIC_STEP_PLATFORM_FINISH: if (!suspend_time && error & 2) platform_restore_cleanup(1); else platform_finish(1); dpm_resume_start(msg); case ATOMIC_STEP_DEVICE_RESUME: if (suspend_time && (error & 2)) platform_recover(1); dpm_resume(msg); if (error || !toi_in_suspend()) pm_restore_gfp_mask(); ftrace_start(); resume_console(); case ATOMIC_STEP_DPM_COMPLETE: dpm_complete(msg); case ATOMIC_STEP_PLATFORM_END: platform_end(1); toi_prepare_status(DONT_CLEAR_BAR, "Post atomic."); } }
static int snapshot_release(struct inode *inode, struct file *filp) { struct snapshot_data *data; lock_system_sleep(); swsusp_free(); free_basic_memory_bitmaps(); data = filp->private_data; free_all_swap_pages(data->swap); if (data->frozen) { pm_restore_gfp_mask(); thaw_processes(); } pm_notifier_call_chain(data->mode == O_RDONLY ? PM_POST_HIBERNATION : PM_POST_RESTORE); atomic_inc(&snapshot_device_available); unlock_system_sleep(); return 0; }
/** * enter_state - Do common work of entering low-power state. * @state: pm_state structure for state we're entering. * * Make sure we're the only ones trying to enter a sleep state. Fail * if someone has beat us to it, since we don't want anything weird to * happen when we wake up. * Then, do the setup for suspend, enter the state, and cleaup (after * we've woken up). */ int enter_state(suspend_state_t state) { int error; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; resume_from_deep_suspend = 0; printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); warn_timeout(SUSPEND_PREPARE_TIMEOUT, error = suspend_prepare() ); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&pm_mutex); return error; }
int enter_state(suspend_state_t state) { int error; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; #if 0//ndef PA_THERM #if !defined(CONFIG_MACH_APQ8064_J1D) && !defined(CONFIG_MACH_APQ8064_J1KD) pm8xxx_adc_unconfigure(); #endif #endif suspend_sys_sync_queue(); pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(); if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: mutex_unlock(&pm_mutex); return error; }
/** * hibernation_snapshot - Quiesce devices and create a hibernation image. * @platform_mode: If set, use platform driver to prepare for the transition. * * This routine must be called with pm_mutex held. */ int hibernation_snapshot(int platform_mode) { pm_message_t msg = PMSG_RECOVER; int error; error = platform_begin(platform_mode); if (error) goto Close; /* Preallocate image memory before shutting down devices. */ error = hibernate_preallocate_memory(); if (error) goto Close; error = freeze_kernel_threads(); if (error) goto Close; if (hibernation_test(TEST_FREEZER) || hibernation_testmode(HIBERNATION_TESTPROC)) { /* * Indicate to the caller that we are returning due to a * successful freezer test. */ freezer_test_done = true; goto Close; } error = dpm_prepare(PMSG_FREEZE); if (error) goto Complete_devices; suspend_console(); pm_restrict_gfp_mask(); error = dpm_suspend(PMSG_FREEZE); if (error) goto Recover_platform; if (hibernation_test(TEST_DEVICES)) goto Recover_platform; error = create_image(platform_mode); /* * Control returns here (1) after the image has been created or the * image creation has failed and (2) after a successful restore. */ Resume_devices: /* We may need to release the preallocated image pages here. */ if (error || !in_suspend) swsusp_free(); msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE; dpm_resume(msg); if (error || !in_suspend) pm_restore_gfp_mask(); resume_console(); Complete_devices: dpm_complete(msg); Close: platform_end(platform_mode); return error; Recover_platform: platform_recover(platform_mode); goto Resume_devices; }
/** * hibernate - Carry out system hibernation, including saving the image. */ int hibernate(void) { int error, nr_calls = 0; bool snapshot_test = false; if (!hibernation_available()) { pr_debug("Hibernation not available.\n"); return -EPERM; } lock_system_sleep(); /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { error = -EBUSY; goto Unlock; } pm_prepare_console(); error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls); if (error) { nr_calls--; goto Exit; } pr_info("Syncing filesystems ... \n"); sys_sync(); pr_info("done.\n"); error = freeze_processes(); if (error) goto Exit; lock_device_hotplug(); /* Allocate memory management structures */ error = create_basic_memory_bitmaps(); if (error) goto Thaw; error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); if (error || freezer_test_done) goto Free_bitmaps; if (in_suspend) { unsigned int flags = 0; if (hibernation_mode == HIBERNATION_PLATFORM) flags |= SF_PLATFORM_MODE; if (nocompress) flags |= SF_NOCOMPRESS_MODE; else flags |= SF_CRC32_MODE; pr_debug("Writing image.\n"); error = swsusp_write(flags); swsusp_free(); if (!error) { if (hibernation_mode == HIBERNATION_TEST_RESUME) snapshot_test = true; else power_down(); } in_suspend = 0; pm_restore_gfp_mask(); } else { pr_debug("Image restored successfully.\n"); } Free_bitmaps: free_basic_memory_bitmaps(); Thaw: unlock_device_hotplug(); if (snapshot_test) { pr_debug("Checking hibernation image\n"); error = swsusp_check(); if (!error) error = load_image_and_restore(); } thaw_processes(); /* Don't bother checking whether freezer_test_done is true */ freezer_test_done = false; Exit: __pm_notifier_call_chain(PM_POST_HIBERNATION, nr_calls, NULL); pm_restore_console(); atomic_inc(&snapshot_device_available); Unlock: unlock_system_sleep(); return error; }
/** * hibernation_snapshot - Quiesce devices and create a hibernation image. * @platform_mode: If set, use platform driver to prepare for the transition. * * This routine must be called with pm_mutex held. */ int hibernation_snapshot(int platform_mode) { pm_message_t msg; int error; pm_suspend_clear_flags(); error = platform_begin(platform_mode); if (error) goto Close; /* Preallocate image memory before shutting down devices. */ error = hibernate_preallocate_memory(); if (error) goto Close; error = freeze_kernel_threads(); if (error) goto Cleanup; if (hibernation_test(TEST_FREEZER)) { /* * Indicate to the caller that we are returning due to a * successful freezer test. */ freezer_test_done = true; goto Thaw; } error = dpm_prepare(PMSG_FREEZE); if (error) { dpm_complete(PMSG_RECOVER); goto Thaw; } suspend_console(); pm_restrict_gfp_mask(); error = dpm_suspend(PMSG_FREEZE); if (error || hibernation_test(TEST_DEVICES)) platform_recover(platform_mode); else error = create_image(platform_mode); /* * In the case that we call create_image() above, the control * returns here (1) after the image has been created or the * image creation has failed and (2) after a successful restore. */ /* We may need to release the preallocated image pages here. */ if (error || !in_suspend) swsusp_free(); msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE; dpm_resume(msg); if (error || !in_suspend) pm_restore_gfp_mask(); resume_console(); dpm_complete(msg); Close: platform_end(platform_mode); return error; Thaw: thaw_kernel_threads(); Cleanup: swsusp_free(); goto Close; }
int enter_state(suspend_state_t state) { int error; int dock=0; int retries=3; if (!valid_state(state)) return -ENODEV; if (!mutex_trylock(&pm_mutex)) return -EBUSY; printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); #ifdef CONFIG_ASUSEC if (gpio_get_value(TEGRA_GPIO_PX5)==0){ dock=1; hub_suspended=0; //// nousb=1; // printk("mutex+\n"); // mutex_lock(&usb_mutex); if (nousb==1) { printk("usb wait1\n"); msleep(500); } asusec_close_keyboard(); //// asusec_suspend_hub_callback2(); /* while (!hub_suspended) { asusec_suspend_hub_callback(); if (retries-- == 0) break; if (!hub_suspended) { stop_dock(); msleep(500); asusec_resume(0); msleep(500); // printk("try to restart asusec\n"); // reload_asusec(); } } */ // printk("mutex-\n"); // mutex_unlock(&usb_mutex); /* if (!hub_suspended) { stop_dock(); printk("Dock problem\n"); if (failed_dock < 3) { printk("aborted suspend\n"); failed_dock++; asusec_resume(0); error=999; // nousb=0; goto Unlock; } } */ // nousb=0; failed_dock=0; msleep(2000); // cpu_down(1); } #endif pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); error = suspend_prepare(); if (error) { if (dock==1) { asusec_resume(0); } goto Unlock; } if (suspend_test(TEST_FREEZER)) goto Finish; pr_debug("PM: Entering %s sleep\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish(); Unlock: // asusec_resume(0); mutex_unlock(&pm_mutex); return error; }
static void __toi_power_down(int method) { int error; toi_cond_pause(1, test_action_state(TOI_REBOOT) ? "Ready to reboot." : "Powering down."); if (test_result_state(TOI_ABORTED)) goto out; if (test_action_state(TOI_REBOOT)) kernel_restart(NULL); switch (method) { case 0: break; case 3: /* * Re-read the overwritten part of pageset2 to make post-resume * faster. */ if (read_pageset2(1)) panic("Attempt to reload pagedir 2 failed. " "Try rebooting."); pm_prepare_console(); error = pm_notifier_call_chain(PM_SUSPEND_PREPARE); if (!error) { pm_restore_gfp_mask(); error = suspend_devices_and_enter(PM_SUSPEND_MEM); pm_restrict_gfp_mask(); if (!error) did_suspend_to_both = 1; } pm_notifier_call_chain(PM_POST_SUSPEND); pm_restore_console(); // jonathan.jmchen: FIXME, Create API to add another wakeup source to power down, // if system is idle after xxx (e.g., 5 min) without user interaction!! /* Success - we're now post-resume-from-ram */ if (did_suspend_to_both) return; /* Failed to suspend to ram - do normal power off */ break; case 4: /* * If succeeds, doesn't return. If fails, do a simple * powerdown. */ hibernation_platform_enter(); break; case 5: /* Historic entry only now */ break; } if (method && method != 5) toi_cond_pause(1, "Falling back to alternate power off method."); if (test_result_state(TOI_ABORTED)) goto out; kernel_power_off(); kernel_halt(); toi_cond_pause(1, "Powerdown failed."); while (1) cpu_relax(); out: if (read_pageset2(1)) panic("Attempt to reload pagedir 2 failed. Try rebooting."); return; }
/** * hibernate - Carry out system hibernation, including saving the image. */ int hibernate(void) { int error; lock_system_sleep(); /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { error = -EBUSY; goto Unlock; } pm_prepare_console(); error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); if (error) goto Exit; /* Allocate memory management structures */ error = create_basic_memory_bitmaps(); if (error) goto Exit; printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); error = freeze_processes(); if (error) goto Free_bitmaps; error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); if (error) goto Thaw; if (freezer_test_done) { freezer_test_done = false; goto Thaw; } if (in_suspend) { unsigned int flags = 0; if (hibernation_mode == HIBERNATION_PLATFORM) flags |= SF_PLATFORM_MODE; if (nocompress) flags |= SF_NOCOMPRESS_MODE; else flags |= SF_CRC32_MODE; pr_debug("PM: writing image.\n"); error = swsusp_write(flags); swsusp_free(); if (!error) power_down(); in_suspend = 0; pm_restore_gfp_mask(); } else { pr_debug("PM: Image restored successfully.\n"); } Thaw: thaw_processes(); Free_bitmaps: free_basic_memory_bitmaps(); Exit: pm_notifier_call_chain(PM_POST_HIBERNATION); pm_restore_console(); atomic_inc(&snapshot_device_available); Unlock: unlock_system_sleep(); return error; }
static long snapshot_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int error = 0; struct snapshot_data *data; loff_t size; sector_t offset; if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR) return -ENOTTY; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!mutex_trylock(&pm_mutex)) return -EBUSY; data = filp->private_data; switch (cmd) { case SNAPSHOT_FREEZE: if (data->frozen) break; printk("Syncing filesystems ... "); sys_sync(); printk("done.\n"); error = usermodehelper_disable(); if (error) break; error = freeze_processes(); if (error) usermodehelper_enable(); else data->frozen = 1; break; case SNAPSHOT_UNFREEZE: if (!data->frozen || data->ready) break; pm_restore_gfp_mask(); thaw_processes(); usermodehelper_enable(); data->frozen = 0; break; case SNAPSHOT_CREATE_IMAGE: if (data->mode != O_RDONLY || !data->frozen || data->ready) { error = -EPERM; break; } pm_restore_gfp_mask(); error = hibernation_snapshot(data->platform_support); if (!error) { error = put_user(in_suspend, (int __user *)arg); if (!error && !freezer_test_done) data->ready = 1; if (freezer_test_done) { freezer_test_done = false; thaw_processes(); } } break; case SNAPSHOT_ATOMIC_RESTORE: snapshot_write_finalize(&data->handle); if (data->mode != O_WRONLY || !data->frozen || !snapshot_image_loaded(&data->handle)) { error = -EPERM; break; } error = hibernation_restore(data->platform_support); break; case SNAPSHOT_FREE: swsusp_free(); memset(&data->handle, 0, sizeof(struct snapshot_handle)); data->ready = 0; /* * It is necessary to thaw kernel threads here, because * SNAPSHOT_CREATE_IMAGE may be invoked directly after * SNAPSHOT_FREE. In that case, if kernel threads were not * thawed, the preallocation of memory carried out by * hibernation_snapshot() might run into problems (i.e. it * might fail or even deadlock). */ thaw_kernel_threads(); break; case SNAPSHOT_PREF_IMAGE_SIZE: image_size = arg; break; case SNAPSHOT_GET_IMAGE_SIZE: if (!data->ready) { error = -ENODATA; break; } size = snapshot_get_image_size(); size <<= PAGE_SHIFT; error = put_user(size, (loff_t __user *)arg); break; case SNAPSHOT_AVAIL_SWAP_SIZE: size = count_swap_pages(data->swap, 1); size <<= PAGE_SHIFT; error = put_user(size, (loff_t __user *)arg); break; case SNAPSHOT_ALLOC_SWAP_PAGE: if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { error = -ENODEV; break; } offset = alloc_swapdev_block(data->swap); if (offset) { offset <<= PAGE_SHIFT; error = put_user(offset, (loff_t __user *)arg); } else { error = -ENOSPC; } break; case SNAPSHOT_FREE_SWAP_PAGES: if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { error = -ENODEV; break; } free_all_swap_pages(data->swap); break; case SNAPSHOT_S2RAM: if (!data->frozen) { error = -EPERM; break; } /* * Tasks are frozen and the notifiers have been called with * PM_HIBERNATION_PREPARE */ error = suspend_devices_and_enter(PM_SUSPEND_MEM); data->ready = 0; break; case SNAPSHOT_PLATFORM_SUPPORT: data->platform_support = !!arg; break; case SNAPSHOT_POWER_OFF: if (data->platform_support) error = hibernation_platform_enter(); break; case SNAPSHOT_SET_SWAP_AREA: if (swsusp_swap_in_use()) { error = -EPERM; } else { struct resume_swap_area swap_area; dev_t swdev; error = copy_from_user(&swap_area, (void __user *)arg, sizeof(struct resume_swap_area)); if (error) { error = -EFAULT; break; } /* * User space encodes device types as two-byte values, * so we need to recode them */ swdev = new_decode_dev(swap_area.dev); if (swdev) { offset = swap_area.offset; data->swap = swap_type_of(swdev, offset, NULL); if (data->swap < 0) error = -ENODEV; } else { data->swap = -1; error = -EINVAL; } } break; default: error = -ENOTTY; } mutex_unlock(&pm_mutex); return error; }
static long snapshot_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int error = 0; struct snapshot_data *data; loff_t size; sector_t offset; if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR) return -ENOTTY; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!mutex_trylock(&pm_mutex)) return -EBUSY; data = filp->private_data; switch (cmd) { case SNAPSHOT_FREEZE: if (data->frozen) break; printk("Syncing filesystems ... "); sys_sync(); printk("done.\n"); error = freeze_processes(); if (!error) data->frozen = 1; break; case SNAPSHOT_UNFREEZE: if (!data->frozen || data->ready) break; pm_restore_gfp_mask(); thaw_processes(); data->frozen = 0; break; case SNAPSHOT_CREATE_IMAGE: if (data->mode != O_RDONLY || !data->frozen || data->ready) { error = -EPERM; break; } pm_restore_gfp_mask(); error = hibernation_snapshot(data->platform_support); if (!error) { error = put_user(in_suspend, (int __user *)arg); data->ready = !freezer_test_done && !error; freezer_test_done = false; } break; case SNAPSHOT_ATOMIC_RESTORE: snapshot_write_finalize(&data->handle); if (data->mode != O_WRONLY || !data->frozen || !snapshot_image_loaded(&data->handle)) { error = -EPERM; break; } error = hibernation_restore(data->platform_support); break; case SNAPSHOT_FREE: swsusp_free(); memset(&data->handle, 0, sizeof(struct snapshot_handle)); data->ready = 0; thaw_kernel_threads(); break; case SNAPSHOT_PREF_IMAGE_SIZE: image_size = arg; break; case SNAPSHOT_GET_IMAGE_SIZE: if (!data->ready) { error = -ENODATA; break; } size = snapshot_get_image_size(); size <<= PAGE_SHIFT; error = put_user(size, (loff_t __user *)arg); break; case SNAPSHOT_AVAIL_SWAP_SIZE: size = count_swap_pages(data->swap, 1); size <<= PAGE_SHIFT; error = put_user(size, (loff_t __user *)arg); break; case SNAPSHOT_ALLOC_SWAP_PAGE: if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { error = -ENODEV; break; } offset = alloc_swapdev_block(data->swap); if (offset) { offset <<= PAGE_SHIFT; error = put_user(offset, (loff_t __user *)arg); } else { error = -ENOSPC; } break; case SNAPSHOT_FREE_SWAP_PAGES: if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { error = -ENODEV; break; } free_all_swap_pages(data->swap); break; case SNAPSHOT_S2RAM: if (!data->frozen) { error = -EPERM; break; } error = suspend_devices_and_enter(PM_SUSPEND_MEM); data->ready = 0; break; case SNAPSHOT_PLATFORM_SUPPORT: data->platform_support = !!arg; break; case SNAPSHOT_POWER_OFF: if (data->platform_support) error = hibernation_platform_enter(); break; case SNAPSHOT_SET_SWAP_AREA: if (swsusp_swap_in_use()) { error = -EPERM; } else { struct resume_swap_area swap_area; dev_t swdev; error = copy_from_user(&swap_area, (void __user *)arg, sizeof(struct resume_swap_area)); if (error) { error = -EFAULT; break; } swdev = new_decode_dev(swap_area.dev); if (swdev) { offset = swap_area.offset; data->swap = swap_type_of(swdev, offset, NULL); if (data->swap < 0) error = -ENODEV; } else { data->swap = -1; error = -EINVAL; } } break; default: error = -ENOTTY; } mutex_unlock(&pm_mutex); return error; }
static long snapshot_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int error = 0; struct snapshot_data *data; loff_t size; sector_t offset; if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR) return -ENOTTY; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!mutex_trylock(&pm_mutex)) return -EBUSY; data = filp->private_data; switch (cmd) { case SNAPSHOT_FREEZE: if (data->frozen) break; printk("Syncing filesystems ... "); sys_sync(); printk("done.\n"); error = usermodehelper_disable(); if (error) break; error = freeze_processes(); if (error) { thaw_processes(); usermodehelper_enable(); } if (!error) data->frozen = 1; break; case SNAPSHOT_UNFREEZE: if (!data->frozen || data->ready) break; pm_restore_gfp_mask(); thaw_processes(); usermodehelper_enable(); data->frozen = 0; break; case SNAPSHOT_ATOMIC_SNAPSHOT: snapshot_deprecated_ioctl(cmd); case SNAPSHOT_CREATE_IMAGE: if (data->mode != O_RDONLY || !data->frozen || data->ready) { error = -EPERM; break; } pm_restore_gfp_mask(); error = hibernation_snapshot(data->platform_support); if (!error) error = put_user(in_suspend, (int __user *)arg); if (!error) data->ready = 1; break; case SNAPSHOT_ATOMIC_RESTORE: snapshot_write_finalize(&data->handle); if (data->mode != O_WRONLY || !data->frozen || !snapshot_image_loaded(&data->handle)) { error = -EPERM; break; } error = hibernation_restore(data->platform_support); break; case SNAPSHOT_FREE: swsusp_free(); memset(&data->handle, 0, sizeof(struct snapshot_handle)); data->ready = 0; break; case SNAPSHOT_SET_IMAGE_SIZE: snapshot_deprecated_ioctl(cmd); case SNAPSHOT_PREF_IMAGE_SIZE: image_size = arg; break; case SNAPSHOT_GET_IMAGE_SIZE: if (!data->ready) { error = -ENODATA; break; } size = snapshot_get_image_size(); size <<= PAGE_SHIFT; error = put_user(size, (loff_t __user *)arg); break; case SNAPSHOT_AVAIL_SWAP: snapshot_deprecated_ioctl(cmd); case SNAPSHOT_AVAIL_SWAP_SIZE: size = count_swap_pages(data->swap, 1); size <<= PAGE_SHIFT; error = put_user(size, (loff_t __user *)arg); break; case SNAPSHOT_GET_SWAP_PAGE: snapshot_deprecated_ioctl(cmd); case SNAPSHOT_ALLOC_SWAP_PAGE: if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { error = -ENODEV; break; } offset = alloc_swapdev_block(data->swap); if (offset) { offset <<= PAGE_SHIFT; error = put_user(offset, (loff_t __user *)arg); } else { error = -ENOSPC; } break; case SNAPSHOT_FREE_SWAP_PAGES: if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { error = -ENODEV; break; } free_all_swap_pages(data->swap); break; case SNAPSHOT_SET_SWAP_FILE: /* This ioctl is deprecated */ snapshot_deprecated_ioctl(cmd); if (!swsusp_swap_in_use()) { /* * User space encodes device types as two-byte values, * so we need to recode them */ if (old_decode_dev(arg)) { data->swap = swap_type_of(old_decode_dev(arg), 0, NULL); if (data->swap < 0) error = -ENODEV; } else { data->swap = -1; error = -EINVAL; } } else { error = -EPERM; } break; case SNAPSHOT_S2RAM: if (!data->frozen) { error = -EPERM; break; } /* * Tasks are frozen and the notifiers have been called with * PM_HIBERNATION_PREPARE */ error = suspend_devices_and_enter(PM_SUSPEND_MEM); break; case SNAPSHOT_PLATFORM_SUPPORT: data->platform_support = !!arg; break; case SNAPSHOT_POWER_OFF: if (data->platform_support) error = hibernation_platform_enter(); break; case SNAPSHOT_PMOPS: /* This ioctl is deprecated */ snapshot_deprecated_ioctl(cmd); error = -EINVAL; switch (arg) { case PMOPS_PREPARE: data->platform_support = 1; error = 0; break; case PMOPS_ENTER: if (data->platform_support) error = hibernation_platform_enter(); break; case PMOPS_FINISH: if (data->platform_support) error = 0; break; default: printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg); } break; case SNAPSHOT_SET_SWAP_AREA: if (swsusp_swap_in_use()) { error = -EPERM; } else { struct resume_swap_area swap_area; dev_t swdev; error = copy_from_user(&swap_area, (void __user *)arg, sizeof(struct resume_swap_area)); if (error) { error = -EFAULT; break; } /* * User space encodes device types as two-byte values, * so we need to recode them */ swdev = new_decode_dev(swap_area.dev); if (swdev) { offset = swap_area.offset; data->swap = swap_type_of(swdev, offset, NULL); if (data->swap < 0) error = -ENODEV; } else { data->swap = -1; error = -EINVAL; } } break; default: error = -ENOTTY; } mutex_unlock(&pm_mutex); return error; }