set_irq_wake: fix return code and wake status tracking
Since 15a647eba9
set_irq_wake returned -ENXIO
if another device had it already enabled. Zero is the right value to
return in this case. Moreover the change to desc->status was not reverted
if desc->chip->set_wake returned an error.
Signed-off-by: Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
1bad879a07
commit
2db873211b
1 changed files with 27 additions and 12 deletions
|
@ -217,6 +217,17 @@ void enable_irq(unsigned int irq)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(enable_irq);
|
EXPORT_SYMBOL(enable_irq);
|
||||||
|
|
||||||
|
int set_irq_wake_real(unsigned int irq, unsigned int on)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc = irq_desc + irq;
|
||||||
|
int ret = -ENXIO;
|
||||||
|
|
||||||
|
if (desc->chip->set_wake)
|
||||||
|
ret = desc->chip->set_wake(irq, on);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set_irq_wake - control irq power management wakeup
|
* set_irq_wake - control irq power management wakeup
|
||||||
* @irq: interrupt to control
|
* @irq: interrupt to control
|
||||||
|
@ -233,30 +244,34 @@ int set_irq_wake(unsigned int irq, unsigned int on)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_desc + irq;
|
struct irq_desc *desc = irq_desc + irq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = -ENXIO;
|
int ret = 0;
|
||||||
int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake;
|
|
||||||
|
|
||||||
/* wakeup-capable irqs can be shared between drivers that
|
/* wakeup-capable irqs can be shared between drivers that
|
||||||
* don't need to have the same sleep mode behaviors.
|
* don't need to have the same sleep mode behaviors.
|
||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&desc->lock, flags);
|
spin_lock_irqsave(&desc->lock, flags);
|
||||||
if (on) {
|
if (on) {
|
||||||
if (desc->wake_depth++ == 0)
|
if (desc->wake_depth++ == 0) {
|
||||||
desc->status |= IRQ_WAKEUP;
|
ret = set_irq_wake_real(irq, on);
|
||||||
else
|
if (ret)
|
||||||
set_wake = NULL;
|
desc->wake_depth = 0;
|
||||||
|
else
|
||||||
|
desc->status |= IRQ_WAKEUP;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (desc->wake_depth == 0) {
|
if (desc->wake_depth == 0) {
|
||||||
printk(KERN_WARNING "Unbalanced IRQ %d "
|
printk(KERN_WARNING "Unbalanced IRQ %d "
|
||||||
"wake disable\n", irq);
|
"wake disable\n", irq);
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
} else if (--desc->wake_depth == 0)
|
} else if (--desc->wake_depth == 0) {
|
||||||
desc->status &= ~IRQ_WAKEUP;
|
ret = set_irq_wake_real(irq, on);
|
||||||
else
|
if (ret)
|
||||||
set_wake = NULL;
|
desc->wake_depth = 1;
|
||||||
|
else
|
||||||
|
desc->status &= ~IRQ_WAKEUP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (set_wake)
|
|
||||||
ret = desc->chip->set_wake(irq, on);
|
|
||||||
spin_unlock_irqrestore(&desc->lock, flags);
|
spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue