aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/main.c')
-rw-r--r--kernel/power/main.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 4cdebc972ff2..71aa0fd22007 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -19,6 +19,9 @@
19 19
20#include "power.h" 20#include "power.h"
21 21
22/*This is just an arbitrary number */
23#define FREE_PAGE_NUMBER (100)
24
22DECLARE_MUTEX(pm_sem); 25DECLARE_MUTEX(pm_sem);
23 26
24struct pm_ops * pm_ops = NULL; 27struct pm_ops * pm_ops = NULL;
@@ -49,17 +52,35 @@ void pm_set_ops(struct pm_ops * ops)
49static int suspend_prepare(suspend_state_t state) 52static int suspend_prepare(suspend_state_t state)
50{ 53{
51 int error = 0; 54 int error = 0;
55 unsigned int free_pages;
52 56
53 if (!pm_ops || !pm_ops->enter) 57 if (!pm_ops || !pm_ops->enter)
54 return -EPERM; 58 return -EPERM;
55 59
56 pm_prepare_console(); 60 pm_prepare_console();
57 61
62 disable_nonboot_cpus();
63
64 if (num_online_cpus() != 1) {
65 error = -EPERM;
66 goto Enable_cpu;
67 }
68
58 if (freeze_processes()) { 69 if (freeze_processes()) {
59 error = -EAGAIN; 70 error = -EAGAIN;
60 goto Thaw; 71 goto Thaw;
61 } 72 }
62 73
74 if ((free_pages = nr_free_pages()) < FREE_PAGE_NUMBER) {
75 pr_debug("PM: free some memory\n");
76 shrink_all_memory(FREE_PAGE_NUMBER - free_pages);
77 if (nr_free_pages() < FREE_PAGE_NUMBER) {
78 error = -ENOMEM;
79 printk(KERN_ERR "PM: No enough memory\n");
80 goto Thaw;
81 }
82 }
83
63 if (pm_ops->prepare) { 84 if (pm_ops->prepare) {
64 if ((error = pm_ops->prepare(state))) 85 if ((error = pm_ops->prepare(state)))
65 goto Thaw; 86 goto Thaw;
@@ -75,6 +96,8 @@ static int suspend_prepare(suspend_state_t state)
75 pm_ops->finish(state); 96 pm_ops->finish(state);
76 Thaw: 97 Thaw:
77 thaw_processes(); 98 thaw_processes();
99 Enable_cpu:
100 enable_nonboot_cpus();
78 pm_restore_console(); 101 pm_restore_console();
79 return error; 102 return error;
80} 103}
@@ -113,6 +136,7 @@ static void suspend_finish(suspend_state_t state)
113 if (pm_ops && pm_ops->finish) 136 if (pm_ops && pm_ops->finish)
114 pm_ops->finish(state); 137 pm_ops->finish(state);
115 thaw_processes(); 138 thaw_processes();
139 enable_nonboot_cpus();
116 pm_restore_console(); 140 pm_restore_console();
117} 141}
118 142
@@ -150,12 +174,6 @@ static int enter_state(suspend_state_t state)
150 goto Unlock; 174 goto Unlock;
151 } 175 }
152 176
153 /* Suspend is hard to get right on SMP. */
154 if (num_online_cpus() != 1) {
155 error = -EPERM;
156 goto Unlock;
157 }
158
159 pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); 177 pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
160 if ((error = suspend_prepare(state))) 178 if ((error = suspend_prepare(state)))
161 goto Unlock; 179 goto Unlock;
@@ -190,7 +208,7 @@ int software_suspend(void)
190 208
191int pm_suspend(suspend_state_t state) 209int pm_suspend(suspend_state_t state)
192{ 210{
193 if (state > PM_SUSPEND_ON && state < PM_SUSPEND_MAX) 211 if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX)
194 return enter_state(state); 212 return enter_state(state);
195 return -EINVAL; 213 return -EINVAL;
196} 214}