]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'pm-freezer' into pm-sleep
authorRafael J. Wysocki <rjw@sisk.pl>
Tue, 6 Dec 2011 21:12:50 +0000 (22:12 +0100)
committerRafael J. Wysocki <rjw@sisk.pl>
Tue, 6 Dec 2011 21:12:50 +0000 (22:12 +0100)
* pm-freezer: (26 commits)
  Freezer / sunrpc / NFS: don't allow TASK_KILLABLE sleeps to block the freezer
  Freezer: fix more fallout from the thaw_process rename
  freezer: fix wait_event_freezable/__thaw_task races
  freezer: kill unused set_freezable_with_signal()
  dmatest: don't use set_freezable_with_signal()
  usb_storage: don't use set_freezable_with_signal()
  freezer: remove unused @sig_only from freeze_task()
  freezer: use lock_task_sighand() in fake_signal_wake_up()
  freezer: restructure __refrigerator()
  freezer: fix set_freezable[_with_signal]() race
  freezer: remove should_send_signal() and update frozen()
  freezer: remove now unused TIF_FREEZE
  freezer: make freezing() test freeze conditions in effect instead of TIF_FREEZE
  cgroup_freezer: prepare for removal of TIF_FREEZE
  freezer: clean up freeze_processes() failure path
  freezer: kill PF_FREEZING
  freezer: test freezable conditions while holding freezer_lock
  freezer: make freezing indicate freeze condition in effect
  freezer: use dedicated lock instead of task_lock() + memory barrier
  freezer: don't distinguish nosig tasks on thaw
  ...

drivers/acpi/sleep.c
drivers/base/power/main.c
include/linux/suspend.h
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/power.h
kernel/power/user.c

index 6d9a3ab58db2608c3101cea8cf7ccefa54439d66..0a7ed69546ba47db0c322542864c168068baa7f4 100644 (file)
@@ -476,6 +476,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
                },
        },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Asus K54C",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Asus K54HR",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
index c3d2dfcf438dd1735fcf401be9f8185440e9a1a9..b570189d4f2dfc1618063851de4dcbb353818439 100644 (file)
@@ -164,8 +164,9 @@ static ktime_t initcall_debug_start(struct device *dev)
        ktime_t calltime = ktime_set(0, 0);
 
        if (initcall_debug) {
-               pr_info("calling  %s+ @ %i\n",
-                               dev_name(dev), task_pid_nr(current));
+               pr_info("calling  %s+ @ %i, parent: %s\n",
+                       dev_name(dev), task_pid_nr(current),
+                       dev->parent ? dev_name(dev->parent) : "none");
                calltime = ktime_get();
        }
 
@@ -210,6 +211,24 @@ static void dpm_wait_for_children(struct device *dev, bool async)
        device_for_each_child(dev, &async, dpm_wait_fn);
 }
 
+static int dpm_run_callback(struct device *dev, int (*cb)(struct device *))
+{
+       ktime_t calltime;
+       int error;
+
+       if (!cb)
+               return 0;
+
+       calltime = initcall_debug_start(dev);
+
+       error = cb(dev);
+       suspend_report_result(cb, error);
+
+       initcall_debug_report(dev, calltime, error);
+
+       return error;
+}
+
 /**
  * pm_op - Execute the PM operation appropriate for given PM event.
  * @dev: Device to handle.
@@ -221,59 +240,36 @@ static int pm_op(struct device *dev,
                 pm_message_t state)
 {
        int error = 0;
-       ktime_t calltime;
-
-       calltime = initcall_debug_start(dev);
 
        switch (state.event) {
 #ifdef CONFIG_SUSPEND
        case PM_EVENT_SUSPEND:
-               if (ops->suspend) {
-                       error = ops->suspend(dev);
-                       suspend_report_result(ops->suspend, error);
-               }
+               error = dpm_run_callback(dev, ops->suspend);
                break;
        case PM_EVENT_RESUME:
-               if (ops->resume) {
-                       error = ops->resume(dev);
-                       suspend_report_result(ops->resume, error);
-               }
+               error = dpm_run_callback(dev, ops->resume);
                break;
 #endif /* CONFIG_SUSPEND */
 #ifdef CONFIG_HIBERNATE_CALLBACKS
        case PM_EVENT_FREEZE:
        case PM_EVENT_QUIESCE:
