Commit 2db87321 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Linus Torvalds

set_irq_wake: fix return code and wake status tracking

Since 15a647eb 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: default avatarUwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Acked-by: default avatarDavid 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: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1bad879a
...@@ -217,6 +217,17 @@ void enable_irq(unsigned int irq) ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment