aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/user.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/kernel/power/user.c b/kernel/power/user.c
index b70d83d6b16e..dd09efe7df54 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -37,6 +37,7 @@ static struct snapshot_data {
37 int mode; 37 int mode;
38 char frozen; 38 char frozen;
39 char ready; 39 char ready;
40 char platform_suspend;
40} snapshot_state; 41} snapshot_state;
41 42
42static atomic_t device_available = ATOMIC_INIT(1); 43static atomic_t device_available = ATOMIC_INIT(1);
@@ -66,6 +67,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
66 data->bitmap = NULL; 67 data->bitmap = NULL;
67 data->frozen = 0; 68 data->frozen = 0;
68 data->ready = 0; 69 data->ready = 0;
70 data->platform_suspend = 0;
69 71
70 return 0; 72 return 0;
71} 73}
@@ -122,7 +124,23 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
122 return res; 124 return res;
123} 125}
124 126
125static int snapshot_suspend(void) 127static inline int platform_prepare(void)
128{
129 int error = 0;
130
131 if (pm_ops && pm_ops->prepare)
132 error = pm_ops->prepare(PM_SUSPEND_DISK);
133
134 return error;
135}
136
137static inline void platform_finish(void)
138{
139 if (pm_ops && pm_ops->finish)
140 pm_ops->finish(PM_SUSPEND_DISK);
141}
142
143static inline int snapshot_suspend(int platform_suspend)
126{ 144{
127 int error; 145 int error;
128 146
@@ -132,6 +150,11 @@ static int snapshot_suspend(void)
132 if (error) 150 if (error)
133 goto Finish; 151 goto Finish;
134 152
153 if (platform_suspend) {
154 error = platform_prepare();
155 if (error)
156 goto Finish;
157 }
135 suspend_console(); 158 suspend_console();
136 error = device_suspend(PMSG_FREEZE); 159 error = device_suspend(PMSG_FREEZE);
137 if (error) 160 if (error)
@@ -144,6 +167,9 @@ static int snapshot_suspend(void)
144 } 167 }
145 enable_nonboot_cpus(); 168 enable_nonboot_cpus();
146 Resume_devices: 169 Resume_devices:
170 if (platform_suspend)
171 platform_finish();
172
147 device_resume(); 173 device_resume();
148 resume_console(); 174 resume_console();
149 Finish: 175 Finish:
@@ -151,12 +177,17 @@ static int snapshot_suspend(void)
151 return error; 177 return error;
152} 178}
153 179
154static int snapshot_restore(void) 180static inline int snapshot_restore(int platform_suspend)
155{ 181{
156 int error; 182 int error;
157 183
158 mutex_lock(&pm_mutex); 184 mutex_lock(&pm_mutex);
159 pm_prepare_console(); 185 pm_prepare_console();
186 if (platform_suspend) {
187 error = platform_prepare();
188 if (error)
189 goto Finish;
190 }
160 suspend_console(); 191 suspend_console();
161 error = device_suspend(PMSG_PRETHAW); 192 error = device_suspend(PMSG_PRETHAW);
162 if (error) 193 if (error)
@@ -168,8 +199,12 @@ static int snapshot_restore(void)
168 199
169 enable_nonboot_cpus(); 200 enable_nonboot_cpus();
170 Resume_devices: 201 Resume_devices:
202 if (platform_suspend)
203 platform_finish();
204
171 device_resume(); 205 device_resume();
172 resume_console(); 206 resume_console();
207 Finish:
173 pm_restore_console(); 208 pm_restore_console();
174 mutex_unlock(&pm_mutex); 209 mutex_unlock(&pm_mutex);
175 return error; 210 return error;
@@ -221,7 +256,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
221 error = -EPERM; 256 error = -EPERM;
222 break; 257 break;
223 } 258 }
224 error = snapshot_suspend(); 259 error = snapshot_suspend(data->platform_suspend);
225 if (!error) 260 if (!error)
226 error = put_user(in_suspend, (unsigned int __user *)arg); 261 error = put_user(in_suspend, (unsigned int __user *)arg);
227 if (!error) 262 if (!error)
@@ -235,7 +270,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
235 error = -EPERM; 270 error = -EPERM;
236 break; 271 break;
237 } 272 }
238 error = snapshot_restore(); 273 error = snapshot_restore(data->platform_suspend);
239 break; 274 break;
240 275
241 case SNAPSHOT_FREE: 276 case SNAPSHOT_FREE:
@@ -306,6 +341,11 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
306 break; 341 break;
307 342
308 case SNAPSHOT_S2RAM: 343 case SNAPSHOT_S2RAM:
344 if (!pm_ops) {
345 error = -ENOSYS;
346 break;
347 }
348
309 if (!data->frozen) { 349 if (!data->frozen) {
310 error = -EPERM; 350 error = -EPERM;
311 break; 351 break;
@@ -343,28 +383,35 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
343 break; 383 break;
344 384
345 case SNAPSHOT_PMOPS: 385 case SNAPSHOT_PMOPS:
386 error = -EINVAL;
387
346 switch (arg) { 388 switch (arg) {
347 389
348 case PMOPS_PREPARE: 390 case PMOPS_PREPARE:
349 if (pm_ops->prepare) { 391 if (pm_ops && pm_ops->enter) {
350 error = pm_ops->prepare(PM_SUSPEND_DISK); 392 data->platform_suspend = 1;
393 error = 0;
394 } else {
395 error = -ENOSYS;
351 } 396 }
352 break; 397 break;
353 398
354 case PMOPS_ENTER: 399 case PMOPS_ENTER:
355 kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); 400 if (data->platform_suspend) {
356 error = pm_ops->enter(PM_SUSPEND_DISK); 401 kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
402 error = pm_ops->enter(PM_SUSPEND_DISK);
403 error = 0;
404 }
357 break; 405 break;
358 406
359 case PMOPS_FINISH: 407 case PMOPS_FINISH:
360 if (pm_ops && pm_ops->finish) { 408 if (data->platform_suspend)
361 pm_ops->finish(PM_SUSPEND_DISK); 409 error = 0;
362 } 410
363 break; 411 break;
364 412
365 default: 413 default:
366 printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg); 414 printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg);
367 error = -EINVAL;
368 415
369 } 416 }
370 break; 417 break;