-               if (ops->freeze) {
-                       error = ops->freeze(dev);
-                       suspend_report_result(ops->freeze, error);
-               }
+               error = dpm_run_callback(dev, ops->freeze);
                break;
        case PM_EVENT_HIBERNATE:
-               if (ops->poweroff) {
-                       error = ops->poweroff(dev);
-                       suspend_report_result(ops->poweroff, error);
-               }
+               error = dpm_run_callback(dev, ops->poweroff);
                break;
        case PM_EVENT_THAW:
        case PM_EVENT_RECOVER:
-               if (ops->thaw) {
-                       error = ops->thaw(dev);
-                       suspend_report_result(ops->thaw, error);
-               }
+               error = dpm_run_callback(dev, ops->thaw);
                break;
        case PM_EVENT_RESTORE:
-               if (ops->restore) {
-                       error = ops->restore(dev);
-                       suspend_report_result(ops->restore, error);
-               }
+               error = dpm_run_callback(dev, ops->restore);
                break;
 #endif /* CONFIG_HIBERNATE_CALLBACKS */
        default:
                error = -EINVAL;
        }
 
-       initcall_debug_report(dev, calltime, error);
-
        return error;
 }
 
@@ -291,70 +287,36 @@ static int pm_noirq_op(struct device *dev,
                        pm_message_t state)
 {
        int error = 0;
-       ktime_t calltime = ktime_set(0, 0), delta, rettime;
-
-       if (initcall_debug) {
-               pr_info("calling  %s+ @ %i, parent: %s\n",
-                               dev_name(dev), task_pid_nr(current),
-                               dev->parent ? dev_name(dev->parent) : "none");
-               calltime = ktime_get();
-       }
 
        switch (state.event) {
 #ifdef CONFIG_SUSPEND
        case PM_EVENT_SUSPEND:
-               if (ops->suspend_noirq) {
-                       error = ops->suspend_noirq(dev);
-                       suspend_report_result(ops->suspend_noirq, error);
-               }
+               error = dpm_run_callback(dev, ops->suspend_noirq);
                break;
        case PM_EVENT_RESUME:
-               if (ops->resume_noirq) {
-                       error = ops->resume_noirq(dev);
-                       suspend_report_result(ops->resume_noirq, error);
-               }
+               error = dpm_run_callback(dev, ops->resume_noirq);
                break;
 #endif /* CONFIG_SUSPEND */
 #ifdef CONFIG_HIBERNATE_CALLBACKS
        case PM_EVENT_FREEZE:
        case PM_EVENT_QUIESCE:
-               if (ops->freeze_noirq) {
-                       error = ops->freeze_noirq(dev);
-                       suspend_report_result(ops->freeze_noirq, error);
-               }
+               error = dpm_run_callback(dev, ops->freeze_noirq);
                break;
        case PM_EVENT_HIBERNATE:
-               if (ops->poweroff_noirq) {
-                       error = ops->poweroff_noirq(dev);
-                       suspend_report_result(ops->poweroff_noirq, error);
-               }
+               error = dpm_run_callback(dev, ops->poweroff_noirq);
                break;
        case PM_EVENT_THAW:
        case PM_EVENT_RECOVER:
-               if (ops->thaw_noirq) {
-                       error = ops->thaw_noirq(dev);
-                       suspend_report_result(ops->thaw_noirq, error);
-               }
+               error = dpm_run_callback(dev, ops->thaw_noirq);
                break;
        case PM_EVENT_RESTORE:
-               if (ops->restore_noirq) {
-                       error = ops->restore_noirq(dev);
-                       suspend_report_result(ops->restore_noirq, error);
-               }
+               error = dpm_run_callback(dev, ops->restore_noirq);
                break;
 #endif /* CONFIG_HIBERNATE_CALLBACKS */
        default:
                error = -EINVAL;
        }
 
-       if (initcall_debug) {
-               rettime = ktime_get();
-               delta = ktime_sub(rettime, calltime);
-               printk("initcall %s_i+ returned %d after %Ld usecs\n",
-                       dev_name(dev), error,
-                       (unsigned long long)ktime_to_ns(delta) >> 10);
-       }
-
        return error;
 }
 
