diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-02 14:29:57 +1100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-02 14:29:57 +1100 |
commit | 687fcdf741e4a268c2c7bac8b3734de761bb9719 (patch) | |
tree | 82603cd0f892b13d4252cc525ecaec99bb86c0cd /kernel/power/user.c | |
parent | 215e871aaa3d94540121a3809d80d0c5e5686e4f (diff) | |
parent | a6eb84bc1e069e1d285167e09035ed6c27978feb (diff) |
Merge branch 'suspend' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'suspend' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (38 commits)
suspend: cleanup reference to swsusp_pg_dir[]
PM: Remove obsolete /sys/devices/.../power/state docs
Hibernation: Invoke suspend notifications after console switch
Suspend: Invoke suspend notifications after console switch
Suspend: Clean up suspend_64.c
Suspend: Add config option to disable the freezer if architecture wants that
ACPI: Print message before calling _PTS
ACPI hibernation: Call _PTS before suspending devices
Hibernation: Introduce begin() and end() callbacks
ACPI suspend: Call _PTS before suspending devices
ACPI: Separate disabling of GPEs from _PTS
ACPI: Separate invocations of _GTS and _BFS from _PTS and _WAK
Suspend: Introduce begin() and end() callbacks
suspend: fix ia64 allmodconfig build
ACPI: clear GPE earily in resume to avoid warning
Suspend: Clean up Kconfig (V2)
Hibernation: Clean up Kconfig (V2)
Hibernation: Update messages
Suspend: Use common prefix in messages
Hibernation: Remove unnecessary variable declaration
...
Diffstat (limited to 'kernel/power/user.c')
-rw-r--r-- | kernel/power/user.c | 109 |
1 files changed, 80 insertions, 29 deletions
diff --git a/kernel/power/user.c b/kernel/power/user.c index 5bd321bcbb7..f5512cb3aa8 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -28,6 +28,29 @@ #include "power.h" +/* + * NOTE: The SNAPSHOT_SET_SWAP_FILE and SNAPSHOT_PMOPS ioctls are obsolete and + * will be removed in the future. They are only preserved here for + * compatibility with existing userland utilities. + */ +#define SNAPSHOT_SET_SWAP_FILE _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int) +#define SNAPSHOT_PMOPS _IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned int) + +#define PMOPS_PREPARE 1 +#define PMOPS_ENTER 2 +#define PMOPS_FINISH 3 + +/* + * NOTE: The following ioctl definitions are wrong and have been replaced with + * correct ones. They are only preserved here for compatibility with existing + * userland utilities and will be removed in the future. + */ +#define SNAPSHOT_ATOMIC_SNAPSHOT _IOW(SNAPSHOT_IOC_MAGIC, 3, void *) +#define SNAPSHOT_SET_IMAGE_SIZE _IOW(SNAPSHOT_IOC_MAGIC, 6, unsigned long) +#define SNAPSHOT_AVAIL_SWAP _IOR(SNAPSHOT_IOC_MAGIC, 7, void *) +#define SNAPSHOT_GET_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 8, void *) + + #define SNAPSHOT_MINOR 231 static struct snapshot_data { @@ -36,7 +59,7 @@ static struct snapshot_data { int mode; char frozen; char ready; - char platform_suspend; + char platform_support; } snapshot_state; atomic_t snapshot_device_available = ATOMIC_INIT(1); @@ -44,6 +67,7 @@ atomic_t snapshot_device_available = ATOMIC_INIT(1); static int snapshot_open(struct inode *inode, struct file *filp) { struct snapshot_data *data; + int error; if (!atomic_add_unless(&snapshot_device_available, -1, 0)) return -EBUSY; @@ -64,13 +88,23 @@ static int snapshot_open(struct inode *inode, struct file *filp) data->swap = swsusp_resume_device ? swap_type_of(swsusp_resume_device, 0, NULL) : -1; data->mode = O_RDONLY; + error = pm_notifier_call_chain(PM_RESTORE_PREPARE); + if (error) + pm_notifier_call_chain(PM_POST_RESTORE); } else { data->swap = -1; data->mode = O_WRONLY; + error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); + if (error) + pm_notifier_call_chain(PM_POST_HIBERNATION); + } + if (error) { + atomic_inc(&snapshot_device_available); + return error; } data->frozen = 0; data->ready = 0; - data->platform_suspend = 0; + data->platform_support = 0; return 0; } @@ -88,6 +122,8 @@ static int snapshot_release(struct inode *inode, struct file *filp) thaw_processes(); mutex_unlock(&pm_mutex); } + pm_notifier_call_chain(data->mode == O_WRONLY ? + PM_POST_HIBERNATION : PM_POST_RESTORE); atomic_inc(&snapshot_device_available); return 0; } @@ -133,7 +169,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, { int error = 0; struct snapshot_data *data; - loff_t avail; + loff_t size; sector_t offset; if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) @@ -151,18 +187,13 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, if (data->frozen) break; mutex_lock(&pm_mutex); - error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); - if (!error) { - printk("Syncing filesystems ... "); - sys_sync(); - printk("done.\n"); - - error = freeze_processes(); - if (error) - thaw_processes(); - } + printk("Syncing filesystems ... "); + sys_sync(); + printk("done.\n"); + + error = freeze_processes(); if (error) - pm_notifier_call_chain(PM_POST_HIBERNATION); + thaw_processes(); mutex_unlock(&pm_mutex); if (!error) data->frozen = 1; @@ -173,19 +204,19 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, break; mutex_lock(&pm_mutex); thaw_processes(); - pm_notifier_call_chain(PM_POST_HIBERNATION); mutex_unlock(&pm_mutex); data->frozen = 0; break; + case SNAPSHOT_CREATE_IMAGE: case SNAPSHOT_ATOMIC_SNAPSHOT: if (data->mode != O_RDONLY || !data->frozen || data->ready) { error = -EPERM; break; } - error = hibernation_snapshot(data->platform_suspend); + error = hibernation_snapshot(data->platform_support); if (!error) - error = put_user(in_suspend, (unsigned int __user *)arg); + error = put_user(in_suspend, (int __user *)arg); if (!error) data->ready = 1; break; @@ -197,7 +228,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, error = -EPERM; break; } - error = hibernation_restore(data->platform_suspend); + error = hibernation_restore(data->platform_support); break; case SNAPSHOT_FREE: @@ -206,16 +237,29 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, data->ready = 0; break; + case SNAPSHOT_PREF_IMAGE_SIZE: case SNAPSHOT_SET_IMAGE_SIZE: image_size = arg; break; + case SNAPSHOT_GET_IMAGE_SIZE: + if (!data->ready) { + error = -ENODATA; + break; + } + size = snapshot_get_image_size(); + size <<= PAGE_SHIFT; + error = put_user(size, (loff_t __user *)arg); + break; + + case SNAPSHOT_AVAIL_SWAP_SIZE: case SNAPSHOT_AVAIL_SWAP: - avail = count_swap_pages(data->swap, 1); - avail <<= PAGE_SHIFT; - error = put_user(avail, (loff_t __user *)arg); + size = count_swap_pages(data->swap, 1); + size <<= PAGE_SHIFT; + error = put_user(size, (loff_t __user *)arg); break; + case SNAPSHOT_ALLOC_SWAP_PAGE: case SNAPSHOT_GET_SWAP_PAGE: if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { error = -ENODEV; @@ -224,7 +268,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, offset = alloc_swapdev_block(data->swap); if (offset) { offset <<= PAGE_SHIFT; - error = put_user(offset, (sector_t __user *)arg); + error = put_user(offset, (loff_t __user *)arg); } else { error = -ENOSPC; } @@ -238,7 +282,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, free_all_swap_pages(data->swap); break; - case SNAPSHOT_SET_SWAP_FILE: + case SNAPSHOT_SET_SWAP_FILE: /* This ioctl is deprecated */ if (!swsusp_swap_in_use()) { /* * User space encodes device types as two-byte values, @@ -275,26 +319,33 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, mutex_unlock(&pm_mutex); break; - case SNAPSHOT_PMOPS: + case SNAPSHOT_PLATFORM_SUPPORT: + data->platform_support = !!arg; + break; + + case SNAPSHOT_POWER_OFF: + if (data->platform_support) + error = hibernation_platform_enter(); + break; + + case SNAPSHOT_PMOPS: /* This ioctl is deprecated */ error = -EINVAL; switch (arg) { case PMOPS_PREPARE: - data->platform_suspend = 1; + data->platform_support = 1; error = 0; break; case PMOPS_ENTER: - if (data->platform_suspend) + if (data->platform_support) error = hibernation_platform_enter(); - break; case PMOPS_FINISH: - if (data->platform_suspend) + if (data->platform_support) error = 0; - break; default: |