2 * linux/kernel/power/user.c
4 * This file provides the user space interface for software suspend/resume.
6 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
8 * This file is released under the GPLv2.
12 #include <linux/suspend.h>
13 #include <linux/syscalls.h>
14 #include <linux/string.h>
15 #include <linux/device.h>
16 #include <linux/miscdevice.h>
18 #include <linux/swap.h>
19 #include <linux/swapops.h>
23 #include <asm/uaccess.h>
27 #define SNAPSHOT_MINOR 231
29 static struct snapshot_data
{
30 struct snapshot_handle handle
;
32 struct bitmap_page
*bitmap
;
38 static atomic_t device_available
= ATOMIC_INIT(1);
40 static int snapshot_open(struct inode
*inode
, struct file
*filp
)
42 struct snapshot_data
*data
;
44 if (!atomic_add_unless(&device_available
, -1, 0))
47 if ((filp
->f_flags
& O_ACCMODE
) == O_RDWR
)
50 nonseekable_open(inode
, filp
);
51 data
= &snapshot_state
;
52 filp
->private_data
= data
;
53 memset(&data
->handle
, 0, sizeof(struct snapshot_handle
));
54 if ((filp
->f_flags
& O_ACCMODE
) == O_RDONLY
) {
55 data
->swap
= swsusp_resume_device
? swap_type_of(swsusp_resume_device
) : -1;
56 data
->mode
= O_RDONLY
;
59 data
->mode
= O_WRONLY
;
68 static int snapshot_release(struct inode
*inode
, struct file
*filp
)
70 struct snapshot_data
*data
;
73 data
= filp
->private_data
;
74 free_all_swap_pages(data
->swap
, data
->bitmap
);
75 free_bitmap(data
->bitmap
);
79 enable_nonboot_cpus();
82 atomic_inc(&device_available
);
86 static ssize_t
snapshot_read(struct file
*filp
, char __user
*buf
,
87 size_t count
, loff_t
*offp
)
89 struct snapshot_data
*data
;
92 data
= filp
->private_data
;
93 res
= snapshot_read_next(&data
->handle
, count
);
95 if (copy_to_user(buf
, data_of(data
->handle
), res
))
98 *offp
= data
->handle
.offset
;
103 static ssize_t
snapshot_write(struct file
*filp
, const char __user
*buf
,
104 size_t count
, loff_t
*offp
)
106 struct snapshot_data
*data
;
109 data
= filp
->private_data
;
110 res
= snapshot_write_next(&data
->handle
, count
);
112 if (copy_from_user(data_of(data
->handle
), buf
, res
))
115 *offp
= data
->handle
.offset
;
120 static int snapshot_ioctl(struct inode
*inode
, struct file
*filp
,
121 unsigned int cmd
, unsigned long arg
)
124 struct snapshot_data
*data
;
125 loff_t offset
, avail
;
127 if (_IOC_TYPE(cmd
) != SNAPSHOT_IOC_MAGIC
)
129 if (_IOC_NR(cmd
) > SNAPSHOT_IOC_MAXNR
)
131 if (!capable(CAP_SYS_ADMIN
))
134 data
= filp
->private_data
;
138 case SNAPSHOT_FREEZE
:
142 disable_nonboot_cpus();
143 if (freeze_processes()) {
145 enable_nonboot_cpus();
153 case SNAPSHOT_UNFREEZE
:
158 enable_nonboot_cpus();
163 case SNAPSHOT_ATOMIC_SNAPSHOT
:
164 if (data
->mode
!= O_RDONLY
|| !data
->frozen
|| data
->ready
) {
169 /* Free memory before shutting down devices. */
170 error
= swsusp_shrink_memory();
172 error
= device_suspend(PMSG_FREEZE
);
175 error
= swsusp_suspend();
181 error
= put_user(in_suspend
, (unsigned int __user
*)arg
);
186 case SNAPSHOT_ATOMIC_RESTORE
:
187 if (data
->mode
!= O_WRONLY
|| !data
->frozen
||
188 !snapshot_image_loaded(&data
->handle
)) {
193 pm_prepare_console();
194 error
= device_suspend(PMSG_FREEZE
);
196 error
= swsusp_resume();
199 pm_restore_console();
205 memset(&data
->handle
, 0, sizeof(struct snapshot_handle
));
209 case SNAPSHOT_SET_IMAGE_SIZE
:
213 case SNAPSHOT_AVAIL_SWAP
:
214 avail
= count_swap_pages(data
->swap
, 1);
215 avail
<<= PAGE_SHIFT
;
216 error
= put_user(avail
, (loff_t __user
*)arg
);
219 case SNAPSHOT_GET_SWAP_PAGE
:
220 if (data
->swap
< 0 || data
->swap
>= MAX_SWAPFILES
) {
225 data
->bitmap
= alloc_bitmap(count_swap_pages(data
->swap
, 0));
231 offset
= alloc_swap_page(data
->swap
, data
->bitmap
);
233 offset
<<= PAGE_SHIFT
;
234 error
= put_user(offset
, (loff_t __user
*)arg
);
240 case SNAPSHOT_FREE_SWAP_PAGES
:
241 if (data
->swap
< 0 || data
->swap
>= MAX_SWAPFILES
) {
245 free_all_swap_pages(data
->swap
, data
->bitmap
);
246 free_bitmap(data
->bitmap
);
250 case SNAPSHOT_SET_SWAP_FILE
:
253 * User space encodes device types as two-byte values,
254 * so we need to recode them
256 if (old_decode_dev(arg
)) {
257 data
->swap
= swap_type_of(old_decode_dev(arg
));
275 if (down_trylock(&pm_sem
)) {
280 if (pm_ops
->prepare
) {
281 error
= pm_ops
->prepare(PM_SUSPEND_MEM
);
286 /* Put devices to sleep */
287 error
= device_suspend(PMSG_SUSPEND
);
289 printk(KERN_ERR
"Failed to suspend some devices.\n");
291 /* Enter S3, system is already frozen */
292 suspend_enter(PM_SUSPEND_MEM
);
294 /* Wake up devices */
299 pm_ops
->finish(PM_SUSPEND_MEM
);
313 static struct file_operations snapshot_fops
= {
314 .open
= snapshot_open
,
315 .release
= snapshot_release
,
316 .read
= snapshot_read
,
317 .write
= snapshot_write
,
319 .ioctl
= snapshot_ioctl
,
322 static struct miscdevice snapshot_device
= {
323 .minor
= SNAPSHOT_MINOR
,
325 .fops
= &snapshot_fops
,
328 static int __init
snapshot_device_init(void)
330 return misc_register(&snapshot_device
);
333 device_initcall(snapshot_device_init
);