@@ -485,26 +447,6 @@ void dpm_resume_noirq(pm_message_t state)
 }
 EXPORT_SYMBOL_GPL(dpm_resume_noirq);
 
-/**
- * legacy_resume - Execute a legacy (bus or class) resume callback for device.
- * @dev: Device to resume.
- * @cb: Resume callback to execute.
- */
-static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
-{
-       int error;
-       ktime_t calltime;
-
-       calltime = initcall_debug_start(dev);
-
-       error = cb(dev);
-       suspend_report_result(cb, error);
-
-       initcall_debug_report(dev, calltime, error);
-
-       return error;
-}
-
 /**
  * device_resume - Execute "resume" callbacks for given device.
  * @dev: Device to handle.
@@ -553,7 +495,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
                        goto End;
                } else if (dev->class->resume) {
                        pm_dev_dbg(dev, state, "legacy class ");
-                       error = legacy_resume(dev, dev->class->resume);
+                       error = dpm_run_callback(dev, dev->class->resume);
                        goto End;
                }
        }
@@ -564,7 +506,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
                        error = pm_op(dev, dev->bus->pm, state);
                } else if (dev->bus->resume) {
                        pm_dev_dbg(dev, state, "legacy ");
-                       error = legacy_resume(dev, dev->bus->resume);
+                       error = dpm_run_callback(dev, dev->bus->resume);
                }
        }
 
@@ -763,31 +705,23 @@ static pm_message_t resume_event(pm_message_t sleep_state)
  */
 static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
-       int error;
+       int error = 0;
 
        if (dev->pm_domain) {
                pm_dev_dbg(dev, state, "LATE power domain ");
                error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
-               if (error)
-                       return error;
        } else if (dev->type && dev->type->pm) {
                pm_dev_dbg(dev, state, "LATE type ");
                error = pm_noirq_op(dev, dev->type->pm, state);
-               if (error)
-                       return error;
        } else if (dev->class && dev->class->pm) {
                pm_dev_dbg(dev, state, "LATE class ");
                error = pm_noirq_op(dev, dev->class->pm, state);
-               if (error)
-                       return error;
        } else if (dev->bus && dev->bus->pm) {
                pm_dev_dbg(dev, state, "LATE ");
                error = pm_noirq_op(dev, dev->bus->pm, state);
-               if (error)
-                       return error;
        }
 
-       return 0;
+       return error;
 }
 
 /**
@@ -1033,22 +967,16 @@ static int device_prepare(struct device *dev, pm_message_t state)
                if (dev->pm_domain->ops.prepare)
                        error = dev->pm_domain->ops.prepare(dev);
                suspend_report_result(dev->pm_domain->ops.prepare, error);
-               if (error)
-                       goto End;
        } else if (dev->type && dev->type->pm) {
                pm_dev_dbg(dev, state, "preparing type ");
                if (dev->type->pm->prepare)
                        error = dev->type->pm->prepare(dev);
                suspend_report_result(dev->type->pm->prepare, error);
-               if (error)
-                       goto End;
        } else if (dev->class && dev->class->pm) {
                pm_dev_dbg(dev, state, "preparing class ");
                if (dev->class->pm->prepare)
                        error = dev->class->pm->prepare(dev);
                suspend_report_result(dev->class->pm->prepare, error);
-               if (error)
-                       goto End;
        } else if (dev->bus && dev->bus->pm) {
                pm_dev_dbg(dev, state, "preparing ");
                if (dev->bus->pm->prepare)
@@ -1056,7 +984,6 @@ static int device_prepare(struct device *dev, pm_message_t state)
                suspend_report_result(dev->bus->pm->prepare, error);
        }
 
- End:
        device_unlock(dev);
 
        return error;
index 57a692432f8ae1665368e46e8499afa55a2a913d..1f7fff47cfac101517600f38c07ae3c3808b89ce 100644 (file)
@@ -380,12 +380,16 @@ static inline void unlock_system_sleep(void) {}
 
 static inline void lock_system_sleep(void)
 {
+       /* simplified freezer_do_not_count() */
+       current->flags |= PF_FREEZER_SKIP;
        mutex_lock(&pm_mutex);
 }
 
 static inline void unlock_system_sleep(void)
 {
        mutex_unlock(&pm_mutex);
+       /* simplified freezer_count() */
+       current->flags &= ~PF_FREEZER_SKIP;
 }
 #endif
 
