Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+27 −12
Original line number Original line Diff line number Diff line
@@ -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);
			if (ret)
				desc->wake_depth = 0;
			else
			else
			set_wake = NULL;
				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);
			if (ret)
				desc->wake_depth = 1;
			else
			else
			set_wake = NULL;
				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;
}
}