Merge tag 'sound-fix-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[linux-2.6-microblaze.git] / kernel / power / user.c
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/reboot.h>
14 #include <linux/string.h>
15 #include <linux/device.h>
16 #include <linux/miscdevice.h>
17 #include <linux/mm.h>
18 #include <linux/swap.h>
19 #include <linux/swapops.h>
20 #include <linux/pm.h>
21 #include <linux/fs.h>
22 #include <linux/compat.h>
23 #include <linux/console.h>
24 #include <linux/cpu.h>
25 #include <linux/freezer.h>
26
27 #include <linux/uaccess.h>
28
29 #include "power.h"
30
31
32 #define SNAPSHOT_MINOR  231
33
34 static struct snapshot_data {
35         struct snapshot_handle handle;
36         int swap;
37         int mode;
38         bool frozen;
39         bool ready;
40         bool platform_support;
41         bool free_bitmaps;
42 } snapshot_state;
43
44 atomic_t snapshot_device_available = ATOMIC_INIT(1);
45
46 static int snapshot_open(struct inode *inode, struct file *filp)
47 {
48         struct snapshot_data *data;
49         int error, nr_calls = 0;
50
51         if (!hibernation_available())
52                 return -EPERM;
53
54         lock_system_sleep();
55
56         if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
57                 error = -EBUSY;
58                 goto Unlock;
59         }
60
61         if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
62                 atomic_inc(&snapshot_device_available);
63                 error = -ENOSYS;
64                 goto Unlock;
65         }
66         nonseekable_open(inode, filp);
67         data = &snapshot_state;
68         filp->private_data = data;
69         memset(&data->handle, 0, sizeof(struct snapshot_handle));
70         if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
71                 /* Hibernating.  The image device should be accessible. */
72                 data->swap = swsusp_resume_device ?
73                         swap_type_of(swsusp_resume_device, 0, NULL) : -1;
74                 data->mode = O_RDONLY;
75                 data->free_bitmaps = false;
76                 error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
77                 if (error)
78                         __pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL);
79         } else {
80                 /*
81                  * Resuming.  We may need to wait for the image device to
82                  * appear.
83                  */
84                 wait_for_device_probe();
85
86                 data->swap = -1;
87                 data->mode = O_WRONLY;
88                 error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
89                 if (!error) {
90                         error = create_basic_memory_bitmaps();
91                         data->free_bitmaps = !error;
92                 } else
93                         nr_calls--;
94
95                 if (error)
96                         __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
97         }
98         if (error)
99                 atomic_inc(&snapshot_device_available);
100
101         data->frozen = false;
102         data->ready = false;
103         data->platform_support = false;
104
105  Unlock:
106         unlock_system_sleep();
107
108         return error;
109 }
110
111 static int snapshot_release(struct inode *inode, struct file *filp)
112 {
113         struct snapshot_data *data;
114
115         lock_system_sleep();
116
117         swsusp_free();
118         data = filp->private_data;
119         free_all_swap_pages(data->swap);
120         if (data->frozen) {
121                 pm_restore_gfp_mask();
122                 free_basic_memory_bitmaps();
123                 thaw_processes();
124         } else if (data->free_bitmaps) {
125                 free_basic_memory_bitmaps();
126         }
127         pm_notifier_call_chain(data->mode == O_RDONLY ?
128                         PM_POST_HIBERNATION : PM_POST_RESTORE);
129         atomic_inc(&snapshot_device_available);
130
131         unlock_system_sleep();
132
133         return 0;
134 }
135
136 static ssize_t snapshot_read(struct file *filp, char __user *buf,
137                              size_t count, loff_t *offp)
138 {
139         struct snapshot_data *data;
140         ssize_t res;
141         loff_t pg_offp = *offp & ~PAGE_MASK;
142
143         lock_system_sleep();
144
145         data = filp->private_data;
146         if (!data->ready) {
147                 res = -ENODATA;
148                 goto Unlock;
149         }
150         if (!pg_offp) { /* on page boundary? */
151                 res = snapshot_read_next(&data->handle);
152                 if (res <= 0)
153                         goto Unlock;
154         } else {
155                 res = PAGE_SIZE - pg_offp;
156         }
157
158         res = simple_read_from_buffer(buf, count, &pg_offp,
159                         data_of(data->handle), res);
160         if (res > 0)
161                 *offp += res;
162
163  Unlock:
164         unlock_system_sleep();
165
166         return res;
167 }
168
169 static ssize_t snapshot_write(struct file *filp, const char __user *buf,
170                               size_t count, loff_t *offp)
171 {
172         struct snapshot_data *data;
173         ssize_t res;
174         loff_t pg_offp = *offp & ~PAGE_MASK;
175
176         lock_system_sleep();
177
178         data = filp->private_data;
179
180         if (!pg_offp) {
181                 res = snapshot_write_next(&data->handle);
182                 if (res <= 0)
183                         goto unlock;
184         } else {
185                 res = PAGE_SIZE - pg_offp;
186         }
187
188         if (!data_of(data->handle)) {
189                 res = -EINVAL;
190                 goto unlock;
191         }
192
193         res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
194                         buf, count);
195         if (res > 0)
196                 *offp += res;
197 unlock:
198         unlock_system_sleep();
199
200         return res;
201 }
202
203 static long snapshot_ioctl(struct file *filp, unsigned int cmd,
204                                                         unsigned long arg)
205 {
206         int error = 0;
207         struct snapshot_data *data;
208         loff_t size;
209         sector_t offset;
210
211         if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
212                 return -ENOTTY;
213         if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR)
214                 return -ENOTTY;
215         if (!capable(CAP_SYS_ADMIN))
216                 return -EPERM;
217
218         if (!mutex_trylock(&system_transition_mutex))
219                 return -EBUSY;
220
221         lock_device_hotplug();
222         data = filp->private_data;
223
224         switch (cmd) {
225
226         case SNAPSHOT_FREEZE:
227                 if (data->frozen)
228                         break;
229
230                 ksys_sync_helper();
231
232                 error = freeze_processes();
233                 if (error)
234                         break;
235
236                 error = create_basic_memory_bitmaps();
237                 if (error)
238                         thaw_processes();
239                 else
240                         data->frozen = true;
241
242                 break;
243
244         case SNAPSHOT_UNFREEZE:
245                 if (!data->frozen || data->ready)
246                         break;
247                 pm_restore_gfp_mask();
248                 free_basic_memory_bitmaps();
249                 data->free_bitmaps = false;
250                 thaw_processes();
251                 data->frozen = false;
252                 break;
253
254         case SNAPSHOT_CREATE_IMAGE:
255                 if (data->mode != O_RDONLY || !data->frozen  || data->ready) {
256                         error = -EPERM;
257                         break;
258                 }
259                 pm_restore_gfp_mask();
260                 error = hibernation_snapshot(data->platform_support);
261                 if (!error) {
262                         error = put_user(in_suspend, (int __user *)arg);
263                         data->ready = !freezer_test_done && !error;
264                         freezer_test_done = false;
265                 }
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 = hibernation_restore(data->platform_support);
276                 break;
277
278         case SNAPSHOT_FREE:
279                 swsusp_free();
280                 memset(&data->handle, 0, sizeof(struct snapshot_handle));
281                 data->ready = false;
282                 /*
283                  * It is necessary to thaw kernel threads here, because
284                  * SNAPSHOT_CREATE_IMAGE may be invoked directly after
285                  * SNAPSHOT_FREE.  In that case, if kernel threads were not
286                  * thawed, the preallocation of memory carried out by
287                  * hibernation_snapshot() might run into problems (i.e. it
288                  * might fail or even deadlock).
289                  */
290                 thaw_kernel_threads();
291                 break;
292
293         case SNAPSHOT_PREF_IMAGE_SIZE:
294                 image_size = arg;
295                 break;
296
297         case SNAPSHOT_GET_IMAGE_SIZE:
298                 if (!data->ready) {
299                         error = -ENODATA;
300                         break;
301                 }
302                 size = snapshot_get_image_size();
303                 size <<= PAGE_SHIFT;
304                 error = put_user(size, (loff_t __user *)arg);
305                 break;
306
307         case SNAPSHOT_AVAIL_SWAP_SIZE:
308                 size = count_swap_pages(data->swap, 1);
309                 size <<= PAGE_SHIFT;
310                 error = put_user(size, (loff_t __user *)arg);
311                 break;
312
313         case SNAPSHOT_ALLOC_SWAP_PAGE:
314                 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
315                         error = -ENODEV;
316                         break;
317                 }
318                 offset = alloc_swapdev_block(data->swap);
319                 if (offset) {
320                         offset <<= PAGE_SHIFT;
321                         error = put_user(offset, (loff_t __user *)arg);
322                 } else {
323                         error = -ENOSPC;
324                 }
325                 break;
326
327         case SNAPSHOT_FREE_SWAP_PAGES:
328                 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
329                         error = -ENODEV;
330                         break;
331                 }
332                 free_all_swap_pages(data->swap);
333                 break;
334
335         case SNAPSHOT_S2RAM:
336                 if (!data->frozen) {
337                         error = -EPERM;
338                         break;
339                 }
340                 /*
341                  * Tasks are frozen and the notifiers have been called with
342                  * PM_HIBERNATION_PREPARE
343                  */
344                 error = suspend_devices_and_enter(PM_SUSPEND_MEM);
345                 data->ready = false;
346                 break;
347
348         case SNAPSHOT_PLATFORM_SUPPORT:
349                 data->platform_support = !!arg;
350                 break;
351
352         case SNAPSHOT_POWER_OFF:
353                 if (data->platform_support)
354                         error = hibernation_platform_enter();
355                 break;
356
357         case SNAPSHOT_SET_SWAP_AREA:
358                 if (swsusp_swap_in_use()) {
359                         error = -EPERM;
360                 } else {
361                         struct resume_swap_area swap_area;
362                         dev_t swdev;
363
364                         error = copy_from_user(&swap_area, (void __user *)arg,
365                                         sizeof(struct resume_swap_area));
366                         if (error) {
367                                 error = -EFAULT;
368                                 break;
369                         }
370
371                         /*
372                          * User space encodes device types as two-byte values,
373                          * so we need to recode them
374                          */
375                         swdev = new_decode_dev(swap_area.dev);
376                         if (swdev) {
377                                 offset = swap_area.offset;
378                                 data->swap = swap_type_of(swdev, offset, NULL);
379                                 if (data->swap < 0)
380                                         error = -ENODEV;
381                         } else {
382                                 data->swap = -1;
383                                 error = -EINVAL;
384                         }
385                 }
386                 break;
387
388         default:
389                 error = -ENOTTY;
390
391         }
392
393         unlock_device_hotplug();
394         mutex_unlock(&system_transition_mutex);
395
396         return error;
397 }
398
399 #ifdef CONFIG_COMPAT
400
401 struct compat_resume_swap_area {
402         compat_loff_t offset;
403         u32 dev;
404 } __packed;
405
406 static long
407 snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
408 {
409         BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));
410
411         switch (cmd) {
412         case SNAPSHOT_GET_IMAGE_SIZE:
413         case SNAPSHOT_AVAIL_SWAP_SIZE:
414         case SNAPSHOT_ALLOC_SWAP_PAGE: {
415                 compat_loff_t __user *uoffset = compat_ptr(arg);
416                 loff_t offset;
417                 mm_segment_t old_fs;
418                 int err;
419
420                 old_fs = get_fs();
421                 set_fs(KERNEL_DS);
422                 err = snapshot_ioctl(file, cmd, (unsigned long) &offset);
423                 set_fs(old_fs);
424                 if (!err && put_user(offset, uoffset))
425                         err = -EFAULT;
426                 return err;
427         }
428
429         case SNAPSHOT_CREATE_IMAGE:
430                 return snapshot_ioctl(file, cmd,
431                                       (unsigned long) compat_ptr(arg));
432
433         case SNAPSHOT_SET_SWAP_AREA: {
434                 struct compat_resume_swap_area __user *u_swap_area =
435                         compat_ptr(arg);
436                 struct resume_swap_area swap_area;
437                 mm_segment_t old_fs;
438                 int err;
439
440                 err = get_user(swap_area.offset, &u_swap_area->offset);
441                 err |= get_user(swap_area.dev, &u_swap_area->dev);
442                 if (err)
443                         return -EFAULT;
444                 old_fs = get_fs();
445                 set_fs(KERNEL_DS);
446                 err = snapshot_ioctl(file, SNAPSHOT_SET_SWAP_AREA,
447                                      (unsigned long) &swap_area);
448                 set_fs(old_fs);
449                 return err;
450         }
451
452         default:
453                 return snapshot_ioctl(file, cmd, arg);
454         }
455 }
456
457 #endif /* CONFIG_COMPAT */
458
459 static const struct file_operations snapshot_fops = {
460         .open = snapshot_open,
461         .release = snapshot_release,
462         .read = snapshot_read,
463         .write = snapshot_write,
464         .llseek = no_llseek,
465         .unlocked_ioctl = snapshot_ioctl,
466 #ifdef CONFIG_COMPAT
467         .compat_ioctl = snapshot_compat_ioctl,
468 #endif
469 };
470
471 static struct miscdevice snapshot_device = {
472         .minor = SNAPSHOT_MINOR,
473         .name = "snapshot",
474         .fops = &snapshot_fops,
475 };
476
477 static int __init snapshot_device_init(void)
478 {
479         return misc_register(&snapshot_device);
480 };
481
482 device_initcall(snapshot_device_init);