Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pm.c
Go to the documentation of this file.
1 /*
2  * linux/kernel/irq/pm.c
3  *
4  * Copyright (C) 2009 Rafael J. Wysocki <[email protected]>, Novell Inc.
5  *
6  * This file contains power management functions related to interrupts.
7  */
8 
9 #include <linux/irq.h>
10 #include <linux/module.h>
11 #include <linux/interrupt.h>
12 #include <linux/syscore_ops.h>
13 
14 #include "internals.h"
15 
25 {
26  struct irq_desc *desc;
27  int irq;
28 
29  for_each_irq_desc(irq, desc) {
30  unsigned long flags;
31 
32  raw_spin_lock_irqsave(&desc->lock, flags);
33  __disable_irq(desc, irq, true);
34  raw_spin_unlock_irqrestore(&desc->lock, flags);
35  }
36 
37  for_each_irq_desc(irq, desc)
38  if (desc->istate & IRQS_SUSPENDED)
39  synchronize_irq(irq);
40 }
42 
43 static void resume_irqs(bool want_early)
44 {
45  struct irq_desc *desc;
46  int irq;
47 
48  for_each_irq_desc(irq, desc) {
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 
56  raw_spin_lock_irqsave(&desc->lock, flags);
57  __enable_irq(desc, irq, true);
58  raw_spin_unlock_irqrestore(&desc->lock, flags);
59  }
60 }
61 
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 
92 {
93  resume_irqs(false);
94 }
96 
101 {
102  struct irq_desc *desc;
103  int irq;
104 
105  for_each_irq_desc(irq, desc) {
106  /*
107  * Only interrupts which are marked as wakeup source
108  * and have not been disabled before the suspend check
109  * can abort suspend.
110  */
111  if (irqd_is_wakeup_set(&desc->irq_data)) {
112  if (desc->depth == 1 && desc->istate & IRQS_PENDING)
113  return -EBUSY;
114  continue;
115  }
116  /*
117  * Check the non wakeup interrupts whether they need
118  * to be masked before finally going into suspend
119  * state. That's for hardware which has no wakeup
120  * source configuration facility. The chip
121  * implementation indicates that with
122  * IRQCHIP_MASK_ON_SUSPEND.
123  */
124  if (desc->istate & IRQS_SUSPENDED &&
125  irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
126  mask_irq(desc);
127  }
128 
129  return 0;
130 }