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>
22 #include <linux/cpu.h>
24 #include <asm/uaccess.h>
28 #define SNAPSHOT_MINOR 231
30 static struct snapshot_data
{
31 struct snapshot_handle handle
;
33 struct bitmap_page
*bitmap
;
39 static atomic_t device_available
= ATOMIC_INIT(1);
41 static int snapshot_open(struct inode
*inode
, struct file
*filp
)
43 struct snapshot_data
*data
;
45 if (!atomic_add_unless(&device_available
, -1, 0))
48 if ((filp
->f_flags
& O_ACCMODE
) == O_RDWR
)
51 nonseekable_open(inode
, filp
);
52 data
= &snapshot_state
;
53 filp
->private_data
= data
;
54 memset(&data
->handle
, 0, sizeof(struct snapshot_handle
));
55 if ((filp
->f_flags
& O_ACCMODE
) == O_RDONLY
) {
56 data
->swap
= swsusp_resume_device
? swap_type_of(swsusp_resume_device
) : -1;
57 data
->mode
= O_RDONLY
;
60 data
->mode
= O_WRONLY
;
69 static int snapshot_release(struct inode
*inode
, struct file
*filp
)
71 struct snapshot_data
*data
;
74 data
= filp
->private_data
;
75 free_all_swap_pages(data
->swap
, data
->bitmap
);
76 free_bitmap(data
->bitmap
);
80 enable_nonboot_cpus();
83 atomic_inc(&device_available
);
87 static ssize_t
snapshot_read(struct file
*filp
, char __user
*buf
,
88 size_t count
, loff_t
*offp
)
90 struct snapshot_data
*data
;
93 data
= filp
->private_data
;
94 res
= snapshot_read_next(&data
->handle
, count
);
96 if (copy_to_user(buf
, data_of(data
->handle
), res
))
99 *offp
= data
->handle
.offset
;
104 static ssize_t
snapshot_write(struct file
*filp
, const char __user
*buf
,
105 size_t count
, loff_t
*offp
)
107 struct snapshot_data
*data
;
110 data
= filp
->private_data
;
111 res
= snapshot_write_next(&data
->handle
, count
);
113 if (copy_from_user(data_of(data
->handle
), buf
, res
))
116 *offp
= data
->handle
.offset
;
121 static int snapshot_ioctl(struct inode
*inode
, struct file
*filp
,
122 unsigned int cmd
, unsigned long arg
)
125 struct snapshot_data
*data
;
126 loff_t offset
, avail
;
128 if (_IOC_TYPE(cmd
) != SNAPSHOT_IOC_MAGIC
)
130 if (_IOC_NR(cmd
) > SNAPSHOT_IOC_MAXNR
)
132 if (!capable(CAP_SYS_ADMIN
))
135 data
= filp
->private_data
;
139 case SNAPSHOT_FREEZE
:
143 error
= disable_nonboot_cpus();
145 error
= freeze_processes();
151 enable_nonboot_cpus();
157 case SNAPSHOT_UNFREEZE
:
162 enable_nonboot_cpus();
167 case SNAPSHOT_ATOMIC_SNAPSHOT
:
168 if (data
->mode
!= O_RDONLY
|| !data
->frozen
|| data
->ready
) {
173 /* Free memory before shutting down devices. */
174 error
= swsusp_shrink_memory();
176 error
= device_suspend(PMSG_FREEZE
);
179 error
= swsusp_suspend();
185 error
= put_user(in_suspend
, (unsigned int __user
*)arg
);
190 case SNAPSHOT_ATOMIC_RESTORE
:
191 if (data
->mode
!= O_WRONLY
|| !data
->frozen
||
192 !snapshot_image_loaded(&data
->handle
)) {
196 snapshot_free_unused_memory(&data
->handle
);
198 pm_prepare_console();
199 error
= device_suspend(PMSG_PRETHAW
);
201 error
= swsusp_resume();
204 pm_restore_console();
210 memset(&data
->handle
, 0, sizeof(struct snapshot_handle
));
214 case SNAPSHOT_SET_IMAGE_SIZE
:
218 case SNAPSHOT_AVAIL_SWAP
:
219 avail
= count_swap_pages(data
->swap
, 1);
220 avail
<<= PAGE_SHIFT
;
221 error
= put_user(avail
, (loff_t __user
*)arg
);
224 case SNAPSHOT_GET_SWAP_PAGE
:
225 if (data
->swap
< 0 || data
->swap
>= MAX_SWAPFILES
) {
230 data
->bitmap
= alloc_bitmap(count_swap_pages(data
->swap
, 0));
236 offset
= alloc_swap_page(data
->swap
, data
->bitmap
);
238 offset
<<= PAGE_SHIFT
;
239 error
= put_user(offset
, (loff_t __user
*)arg
);
245 case SNAPSHOT_FREE_SWAP_PAGES
:
246 if (data
->swap
< 0 || data
->swap
>= MAX_SWAPFILES
) {
250 free_all_swap_pages(data
->swap
, data
->bitmap
);
251 free_bitmap(data
->bitmap
);
255 case SNAPSHOT_SET_SWAP_FILE
:
258 * User space encodes device types as two-byte values,
259 * so we need to recode them
261 if (old_decode_dev(arg
)) {
262 data
->swap
= swap_type_of(old_decode_dev(arg
));
280 if (down_trylock(&pm_sem
)) {
285 if (pm_ops
->prepare
) {
286 error
= pm_ops
->prepare(PM_SUSPEND_MEM
);
291 /* Put devices to sleep */
292 error
= device_suspend(PMSG_SUSPEND
);
294 printk(KERN_ERR
"Failed to suspend some devices.\n");
296 /* Enter S3, system is already frozen */
297 suspend_enter(PM_SUSPEND_MEM
);
299 /* Wake up devices */
304 pm_ops
->finish(PM_SUSPEND_MEM
);
318 static struct file_operations snapshot_fops
= {
319 .open
= snapshot_open
,
320 .release
= snapshot_release
,
321 .read
= snapshot_read
,
322 .write
= snapshot_write
,
324 .ioctl
= snapshot_ioctl
,
327 static struct miscdevice snapshot_device
= {
328 .minor
= SNAPSHOT_MINOR
,
330 .fops
= &snapshot_fops
,
333 static int __init
snapshot_device_init(void)
335 return misc_register(&snapshot_device
);
338 device_initcall(snapshot_device_init
);