diff options
Diffstat (limited to 'kernel/power/user.c')
-rw-r--r-- | kernel/power/user.c | 102 |
1 files changed, 82 insertions, 20 deletions
diff --git a/kernel/power/user.c b/kernel/power/user.c index d991d3b0e5a4..89443b85163b 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/suspend.h> | 12 | #include <linux/suspend.h> |
13 | #include <linux/syscalls.h> | 13 | #include <linux/syscalls.h> |
14 | #include <linux/reboot.h> | ||
14 | #include <linux/string.h> | 15 | #include <linux/string.h> |
15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
16 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
@@ -21,6 +22,7 @@ | |||
21 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
22 | #include <linux/console.h> | 23 | #include <linux/console.h> |
23 | #include <linux/cpu.h> | 24 | #include <linux/cpu.h> |
25 | #include <linux/freezer.h> | ||
24 | 26 | ||
25 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
26 | 28 | ||
@@ -54,7 +56,8 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
54 | filp->private_data = data; | 56 | filp->private_data = data; |
55 | memset(&data->handle, 0, sizeof(struct snapshot_handle)); | 57 | memset(&data->handle, 0, sizeof(struct snapshot_handle)); |
56 | if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { | 58 | if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { |
57 | data->swap = swsusp_resume_device ? swap_type_of(swsusp_resume_device) : -1; | 59 | data->swap = swsusp_resume_device ? |
60 | swap_type_of(swsusp_resume_device, 0) : -1; | ||
58 | data->mode = O_RDONLY; | 61 | data->mode = O_RDONLY; |
59 | } else { | 62 | } else { |
60 | data->swap = -1; | 63 | data->swap = -1; |
@@ -76,10 +79,10 @@ static int snapshot_release(struct inode *inode, struct file *filp) | |||
76 | free_all_swap_pages(data->swap, data->bitmap); | 79 | free_all_swap_pages(data->swap, data->bitmap); |
77 | free_bitmap(data->bitmap); | 80 | free_bitmap(data->bitmap); |
78 | if (data->frozen) { | 81 | if (data->frozen) { |
79 | down(&pm_sem); | 82 | mutex_lock(&pm_mutex); |
80 | thaw_processes(); | 83 | thaw_processes(); |
81 | enable_nonboot_cpus(); | 84 | enable_nonboot_cpus(); |
82 | up(&pm_sem); | 85 | mutex_unlock(&pm_mutex); |
83 | } | 86 | } |
84 | atomic_inc(&device_available); | 87 | atomic_inc(&device_available); |
85 | return 0; | 88 | return 0; |
@@ -124,7 +127,8 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
124 | { | 127 | { |
125 | int error = 0; | 128 | int error = 0; |
126 | struct snapshot_data *data; | 129 | struct snapshot_data *data; |
127 | loff_t offset, avail; | 130 | loff_t avail; |
131 | sector_t offset; | ||
128 | 132 | ||
129 | if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) | 133 | if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) |
130 | return -ENOTTY; | 134 | return -ENOTTY; |
@@ -140,7 +144,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
140 | case SNAPSHOT_FREEZE: | 144 | case SNAPSHOT_FREEZE: |
141 | if (data->frozen) | 145 | if (data->frozen) |
142 | break; | 146 | break; |
143 | down(&pm_sem); | 147 | mutex_lock(&pm_mutex); |
144 | error = disable_nonboot_cpus(); | 148 | error = disable_nonboot_cpus(); |
145 | if (!error) { | 149 | if (!error) { |
146 | error = freeze_processes(); | 150 | error = freeze_processes(); |
@@ -150,7 +154,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
150 | error = -EBUSY; | 154 | error = -EBUSY; |
151 | } | 155 | } |
152 | } | 156 | } |
153 | up(&pm_sem); | 157 | mutex_unlock(&pm_mutex); |
154 | if (!error) | 158 | if (!error) |
155 | data->frozen = 1; | 159 | data->frozen = 1; |
156 | break; | 160 | break; |
@@ -158,10 +162,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
158 | case SNAPSHOT_UNFREEZE: | 162 | case SNAPSHOT_UNFREEZE: |
159 | if (!data->frozen) | 163 | if (!data->frozen) |
160 | break; | 164 | break; |
161 | down(&pm_sem); | 165 | mutex_lock(&pm_mutex); |
162 | thaw_processes(); | 166 | thaw_processes(); |
163 | enable_nonboot_cpus(); | 167 | enable_nonboot_cpus(); |
164 | up(&pm_sem); | 168 | mutex_unlock(&pm_mutex); |
165 | data->frozen = 0; | 169 | data->frozen = 0; |
166 | break; | 170 | break; |
167 | 171 | ||
@@ -170,7 +174,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
170 | error = -EPERM; | 174 | error = -EPERM; |
171 | break; | 175 | break; |
172 | } | 176 | } |
173 | down(&pm_sem); | 177 | mutex_lock(&pm_mutex); |
174 | /* Free memory before shutting down devices. */ | 178 | /* Free memory before shutting down devices. */ |
175 | error = swsusp_shrink_memory(); | 179 | error = swsusp_shrink_memory(); |
176 | if (!error) { | 180 | if (!error) { |
@@ -183,7 +187,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
183 | } | 187 | } |
184 | resume_console(); | 188 | resume_console(); |
185 | } | 189 | } |
186 | up(&pm_sem); | 190 | mutex_unlock(&pm_mutex); |
187 | if (!error) | 191 | if (!error) |
188 | error = put_user(in_suspend, (unsigned int __user *)arg); | 192 | error = put_user(in_suspend, (unsigned int __user *)arg); |
189 | if (!error) | 193 | if (!error) |
@@ -191,13 +195,13 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
191 | break; | 195 | break; |
192 | 196 | ||
193 | case SNAPSHOT_ATOMIC_RESTORE: | 197 | case SNAPSHOT_ATOMIC_RESTORE: |
198 | snapshot_write_finalize(&data->handle); | ||
194 | if (data->mode != O_WRONLY || !data->frozen || | 199 | if (data->mode != O_WRONLY || !data->frozen || |
195 | !snapshot_image_loaded(&data->handle)) { | 200 | !snapshot_image_loaded(&data->handle)) { |
196 | error = -EPERM; | 201 | error = -EPERM; |
197 | break; | 202 | break; |
198 | } | 203 | } |
199 | snapshot_free_unused_memory(&data->handle); | 204 | mutex_lock(&pm_mutex); |
200 | down(&pm_sem); | ||
201 | pm_prepare_console(); | 205 | pm_prepare_console(); |
202 | suspend_console(); | 206 | suspend_console(); |
203 | error = device_suspend(PMSG_PRETHAW); | 207 | error = device_suspend(PMSG_PRETHAW); |
@@ -207,7 +211,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
207 | } | 211 | } |
208 | resume_console(); | 212 | resume_console(); |
209 | pm_restore_console(); | 213 | pm_restore_console(); |
210 | up(&pm_sem); | 214 | mutex_unlock(&pm_mutex); |
211 | break; | 215 | break; |
212 | 216 | ||
213 | case SNAPSHOT_FREE: | 217 | case SNAPSHOT_FREE: |
@@ -238,10 +242,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
238 | break; | 242 | break; |
239 | } | 243 | } |
240 | } | 244 | } |
241 | offset = alloc_swap_page(data->swap, data->bitmap); | 245 | offset = alloc_swapdev_block(data->swap, data->bitmap); |
242 | if (offset) { | 246 | if (offset) { |
243 | offset <<= PAGE_SHIFT; | 247 | offset <<= PAGE_SHIFT; |
244 | error = put_user(offset, (loff_t __user *)arg); | 248 | error = put_user(offset, (sector_t __user *)arg); |
245 | } else { | 249 | } else { |
246 | error = -ENOSPC; | 250 | error = -ENOSPC; |
247 | } | 251 | } |
@@ -264,7 +268,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
264 | * so we need to recode them | 268 | * so we need to recode them |
265 | */ | 269 | */ |
266 | if (old_decode_dev(arg)) { | 270 | if (old_decode_dev(arg)) { |
267 | data->swap = swap_type_of(old_decode_dev(arg)); | 271 | data->swap = swap_type_of(old_decode_dev(arg), 0); |
268 | if (data->swap < 0) | 272 | if (data->swap < 0) |
269 | error = -ENODEV; | 273 | error = -ENODEV; |
270 | } else { | 274 | } else { |
@@ -282,7 +286,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
282 | break; | 286 | break; |
283 | } | 287 | } |
284 | 288 | ||
285 | if (down_trylock(&pm_sem)) { | 289 | if (!mutex_trylock(&pm_mutex)) { |
286 | error = -EBUSY; | 290 | error = -EBUSY; |
287 | break; | 291 | break; |
288 | } | 292 | } |
@@ -309,8 +313,66 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
309 | if (pm_ops->finish) | 313 | if (pm_ops->finish) |
310 | pm_ops->finish(PM_SUSPEND_MEM); | 314 | pm_ops->finish(PM_SUSPEND_MEM); |
311 | 315 | ||
312 | OutS3: | 316 | OutS3: |
313 | up(&pm_sem); | 317 | mutex_unlock(&pm_mutex); |
318 | break; | ||
319 | |||
320 | case SNAPSHOT_PMOPS: | ||
321 | switch (arg) { | ||
322 | |||
323 | case PMOPS_PREPARE: | ||
324 | if (pm_ops->prepare) { | ||
325 | error = pm_ops->prepare(PM_SUSPEND_DISK); | ||
326 | } | ||
327 | break; | ||
328 | |||
329 | case PMOPS_ENTER: | ||
330 | kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); | ||
331 | error = pm_ops->enter(PM_SUSPEND_DISK); | ||
332 | break; | ||
333 | |||
334 | case PMOPS_FINISH: | ||
335 | if (pm_ops && pm_ops->finish) { | ||
336 | pm_ops->finish(PM_SUSPEND_DISK); | ||
337 | } | ||
338 | break; | ||
339 | |||
340 | default: | ||
341 | printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg); | ||
342 | error = -EINVAL; | ||
343 | |||
344 | } | ||
345 | break; | ||
346 | |||
347 | case SNAPSHOT_SET_SWAP_AREA: | ||
348 | if (data->bitmap) { | ||
349 | error = -EPERM; | ||
350 | } else { | ||
351 | struct resume_swap_area swap_area; | ||
352 | dev_t swdev; | ||
353 | |||
354 | error = copy_from_user(&swap_area, (void __user *)arg, | ||
355 | sizeof(struct resume_swap_area)); | ||
356 | if (error) { | ||
357 | error = -EFAULT; | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * User space encodes device types as two-byte values, | ||
363 | * so we need to recode them | ||
364 | */ | ||
365 | swdev = old_decode_dev(swap_area.dev); | ||
366 | if (swdev) { | ||
367 | offset = swap_area.offset; | ||
368 | data->swap = swap_type_of(swdev, offset); | ||
369 | if (data->swap < 0) | ||
370 | error = -ENODEV; | ||
371 | } else { | ||
372 | data->swap = -1; | ||
373 | error = -EINVAL; | ||
374 | } | ||
375 | } | ||
314 | break; | 376 | break; |
315 | 377 | ||
316 | default: | 378 | default: |
@@ -321,7 +383,7 @@ OutS3: | |||
321 | return error; | 383 | return error; |
322 | } | 384 | } |
323 | 385 | ||
324 | static struct file_operations snapshot_fops = { | 386 | static const struct file_operations snapshot_fops = { |
325 | .open = snapshot_open, | 387 | .open = snapshot_open, |
326 | .release = snapshot_release, | 388 | .release = snapshot_release, |
327 | .read = snapshot_read, | 389 | .read = snapshot_read, |