From ef557d76dfbdf74c240f76be15fa90d62f1ae61f Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski Date: Wed, 6 Dec 2006 17:13:48 -0800 Subject: ARM: OMAP: correct misc 15xx and non-15xx platform code Disable accesses to SOFT_REQ_REG2 and ULPD_SOFT_DISABLE_REQ_REG registers for 15xx processors that don't have these registers. Enable level 2 interrupt handler for processors that identify as OMAP 15xx (e.g 310) and not 1510 specifically. Also fix the following compiler warning (only visible with CONFIG_OMAP_RESET_CLOCKS): arch/arm/mach-omap1/clock.c: In function 'omap1_clk_disable_unused': arch/arm/mach-omap1/clock.c:634: warning: 'return' with a value, in function returning void Signed-off-by: Andrzej Zaborowski Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-omap1/pm.c') diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index 4834758d340c..8ff232034871 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -256,7 +256,8 @@ void omap_pm_suspend(void) tps65010_set_led(LED1, OFF); } - omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG); + if (!cpu_is_omap15xx()) + omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG); /* * Step 1: turn off interrupts (FIXME: NOTE: already disabled) @@ -434,7 +435,8 @@ void omap_pm_suspend(void) MPUI1610_RESTORE(OMAP_IH2_3_MIR); } - omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG); + if (!cpu_is_omap15xx()) + omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG); /* * Reenable interrupts -- cgit v1.2.3 From 2f5c4b6f1ce6595fd977963051a3030911ae4461 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Wed, 6 Dec 2006 17:14:04 -0800 Subject: ARM: OMAP: Fix warning in mach-omap1 Fix warning arch/arm/mach-omap1/pm.c: In function 'omap_pm_init': arch/arm/mach-omap1/pm.c:765: warning: ignoring return value of 'subsys_create_file', declared with attribute warn_unused_result Signed-off-by: Dirk Behme Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/pm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-omap1/pm.c') diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index 8ff232034871..49efe903dacd 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -706,6 +706,8 @@ static struct pm_ops omap_pm_ops ={ static int __init omap_pm_init(void) { + int error; + printk("Power Management for TI OMAP.\n"); /* @@ -762,7 +764,9 @@ static int __init omap_pm_init(void) omap_pm_init_proc(); #endif - subsys_create_file(&power_subsys, &sleep_while_idle_attr); + error = subsys_create_file(&power_subsys, &sleep_while_idle_attr); + if (error) + printk(KERN_ERR "subsys_create_file failed: %d\n", error); if (cpu_is_omap16xx()) { /* configure LOW_PWR pin */ -- cgit v1.2.3 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 'arch/arm/mach-omap1/pm.c') 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 v1.2.3 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 'arch/arm/mach-omap1/pm.c') 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 v1.2.3