diff options
Diffstat (limited to 'kernel/power/user.c')
-rw-r--r-- | kernel/power/user.c | 71 |
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 | ||
42 | static atomic_t device_available = ATOMIC_INIT(1); | 43 | static 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 | ||
125 | static int snapshot_suspend(void) | 127 | static 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 | |||
137 | static inline void platform_finish(void) | ||
138 | { | ||
139 | if (pm_ops && pm_ops->finish) | ||
140 | pm_ops->finish(PM_SUSPEND_DISK); | ||
141 | } | ||
142 | |||
143 | static 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 | ||
154 | static int snapshot_restore(void) | 180 | static 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; |