Commit | Line | Data |
---|---|---|
151f4e2b | 1 | ==================================== |
27f3d186 | 2 | System Suspend and Device Interrupts |
151f4e2b | 3 | ==================================== |
27f3d186 RW |
4 | |
5 | Copyright (C) 2014 Intel Corp. | |
6 | Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | |
7 | ||
8 | ||
9 | Suspending and Resuming Device IRQs | |
10 | ----------------------------------- | |
11 | ||
12 | Device interrupt request lines (IRQs) are generally disabled during system | |
13 | suspend after the "late" phase of suspending devices (that is, after all of the | |
14 | ->prepare, ->suspend and ->suspend_late callbacks have been executed for all | |
15 | devices). That is done by suspend_device_irqs(). | |
16 | ||
17 | The rationale for doing so is that after the "late" phase of device suspend | |
18 | there is no legitimate reason why any interrupts from suspended devices should | |
19 | trigger and if any devices have not been suspended properly yet, it is better to | |
20 | block interrupts from them anyway. Also, in the past we had problems with | |
21 | interrupt handlers for shared IRQs that device drivers implementing them were | |
22 | not prepared for interrupts triggering after their devices had been suspended. | |
23 | In some cases they would attempt to access, for example, memory address spaces | |
24 | of suspended devices and cause unpredictable behavior to ensue as a result. | |
25 | Unfortunately, such problems are very difficult to debug and the introduction | |
26 | of suspend_device_irqs(), along with the "noirq" phase of device suspend and | |
27 | resume, was the only practical way to mitigate them. | |
28 | ||
29 | Device IRQs are re-enabled during system resume, right before the "early" phase | |
30 | of resuming devices (that is, before starting to execute ->resume_early | |
31 | callbacks for devices). The function doing that is resume_device_irqs(). | |
32 | ||
33 | ||
34 | The IRQF_NO_SUSPEND Flag | |
35 | ------------------------ | |
36 | ||
37 | There are interrupts that can legitimately trigger during the entire system | |
38 | suspend-resume cycle, including the "noirq" phases of suspending and resuming | |
39 | devices as well as during the time when nonboot CPUs are taken offline and | |
40 | brought back online. That applies to timer interrupts in the first place, | |
41 | but also to IPIs and to some other special-purpose interrupts. | |
42 | ||
43 | The IRQF_NO_SUSPEND flag is used to indicate that to the IRQ subsystem when | |
44 | requesting a special-purpose interrupt. It causes suspend_device_irqs() to | |
737eb030 MR |
45 | leave the corresponding IRQ enabled so as to allow the interrupt to work as |
46 | expected during the suspend-resume cycle, but does not guarantee that the | |
47 | interrupt will wake the system from a suspended state -- for such cases it is | |
48 | necessary to use enable_irq_wake(). | |
27f3d186 RW |
49 | |
50 | Note that the IRQF_NO_SUSPEND flag affects the entire IRQ and not just one | |
51 | user of it. Thus, if the IRQ is shared, all of the interrupt handlers installed | |
52 | for it will be executed as usual after suspend_device_irqs(), even if the | |
53 | IRQF_NO_SUSPEND flag was not passed to request_irq() (or equivalent) by some of | |
54 | the IRQ's users. For this reason, using IRQF_NO_SUSPEND and IRQF_SHARED at the | |
55 | same time should be avoided. | |
56 | ||
57 | ||
58 | System Wakeup Interrupts, enable_irq_wake() and disable_irq_wake() | |
59 | ------------------------------------------------------------------ | |
60 | ||
61 | System wakeup interrupts generally need to be configured to wake up the system | |
62 | from sleep states, especially if they are used for different purposes (e.g. as | |
63 | I/O interrupts) in the working state. | |
64 | ||
65 | That may involve turning on a special signal handling logic within the platform | |
66 | (such as an SoC) so that signals from a given line are routed in a different way | |
67 | during system sleep so as to trigger a system wakeup when needed. For example, | |
68 | the platform may include a dedicated interrupt controller used specifically for | |
69 | handling system wakeup events. Then, if a given interrupt line is supposed to | |
71bc571c | 70 | wake up the system from sleep states, the corresponding input of that interrupt |
27f3d186 RW |
71 | controller needs to be enabled to receive signals from the line in question. |
72 | After wakeup, it generally is better to disable that input to prevent the | |
73 | dedicated controller from triggering interrupts unnecessarily. | |
74 | ||
75 | The IRQ subsystem provides two helper functions to be used by device drivers for | |
76 | those purposes. Namely, enable_irq_wake() turns on the platform's logic for | |
77 | handling the given IRQ as a system wakeup interrupt line and disable_irq_wake() | |
78 | turns that logic off. | |
79 | ||
80 | Calling enable_irq_wake() causes suspend_device_irqs() to treat the given IRQ | |
81 | in a special way. Namely, the IRQ remains enabled, by on the first interrupt | |
82 | it will be disabled, marked as pending and "suspended" so that it will be | |
83 | re-enabled by resume_device_irqs() during the subsequent system resume. Also | |
1f999d14 | 84 | the PM core is notified about the event which causes the system suspend in |
27f3d186 RW |
85 | progress to be aborted (that doesn't have to happen immediately, but at one |
86 | of the points where the suspend thread looks for pending wakeup events). | |
87 | ||
88 | This way every interrupt from a wakeup interrupt source will either cause the | |
89 | system suspend currently in progress to be aborted or wake up the system if | |
90 | already suspended. However, after suspend_device_irqs() interrupt handlers are | |
91 | not executed for system wakeup IRQs. They are only executed for IRQF_NO_SUSPEND | |
92 | IRQs at that time, but those IRQs should not be configured for system wakeup | |
93 | using enable_irq_wake(). | |
94 | ||
95 | ||
96 | Interrupts and Suspend-to-Idle | |
97 | ------------------------------ | |
98 | ||
99 | Suspend-to-idle (also known as the "freeze" sleep state) is a relatively new | |
100 | system sleep state that works by idling all of the processors and waiting for | |
101 | interrupts right after the "noirq" phase of suspending devices. | |
102 | ||
103 | Of course, this means that all of the interrupts with the IRQF_NO_SUSPEND flag | |
104 | set will bring CPUs out of idle while in that state, but they will not cause the | |
105 | IRQ subsystem to trigger a system wakeup. | |
106 | ||
107 | System wakeup interrupts, in turn, will trigger wakeup from suspend-to-idle in | |
108 | analogy with what they do in the full system suspend case. The only difference | |
109 | is that the wakeup from suspend-to-idle is signaled using the usual working | |
110 | state interrupt delivery mechanisms and doesn't require the platform to use | |
111 | any special interrupt handling logic for it to work. | |
112 | ||
113 | ||
114 | IRQF_NO_SUSPEND and enable_irq_wake() | |
115 | ------------------------------------- | |
116 | ||
7438b633 MR |
117 | There are very few valid reasons to use both enable_irq_wake() and the |
118 | IRQF_NO_SUSPEND flag on the same IRQ, and it is never valid to use both for the | |
119 | same device. | |
27f3d186 RW |
120 | |
121 | First of all, if the IRQ is not shared, the rules for handling IRQF_NO_SUSPEND | |
122 | interrupts (interrupt handlers are invoked after suspend_device_irqs()) are | |
123 | directly at odds with the rules for handling system wakeup interrupts (interrupt | |
124 | handlers are not invoked after suspend_device_irqs()). | |
125 | ||
126 | Second, both enable_irq_wake() and IRQF_NO_SUSPEND apply to entire IRQs and not | |
127 | to individual interrupt handlers, so sharing an IRQ between a system wakeup | |
7438b633 MR |
128 | interrupt source and an IRQF_NO_SUSPEND interrupt source does not generally |
129 | make sense. | |
130 | ||
131 | In rare cases an IRQ can be shared between a wakeup device driver and an | |
132 | IRQF_NO_SUSPEND user. In order for this to be safe, the wakeup device driver | |
133 | must be able to discern spurious IRQs from genuine wakeup events (signalling | |
134 | the latter to the core with pm_system_wakeup()), must use enable_irq_wake() to | |
135 | ensure that the IRQ will function as a wakeup source, and must request the IRQ | |
136 | with IRQF_COND_SUSPEND to tell the core that it meets these requirements. If | |
137 | these requirements are not met, it is not valid to use IRQF_COND_SUSPEND. |