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