genirq: Move suspend/resume logic into irq/pm code

No functional change. Preparatory patch for cleaning up the suspend
abort functionality. Update the comments while at it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Thomas Gleixner 2014-08-28 11:49:28 +02:00 committed by Rafael J. Wysocki
parent 068765ba79
commit 8df2e02c5c
3 changed files with 45 additions and 31 deletions

View File

@ -63,8 +63,8 @@ enum {
extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
unsigned long flags);
extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
extern void __disable_irq(struct irq_desc *desc, unsigned int irq);
extern void __enable_irq(struct irq_desc *desc, unsigned int irq);
extern int irq_startup(struct irq_desc *desc, bool resend);
extern void irq_shutdown(struct irq_desc *desc);

View File

@ -382,14 +382,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
}
#endif
void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
void __disable_irq(struct irq_desc *desc, unsigned int irq)
{
if (suspend) {
if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
return;
desc->istate |= IRQS_SUSPENDED;
}
if (!desc->depth++)
irq_disable(desc);
}
@ -401,7 +395,7 @@ static int __disable_irq_nosync(unsigned int irq)
if (!desc)
return -EINVAL;
__disable_irq(desc, irq, false);
__disable_irq(desc, irq);
irq_put_desc_busunlock(desc, flags);
return 0;
}
@ -442,20 +436,8 @@ void disable_irq(unsigned int irq)
}
EXPORT_SYMBOL(disable_irq);
void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
void __enable_irq(struct irq_desc *desc, unsigned int irq)
{
if (resume) {
if (!(desc->istate & IRQS_SUSPENDED)) {
if (!desc->action)
return;
if (!(desc->action->flags & IRQF_FORCE_RESUME))
return;
/* Pretend that it got disabled ! */
desc->depth++;
}
desc->istate &= ~IRQS_SUSPENDED;
}
switch (desc->depth) {
case 0:
err_out:
@ -497,7 +479,7 @@ void enable_irq(unsigned int irq)
KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
goto out;
__enable_irq(desc, irq, false);
__enable_irq(desc, irq);
out:
irq_put_desc_busunlock(desc, flags);
}
@ -1228,7 +1210,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
*/
if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
desc->istate &= ~IRQS_SPURIOUS_DISABLED;
__enable_irq(desc, irq, false);
__enable_irq(desc, irq);
}
raw_spin_unlock_irqrestore(&desc->lock, flags);

View File

@ -13,13 +13,26 @@
#include "internals.h"
static void suspend_device_irq(struct irq_desc *desc, int irq)
{
if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
return;
desc->istate |= IRQS_SUSPENDED;
__disable_irq(desc, irq);
}
/**
* suspend_device_irqs - disable all currently enabled interrupt lines
*
* During system-wide suspend or hibernation device drivers need to be prevented
* from receiving interrupts and this function is provided for this purpose.
* It marks all interrupt lines in use, except for the timer ones, as disabled
* and sets the IRQS_SUSPENDED flag for each of them.
* During system-wide suspend or hibernation device drivers need to be
* prevented from receiving interrupts and this function is provided
* for this purpose.
*
* So we disable all interrupts and mark them IRQS_SUSPENDED except
* for those which are unused and those which are marked as not
* suspendable via an interrupt request with the flag IRQF_NO_SUSPEND
* set.
*/
void suspend_device_irqs(void)
{
@ -30,7 +43,7 @@ void suspend_device_irqs(void)
unsigned long flags;
raw_spin_lock_irqsave(&desc->lock, flags);
__disable_irq(desc, irq, true);
suspend_device_irq(desc, irq);
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
@ -40,6 +53,25 @@ void suspend_device_irqs(void)
}
EXPORT_SYMBOL_GPL(suspend_device_irqs);
static void resume_irq(struct irq_desc *desc, int irq)
{
if (desc->istate & IRQS_SUSPENDED)
goto resume;
if (!desc->action)
return;
/* Interrupts marked with that flag are force reenabled */
if (!(desc->action->flags & IRQF_FORCE_RESUME))
return;
/* Pretend that it got disabled ! */
desc->depth++;
resume:
desc->istate &= ~IRQS_SUSPENDED;
__enable_irq(desc, irq);
}
static void resume_irqs(bool want_early)
{
struct irq_desc *desc;
@ -54,7 +86,7 @@ static void resume_irqs(bool want_early)
continue;
raw_spin_lock_irqsave(&desc->lock, flags);
__enable_irq(desc, irq, true);
resume_irq(desc, irq);
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}