From 2a9df4945106d62ed9249a44d666fab93c685f7a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 16 Feb 2007 01:38:30 -0800 Subject: power management: fix struct layout and docs Because the pm ops in powermac are obviously not using them as intended, I added documentation for it in kernel-doc format. Reordering the fields in struct pm_ops not only makes the output of kernel-doc make more sense but also removes a hole from the structure on 64-bit platforms. Signed-off-by: Johannes Berg Cc: "Randy.Dunlap" Cc: Rafael J. Wysocki Cc: Pavel Macheck Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pm.h | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'include/linux/pm.h') diff --git a/include/linux/pm.h b/include/linux/pm.h index 070394e846d0..21db05ac7c0b 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -120,15 +120,48 @@ typedef int __bitwise suspend_disk_method_t; #define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6) #define PM_DISK_MAX ((__force suspend_disk_method_t) 7) +/** + * struct pm_ops - Callbacks for managing platform dependent suspend states. + * @valid: Callback to determine whether the given state can be entered. + * If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is + * always valid and never passed to this call. + * If not assigned, all suspend states are advertised as valid + * in /sys/power/state (but can still be rejected by prepare or enter.) + * + * @prepare: Prepare the platform for the given suspend state. Can return a + * negative error code if necessary. + * + * @enter: Enter the given suspend state, must be assigned. Can return a + * negative error code if necessary. + * + * @finish: Called when the system has left the given state and all devices + * are resumed. The return value is ignored. + * + * @pm_disk_mode: Set to the disk method that the user should be able to + * configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN, + * %PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC + * are always allowed, currently only %PM_DISK_PLATFORM + * makes sense. If the user then choses %PM_DISK_PLATFORM, + * the @prepare call will be called before suspending to disk + * (if present), the @enter call should be present and will + * be called after all state has been saved and the machine + * is ready to be shut down/suspended/..., and the @finish + * callback is called after state has been restored. All + * these calls are called with %PM_SUSPEND_DISK as the state. + */ struct pm_ops { - suspend_disk_method_t pm_disk_mode; int (*valid)(suspend_state_t state); int (*prepare)(suspend_state_t state); int (*enter)(suspend_state_t state); int (*finish)(suspend_state_t state); + suspend_disk_method_t pm_disk_mode; }; -extern void pm_set_ops(struct pm_ops *); +/** + * pm_set_ops - set platform dependent power management ops + * @pm_ops: The new power management operations to set. + */ +extern void pm_set_ops(struct pm_ops *pm_ops); extern struct pm_ops *pm_ops; extern int pm_suspend(suspend_state_t state); -- cgit From 075c1771526c85849ed22298d048bc07e400aee5 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 26 Apr 2007 00:12:06 -0700 Subject: define platform wakeup hook, use in pci_enable_wake() This defines a platform hook to enable/disable a device as a wakeup event source. It's initially for use with ACPI, but more generally it could be used whenever enable_irq_wake()/disable_irq_wake() don't suffice. The hook is called -- if available -- inside pci_enable_wake(); and the semantics of that call are enhanced so that support for PCI PME# is no longer needed. It can now work for devices with "legacy PCI PM", when platform support allows it. (That support would use some board-specific signal for for the same purpose as PME#.) [akpm@linux-foundation.org: Make it compile with CONFIG_PM=n] Signed-off-by: David Brownell Signed-off-by: Zhang Rui Cc: Len Brown Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 3 +++ drivers/pci/pci.c | 58 +++++++++++++++++++++++++++++++++-------------- include/linux/pm.h | 19 ++++++++++++++++ 3 files changed, 63 insertions(+), 17 deletions(-) (limited to 'include/linux/pm.h') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index bbbb973a9d3c..05dc8764e765 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -29,6 +29,9 @@ LIST_HEAD(dpm_off_irq); DECLARE_MUTEX(dpm_sem); DECLARE_MUTEX(dpm_list_sem); +int (*platform_enable_wakeup)(struct device *dev, int is_on); + + /** * device_pm_set_parent - Specify power dependency. * @dev: Device who needs power. diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d3eab057b2d3..2a458279327a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -891,31 +892,48 @@ pci_disable_device(struct pci_dev *dev) } /** - * pci_enable_wake - enable device to generate PME# when suspended - * @dev: - PCI device to operate on - * @state: - Current state of device. - * @enable: - Flag to enable or disable generation - * - * Set the bits in the device's PM Capabilities to generate PME# when - * the system is suspended. + * pci_enable_wake - enable PCI device as wakeup event source + * @dev: PCI device affected + * @state: PCI state from which device will issue wakeup events + * @enable: True to enable event generation; false to disable * - * -EIO is returned if device doesn't have PM Capabilities. - * -EINVAL is returned if device supports it, but can't generate wake events. - * 0 if operation is successful. - * + * This enables the device as a wakeup event source, or disables it. + * When such events involves platform-specific hooks, those hooks are + * called automatically by this routine. + * + * Devices with legacy power management (no standard PCI PM capabilities) + * always require such platform hooks. Depending on the platform, devices + * supporting the standard PCI PME# signal may require such platform hooks; + * they always update bits in config space to allow PME# generation. + * + * -EIO is returned if the device can't ever be a wakeup event source. + * -EINVAL is returned if the device can't generate wakeup events from + * the specified PCI state. Returns zero if the operation is successful. */ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { int pm; + int status; u16 value; + /* Note that drivers should verify device_may_wakeup(&dev->dev) + * before calling this function. Platform code should report + * errors when drivers try to enable wakeup on devices that + * can't issue wakeups, or on which wakeups were disabled by + * userspace updating the /sys/devices.../power/wakeup file. + */ + + status = call_platform_enable_wakeup(&dev->dev, enable); + /* find PCI PM capability in list */ pm = pci_find_capability(dev, PCI_CAP_ID_PM); - /* If device doesn't support PM Capabilities, but request is to disable - * wake events, it's a nop; otherwise fail */ - if (!pm) - return enable ? -EIO : 0; + /* If device doesn't support PM Capabilities, but caller wants to + * disable wake events, it's a NOP. Otherwise fail unless the + * platform hooks handled this legacy device already. + */ + if (!pm) + return enable ? status : 0; /* Check device's ability to generate PME# */ pci_read_config_word(dev,pm+PCI_PM_PMC,&value); @@ -924,8 +942,14 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */ /* Check if it can generate PME# from requested state. */ - if (!value || !(value & (1 << state))) + if (!value || !(value & (1 << state))) { + /* if it can't, revert what the platform hook changed, + * always reporting the base "EINVAL, can't PME#" error + */ + if (enable) + call_platform_enable_wakeup(&dev->dev, 0); return enable ? -EINVAL : 0; + } pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); @@ -936,7 +960,7 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) value &= ~PCI_PM_CTRL_PME_ENABLE; pci_write_config_word(dev, pm + PCI_PM_CTRL, value); - + return 0; } diff --git a/include/linux/pm.h b/include/linux/pm.h index 21db05ac7c0b..b0ab623adbf5 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -273,6 +273,20 @@ extern void __suspend_report_result(const char *function, void *fn, int ret); __suspend_report_result(__FUNCTION__, fn, ret); \ } while (0) +/* + * Platform hook to activate device wakeup capability, if that's not already + * handled by enable_irq_wake() etc. + * Returns zero on success, else negative errno + */ +extern int (*platform_enable_wakeup)(struct device *dev, int is_on); + +static inline int call_platform_enable_wakeup(struct device *dev, int is_on) +{ + if (platform_enable_wakeup) + return (*platform_enable_wakeup)(dev, is_on); + return 0; +} + #else /* !CONFIG_PM */ static inline int device_suspend(pm_message_t state) @@ -294,6 +308,11 @@ static inline void dpm_runtime_resume(struct device * dev) #define suspend_report_result(fn, ret) do { } while (0) +static inline int call_platform_enable_wakeup(struct device *dev, int is_on) +{ + return -EIO; +} + #endif /* changes to device_may_wakeup take effect on the next pm state change. -- cgit From a53c46dc8253cc613ad66a2ca7aad6de8b7e61b9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 26 Apr 2007 11:43:58 +0200 Subject: s2ram: add arch irq disable/enable hooks After some more discussion this patch replaces it: From: Johannes Berg Subject: suspend: add arch irq disable/enable hooks For powermac, we need to do some things between suspending devices and device_power_off, for example setting the decrementer. This patch allows architectures to define arch_s2ram_{en,dis}able_irqs in their asm/suspend.h to have control over this step. Signed-off-by: Johannes Berg Acked-by: Pavel Machek Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pm.h | 18 ++++++++++++++++++ kernel/power/main.c | 18 +++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'include/linux/pm.h') diff --git a/include/linux/pm.h b/include/linux/pm.h index b0ab623adbf5..9bd86db4d395 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -166,6 +166,24 @@ extern struct pm_ops *pm_ops; extern int pm_suspend(suspend_state_t state); +/** + * arch_suspend_disable_irqs - disable IRQs for suspend + * + * Disables IRQs (in the default case). This is a weak symbol in the common + * code and thus allows architectures to override it if more needs to be + * done. Not called for suspend to disk. + */ +extern void arch_suspend_disable_irqs(void); + +/** + * arch_suspend_enable_irqs - enable IRQs after suspend + * + * Enables IRQs (in the default case). This is a weak symbol in the common + * code and thus allows architectures to override it if more needs to be + * done. Not called for suspend to disk. + */ +extern void arch_suspend_enable_irqs(void); + /* * Device power management */ diff --git a/kernel/power/main.c b/kernel/power/main.c index a064dfd8877a..3062e940d1fa 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -111,13 +111,24 @@ static int suspend_prepare(suspend_state_t state) return error; } +/* default implementation */ +void __attribute__ ((weak)) arch_suspend_disable_irqs(void) +{ + local_irq_disable(); +} + +/* default implementation */ +void __attribute__ ((weak)) arch_suspend_enable_irqs(void) +{ + local_irq_enable(); +} int suspend_enter(suspend_state_t state) { int error = 0; - unsigned long flags; - local_irq_save(flags); + arch_suspend_disable_irqs(); + BUG_ON(!irqs_disabled()); if ((error = device_power_down(PMSG_SUSPEND))) { printk(KERN_ERR "Some devices failed to power down\n"); @@ -126,7 +137,8 @@ int suspend_enter(suspend_state_t state) error = pm_ops->enter(state); device_power_up(); Done: - local_irq_restore(flags); + arch_suspend_enable_irqs(); + BUG_ON(irqs_disabled()); return error; } -- cgit From fe0c935a6cbf25d72a27c7a345df8a2151de0b74 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Apr 2007 15:09:51 -0700 Subject: rework pm_ops pm_disk_mode, kill misuse This patch series cleans up some misconceptions about pm_ops. Some users of the pm_ops structure attempt to use it to stop the user from entering suspend to disk, this, however, is not possible since the user can always use "shutdown" in /sys/power/disk and then the pm_ops are never invoked. Also, platforms that don't support suspend to disk simply should not allow configuring SOFTWARE_SUSPEND (read the help text on it, it only selects suspend to disk and nothing else, all the other stuff depends on PM). The pm_ops structure is actually intended to provide a way to enter platform-defined sleep states (currently supported states are "standby" and "mem" (suspend to ram)) and additionally (if SOFTWARE_SUSPEND is configured) allows a platform to support a platform specific way to enter low-power mode once everything has been saved to disk. This is currently only used by ACPI (S4). This patch: The pm_ops.pm_disk_mode is used in totally bogus ways since nobody really seems to understand what it actually does. This patch clarifies the pm_disk_mode description. It also removes all the arm and sh users that think they can veto suspend to disk via pm_ops; not so since the user can always do echo shutdown > /sys/power/disk, they need to find a better way involving Kconfig or such. ACPI is the only user left with a non-zero pm_disk_mode. The patch also sets the default mode to shutdown again, but when a new pm_ops is registered its pm_disk_mode is selected as default, that way the default stays for ACPI where it is apparently required. Signed-off-by: Johannes Berg Cc: David Brownell Acked-by: Pavel Machek Cc: Cc: Len Brown Acked-by: Russell King Cc: Greg KH Cc: "Rafael J. Wysocki" Acked-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/common/sharpsl_pm.c | 1 - arch/arm/mach-at91/pm.c | 1 - arch/arm/mach-omap1/pm.c | 1 - arch/arm/mach-omap2/pm.c | 1 - arch/arm/mach-pxa/pm.c | 4 --- arch/arm/mach-sa1100/pm.c | 7 ------ arch/arm/plat-s3c24xx/pm.c | 9 ------- arch/sh/boards/hp6xx/pm.c | 7 ------ include/linux/pm.h | 23 +++++++++-------- kernel/power/disk.c | 60 ++++++++++++++++++++++++++++---------------- kernel/power/main.c | 6 ++++- 11 files changed, 56 insertions(+), 64 deletions(-) (limited to 'include/linux/pm.h') diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index a9bc5b52218f..4cb895d4ae5b 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -766,7 +766,6 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info) } static struct pm_ops sharpsl_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .prepare = pxa_pm_prepare, .enter = corgi_pxa_pm_enter, .finish = pxa_pm_finish, diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index b49bfda53d7f..ff8db29e989e 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -201,7 +201,6 @@ error: static struct pm_ops at91_pm_ops ={ - .pm_disk_mode = 0, .valid = at91_pm_valid_state, .prepare = at91_pm_prepare, .enter = at91_pm_enter, diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index 49efe903dacd..4248117e5e3f 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -698,7 +698,6 @@ static struct irqaction omap_wakeup_irq = { static struct pm_ops omap_pm_ops ={ - .pm_disk_mode = 0, .prepare = omap_pm_prepare, .enter = omap_pm_enter, .finish = omap_pm_finish, diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index d7eee99b7e3f..3e9a128feea1 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -370,7 +370,6 @@ static int omap2_pm_finish(suspend_state_t state) } static struct pm_ops omap_pm_ops = { - .pm_disk_mode = 0, .prepare = omap2_pm_prepare, .enter = omap2_pm_enter, .finish = omap2_pm_finish, diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index b4d8276d6050..0a99ef43b36f 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -223,11 +223,7 @@ int pxa_pm_finish(suspend_state_t state) EXPORT_SYMBOL_GPL(pxa_pm_finish); -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops pxa_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .prepare = pxa_pm_prepare, .enter = pxa_pm_enter, .finish = pxa_pm_finish, diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 786c8534231f..b0837113b2aa 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -59,9 +59,6 @@ static int sa11x0_pm_enter(suspend_state_t state) unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE]; struct timespec delta, rtc; - if (state != PM_SUSPEND_MEM) - return -EINVAL; - /* preserve current time */ rtc.tv_sec = RCNR; rtc.tv_nsec = 0; @@ -134,11 +131,7 @@ unsigned long sleep_phys_sp(void *sp) return virt_to_phys(sp); } -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops sa11x0_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .enter = sa11x0_pm_enter, }; diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index ecf68d611904..d6af3082af30 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c @@ -511,11 +511,6 @@ static int s3c2410_pm_enter(suspend_state_t state) return -EINVAL; } - if (state != PM_SUSPEND_MEM) { - printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n"); - return -EINVAL; - } - /* check if we have anything to wake-up with... bad things seem * to happen if you suspend with no wakeup (system will often * require a full power-cycle) @@ -633,11 +628,7 @@ static int s3c2410_pm_finish(suspend_state_t state) return 0; } -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops s3c2410_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .prepare = s3c2410_pm_prepare, .enter = s3c2410_pm_enter, .finish = s3c2410_pm_finish, diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c index d1947732fb3e..4b2f29a4bde9 100644 --- a/arch/sh/boards/hp6xx/pm.c +++ b/arch/sh/boards/hp6xx/pm.c @@ -27,9 +27,6 @@ static int hp6x0_pm_enter(suspend_state_t state) u16 hd64461_stbcr; #endif - if (state != PM_SUSPEND_MEM) - return -EINVAL; - #ifdef CONFIG_HD64461_ENABLER outb(0, HD64461_PCC1CSCIER); @@ -70,11 +67,7 @@ static int hp6x0_pm_enter(suspend_state_t state) return 0; } -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops hp6x0_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .enter = hp6x0_pm_enter, }; diff --git a/include/linux/pm.h b/include/linux/pm.h index 9bd86db4d395..dfced9188bdc 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -112,6 +112,8 @@ typedef int __bitwise suspend_state_t; typedef int __bitwise suspend_disk_method_t; +/* invalid must be 0 so struct pm_ops initialisers can leave it out */ +#define PM_DISK_INVALID ((__force suspend_disk_method_t) 0) #define PM_DISK_FIRMWARE ((__force suspend_disk_method_t) 1) #define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 2) #define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 3) @@ -137,17 +139,16 @@ typedef int __bitwise suspend_disk_method_t; * @finish: Called when the system has left the given state and all devices * are resumed. The return value is ignored. * - * @pm_disk_mode: Set to the disk method that the user should be able to - * configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN, - * %PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC - * are always allowed, currently only %PM_DISK_PLATFORM - * makes sense. If the user then choses %PM_DISK_PLATFORM, - * the @prepare call will be called before suspending to disk - * (if present), the @enter call should be present and will - * be called after all state has been saved and the machine - * is ready to be shut down/suspended/..., and the @finish - * callback is called after state has been restored. All - * these calls are called with %PM_SUSPEND_DISK as the state. + * @pm_disk_mode: The generic code always allows one of the shutdown methods + * %PM_DISK_SHUTDOWN, %PM_DISK_REBOOT, %PM_DISK_TEST and + * %PM_DISK_TESTPROC. If this variable is set, the mode it is set + * to is allowed in addition to those modes and is also made default. + * When this mode is sent selected, the @prepare call will be called + * before suspending to disk (if present), the @enter call should be + * present and will be called after all state has been saved and the + * machine is ready to be powered off; the @finish callback is called + * after state has been restored. All these calls are called with + * %PM_SUSPEND_DISK as the state. */ struct pm_ops { int (*valid)(suspend_state_t state); diff --git a/kernel/power/disk.c b/kernel/power/disk.c index aec19b063e3f..4de2f69fe095 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -39,7 +39,13 @@ static inline int platform_prepare(void) { int error = 0; - if (pm_disk_mode == PM_DISK_PLATFORM) { + switch (pm_disk_mode) { + case PM_DISK_TEST: + case PM_DISK_TESTPROC: + case PM_DISK_SHUTDOWN: + case PM_DISK_REBOOT: + break; + default: if (pm_ops && pm_ops->prepare) error = pm_ops->prepare(PM_SUSPEND_DISK); } @@ -48,40 +54,48 @@ static inline int platform_prepare(void) /** * power_down - Shut machine down for hibernate. - * @mode: Suspend-to-disk mode * - * Use the platform driver, if configured so, and return gracefully if it - * fails. - * Otherwise, try to power off and reboot. If they fail, halt the machine, - * there ain't no turning back. + * Use the platform driver, if configured so; otherwise try + * to power off or reboot. */ -static void power_down(suspend_disk_method_t mode) +static void power_down(void) { - switch(mode) { - case PM_DISK_PLATFORM: - if (pm_ops && pm_ops->enter) { - kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); - pm_ops->enter(PM_SUSPEND_DISK); - break; - } + switch (pm_disk_mode) { + case PM_DISK_TEST: + case PM_DISK_TESTPROC: + break; case PM_DISK_SHUTDOWN: kernel_power_off(); break; case PM_DISK_REBOOT: kernel_restart(NULL); break; + default: + if (pm_ops && pm_ops->enter) { + kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); + pm_ops->enter(PM_SUSPEND_DISK); + break; + } } kernel_halt(); - /* Valid image is on the disk, if we continue we risk serious data corruption - after resume. */ + /* + * Valid image is on the disk, if we continue we risk serious data + * corruption after resume. + */ printk(KERN_CRIT "Please power me down manually\n"); while(1); } static inline void platform_finish(void) { - if (pm_disk_mode == PM_DISK_PLATFORM) { + switch (pm_disk_mode) { + case PM_DISK_TEST: + case PM_DISK_TESTPROC: + case PM_DISK_SHUTDOWN: + case PM_DISK_REBOOT: + break; + default: if (pm_ops && pm_ops->finish) pm_ops->finish(PM_SUSPEND_DISK); } @@ -166,7 +180,7 @@ int pm_suspend_disk(void) pr_debug("PM: writing image.\n"); error = swsusp_write(); if (!error) - power_down(pm_disk_mode); + power_down(); else { swsusp_free(); goto Thaw; @@ -338,10 +352,14 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n) } } if (mode) { - if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT || - mode == PM_DISK_TEST || mode == PM_DISK_TESTPROC) { + switch (mode) { + case PM_DISK_SHUTDOWN: + case PM_DISK_REBOOT: + case PM_DISK_TEST: + case PM_DISK_TESTPROC: pm_disk_mode = mode; - } else { + break; + default: if (pm_ops && pm_ops->enter && (mode == pm_ops->pm_disk_mode)) pm_disk_mode = mode; diff --git a/kernel/power/main.c b/kernel/power/main.c index 3062e940d1fa..053c0a7d7f57 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -30,7 +30,7 @@ DEFINE_MUTEX(pm_mutex); struct pm_ops *pm_ops; -suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM; +suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN; /** * pm_set_ops - Set the global power method table. @@ -41,6 +41,10 @@ void pm_set_ops(struct pm_ops * ops) { mutex_lock(&pm_mutex); pm_ops = ops; + if (ops && ops->pm_disk_mode != PM_DISK_INVALID) { + pm_disk_mode = ops->pm_disk_mode; + } else + pm_disk_mode = PM_DISK_SHUTDOWN; mutex_unlock(&pm_mutex); } -- cgit From 11d77d0c01b80e44c7aceb21928508dafce774f9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Apr 2007 15:09:53 -0700 Subject: power management: remove firmware disk mode This patch removes the firmware disk suspend mode which is the wrong approach, it is supposed to be used for implementing firmware-based disk suspend but cannot actually be used for that. Signed-off-by: Johannes Berg Acked-by: Pavel Machek Cc: Cc: David Brownell Cc: Len Brown Acked-by: Russell King Cc: Greg KH Cc: "Rafael J. Wysocki" Cc: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/power/interface.txt | 21 +++++---------------- Documentation/power/states.txt | 13 +++++++------ Documentation/power/swsusp.txt | 14 +++++--------- include/linux/pm.h | 13 ++++++------- kernel/power/disk.c | 27 +++++++++++---------------- 5 files changed, 34 insertions(+), 54 deletions(-) (limited to 'include/linux/pm.h') diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt index 74311d7e0f3c..8c5b41bf3f36 100644 --- a/Documentation/power/interface.txt +++ b/Documentation/power/interface.txt @@ -18,17 +18,10 @@ states. /sys/power/disk controls the operating mode of the suspend-to-disk -mechanism. Suspend-to-disk can be handled in several ways. The -greatest distinction is who writes memory to disk - the firmware or -the kernel. If the firmware does it, we assume that it also handles -suspending the system. - -If the kernel does it, then we have three options for putting the system -to sleep - using the platform driver (e.g. ACPI or other PM -registers), powering off the system or rebooting the system (for -testing). The system will support either 'firmware' or 'platform', and -that is known a priori. But, the user may choose 'shutdown' or -'reboot' as alternatives. +mechanism. Suspend-to-disk can be handled in several ways. We have a +few options for putting the system to sleep - using the platform driver +(e.g. ACPI or other pm_ops), powering off the system or rebooting the +system (for testing). Additionally, /sys/power/disk can be used to turn on one of the two testing modes of the suspend-to-disk mechanism: 'testproc' or 'test'. If the @@ -44,16 +37,12 @@ is being slow and which device drivers are misbehaving. Reading from this file will display what the mode is currently set to. Writing to this file will accept one of - 'firmware' - 'platform' + 'platform' (only if the platform supports it) 'shutdown' 'reboot' 'testproc' 'test' -It will only change to 'firmware' or 'platform' if the system supports -it. - /sys/power/image_size controls the size of the image created by the suspend-to-disk mechanism. It can be written a string representing a non-negative integer that will be used as an upper diff --git a/Documentation/power/states.txt b/Documentation/power/states.txt index 0931a330d362..34800cc521bf 100644 --- a/Documentation/power/states.txt +++ b/Documentation/power/states.txt @@ -62,17 +62,18 @@ setup via another operating system for it to use. Despite the inconvenience, this method requires minimal work by the kernel, since the firmware will also handle restoring memory contents on resume. -If the kernel is responsible for persistently saving state, a mechanism -called 'swsusp' (Swap Suspend) is used to write memory contents to -free swap space. swsusp has some restrictive requirements, but should -work in most cases. Some, albeit outdated, documentation can be found -in Documentation/power/swsusp.txt. +For suspend-to-disk, a mechanism called swsusp called 'swsusp' (Swap +Suspend) is used to write memory contents to free swap space. +swsusp has some restrictive requirements, but should work in most +cases. Some, albeit outdated, documentation can be found in +Documentation/power/swsusp.txt. Alternatively, userspace can do most +of the actual suspend to disk work, see userland-swsusp.txt. Once memory state is written to disk, the system may either enter a low-power state (like ACPI S4), or it may simply power down. Powering down offers greater savings, and allows this mechanism to work on any system. However, entering a real low-power state allows the user to -trigger wake up events (e.g. pressing a key or opening a laptop lid). +trigger wake up events (e.g. pressing a key or opening a laptop lid). A transition from Suspend-to-Disk to the On state should take about 30 seconds, though it's typically a bit more with the current diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 0761ff6c57ed..c55bd5079b90 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -156,8 +156,7 @@ instead set the PF_NOFREEZE process flag when creating the thread (and be very careful). -Q: What is the difference between "platform", "shutdown" and -"firmware" in /sys/power/disk? +Q: What is the difference between "platform" and "shutdown"? A: @@ -166,11 +165,8 @@ shutdown: save state in linux, then tell bios to powerdown platform: save state in linux, then tell bios to powerdown and blink "suspended led" -firmware: tell bios to save state itself [needs BIOS-specific suspend - partition, and has very little to do with swsusp] - -"platform" is actually right thing to do, but "shutdown" is most -reliable. +"platform" is actually right thing to do where supported, but +"shutdown" is most reliable (except on ACPI systems). Q: I do not understand why you have such strong objections to idea of selective suspend. @@ -388,8 +384,8 @@ while the system is asleep, maintaining the connection, using true sleep modes like "suspend-to-RAM" or "standby". (Don't write "disk" to the /sys/power/state file; write "standby" or "mem".) We've not seen any hardware that can use these modes through software suspend, although in -theory some systems might support "platform" or "firmware" modes that -won't break the USB connections. +theory some systems might support "platform" modes that won't break the +USB connections. Remember that it's always a bad idea to unplug a disk drive containing a mounted filesystem. That's true even when your system is asleep! The diff --git a/include/linux/pm.h b/include/linux/pm.h index dfced9188bdc..c2a55f94c29a 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -114,13 +114,12 @@ typedef int __bitwise suspend_disk_method_t; /* invalid must be 0 so struct pm_ops initialisers can leave it out */ #define PM_DISK_INVALID ((__force suspend_disk_method_t) 0) -#define PM_DISK_FIRMWARE ((__force suspend_disk_method_t) 1) -#define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 2) -#define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 3) -#define PM_DISK_REBOOT ((__force suspend_disk_method_t) 4) -#define PM_DISK_TEST ((__force suspend_disk_method_t) 5) -#define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6) -#define PM_DISK_MAX ((__force suspend_disk_method_t) 7) +#define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 1) +#define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 2) +#define PM_DISK_REBOOT ((__force suspend_disk_method_t) 3) +#define PM_DISK_TEST ((__force suspend_disk_method_t) 4) +#define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 5) +#define PM_DISK_MAX ((__force suspend_disk_method_t) 6) /** * struct pm_ops - Callbacks for managing platform dependent suspend states. diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 4de2f69fe095..02e4fb69111a 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -122,8 +122,6 @@ static int prepare_processes(void) /** * pm_suspend_disk - The granpappy of hibernation power management. * - * If we're going through the firmware, then get it over with quickly. - * * If not, then call swsusp to do its thing, then figure out how * to power down the system. */ @@ -292,7 +290,6 @@ late_initcall(software_resume); static const char * const pm_disk_modes[] = { - [PM_DISK_FIRMWARE] = "firmware", [PM_DISK_PLATFORM] = "platform", [PM_DISK_SHUTDOWN] = "shutdown", [PM_DISK_REBOOT] = "reboot", @@ -303,27 +300,25 @@ static const char * const pm_disk_modes[] = { /** * disk - Control suspend-to-disk mode * - * Suspend-to-disk can be handled in several ways. The greatest - * distinction is who writes memory to disk - the firmware or the OS. - * If the firmware does it, we assume that it also handles suspending - * the system. - * If the OS does it, then we have three options for putting the system - * to sleep - using the platform driver (e.g. ACPI or other PM registers), - * powering off the system or rebooting the system (for testing). + * Suspend-to-disk can be handled in several ways. We have a few options + * for putting the system to sleep - using the platform driver (e.g. ACPI + * or other pm_ops), powering off the system or rebooting the system + * (for testing) as well as the two test modes. * - * The system will support either 'firmware' or 'platform', and that is - * known a priori (and encoded in pm_ops). But, the user may choose - * 'shutdown' or 'reboot' as alternatives. + * The system can support 'platform', and that is known a priori (and + * encoded in pm_ops). However, the user may choose 'shutdown' or 'reboot' + * as alternatives, as well as the test modes 'test' and 'testproc'. * * show() will display what the mode is currently set to. * store() will accept one of * - * 'firmware' * 'platform' * 'shutdown' * 'reboot' + * 'test' + * 'testproc' * - * It will only change to 'firmware' or 'platform' if the system + * It will only change to 'platform' if the system * supports it (as determined from pm_ops->pm_disk_mode). */ @@ -345,7 +340,7 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n) len = p ? p - buf : n; mutex_lock(&pm_mutex); - for (i = PM_DISK_FIRMWARE; i < PM_DISK_MAX; i++) { + for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) { if (!strncmp(buf, pm_disk_modes[i], len)) { mode = i; break; -- cgit From e8c9c502690efd24b7055bf608e7a3c34216848b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Apr 2007 15:09:54 -0700 Subject: power management: implement pm_ops.valid for everybody Almost all users of pm_ops only support mem sleep, don't check in .valid and don't reject any others in .prepare so users can be confused if they check /sys/power/state, especially when new states are added (these would then result in s-t-r although they're supposed to be something different). This patch implements a generic pm_valid_only_mem function that is then exported for users and puts it to use in almost all existing pm_ops. Signed-off-by: Johannes Berg Cc: David Brownell Acked-by: Pavel Machek Cc: linux-pm@lists.linux-foundation.org Cc: Len Brown Acked-by: Russell King Cc: Greg KH Cc: "Rafael J. Wysocki" Cc: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/common/sharpsl_pm.c | 1 + arch/arm/mach-omap1/pm.c | 1 + arch/arm/mach-omap2/pm.c | 1 + arch/arm/mach-pnx4008/pm.c | 39 ++++----------------------------------- arch/arm/mach-pxa/pm.c | 1 + arch/arm/mach-sa1100/pm.c | 1 + arch/arm/plat-s3c24xx/pm.c | 19 +------------------ arch/sh/boards/hp6xx/pm.c | 1 + drivers/acpi/sleep/main.c | 13 +++++++++++-- include/linux/pm.h | 4 ++++ kernel/power/main.c | 13 +++++++++++++ 11 files changed, 39 insertions(+), 55 deletions(-) (limited to 'include/linux/pm.h') diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index 4cb895d4ae5b..5972df2b9af4 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -769,6 +769,7 @@ static struct pm_ops sharpsl_pm_ops = { .prepare = pxa_pm_prepare, .enter = corgi_pxa_pm_enter, .finish = pxa_pm_finish, + .valid = pm_valid_only_mem, }; static int __init sharpsl_pm_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index 4248117e5e3f..0383ab334270 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -701,6 +701,7 @@ static struct pm_ops omap_pm_ops ={ .prepare = omap_pm_prepare, .enter = omap_pm_enter, .finish = omap_pm_finish, + .valid = pm_valid_only_mem, }; static int __init omap_pm_init(void) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 3e9a128feea1..6f4a5436d0ce 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -373,6 +373,7 @@ static struct pm_ops omap_pm_ops = { .prepare = omap2_pm_prepare, .enter = omap2_pm_enter, .finish = omap2_pm_finish, + .valid = pm_valid_only_mem, }; int __init omap2_pm_init(void) diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c index 3649cd3dfc9a..2a137f33f752 100644 --- a/arch/arm/mach-pnx4008/pm.c +++ b/arch/arm/mach-pnx4008/pm.c @@ -107,50 +107,19 @@ static int pnx4008_pm_enter(suspend_state_t state) case PM_SUSPEND_MEM: pnx4008_suspend(); break; - case PM_SUSPEND_DISK: - return -ENOTSUPP; - default: - return -EINVAL; } return 0; } -/* - * Called after processes are frozen, but before we shut down devices. - */ -static int pnx4008_pm_prepare(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - break; - - case PM_SUSPEND_DISK: - return -ENOTSUPP; - break; - - default: - return -EINVAL; - break; - } - return 0; -} - -/* - * Called after devices are re-setup, but before processes are thawed. - */ -static int pnx4008_pm_finish(suspend_state_t state) +static int pnx4008_pm_valid(suspend_state_t state) { - return 0; + return (state == PM_SUSPEND_STANDBY) || + (state == PM_SUSPEND_MEM); } -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops pnx4008_pm_ops = { - .prepare = pnx4008_pm_prepare, .enter = pnx4008_pm_enter, - .finish = pnx4008_pm_finish, + .valid = pnx4008_pm_valid, }; static int __init pnx4008_pm_init(void) diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 0a99ef43b36f..6bf15ae73848 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -227,6 +227,7 @@ static struct pm_ops pxa_pm_ops = { .prepare = pxa_pm_prepare, .enter = pxa_pm_enter, .finish = pxa_pm_finish, + .valid = pm_valid_only_mem, }; static int __init pxa_pm_init(void) diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index b0837113b2aa..d674cf343156 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -133,6 +133,7 @@ unsigned long sleep_phys_sp(void *sp) static struct pm_ops sa11x0_pm_ops = { .enter = sa11x0_pm_enter, + .valid = pm_valid_only_mem, }; static int __init sa11x0_pm_init(void) diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index d6af3082af30..c6b03f8ab260 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c @@ -612,26 +612,9 @@ static int s3c2410_pm_enter(suspend_state_t state) return 0; } -/* - * Called after processes are frozen, but before we shut down devices. - */ -static int s3c2410_pm_prepare(suspend_state_t state) -{ - return 0; -} - -/* - * Called after devices are re-setup, but before processes are thawed. - */ -static int s3c2410_pm_finish(suspend_state_t state) -{ - return 0; -} - static struct pm_ops s3c2410_pm_ops = { - .prepare = s3c2410_pm_prepare, .enter = s3c2410_pm_enter, - .finish = s3c2410_pm_finish, + .valid = pm_valid_only_mem, }; /* s3c2410_pm_init diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c index 4b2f29a4bde9..8143d1b948e7 100644 --- a/arch/sh/boards/hp6xx/pm.c +++ b/arch/sh/boards/hp6xx/pm.c @@ -69,6 +69,7 @@ static int hp6x0_pm_enter(suspend_state_t state) static struct pm_ops hp6x0_pm_ops = { .enter = hp6x0_pm_enter, + .valid = pm_valid_only_mem, }; static int __init hp6x0_pm_init(void) diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 37a0930fc0a6..f8c63410bcbf 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -168,9 +168,18 @@ int acpi_suspend(u32 acpi_state) static int acpi_pm_state_valid(suspend_state_t pm_state) { - u32 acpi_state = acpi_suspend_states[pm_state]; + u32 acpi_state; + + switch (pm_state) { + case PM_SUSPEND_ON: + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + acpi_state = acpi_suspend_states[pm_state]; - return sleep_states[acpi_state]; + return sleep_states[acpi_state]; + default: + return 0; + } } static struct pm_ops acpi_pm_ops = { diff --git a/include/linux/pm.h b/include/linux/pm.h index c2a55f94c29a..6035209cf31e 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -128,6 +128,9 @@ typedef int __bitwise suspend_disk_method_t; * always valid and never passed to this call. * If not assigned, all suspend states are advertised as valid * in /sys/power/state (but can still be rejected by prepare or enter.) + * Since new states can be added for other platforms, you should + * assign this callback. There is a %pm_valid_only_mem function + * available if you only implemented mem sleep. * * @prepare: Prepare the platform for the given suspend state. Can return a * negative error code if necessary. @@ -165,6 +168,7 @@ extern void pm_set_ops(struct pm_ops *pm_ops); extern struct pm_ops *pm_ops; extern int pm_suspend(suspend_state_t state); +extern int pm_valid_only_mem(suspend_state_t state); /** * arch_suspend_disable_irqs - disable IRQs for suspend diff --git a/kernel/power/main.c b/kernel/power/main.c index 053c0a7d7f57..f94f4e20115a 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -48,6 +48,19 @@ void pm_set_ops(struct pm_ops * ops) mutex_unlock(&pm_mutex); } +/** + * pm_valid_only_mem - generic memory-only valid callback + * + * pm_ops drivers that implement mem suspend only and only need + * to check for that in their .valid callback can use this instead + * of rolling their own .valid callback. + */ +int pm_valid_only_mem(suspend_state_t state) +{ + return state == PM_SUSPEND_MEM; +} + + static inline void pm_finish(suspend_state_t state) { if (pm_ops->finish) -- cgit From 9684e51cd157607f0727c1550e7df6e31de40808 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Apr 2007 15:09:55 -0700 Subject: power management: force pm_ops.valid callback to be assigned This patch changes the docs and behaviour from "all states valid" to "no states valid" if no .valid callback is assigned. Users of pm_ops that only need mem sleep can assign pm_valid_only_mem without any overhead, others will require more elaborate callbacks. Now that all users of pm_ops have a .valid callback this is a safe thing to do and prevents things from getting messy again as they were before. Signed-off-by: Johannes Berg Acked-by: Pavel Machek Looks-okay-to: Rafael J. Wysocki Cc: Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pm.h | 12 ++++++------ kernel/power/main.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include/linux/pm.h') diff --git a/include/linux/pm.h b/include/linux/pm.h index 6035209cf31e..7a516690dcb3 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -125,12 +125,12 @@ typedef int __bitwise suspend_disk_method_t; * struct pm_ops - Callbacks for managing platform dependent suspend states. * @valid: Callback to determine whether the given state can be entered. * If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is - * always valid and never passed to this call. - * If not assigned, all suspend states are advertised as valid - * in /sys/power/state (but can still be rejected by prepare or enter.) - * Since new states can be added for other platforms, you should - * assign this callback. There is a %pm_valid_only_mem function - * available if you only implemented mem sleep. + * always valid and never passed to this call. If not assigned, + * no suspend states are valid. + * Valid states are advertised in /sys/power/state but can still + * be rejected by prepare or enter if the conditions aren't right. + * There is a %pm_valid_only_mem function available that can be assigned + * to this if you only implement mem sleep. * * @prepare: Prepare the platform for the given suspend state. Can return a * negative error code if necessary. diff --git a/kernel/power/main.c b/kernel/power/main.c index f94f4e20115a..72419a3b1beb 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -198,8 +198,8 @@ static inline int valid_state(suspend_state_t state) /* all other states need lowlevel support and need to be * valid to the lowlevel implementation, no valid callback - * implies that all are valid. */ - if (!pm_ops || (pm_ops->valid && !pm_ops->valid(state))) + * implies that none are valid. */ + if (!pm_ops || !pm_ops->valid || !pm_ops->valid(state)) return 0; return 1; } -- cgit From 14e38ac823b7b25e3f4e563c182f93fde78167d6 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 30 Apr 2007 15:09:56 -0700 Subject: pm: include EIO from errno-base.h For backwards compatibility, call_platform_enable_wakeup() can return 0 instead of -EIO since we aren't guaranteed to have errno defined. Cc: David Brownell Signed-off-by: David Rientjes Cc: "Randy.Dunlap" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/pm.h') diff --git a/include/linux/pm.h b/include/linux/pm.h index 7a516690dcb3..6e8fa3049e5d 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -332,7 +332,7 @@ static inline void dpm_runtime_resume(struct device * dev) static inline int call_platform_enable_wakeup(struct device *dev, int is_on) { - return -EIO; + return 0; } #endif -- cgit