| 1 | ====================================
|
| 2 | System Suspend and Device Interrupts
|
| 3 | ====================================
|
| 4 |
|
| 5 | Copyright (C) 2014 Intel Corp.
|
| 6 | Author: Rafael J. Wysocki <[email protected]>
|
| 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
|
| 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().
|
| 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
|
| 70 | wake up the system from sleep states, the corresponding input of that interrupt
|
| 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, but 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
|
| 84 | the PM core is notified about the event which causes the system suspend in
|
| 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 |
|
| 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.
|
| 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
|
| 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.
|