| From johannes@sipsolutions.net Thu Apr 26 02:42:09 2007 | 
 | From: Johannes Berg <johannes@sipsolutions.net> | 
 | Date: Thu, 26 Apr 2007 11:43:58 +0200 | 
 | Subject: s2ram: add arch irq disable/enable hooks | 
 | To: akpm@linux-foundation.org | 
 | Cc: greg@kroah.com | 
 | Message-ID: <1177580638.6814.14.camel@johannes.berg> | 
 |  | 
 |  | 
 | After some more discussion this patch replaces it: | 
 |  | 
 | From: Johannes Berg <johannes@sipsolutions.net> | 
 | 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 <johannes@sipsolutions.net> | 
 | Acked-by: Pavel Machek <pavel@ucw.cz> | 
 | Cc: Andrew Morton <akpm@linux-foundation.org> | 
 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | 
 |  | 
 |  | 
 | --- | 
 |  include/linux/pm.h  |   18 ++++++++++++++++++ | 
 |  kernel/power/main.c |   18 +++++++++++++++--- | 
 |  2 files changed, 33 insertions(+), 3 deletions(-) | 
 |  | 
 | --- 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 | 
 |   */ | 
 | --- a/kernel/power/main.c | 
 | +++ b/kernel/power/main.c | 
 | @@ -111,13 +111,24 @@ static int suspend_prepare(suspend_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; | 
 |  } | 
 |   |