diff options
Diffstat (limited to 'kernel/irq/pm.c')
| -rw-r--r-- | kernel/irq/pm.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index f76fc00c9877..15e53b1766a6 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/irq.h> | 9 | #include <linux/irq.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 12 | #include <linux/syscore_ops.h> | ||
| 12 | 13 | ||
| 13 | #include "internals.h" | 14 | #include "internals.h" |
| 14 | 15 | ||
| @@ -39,25 +40,58 @@ void suspend_device_irqs(void) | |||
| 39 | } | 40 | } |
| 40 | EXPORT_SYMBOL_GPL(suspend_device_irqs); | 41 | EXPORT_SYMBOL_GPL(suspend_device_irqs); |
| 41 | 42 | ||
| 42 | /** | 43 | static void resume_irqs(bool want_early) |
| 43 | * resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs() | ||
| 44 | * | ||
| 45 | * Enable all interrupt lines previously disabled by suspend_device_irqs() that | ||
| 46 | * have the IRQS_SUSPENDED flag set. | ||
| 47 | */ | ||
| 48 | void resume_device_irqs(void) | ||
| 49 | { | 44 | { |
| 50 | struct irq_desc *desc; | 45 | struct irq_desc *desc; |
| 51 | int irq; | 46 | int irq; |
| 52 | 47 | ||
| 53 | for_each_irq_desc(irq, desc) { | 48 | for_each_irq_desc(irq, desc) { |
| 54 | unsigned long flags; | 49 | unsigned long flags; |
| 50 | bool is_early = desc->action && | ||
| 51 | desc->action->flags & IRQF_EARLY_RESUME; | ||
| 52 | |||
| 53 | if (is_early != want_early) | ||
| 54 | continue; | ||
| 55 | 55 | ||
| 56 | raw_spin_lock_irqsave(&desc->lock, flags); | 56 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 57 | __enable_irq(desc, irq, true); | 57 | __enable_irq(desc, irq, true); |
| 58 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 58 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 59 | } | 59 | } |
| 60 | } | 60 | } |
| 61 | |||
| 62 | /** | ||
| 63 | * irq_pm_syscore_ops - enable interrupt lines early | ||
| 64 | * | ||
| 65 | * Enable all interrupt lines with %IRQF_EARLY_RESUME set. | ||
| 66 | */ | ||
| 67 | static void irq_pm_syscore_resume(void) | ||
| 68 | { | ||
| 69 | resume_irqs(true); | ||
| 70 | } | ||
| 71 | |||
| 72 | static struct syscore_ops irq_pm_syscore_ops = { | ||
| 73 | .resume = irq_pm_syscore_resume, | ||
| 74 | }; | ||
| 75 | |||
| 76 | static int __init irq_pm_init_ops(void) | ||
| 77 | { | ||
| 78 | register_syscore_ops(&irq_pm_syscore_ops); | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | device_initcall(irq_pm_init_ops); | ||
| 83 | |||
| 84 | /** | ||
| 85 | * resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs() | ||
| 86 | * | ||
| 87 | * Enable all non-%IRQF_EARLY_RESUME interrupt lines previously | ||
| 88 | * disabled by suspend_device_irqs() that have the IRQS_SUSPENDED flag | ||
| 89 | * set as well as those with %IRQF_FORCE_RESUME. | ||
| 90 | */ | ||
| 91 | void resume_device_irqs(void) | ||
| 92 | { | ||
| 93 | resume_irqs(false); | ||
| 94 | } | ||
| 61 | EXPORT_SYMBOL_GPL(resume_device_irqs); | 95 | EXPORT_SYMBOL_GPL(resume_device_irqs); |
| 62 | 96 | ||
| 63 | /** | 97 | /** |
