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