Commit 8df2e02c authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Rafael J. Wysocki

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: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 068765ba
...@@ -63,8 +63,8 @@ enum { ...@@ -63,8 +63,8 @@ enum {
extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
unsigned long flags); unsigned long flags);
extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); extern void __disable_irq(struct irq_desc *desc, unsigned int irq);
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); extern void __enable_irq(struct irq_desc *desc, unsigned int irq);
extern int irq_startup(struct irq_desc *desc, bool resend); extern int irq_startup(struct irq_desc *desc, bool resend);
extern void irq_shutdown(struct irq_desc *desc); extern void irq_shutdown(struct irq_desc *desc);
......
...@@ -382,14 +382,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask) ...@@ -382,14 +382,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
} }
#endif #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++) if (!desc->depth++)
irq_disable(desc); irq_disable(desc);
} }
...@@ -401,7 +395,7 @@ static int __disable_irq_nosync(unsigned int irq) ...@@ -401,7 +395,7 @@ static int __disable_irq_nosync(unsigned int irq)
if (!desc) if (!desc)
return -EINVAL; return -EINVAL;
__disable_irq(desc, irq, false); __disable_irq(desc, irq);
irq_put_desc_busunlock(desc, flags); irq_put_desc_busunlock(desc, flags);
return 0; return 0;
} }
...@@ -442,20 +436,8 @@ void disable_irq(unsigned int irq) ...@@ -442,20 +436,8 @@ void disable_irq(unsigned int irq)
} }
EXPORT_SYMBOL(disable_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) { switch (desc->depth) {
case 0: case 0:
err_out: err_out:
...@@ -497,7 +479,7 @@ void enable_irq(unsigned int irq) ...@@ -497,7 +479,7 @@ void enable_irq(unsigned int irq)
KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq)) KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
goto out; goto out;
__enable_irq(desc, irq, false); __enable_irq(desc, irq);
out: out:
irq_put_desc_busunlock(desc, flags); irq_put_desc_busunlock(desc, flags);
} }
...@@ -1228,7 +1210,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ...@@ -1228,7 +1210,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
*/ */
if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) { if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
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); raw_spin_unlock_irqrestore(&desc->lock, flags);
......
...@@ -13,13 +13,26 @@ ...@@ -13,13 +13,26 @@
#include "internals.h" #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 * suspend_device_irqs - disable all currently enabled interrupt lines
* *
* During system-wide suspend or hibernation device drivers need to be prevented * During system-wide suspend or hibernation device drivers need to be
* from receiving interrupts and this function is provided for this purpose. * prevented from receiving interrupts and this function is provided
* It marks all interrupt lines in use, except for the timer ones, as disabled * for this purpose.
* and sets the IRQS_SUSPENDED flag for each of them. *
* 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) void suspend_device_irqs(void)
{ {
...@@ -30,7 +43,7 @@ void suspend_device_irqs(void) ...@@ -30,7 +43,7 @@ void suspend_device_irqs(void)
unsigned long flags; unsigned long flags;
raw_spin_lock_irqsave(&desc->lock, 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); raw_spin_unlock_irqrestore(&desc->lock, flags);
} }
...@@ -40,6 +53,25 @@ void suspend_device_irqs(void) ...@@ -40,6 +53,25 @@ void suspend_device_irqs(void)
} }
EXPORT_SYMBOL_GPL(suspend_device_irqs); 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) static void resume_irqs(bool want_early)
{ {
struct irq_desc *desc; struct irq_desc *desc;
...@@ -54,7 +86,7 @@ static void resume_irqs(bool want_early) ...@@ -54,7 +86,7 @@ static void resume_irqs(bool want_early)
continue; continue;
raw_spin_lock_irqsave(&desc->lock, flags); raw_spin_lock_irqsave(&desc->lock, flags);
__enable_irq(desc, irq, true); resume_irq(desc, irq);
raw_spin_unlock_irqrestore(&desc->lock, flags); raw_spin_unlock_irqrestore(&desc->lock, flags);
} }
} }
......
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