diff options
-rw-r--r-- | arch/arm/mach-shmobile/pm-sh7372.c | 33 | ||||
-rw-r--r-- | drivers/base/core.c | 3 | ||||
-rw-r--r-- | drivers/base/power/clock_ops.c | 3 | ||||
-rw-r--r-- | drivers/base/power/main.c | 3 | ||||
-rw-r--r-- | drivers/base/power/qos.c | 18 | ||||
-rw-r--r-- | drivers/devfreq/Kconfig | 41 | ||||
-rw-r--r-- | drivers/devfreq/devfreq.c | 10 | ||||
-rw-r--r-- | include/linux/device.h | 5 | ||||
-rw-r--r-- | include/linux/pm.h | 2 | ||||
-rw-r--r-- | include/linux/pm_runtime.h | 6 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 23 | ||||
-rw-r--r-- | kernel/power/main.c | 3 |
12 files changed, 89 insertions, 61 deletions
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 0a5b22942fd3..34bbcbfb1706 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/bitrev.h> | 22 | #include <linux/bitrev.h> |
23 | #include <linux/console.h> | ||
23 | #include <asm/system.h> | 24 | #include <asm/system.h> |
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | #include <asm/tlbflush.h> | 26 | #include <asm/tlbflush.h> |
@@ -106,9 +107,8 @@ static int pd_power_down(struct generic_pm_domain *genpd) | |||
106 | return 0; | 107 | return 0; |
107 | } | 108 | } |
108 | 109 | ||
109 | static int pd_power_up(struct generic_pm_domain *genpd) | 110 | static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume) |
110 | { | 111 | { |
111 | struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); | ||
112 | unsigned int mask = 1 << sh7372_pd->bit_shift; | 112 | unsigned int mask = 1 << sh7372_pd->bit_shift; |
113 | unsigned int retry_count; | 113 | unsigned int retry_count; |
114 | int ret = 0; | 114 | int ret = 0; |
@@ -123,13 +123,13 @@ static int pd_power_up(struct generic_pm_domain *genpd) | |||
123 | 123 | ||
124 | for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { | 124 | for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { |
125 | if (!(__raw_readl(SWUCR) & mask)) | 125 | if (!(__raw_readl(SWUCR) & mask)) |
126 | goto out; | 126 | break; |
127 | if (retry_count > PSTR_RETRIES) | 127 | if (retry_count > PSTR_RETRIES) |
128 | udelay(PSTR_DELAY_US); | 128 | udelay(PSTR_DELAY_US); |
129 | else | 129 | else |
130 | cpu_relax(); | 130 | cpu_relax(); |
131 | } | 131 | } |
132 | if (__raw_readl(SWUCR) & mask) | 132 | if (!retry_count) |
133 | ret = -EIO; | 133 | ret = -EIO; |
134 | 134 | ||
135 | if (!sh7372_pd->no_debug) | 135 | if (!sh7372_pd->no_debug) |
@@ -137,12 +137,17 @@ static int pd_power_up(struct generic_pm_domain *genpd) | |||
137 | mask, __raw_readl(PSTR)); | 137 | mask, __raw_readl(PSTR)); |
138 | 138 | ||
139 | out: | 139 | out: |
140 | if (ret == 0 && sh7372_pd->resume) | 140 | if (ret == 0 && sh7372_pd->resume && do_resume) |
141 | sh7372_pd->resume(); | 141 | sh7372_pd->resume(); |
142 | 142 | ||
143 | return ret; | 143 | return ret; |
144 | } | 144 | } |
145 | 145 | ||
146 | static int pd_power_up(struct generic_pm_domain *genpd) | ||
147 | { | ||
148 | return __pd_power_up(to_sh7372_pd(genpd), true); | ||
149 | } | ||
150 | |||
146 | static void sh7372_a4r_suspend(void) | 151 | static void sh7372_a4r_suspend(void) |
147 | { | 152 | { |
148 | sh7372_intcs_suspend(); | 153 | sh7372_intcs_suspend(); |
@@ -174,7 +179,7 @@ void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) | |||
174 | genpd->active_wakeup = pd_active_wakeup; | 179 | genpd->active_wakeup = pd_active_wakeup; |
175 | genpd->power_off = pd_power_down; | 180 | genpd->power_off = pd_power_down; |
176 | genpd->power_on = pd_power_up; | 181 | genpd->power_on = pd_power_up; |
177 | genpd->power_on(&sh7372_pd->genpd); | 182 | __pd_power_up(sh7372_pd, false); |
178 | } | 183 | } |
179 | 184 | ||
180 | void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, | 185 | void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, |
@@ -227,11 +232,23 @@ struct sh7372_pm_domain sh7372_a3sp = { | |||
227 | .no_debug = true, | 232 | .no_debug = true, |
228 | }; | 233 | }; |
229 | 234 | ||
235 | static void sh7372_a3sp_init(void) | ||
236 | { | ||
237 | /* serial consoles make use of SCIF hardware located in A3SP, | ||
238 | * keep such power domain on if "no_console_suspend" is set. | ||
239 | */ | ||
240 | sh7372_a3sp.stay_on = !console_suspend_enabled; | ||
241 | } | ||
242 | |||
230 | struct sh7372_pm_domain sh7372_a3sg = { | 243 | struct sh7372_pm_domain sh7372_a3sg = { |
231 | .bit_shift = 13, | 244 | .bit_shift = 13, |
232 | }; | 245 | }; |
233 | 246 | ||
234 | #endif /* CONFIG_PM */ | 247 | #else /* !CONFIG_PM */ |
248 | |||
249 | static inline void sh7372_a3sp_init(void) {} | ||
250 | |||
251 | #endif /* !CONFIG_PM */ | ||
235 | 252 | ||
236 | #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) | 253 | #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) |
237 | static int sh7372_do_idle_core_standby(unsigned long unused) | 254 | static int sh7372_do_idle_core_standby(unsigned long unused) |
@@ -465,6 +482,8 @@ void __init sh7372_pm_init(void) | |||
465 | /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ | 482 | /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ |
466 | __raw_writel(0, PDNSEL); | 483 | __raw_writel(0, PDNSEL); |
467 | 484 | ||
485 | sh7372_a3sp_init(); | ||
486 | |||
468 | sh7372_suspend_init(); | 487 | sh7372_suspend_init(); |
469 | sh7372_cpuidle_init(); | 488 | sh7372_cpuidle_init(); |
470 | } | 489 | } |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 82c865452c70..d8b3d89db043 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kallsyms.h> | 22 | #include <linux/kallsyms.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/async.h> | 24 | #include <linux/async.h> |
25 | #include <linux/pm_runtime.h> | ||
25 | 26 | ||
26 | #include "base.h" | 27 | #include "base.h" |
27 | #include "power/power.h" | 28 | #include "power/power.h" |
@@ -1742,6 +1743,8 @@ void device_shutdown(void) | |||
1742 | */ | 1743 | */ |
1743 | list_del_init(&dev->kobj.entry); | 1744 | list_del_init(&dev->kobj.entry); |
1744 | spin_unlock(&devices_kset->list_lock); | 1745 | spin_unlock(&devices_kset->list_lock); |
1746 | /* Disable all device's runtime power management */ | ||
1747 | pm_runtime_disable(dev); | ||
1745 | 1748 | ||
1746 | if (dev->bus && dev->bus->shutdown) { | 1749 | if (dev->bus && dev->bus->shutdown) { |
1747 | dev_dbg(dev, "shutdown\n"); | 1750 | dev_dbg(dev, "shutdown\n"); |
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 5f0f85d5c576..428e55e012dc 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c | |||
@@ -229,7 +229,8 @@ int pm_clk_suspend(struct device *dev) | |||
229 | 229 | ||
230 | list_for_each_entry_reverse(ce, &psd->clock_list, node) { | 230 | list_for_each_entry_reverse(ce, &psd->clock_list, node) { |
231 | if (ce->status < PCE_STATUS_ERROR) { | 231 | if (ce->status < PCE_STATUS_ERROR) { |
232 | clk_disable(ce->clk); | 232 | if (ce->status == PCE_STATUS_ENABLED) |
233 | clk_disable(ce->clk); | ||
233 | ce->status = PCE_STATUS_ACQUIRED; | 234 | ce->status = PCE_STATUS_ACQUIRED; |
234 | } | 235 | } |
235 | } | 236 | } |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 7fa098464dae..c3d2dfcf438d 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -920,7 +920,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
920 | End: | 920 | End: |
921 | if (!error) { | 921 | if (!error) { |
922 | dev->power.is_suspended = true; | 922 | dev->power.is_suspended = true; |
923 | if (dev->power.wakeup_path && dev->parent) | 923 | if (dev->power.wakeup_path |
924 | && dev->parent && !dev->parent->power.ignore_children) | ||
924 | dev->parent->power.wakeup_path = true; | 925 | dev->parent->power.wakeup_path = true; |
925 | } | 926 | } |
926 | 927 | ||
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 30a94eadc200..86de6c50fc41 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
@@ -212,11 +212,9 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, | |||
212 | if (!dev || !req) /*guard against callers passing in null */ | 212 | if (!dev || !req) /*guard against callers passing in null */ |
213 | return -EINVAL; | 213 | return -EINVAL; |
214 | 214 | ||
215 | if (dev_pm_qos_request_active(req)) { | 215 | if (WARN(dev_pm_qos_request_active(req), |
216 | WARN(1, KERN_ERR "dev_pm_qos_add_request() called for already " | 216 | "%s() called for already added request\n", __func__)) |
217 | "added request\n"); | ||
218 | return -EINVAL; | 217 | return -EINVAL; |
219 | } | ||
220 | 218 | ||
221 | req->dev = dev; | 219 | req->dev = dev; |
222 | 220 | ||
@@ -271,11 +269,9 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, | |||
271 | if (!req) /*guard against callers passing in null */ | 269 | if (!req) /*guard against callers passing in null */ |
272 | return -EINVAL; | 270 | return -EINVAL; |
273 | 271 | ||
274 | if (!dev_pm_qos_request_active(req)) { | 272 | if (WARN(!dev_pm_qos_request_active(req), |
275 | WARN(1, KERN_ERR "dev_pm_qos_update_request() called for " | 273 | "%s() called for unknown object\n", __func__)) |
276 | "unknown object\n"); | ||
277 | return -EINVAL; | 274 | return -EINVAL; |
278 | } | ||
279 | 275 | ||
280 | mutex_lock(&dev_pm_qos_mtx); | 276 | mutex_lock(&dev_pm_qos_mtx); |
281 | 277 | ||
@@ -312,11 +308,9 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | |||
312 | if (!req) /*guard against callers passing in null */ | 308 | if (!req) /*guard against callers passing in null */ |
313 | return -EINVAL; | 309 | return -EINVAL; |
314 | 310 | ||
315 | if (!dev_pm_qos_request_active(req)) { | 311 | if (WARN(!dev_pm_qos_request_active(req), |
316 | WARN(1, KERN_ERR "dev_pm_qos_remove_request() called for " | 312 | "%s() called for unknown object\n", __func__)) |
317 | "unknown object\n"); | ||
318 | return -EINVAL; | 313 | return -EINVAL; |
319 | } | ||
320 | 314 | ||
321 | mutex_lock(&dev_pm_qos_mtx); | 315 | mutex_lock(&dev_pm_qos_mtx); |
322 | 316 | ||
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 643b055ed3cd..8f0491037080 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig | |||
@@ -1,36 +1,29 @@ | |||
1 | config ARCH_HAS_DEVFREQ | ||
2 | bool | ||
3 | depends on ARCH_HAS_OPP | ||
4 | help | ||
5 | Denotes that the architecture supports DEVFREQ. If the architecture | ||
6 | supports multiple OPP entries per device and the frequency of the | ||
7 | devices with OPPs may be altered dynamically, the architecture | ||
8 | supports DEVFREQ. | ||
9 | |||
10 | menuconfig PM_DEVFREQ | 1 | menuconfig PM_DEVFREQ |
11 | bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support" | 2 | bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support" |
12 | depends on PM_OPP && ARCH_HAS_DEVFREQ | ||
13 | help | 3 | help |
14 | With OPP support, a device may have a list of frequencies and | 4 | A device may have a list of frequencies and voltages available. |
15 | voltages available. DEVFREQ, a generic DVFS framework can be | 5 | devfreq, a generic DVFS framework can be registered for a device |
16 | registered for a device with OPP support in order to let the | 6 | in order to let the governor provided to devfreq choose an |
17 | governor provided to DEVFREQ choose an operating frequency | 7 | operating frequency based on the device driver's policy. |
18 | based on the OPP's list and the policy given with DEVFREQ. | ||
19 | 8 | ||
20 | Each device may have its own governor and policy. DEVFREQ can | 9 | Each device may have its own governor and policy. Devfreq can |
21 | reevaluate the device state periodically and/or based on the | 10 | reevaluate the device state periodically and/or based on the |
22 | OPP list changes (each frequency/voltage pair in OPP may be | 11 | notification to "nb", a notifier block, of devfreq. |
23 | disabled or enabled). | ||
24 | 12 | ||
25 | Like some CPUs with CPUFREQ, a device may have multiple clocks. | 13 | Like some CPUs with CPUfreq, a device may have multiple clocks. |
26 | However, because the clock frequencies of a single device are | 14 | However, because the clock frequencies of a single device are |
27 | determined by the single device's state, an instance of DEVFREQ | 15 | determined by the single device's state, an instance of devfreq |
28 | is attached to a single device and returns a "representative" | 16 | is attached to a single device and returns a "representative" |
29 | clock frequency from the OPP of the device, which is also attached | 17 | clock frequency of the device, which is also attached |
30 | to a device by 1-to-1. The device registering DEVFREQ takes the | 18 | to a device by 1-to-1. The device registering devfreq takes the |
31 | responsiblity to "interpret" the frequency listed in OPP and | 19 | responsiblity to "interpret" the representative frequency and |
32 | to set its every clock accordingly with the "target" callback | 20 | to set its every clock accordingly with the "target" callback |
33 | given to DEVFREQ. | 21 | given to devfreq. |
22 | |||
23 | When OPP is used with the devfreq device, it is recommended to | ||
24 | register devfreq's nb to the OPP's notifier head. If OPP is | ||
25 | used with the devfreq device, you may use OPP helper | ||
26 | functions defined in devfreq.h. | ||
34 | 27 | ||
35 | if PM_DEVFREQ | 28 | if PM_DEVFREQ |
36 | 29 | ||
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 5d15b812377b..59d24e9cb8c5 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
@@ -15,7 +15,9 @@ | |||
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/stat.h> | ||
19 | #include <linux/opp.h> | 21 | #include <linux/opp.h> |
20 | #include <linux/devfreq.h> | 22 | #include <linux/devfreq.h> |
21 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
@@ -416,10 +418,14 @@ out: | |||
416 | */ | 418 | */ |
417 | int devfreq_remove_device(struct devfreq *devfreq) | 419 | int devfreq_remove_device(struct devfreq *devfreq) |
418 | { | 420 | { |
421 | bool central_polling; | ||
422 | |||
419 | if (!devfreq) | 423 | if (!devfreq) |
420 | return -EINVAL; | 424 | return -EINVAL; |
421 | 425 | ||
422 | if (!devfreq->governor->no_central_polling) { | 426 | central_polling = !devfreq->governor->no_central_polling; |
427 | |||
428 | if (central_polling) { | ||
423 | mutex_lock(&devfreq_list_lock); | 429 | mutex_lock(&devfreq_list_lock); |
424 | while (wait_remove_device == devfreq) { | 430 | while (wait_remove_device == devfreq) { |
425 | mutex_unlock(&devfreq_list_lock); | 431 | mutex_unlock(&devfreq_list_lock); |
@@ -431,7 +437,7 @@ int devfreq_remove_device(struct devfreq *devfreq) | |||
431 | mutex_lock(&devfreq->lock); | 437 | mutex_lock(&devfreq->lock); |
432 | _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */ | 438 | _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */ |
433 | 439 | ||
434 | if (!devfreq->governor->no_central_polling) | 440 | if (central_polling) |
435 | mutex_unlock(&devfreq_list_lock); | 441 | mutex_unlock(&devfreq_list_lock); |
436 | 442 | ||
437 | return 0; | 443 | return 0; |
diff --git a/include/linux/device.h b/include/linux/device.h index ffbcf95cd97d..52b3a4111df9 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -682,6 +682,11 @@ static inline bool device_async_suspend_enabled(struct device *dev) | |||
682 | return !!dev->power.async_suspend; | 682 | return !!dev->power.async_suspend; |
683 | } | 683 | } |
684 | 684 | ||
685 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) | ||
686 | { | ||
687 | dev->power.ignore_children = enable; | ||
688 | } | ||
689 | |||
685 | static inline void device_lock(struct device *dev) | 690 | static inline void device_lock(struct device *dev) |
686 | { | 691 | { |
687 | mutex_lock(&dev->mutex); | 692 | mutex_lock(&dev->mutex); |
diff --git a/include/linux/pm.h b/include/linux/pm.h index f15acb646813..5c4c8b18c8b7 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -447,6 +447,7 @@ struct dev_pm_info { | |||
447 | unsigned int async_suspend:1; | 447 | unsigned int async_suspend:1; |
448 | bool is_prepared:1; /* Owned by the PM core */ | 448 | bool is_prepared:1; /* Owned by the PM core */ |
449 | bool is_suspended:1; /* Ditto */ | 449 | bool is_suspended:1; /* Ditto */ |
450 | bool ignore_children:1; | ||
450 | spinlock_t lock; | 451 | spinlock_t lock; |
451 | #ifdef CONFIG_PM_SLEEP | 452 | #ifdef CONFIG_PM_SLEEP |
452 | struct list_head entry; | 453 | struct list_head entry; |
@@ -464,7 +465,6 @@ struct dev_pm_info { | |||
464 | atomic_t usage_count; | 465 | atomic_t usage_count; |
465 | atomic_t child_count; | 466 | atomic_t child_count; |
466 | unsigned int disable_depth:3; | 467 | unsigned int disable_depth:3; |
467 | unsigned int ignore_children:1; | ||
468 | unsigned int idle_notification:1; | 468 | unsigned int idle_notification:1; |
469 | unsigned int request_pending:1; | 469 | unsigned int request_pending:1; |
470 | unsigned int deferred_resume:1; | 470 | unsigned int deferred_resume:1; |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index d8d903619642..d3085e72a0ee 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
@@ -52,11 +52,6 @@ static inline bool pm_children_suspended(struct device *dev) | |||
52 | || !atomic_read(&dev->power.child_count); | 52 | || !atomic_read(&dev->power.child_count); |
53 | } | 53 | } |
54 | 54 | ||
55 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) | ||
56 | { | ||
57 | dev->power.ignore_children = enable; | ||
58 | } | ||
59 | |||
60 | static inline void pm_runtime_get_noresume(struct device *dev) | 55 | static inline void pm_runtime_get_noresume(struct device *dev) |
61 | { | 56 | { |
62 | atomic_inc(&dev->power.usage_count); | 57 | atomic_inc(&dev->power.usage_count); |
@@ -130,7 +125,6 @@ static inline void pm_runtime_allow(struct device *dev) {} | |||
130 | static inline void pm_runtime_forbid(struct device *dev) {} | 125 | static inline void pm_runtime_forbid(struct device *dev) {} |
131 | 126 | ||
132 | static inline bool pm_children_suspended(struct device *dev) { return false; } | 127 | static inline bool pm_children_suspended(struct device *dev) { return false; } |
133 | static inline void pm_suspend_ignore_children(struct device *dev, bool en) {} | ||
134 | static inline void pm_runtime_get_noresume(struct device *dev) {} | 128 | static inline void pm_runtime_get_noresume(struct device *dev) {} |
135 | static inline void pm_runtime_put_noidle(struct device *dev) {} | 129 | static inline void pm_runtime_put_noidle(struct device *dev) {} |
136 | static inline bool device_run_wake(struct device *dev) { return false; } | 130 | static inline bool device_run_wake(struct device *dev) { return false; } |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index b4511b6d3ef9..196c01268ebd 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -55,6 +55,8 @@ enum { | |||
55 | 55 | ||
56 | static int hibernation_mode = HIBERNATION_SHUTDOWN; | 56 | static int hibernation_mode = HIBERNATION_SHUTDOWN; |
57 | 57 | ||
58 | static bool freezer_test_done; | ||
59 | |||
58 | static const struct platform_hibernation_ops *hibernation_ops; | 60 | static const struct platform_hibernation_ops *hibernation_ops; |
59 | 61 | ||
60 | /** | 62 | /** |
@@ -347,6 +349,17 @@ int hibernation_snapshot(int platform_mode) | |||
347 | if (error) | 349 | if (error) |
348 | goto Close; | 350 | goto Close; |
349 | 351 | ||
352 | if (hibernation_test(TEST_FREEZER) || | ||
353 | hibernation_testmode(HIBERNATION_TESTPROC)) { | ||
354 | |||
355 | /* | ||
356 | * Indicate to the caller that we are returning due to a | ||
357 | * successful freezer test. | ||
358 | */ | ||
359 | freezer_test_done = true; | ||
360 | goto Close; | ||
361 | } | ||
362 | |||
350 | error = dpm_prepare(PMSG_FREEZE); | 363 | error = dpm_prepare(PMSG_FREEZE); |
351 | if (error) | 364 | if (error) |
352 | goto Complete_devices; | 365 | goto Complete_devices; |
@@ -641,15 +654,13 @@ int hibernate(void) | |||
641 | if (error) | 654 | if (error) |
642 | goto Finish; | 655 | goto Finish; |
643 | 656 | ||
644 | if (hibernation_test(TEST_FREEZER)) | ||
645 | goto Thaw; | ||
646 | |||
647 | if (hibernation_testmode(HIBERNATION_TESTPROC)) | ||
648 | goto Thaw; | ||
649 | |||
650 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); | 657 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); |
651 | if (error) | 658 | if (error) |
652 | goto Thaw; | 659 | goto Thaw; |
660 | if (freezer_test_done) { | ||
661 | freezer_test_done = false; | ||
662 | goto Thaw; | ||
663 | } | ||
653 | 664 | ||
654 | if (in_suspend) { | 665 | if (in_suspend) { |
655 | unsigned int flags = 0; | 666 | unsigned int flags = 0; |
diff --git a/kernel/power/main.c b/kernel/power/main.c index 71f49fe4377e..36e0f0903c32 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -290,13 +290,14 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
290 | if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) | 290 | if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) |
291 | break; | 291 | break; |
292 | } | 292 | } |
293 | if (state < PM_SUSPEND_MAX && *s) | 293 | if (state < PM_SUSPEND_MAX && *s) { |
294 | error = enter_state(state); | 294 | error = enter_state(state); |
295 | if (error) { | 295 | if (error) { |
296 | suspend_stats.fail++; | 296 | suspend_stats.fail++; |
297 | dpm_save_failed_errno(error); | 297 | dpm_save_failed_errno(error); |
298 | } else | 298 | } else |
299 | suspend_stats.success++; | 299 | suspend_stats.success++; |
300 | } | ||
300 | #endif | 301 | #endif |
301 | 302 | ||
302 | Exit: | 303 | Exit: |