Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / kernel / power / hibernate.c
index 196c01268ebd73d50c0a5f4d52d913c9aff8bd8b..6d6d28870335831fa05c80428fefc05e20be3f69 100644 (file)
@@ -43,8 +43,6 @@ int in_suspend __nosavedata;
 enum {
        HIBERNATION_INVALID,
        HIBERNATION_PLATFORM,
-       HIBERNATION_TEST,
-       HIBERNATION_TESTPROC,
        HIBERNATION_SHUTDOWN,
        HIBERNATION_REBOOT,
        /* keep last */
@@ -55,7 +53,7 @@ enum {
 
 static int hibernation_mode = HIBERNATION_SHUTDOWN;
 
-static bool freezer_test_done;
+bool freezer_test_done;
 
 static const struct platform_hibernation_ops *hibernation_ops;
 
@@ -71,14 +69,14 @@ void hibernation_set_ops(const struct platform_hibernation_ops *ops)
                WARN_ON(1);
                return;
        }
-       mutex_lock(&pm_mutex);
+       lock_system_sleep();
        hibernation_ops = ops;
        if (ops)
                hibernation_mode = HIBERNATION_PLATFORM;
        else if (hibernation_mode == HIBERNATION_PLATFORM)
                hibernation_mode = HIBERNATION_SHUTDOWN;
 
-       mutex_unlock(&pm_mutex);
+       unlock_system_sleep();
 }
 
 static bool entering_platform_hibernation;
@@ -96,15 +94,6 @@ static void hibernation_debug_sleep(void)
        mdelay(5000);
 }
 
