aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
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
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')
-rw-r--r--kernel/irq/internals.h4
-rw-r--r--kernel/irq/manage.c28
-rw-r--r--kernel/irq/pm.c44
3 files changed, 45 insertions, 31 deletions
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 099ea2e0eb88..af2821178900 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -63,8 +63,8 @@ enum {
63 63
64extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, 64extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
65 unsigned long flags); 65 unsigned long flags);
66extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); 66extern void __disable_irq(struct irq_desc *desc, unsigned int irq);
67extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); 67extern void __enable_irq(struct irq_desc *desc, unsigned int irq);
68 68
69extern int irq_startup(struct irq_desc *desc, bool resend); 69extern int irq_startup(struct irq_desc *desc, bool resend);
70extern void irq_shutdown(struct irq_desc *desc); 70extern void irq_shutdown(struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 3dc6a61bf06a..fa564e8db996 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -382,14 +382,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
382} 382}
383#endif 383#endif
384 384
385void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) 385void __disable_irq(struct irq_desc *desc, unsigned int irq)
386{ 386{
387 if (suspend) {
388 if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
389 return;
390 desc->istate |= IRQS_SUSPENDED;
391 }
392
393 if (!desc->depth++) 387 if (!desc->depth++)
394 irq_disable(desc); 388 irq_disable(desc);
395} 389}
@@ -401,7 +395,7 @@ static int __disable_irq_nosync(unsigned int irq)
401 395
402 if (!desc) 396 if (!desc)
403 return -EINVAL; 397 return -EINVAL;
404 __disable_irq(desc, irq, false); 398 __disable_irq(desc, irq);
405 irq_put_desc_busunlock(desc, flags); 399 irq_put_desc_busunlock(desc, flags);
406 return 0; 400 return 0;
407} 401}
@@ -442,20 +436,8 @@ void disable_irq(unsigned int irq)
442} 436}
443EXPORT_SYMBOL(disable_irq); 437EXPORT_SYMBOL(disable_irq);
444 438
445void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) 439void __enable_irq(struct irq_desc *desc, unsigned int irq)
446{ 440{
447 if (resume) {
448 if (!(desc->istate & IRQS_SUSPENDED)) {
449 if (!desc->action)
450 return;
451 if (!(desc->action->flags & IRQF_FORCE_RESUME))
452 return;
453 /* Pretend that it got disabled ! */
454 desc->depth++;
455 }
456 desc->istate &= ~IRQS_SUSPENDED;
457 }
458
459 switch (desc->depth) { 441 switch (desc->depth) {
460 case 0: 442 case 0:
461 err_out: 443 err_out:
@@ -497,7 +479,7 @@ void enable_irq(unsigned int irq)
497 KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq)) 479 KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
498 goto out; 480 goto out;
499 481
500 __enable_irq(desc, irq, false); 482 __enable_irq(desc, irq);
501out: 483out:
502 irq_put_desc_busunlock(desc, flags); 484 irq_put_desc_busunlock(desc, flags);
503} 485}
@@ -1228,7 +1210,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
1228 */ 1210 */
1229 if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) { 1211 if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
1230 desc->istate &= ~IRQS_SPURIOUS_DISABLED; 1212 desc->istate &= ~IRQS_SPURIOUS_DISABLED;
1231 __enable_irq(desc, irq, false); 1213 __enable_irq(desc, irq);
1232 } 1214 }
1233 1215
1234 raw_spin_unlock_irqrestore(&desc->lock, flags); 1216 raw_spin_unlock_irqrestore(&desc->lock, flags);
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}