diff options
-rw-r--r-- | kernel/cpu.c | 2 | ||||
-rw-r--r-- | kernel/power/disk.c | 115 |
2 files changed, 60 insertions, 57 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 7406fe6966f9..3d4206ada5c9 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -309,6 +309,8 @@ void enable_nonboot_cpus(void) | |||
309 | mutex_lock(&cpu_add_remove_lock); | 309 | mutex_lock(&cpu_add_remove_lock); |
310 | cpu_hotplug_disabled = 0; | 310 | cpu_hotplug_disabled = 0; |
311 | mutex_unlock(&cpu_add_remove_lock); | 311 | mutex_unlock(&cpu_add_remove_lock); |
312 | if (cpus_empty(frozen_cpus)) | ||
313 | return; | ||
312 | 314 | ||
313 | printk("Enabling non-boot CPUs ...\n"); | 315 | printk("Enabling non-boot CPUs ...\n"); |
314 | for_each_cpu_mask(cpu, frozen_cpus) { | 316 | for_each_cpu_mask(cpu, frozen_cpus) { |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 88fc5d7ac737..406b20adb27a 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -87,52 +87,24 @@ static inline void platform_finish(void) | |||
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
90 | static void unprepare_processes(void) | ||
91 | { | ||
92 | thaw_processes(); | ||
93 | pm_restore_console(); | ||
94 | } | ||
95 | |||
90 | static int prepare_processes(void) | 96 | static int prepare_processes(void) |
91 | { | 97 | { |
92 | int error = 0; | 98 | int error = 0; |
93 | 99 | ||
94 | pm_prepare_console(); | 100 | pm_prepare_console(); |
95 | |||
96 | error = disable_nonboot_cpus(); | ||
97 | if (error) | ||
98 | goto enable_cpus; | ||
99 | |||
100 | if (freeze_processes()) { | 101 | if (freeze_processes()) { |
101 | error = -EBUSY; | 102 | error = -EBUSY; |
102 | goto thaw; | 103 | unprepare_processes(); |
103 | } | 104 | } |
104 | |||
105 | if (pm_disk_mode == PM_DISK_TESTPROC) { | ||
106 | printk("swsusp debug: Waiting for 5 seconds.\n"); | ||
107 | mdelay(5000); | ||
108 | goto thaw; | ||
109 | } | ||
110 | |||
111 | error = platform_prepare(); | ||
112 | if (error) | ||
113 | goto thaw; | ||
114 | |||
115 | /* Free memory before shutting down devices. */ | ||
116 | if (!(error = swsusp_shrink_memory())) | ||
117 | return 0; | ||
118 | |||
119 | platform_finish(); | ||
120 | thaw: | ||
121 | thaw_processes(); | ||
122 | enable_cpus: | ||
123 | enable_nonboot_cpus(); | ||
124 | pm_restore_console(); | ||
125 | return error; | 105 | return error; |
126 | } | 106 | } |
127 | 107 | ||
128 | static void unprepare_processes(void) | ||
129 | { | ||
130 | platform_finish(); | ||
131 | thaw_processes(); | ||
132 | enable_nonboot_cpus(); | ||
133 | pm_restore_console(); | ||
134 | } | ||
135 | |||
136 | /** | 108 | /** |
137 | * pm_suspend_disk - The granpappy of hibernation power management. | 109 | * pm_suspend_disk - The granpappy of hibernation power management. |
138 | * | 110 | * |
@@ -150,29 +122,45 @@ int pm_suspend_disk(void) | |||
150 | if (error) | 122 | if (error) |
151 | return error; | 123 | return error; |
152 | 124 | ||
153 | if (pm_disk_mode == PM_DISK_TESTPROC) | 125 | if (pm_disk_mode == PM_DISK_TESTPROC) { |
154 | return 0; | 126 | printk("swsusp debug: Waiting for 5 seconds.\n"); |
127 | mdelay(5000); | ||
128 | goto Thaw; | ||
129 | } | ||
130 | /* Free memory before shutting down devices. */ | ||
131 | error = swsusp_shrink_memory(); | ||
132 | if (error) | ||
133 | goto Thaw; | ||
134 | |||
135 | error = platform_prepare(); | ||
136 | if (error) | ||
137 | goto Thaw; | ||
155 | 138 | ||
156 | suspend_console(); | 139 | suspend_console(); |
157 | error = device_suspend(PMSG_FREEZE); | 140 | error = device_suspend(PMSG_FREEZE); |
158 | if (error) { | 141 | if (error) { |
159 | resume_console(); | 142 | printk(KERN_ERR "PM: Some devices failed to suspend\n"); |
160 | printk("Some devices failed to suspend\n"); | 143 | goto Resume_devices; |
161 | goto Thaw; | ||
162 | } | 144 | } |
145 | error = disable_nonboot_cpus(); | ||
146 | if (error) | ||
147 | goto Enable_cpus; | ||
163 | 148 | ||
164 | if (pm_disk_mode == PM_DISK_TEST) { | 149 | if (pm_disk_mode == PM_DISK_TEST) { |
165 | printk("swsusp debug: Waiting for 5 seconds.\n"); | 150 | printk("swsusp debug: Waiting for 5 seconds.\n"); |
166 | mdelay(5000); | 151 | mdelay(5000); |
167 | goto Done; | 152 | goto Enable_cpus; |
168 | } | 153 | } |
169 | 154 | ||
170 | pr_debug("PM: snapshotting memory.\n"); | 155 | pr_debug("PM: snapshotting memory.\n"); |
171 | in_suspend = 1; | 156 | in_suspend = 1; |
172 | if ((error = swsusp_suspend())) | 157 | error = swsusp_suspend(); |
173 | goto Done; | 158 | if (error) |
159 | goto Enable_cpus; | ||
174 | 160 | ||
175 | if (in_suspend) { | 161 | if (in_suspend) { |
162 | enable_nonboot_cpus(); | ||
163 | platform_finish(); | ||
176 | device_resume(); | 164 | device_resume(); |
177 | resume_console(); | 165 | resume_console(); |
178 | pr_debug("PM: writing image.\n"); | 166 | pr_debug("PM: writing image.\n"); |
@@ -188,7 +176,10 @@ int pm_suspend_disk(void) | |||
188 | } | 176 | } |
189 | 177 | ||
190 | swsusp_free(); | 178 | swsusp_free(); |
191 | Done: | 179 | Enable_cpus: |
180 | enable_nonboot_cpus(); | ||
181 | Resume_devices: | ||
182 | platform_finish(); | ||
192 | device_resume(); | 183 | device_resume(); |
193 | resume_console(); | 184 | resume_console(); |
194 | Thaw: | 185 | Thaw: |
@@ -237,19 +228,28 @@ static int software_resume(void) | |||
237 | 228 | ||
238 | pr_debug("PM: Checking swsusp image.\n"); | 229 | pr_debug("PM: Checking swsusp image.\n"); |
239 | 230 | ||
240 | if ((error = swsusp_check())) | 231 | error = swsusp_check(); |
232 | if (error) | ||
241 | goto Done; | 233 | goto Done; |
242 | 234 | ||
243 | pr_debug("PM: Preparing processes for restore.\n"); | 235 | pr_debug("PM: Preparing processes for restore.\n"); |
244 | 236 | ||
245 | if ((error = prepare_processes())) { | 237 | error = prepare_processes(); |
238 | if (error) { | ||
246 | swsusp_close(); | 239 | swsusp_close(); |
247 | goto Done; | 240 | goto Done; |
248 | } | 241 | } |
249 | 242 | ||
243 | error = platform_prepare(); | ||
244 | if (error) { | ||
245 | swsusp_free(); | ||
246 | goto Thaw; | ||
247 | } | ||
248 | |||
250 | pr_debug("PM: Reading swsusp image.\n"); | 249 | pr_debug("PM: Reading swsusp image.\n"); |
251 | 250 | ||
252 | if ((error = swsusp_read())) { | 251 | error = swsusp_read(); |
252 | if (error) { | ||
253 | swsusp_free(); | 253 | swsusp_free(); |
254 | goto Thaw; | 254 | goto Thaw; |
255 | } | 255 | } |
@@ -257,21 +257,22 @@ static int software_resume(void) | |||
257 | pr_debug("PM: Preparing devices for restore.\n"); | 257 | pr_debug("PM: Preparing devices for restore.\n"); |
258 | 258 | ||
259 | suspend_console(); | 259 | suspend_console(); |
260 | if ((error = device_suspend(PMSG_PRETHAW))) { | 260 | error = device_suspend(PMSG_PRETHAW); |
261 | resume_console(); | 261 | if (error) |
262 | printk("Some devices failed to suspend\n"); | 262 | goto Free; |
263 | swsusp_free(); | ||
264 | goto Thaw; | ||
265 | } | ||
266 | 263 | ||
267 | mb(); | 264 | error = disable_nonboot_cpus(); |
265 | if (!error) | ||
266 | swsusp_resume(); | ||
268 | 267 | ||
269 | pr_debug("PM: Restoring saved image.\n"); | 268 | enable_nonboot_cpus(); |
270 | swsusp_resume(); | 269 | Free: |
271 | pr_debug("PM: Restore failed, recovering.n"); | 270 | swsusp_free(); |
271 | platform_finish(); | ||
272 | device_resume(); | 272 | device_resume(); |
273 | resume_console(); | 273 | resume_console(); |
274 | Thaw: | 274 | Thaw: |
275 | printk(KERN_ERR "PM: Restore failed, recovering.\n"); | ||
275 | unprepare_processes(); | 276 | unprepare_processes(); |
276 | Done: | 277 | Done: |
277 | /* For success case, the suspend path will release the lock */ | 278 | /* For success case, the suspend path will release the lock */ |