-static int hibernation_testmode(int mode)
-{
-       if (hibernation_mode == mode) {
-               hibernation_debug_sleep();
-               return 1;
-       }
-       return 0;
-}
-
 static int hibernation_test(int level)
 {
        if (pm_test_level == level) {
@@ -114,7 +103,6 @@ static int hibernation_test(int level)
        return 0;
 }
 #else /* !CONFIG_PM_DEBUG */
-static int hibernation_testmode(int mode) { return 0; }
 static int hibernation_test(int level) { return 0; }
 #endif /* !CONFIG_PM_DEBUG */
 
@@ -278,8 +266,7 @@ static int create_image(int platform_mode)
                goto Platform_finish;
 
        error = disable_nonboot_cpus();
-       if (error || hibernation_test(TEST_CPUS)
-           || hibernation_testmode(HIBERNATION_TEST))
+       if (error || hibernation_test(TEST_CPUS))
                goto Enable_cpus;
 
        local_irq_disable();
@@ -333,7 +320,7 @@ static int create_image(int platform_mode)
  */
 int hibernation_snapshot(int platform_mode)
 {
-       pm_message_t msg = PMSG_RECOVER;
+       pm_message_t msg;
        int error;
 
        error = platform_begin(platform_mode);
@@ -347,39 +334,40 @@ int hibernation_snapshot(int platform_mode)
 
        error = freeze_kernel_threads();
        if (error)
-               goto Close;
+               goto Cleanup;
 
-       if (hibernation_test(TEST_FREEZER) ||
-               hibernation_testmode(HIBERNATION_TESTPROC)) {
+       if (hibernation_test(TEST_FREEZER)) {
 
                /*
                 * Indicate to the caller that we are returning due to a
                 * successful freezer test.
                 */
                freezer_test_done = true;
-               goto Close;
+               goto Cleanup;
        }
 
        error = dpm_prepare(PMSG_FREEZE);
-       if (error)
-               goto Complete_devices;
+       if (error) {
+               dpm_complete(PMSG_RECOVER);
+               goto Cleanup;
+       }
 
        suspend_console();
        pm_restrict_gfp_mask();
+
        error = dpm_suspend(PMSG_FREEZE);
-       if (error)
-               goto Recover_platform;
 
-       if (hibernation_test(TEST_DEVICES))
-               goto Recover_platform;
+       if (error || hibernation_test(TEST_DEVICES))
+               platform_recover(platform_mode);
+       else
+               error = create_image(platform_mode);
 
-       error = create_image(platform_mode);
        /*
-        * Control returns here (1) after the image has been created or the
+        * 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.
         */
 
- Resume_devices:
        /* We may need to release the preallocated image pages here. */
        if (error || !in_suspend)
                swsusp_free();
@@ -391,17 +379,15 @@ int hibernation_snapshot(int platform_mode)
                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;
Cleanup:
+       swsusp_free();
+       goto Close;
 }
 
 /**
@@ -586,9 +572,6 @@ int hibernation_platform_enter(void)
 static void power_down(void)
 {
        switch (hibernation_mode) {
-       case HIBERNATION_TEST:
-       case HIBERNATION_TESTPROC:
-               break;
        case HIBERNATION_REBOOT:
                kernel_restart(NULL);
                break;
@@ -607,17 +590,6 @@ static void power_down(void)
        while(1);
 }
 
-static int prepare_processes(void)
-{
-       int error = 0;
-
-       if (freeze_processes()) {
-               error = -EBUSY;
-               thaw_processes();
-       }
-       return error;
-}
-
 /**
  * hibernate - Carry out system hibernation, including saving the image.
  */
@@ -625,7 +597,7 @@ int hibernate(void)
 {
        int error;
 
-       mutex_lock(&pm_mutex);
+       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;
@@ -650,7 +622,7 @@ int hibernate(void)
        sys_sync();
        printk("done.\n");
 
-       error = prepare_processes();
+       error = freeze_processes();
        if (error)
                goto Finish;
 
@@ -693,7 +665,7 @@ int hibernate(void)
        pm_restore_console();
        atomic_inc(&snapshot_device_available);
  Unlock:
-       mutex_unlock(&pm_mutex);
+       unlock_system_sleep();
        return error;
 }
 
@@ -807,11 +779,13 @@ static int software_resume(void)
                goto close_finish;
 
        error = create_basic_memory_bitmaps();
-       if (error)
+       if (error) {
+               usermodehelper_enable();
                goto close_finish;
+       }
 
        pr_debug("PM: Preparing processes for restore.\n");
-       error = prepare_processes();
+       error = freeze_processes();
        if (error) {
                swsusp_close(FMODE_READ);
                goto Done;
@@ -851,8 +825,6 @@ static const char * const hibernation_modes[] = {
        [HIBERNATION_PLATFORM]  = "platform",
        [HIBERNATION_SHUTDOWN]  = "shutdown",
        [HIBERNATION_REBOOT]    = "reboot",
-       [HIBERNATION_TEST]      = "test",
-       [HIBERNATION_TESTPROC]  = "testproc",
 };
 
 /*
@@ -861,17 +833,15 @@ static const char * const hibernation_modes[] = {
  * Hibernation can be handled in several ways.  There are a few different ways
  * to put the system into the sleep state: using the platform driver (e.g. ACPI
  * or other hibernation_ops), powering it off or rebooting it (for testing
- * mostly), or using one of the two available test modes.
+ * mostly).
  *
  * The sysfs file /sys/power/disk provides an interface for selecting the
  * hibernation mode to use.  Reading from this file causes the available modes
- * to be printed.  There are 5 modes that can be supported:
+ * to be printed.  There are 3 modes that can be supported:
  *
  *     'platform'
  *     'shutdown'
  *     'reboot'
- *     'test'
- *     'testproc'
  *
  * If a platform hibernation driver is in use, 'platform' will be supported
  * and will be used by default.  Otherwise, 'shutdown' will be used by default.
@@ -895,8 +865,6 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
                switch (i) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
-               case HIBERNATION_TEST:
-               case HIBERNATION_TESTPROC:
                        break;
                case HIBERNATION_PLATFORM:
                        if (hibernation_ops)
@@ -925,7 +893,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
        p = memchr(buf, '\n', n);
        len = p ? p - buf : n;
 
-       mutex_lock(&pm_mutex);
+       lock_system_sleep();
        for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
                if (len == strlen(hibernation_modes[i])
                    && !strncmp(buf, hibernation_modes[i], len)) {
@@ -937,8 +905,6 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
                switch (mode) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
-               case HIBERNATION_TEST:
-               case HIBERNATION_TESTPROC:
                        hibernation_mode = mode;
                        break;
                case HIBERNATION_PLATFORM:
@@ -953,7 +919,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
        if (!error)
                pr_debug("PM: Hibernation mode set to '%s'\n",
                         hibernation_modes[mode]);
-       mutex_unlock(&pm_mutex);
+       unlock_system_sleep();
        return error ? error : n;
 }
 
@@ -980,9 +946,9 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
        if (maj != MAJOR(res) || min != MINOR(res))
                goto out;
 
-       mutex_lock(&pm_mutex);
+       lock_system_sleep();
        swsusp_resume_device = res;
-       mutex_unlock(&pm_mutex);
+       unlock_system_sleep();
        printk(KERN_INFO "PM: Starting manual resume from disk\n");
        noresume = 0;
        software_resume();