aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/pm.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-08-28 05:49:28 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-09-01 07:47:57 -0400
commit8df2e02c5c4de9e65ee60153dd9c442356534ad9 (patch)
treeb4080a4efddd018fac2bd4aa57c8c6ced8b6f0b4 /kernel/irq/pm.c
parent068765ba7987e73d4381edfe47b70aa121c7155c (diff)
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>
Diffstat (limited to 'kernel/irq/pm.c')
-rw-r--r--kernel/irq/pm.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index abcd6ca86cb7..b84141dcee5e 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -13,13 +13,26 @@
13 13
14#include "internals.h" 14#include "internals.h"
15 15
16static void suspend_device_irq(struct irq_desc *desc, int irq)
17{
18 if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
19 return;
20
21 desc->istate |= IRQS_SUSPENDED;
22 __disable_irq(desc, irq);
23}
24
16/** 25/**
17 * suspend_device_irqs - disable all currently enabled interrupt lines 26 * suspend_device_irqs - disable all currently enabled interrupt lines
18 * 27 *
19 * During system-wide suspend or hibernation device drivers need to be prevented 28 * During system-wide suspend or hibernation device drivers need to be
20 * from receiving interrupts and this function is provided for this purpose. 29 * prevented from receiving interrupts and this function is provided
21 * It marks all interrupt lines in use, except for the timer ones, as disabled 30 * for this purpose.
22 * and sets the IRQS_SUSPENDED flag for each of them. 31 *
32 * So we disable all interrupts and mark them IRQS_SUSPENDED except
33 * for those which are unused and those which are marked as not
34 * suspendable via an interrupt request with the flag IRQF_NO_SUSPEND
35 * set.
23 */ 36 */
24void suspend_device_irqs(void) 37void suspend_device_irqs(void)
25{ 38{
@@ -30,7 +43,7 @@ void suspend_device_irqs(void)
30 unsigned long flags; 43 unsigned long flags;
31 44
32 raw_spin_lock_irqsave(&desc->lock, flags); 45 raw_spin_lock_irqsave(&desc->lock, flags);
33 __disable_irq(desc, irq, true); 46 suspend_device_irq(desc, irq);
34 raw_spin_unlock_irqrestore(&desc->lock, flags); 47 raw_spin_unlock_irqrestore(&desc->lock, flags);
35 } 48 }
36 49
@@ -40,6 +53,25 @@ void suspend_device_irqs(void)
40} 53}
41EXPORT_SYMBOL_GPL(suspend_device_irqs); 54EXPORT_SYMBOL_GPL(suspend_device_irqs);
42 55
56static void resume_irq(struct irq_desc *desc, int irq)
57{
58 if (desc->istate & IRQS_SUSPENDED)
59 goto resume;
60
61 if (!desc->action)
62 return;
63
64 /* Interrupts marked with that flag are force reenabled */
65 if (!(desc->action->flags & IRQF_FORCE_RESUME))
66 return;
67
68 /* Pretend that it got disabled ! */
69 desc->depth++;
70resume:
71 desc->istate &= ~IRQS_SUSPENDED;
72 __enable_irq(desc, irq);
73}
74
43static void resume_irqs(bool want_early) 75static void resume_irqs(bool want_early)
44{ 76{
45 struct irq_desc *desc; 77 struct irq_desc *desc;
@@ -54,7 +86,7 @@ static void resume_irqs(bool want_early)
54 continue; 86 continue;
55 87
56 raw_spin_lock_irqsave(&desc->lock, flags); 88 raw_spin_lock_irqsave(&desc->lock, flags);
57 __enable_irq(desc, irq, true); 89 resume_irq(desc, irq);
58 raw_spin_unlock_irqrestore(&desc->lock, flags); 90 raw_spin_unlock_irqrestore(&desc->lock, flags);
59 } 91 }
60} 92}