1 /* 2 * linux/kernel/power/user.c 3 * 4 * This file provides the user space interface for software suspend/resume. 5 * 6 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> 7 * 8 * This file is released under the GPLv2. 9 * 10 */ 11 12 #include <linux/suspend.h> 13 #include <linux/syscalls.h> 14 #include <linux/reboot.h> 15 #include <linux/string.h> 16 #include <linux/device.h> 17 #include <linux/miscdevice.h> 18 #include <linux/mm.h> 19 #include <linux/swap.h> 20 #include <linux/swapops.h> 21 #include <linux/pm.h> 22 #include <linux/fs.h> 23 #include <linux/console.h> 24 #include <linux/cpu.h> 25 #include <linux/freezer.h> 26 27 #include <asm/uaccess.h> 28 29 #include "power.h" 30 31 #define SNAPSHOT_MINOR 231 32 33 static struct snapshot_data { 34 struct snapshot_handle handle; 35 int swap; 36 int mode; 37 char frozen; 38 char ready; 39 char platform_suspend; 40 } snapshot_state; 41 42 atomic_t snapshot_device_available = ATOMIC_INIT(1); 43 44 static int snapshot_open(struct inode *inode, struct file *filp) 45 { 46 struct snapshot_data *data; 47 48 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) 49 return -EBUSY; 50 51 if ((filp->f_flags & O_ACCMODE) == O_RDWR) { 52 atomic_inc(&snapshot_device_available); 53 return -ENOSYS; 54 } 55 if(create_basic_memory_bitmaps()) { 56 atomic_inc(&snapshot_device_available); 57 return -ENOMEM; 58 } 59 nonseekable_open(inode, filp); 60 data = &snapshot_state; 61 filp->private_data = data; 62 memset(&data->handle, 0, sizeof(struct snapshot_handle)); 63 if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { 64 data->swap = swsusp_resume_device ? 65 swap_type_of(swsusp_resume_device, 0, NULL) : -1; 66 data->mode = O_RDONLY; 67 } else { 68 data->swap = -1; 69 data->mode = O_WRONLY; 70 } 71 data->frozen = 0; 72 data->ready = 0; 73 data->platform_suspend = 0; 74 75 return 0; 76 } 77 78 static int snapshot_release(struct inode *inode, struct file *filp) 79 { 80 struct snapshot_data *data; 81 82 swsusp_free(); 83 free_basic_memory_bitmaps(); 84 data = filp->private_data; 85 free_all_swap_pages(data->swap); 86 if (data->frozen) { 87 mutex_lock(&pm_mutex); 88 thaw_processes(); 89 mutex_unlock(&pm_mutex); 90 } 91 atomic_inc(&snapshot_device_available); 92 return 0; 93 } 94 95 static ssize_t snapshot_read(struct file *filp, char __user *buf, 96 size_t count, loff_t *offp) 97 { 98 struct snapshot_data *data; 99 ssize_t res; 100 101 data = filp->private_data; 102 res = snapshot_read_next(&data->handle, count); 103 if (res > 0) { 104 if (copy_to_user(buf, data_of(data->handle), res)) 105 res = -EFAULT; 106 else 107 *offp = data->handle.offset; 108 } 109 return res; 110 } 111 112 static ssize_t snapshot_write(struct file *filp, const char __user *buf, 113 size_t count, loff_t *offp) 114 { 115 struct snapshot_data *data; 116 ssize_t res; 117 118 data = filp->private_data; 119 res = snapshot_write_next(&data->handle, count); 120 if (res > 0) { 121 if (copy_from_user(data_of(data->handle), buf, res)) 122 res = -EFAULT; 123 else 124 *offp = data->handle.offset; 125 } 126 return res; 127 } 128 129 static inline int platform_prepare(void) 130 { 131 int error = 0; 132 133 if (hibernation_ops) 134 error = hibernation_ops->prepare(); 135 136 return error; 137 } 138 139 static inline void platform_finish(void) 140 { 141 if (hibernation_ops) 142 hibernation_ops->finish(); 143 } 144 145 static inline int snapshot_suspend(int platform_suspend) 146 { 147 int error; 148 149 mutex_lock(&pm_mutex); 150 /* Free memory before shutting down devices. */ 151 error = swsusp_shrink_memory(); 152 if (error) 153 goto Finish; 154 155 if (platform_suspend) { 156 error = platform_prepare(); 157 if (error) 158 goto Finish; 159 } 160 suspend_console(); 161 error = device_suspend(PMSG_FREEZE); 162 if (error) 163 goto Resume_devices; 164 165 error = disable_nonboot_cpus(); 166 if (!error) { 167 in_suspend = 1; 168 error = swsusp_suspend(); 169 } 170 enable_nonboot_cpus(); 171 Resume_devices: 172 if (platform_suspend) 173 platform_finish(); 174 175 device_resume(); 176 resume_console(); 177 Finish: 178 mutex_unlock(&pm_mutex); 179 return error; 180 } 181 182 static inline int snapshot_restore(int platform_suspend) 183 { 184 int error; 185 186 mutex_lock(&pm_mutex); 187 pm_prepare_console(); 188 if (platform_suspend) { 189 error = platform_prepare(); 190 if (error) 191 goto Finish; 192 } 193 suspend_console(); 194 error = device_suspend(PMSG_PRETHAW); 195 if (error) 196 goto Resume_devices; 197 198 error = disable_nonboot_cpus(); 199 if (!error) 200 error = swsusp_resume(); 201 202 enable_nonboot_cpus(); 203 Resume_devices: 204 if (platform_suspend) 205 platform_finish(); 206 207 device_resume(); 208 resume_console(); 209 Finish: 210 pm_restore_console(); 211 mutex_unlock(&pm_mutex); 212 return error; 213 } 214 215 static int snapshot_ioctl(struct inode *inode, struct file *filp, 216 unsigned int cmd, unsigned long arg) 217 { 218 int error = 0; 219 struct snapshot_data *data; 220 loff_t avail; 221 sector_t offset; 222 223 if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) 224 return -ENOTTY; 225 if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR) 226 return -ENOTTY; 227 if (!capable(CAP_SYS_ADMIN)) 228 return -EPERM; 229 230 data = filp->private_data; 231 232 switch (cmd) { 233 234 case SNAPSHOT_FREEZE: 235 if (data->frozen) 236 break; 237 mutex_lock(&pm_mutex); 238 if (freeze_processes()) { 239 thaw_processes(); 240 error = -EBUSY; 241 } 242 mutex_unlock(&pm_mutex); 243 if (!error) 244 data->frozen = 1; 245 break; 246 247 case SNAPSHOT_UNFREEZE: 248 if (!data->frozen) 249 break; 250 mutex_lock(&pm_mutex); 251 thaw_processes(); 252 mutex_unlock(&pm_mutex); 253 data->frozen = 0; 254 break; 255 256 case SNAPSHOT_ATOMIC_SNAPSHOT: 257 if (data->mode != O_RDONLY || !data->frozen || data->ready) { 258 error = -EPERM; 259 break; 260 } 261 error = snapshot_suspend(data->platform_suspend); 262 if (!error) 263 error = put_user(in_suspend, (unsigned int __user *)arg); 264 if (!error) 265 data->ready = 1; 266 break; 267 268 case SNAPSHOT_ATOMIC_RESTORE: 269 snapshot_write_finalize(&data->handle); 270 if (data->mode != O_WRONLY || !data->frozen || 271 !snapshot_image_loaded(&data->handle)) { 272 error = -EPERM; 273 break; 274 } 275 error = snapshot_restore(data->platform_suspend); 276 break; 277 278 case SNAPSHOT_FREE: 279 swsusp_free(); 280 memset(&data->handle, 0, sizeof(struct snapshot_handle)); 281 data->ready = 0; 282 break; 283 284 case SNAPSHOT_SET_IMAGE_SIZE: 285 image_size = arg; 286 break; 287 288 case SNAPSHOT_AVAIL_SWAP: 289 avail = count_swap_pages(data->swap, 1); 290 avail <<= PAGE_SHIFT; 291 error = put_user(avail, (loff_t __user *)arg); 292 break; 293 294 case SNAPSHOT_GET_SWAP_PAGE: 295 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { 296 error = -ENODEV; 297 break; 298 } 299 offset = alloc_swapdev_block(data->swap); 300 if (offset) { 301 offset <<= PAGE_SHIFT; 302 error = put_user(offset, (sector_t __user *)arg); 303 } else { 304 error = -ENOSPC; 305 } 306 break; 307 308 case SNAPSHOT_FREE_SWAP_PAGES: 309 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { 310 error = -ENODEV; 311 break; 312 } 313 free_all_swap_pages(data->swap); 314 break; 315 316 case SNAPSHOT_SET_SWAP_FILE: 317 if (!swsusp_swap_in_use()) { 318 /* 319 * User space encodes device types as two-byte values, 320 * so we need to recode them 321 */ 322 if (old_decode_dev(arg)) { 323 data->swap = swap_type_of(old_decode_dev(arg), 324 0, NULL); 325 if (data->swap < 0) 326 error = -ENODEV; 327 } else { 328 data->swap = -1; 329 error = -EINVAL; 330 } 331 } else { 332 error = -EPERM; 333 } 334 break; 335 336 case SNAPSHOT_S2RAM: 337 if (!pm_ops) { 338 error = -ENOSYS; 339 break; 340 } 341 342 if (!data->frozen) { 343 error = -EPERM; 344 break; 345 } 346 347 if (!mutex_trylock(&pm_mutex)) { 348 error = -EBUSY; 349 break; 350 } 351 352 if (pm_ops->prepare) { 353 error = pm_ops->prepare(PM_SUSPEND_MEM); 354 if (error) 355 goto OutS3; 356 } 357 358 /* Put devices to sleep */ 359 suspend_console(); 360 error = device_suspend(PMSG_SUSPEND); 361 if (error) { 362 printk(KERN_ERR "Failed to suspend some devices.\n"); 363 } else { 364 error = disable_nonboot_cpus(); 365 if (!error) { 366 /* Enter S3, system is already frozen */ 367 suspend_enter(PM_SUSPEND_MEM); 368 enable_nonboot_cpus(); 369 } 370 /* Wake up devices */ 371 device_resume(); 372 } 373 resume_console(); 374 if (pm_ops->finish) 375 pm_ops->finish(PM_SUSPEND_MEM); 376 377 OutS3: 378 mutex_unlock(&pm_mutex); 379 break; 380 381 case SNAPSHOT_PMOPS: 382 error = -EINVAL; 383 384 switch (arg) { 385 386 case PMOPS_PREPARE: 387 if (hibernation_ops) { 388 data->platform_suspend = 1; 389 error = 0; 390 } else { 391 error = -ENOSYS; 392 } 393 break; 394 395 case PMOPS_ENTER: 396 if (data->platform_suspend) { 397 kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); 398 error = hibernation_ops->enter(); 399 } 400 break; 401 402 case PMOPS_FINISH: 403 if (data->platform_suspend) 404 error = 0; 405 406 break; 407 408 default: 409 printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg); 410 411 } 412 break; 413 414 case SNAPSHOT_SET_SWAP_AREA: 415 if (swsusp_swap_in_use()) { 416 error = -EPERM; 417 } else { 418 struct resume_swap_area swap_area; 419 dev_t swdev; 420 421 error = copy_from_user(&swap_area, (void __user *)arg, 422 sizeof(struct resume_swap_area)); 423 if (error) { 424 error = -EFAULT; 425 break; 426 } 427 428 /* 429 * User space encodes device types as two-byte values, 430 * so we need to recode them 431 */ 432 swdev = old_decode_dev(swap_area.dev); 433 if (swdev) { 434 offset = swap_area.offset; 435 data->swap = swap_type_of(swdev, offset, NULL); 436 if (data->swap < 0) 437 error = -ENODEV; 438 } else { 439 data->swap = -1; 440 error = -EINVAL; 441 } 442 } 443 break; 444 445 default: 446 error = -ENOTTY; 447 448 } 449 450 return error; 451 } 452 453 static const struct file_operations snapshot_fops = { 454 .open = snapshot_open, 455 .release = snapshot_release, 456 .read = snapshot_read, 457 .write = snapshot_write, 458 .llseek = no_llseek, 459 .ioctl = snapshot_ioctl, 460 }; 461 462 static struct miscdevice snapshot_device = { 463 .minor = SNAPSHOT_MINOR, 464 .name = "snapshot", 465 .fops = &snapshot_fops, 466 }; 467 468 static int __init snapshot_device_init(void) 469 { 470 return misc_register(&snapshot_device); 471 }; 472 473 device_initcall(snapshot_device_init); 474