index e7ffa8952083808dd71028569059433f39e4dd9c..605149a6d21904153779aaefda353f7df013bacd 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;
 
@@ -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);
@@ -349,8 +336,7 @@ int hibernation_snapshot(int platform_mode)
        if (error)
                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
@@ -362,26 +348,26 @@ int hibernation_snapshot(int platform_mode)
 
        error = dpm_prepare(PMSG_FREEZE);
        if (error) {
-               dpm_complete(msg);
+               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();
@@ -399,10 +385,6 @@ int hibernation_snapshot(int platform_mode)
        platform_end(platform_mode);
        return error;
 
- Recover_platform:
-       platform_recover(platform_mode);
-       goto Resume_devices;
-
  Cleanup:
        swsusp_free();
        goto Close;
@@ -590,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;
@@ -800,8 +779,10 @@ 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 = freeze_processes();
@@ -844,8 +825,6 @@ static const char * const hibernation_modes[] = {
        [HIBERNATION_PLATFORM]  = "platform",
        [HIBERNATION_SHUTDOWN]  = "shutdown",
        [HIBERNATION_REBOOT]    = "reboot",
-       [HIBERNATION_TEST]      = "test",
-       [HIBERNATION_TESTPROC]  = "testproc",
 };
 
 /*
@@ -854,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.
@@ -888,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)
@@ -930,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:
index 36e0f0903c3245e60d2994121d1aaa28c8fc0a23..7d36fb31e4c45aede5c2e440ee47f92588b66bf0 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2003 Patrick Mochel
  * Copyright (c) 2003 Open Source Development Lab
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -240,7 +240,7 @@ struct kobject *power_kobj;
  *     'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
  *     'disk' (Suspend-to-Disk).
  *
- *     store() accepts one of those strings, translates it into the 
+ *     store() accepts one of those strings, translates it into the
  *     proper enumerated value, and initiates a suspend transition.
  */
 static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -282,7 +282,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
        /* First, check if we are requested to hibernate */
        if (len == 4 && !strncmp(buf, "disk", len)) {
                error = hibernate();
-  goto Exit;
+               goto Exit;
        }
 
 #ifdef CONFIG_SUSPEND
index 23a2db1ec442352a4e0d7cbebd3c1763f38a2711..0c4defe6d3b873443e927c63755e27ffa9db051b 100644 (file)
@@ -50,6 +50,8 @@ static inline char *check_image_kernel(struct swsusp_info *info)
 #define SPARE_PAGES    ((1024 * 1024) >> PAGE_SHIFT)
 
 /* kernel/power/hibernate.c */
+extern bool freezer_test_done;
+
 extern int hibernation_snapshot(int platform_mode);
 extern int hibernation_restore(int platform_mode);
 extern int hibernation_platform_enter(void);
index 7cc3f5bc5c24801365a4fafe4ddbcb0154baf5f9..c202e2e1a2d5dbd56bf4d2f33669abf99141d7da 100644 (file)
@@ -281,10 +281,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                }
                pm_restore_gfp_mask();
                error = hibernation_snapshot(data->platform_support);
-               if (!error)
+               if (!error) {
                        error = put_user(in_suspend, (int __user *)arg);
-               if (!error)
-                       data->ready = 1;
+                       if (!error && !freezer_test_done)
+                               data->ready = 1;
+                       if (freezer_test_done) {
+                               freezer_test_done = false;
+                               thaw_processes();
+                       }
+               }
                break;
 
        case SNAPSHOT_ATOMIC_RESTORE: