1System 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 as 44expected during the suspend-resume cycle, but does not guarantee that the 45interrupt will wake the system from a suspended state -- for such cases it is 46necessary to use enable_irq_wake(). 47 48Note that the IRQF_NO_SUSPEND flag affects the entire IRQ and not just one 49user of it. Thus, if the IRQ is shared, all of the interrupt handlers installed 50for it will be executed as usual after suspend_device_irqs(), even if the 51IRQF_NO_SUSPEND flag was not passed to request_irq() (or equivalent) by some of 52the IRQ's users. For this reason, using IRQF_NO_SUSPEND and IRQF_SHARED at the 53same time should be avoided. 54 55 56System Wakeup Interrupts, enable_irq_wake() and disable_irq_wake() 57------------------------------------------------------------------ 58 59System wakeup interrupts generally need to be configured to wake up the system 60from sleep states, especially if they are used for different purposes (e.g. as 61I/O interrupts) in the working state. 62 63That may involve turning on a special signal handling logic within the platform 64(such as an SoC) so that signals from a given line are routed in a different way 65during system sleep so as to trigger a system wakeup when needed. For example, 66the platform may include a dedicated interrupt controller used specifically for 67handling system wakeup events. Then, if a given interrupt line is supposed to 68wake up the system from sleep sates, the corresponding input of that interrupt 69controller needs to be enabled to receive signals from the line in question. 70After wakeup, it generally is better to disable that input to prevent the 71dedicated controller from triggering interrupts unnecessarily. 72 73The IRQ subsystem provides two helper functions to be used by device drivers for 74those purposes. Namely, enable_irq_wake() turns on the platform's logic for 75handling the given IRQ as a system wakeup interrupt line and disable_irq_wake() 76turns that logic off. 77 78Calling enable_irq_wake() causes suspend_device_irqs() to treat the given IRQ 79in a special way. Namely, the IRQ remains enabled, by on the first interrupt 80it will be disabled, marked as pending and "suspended" so that it will be 81re-enabled by resume_device_irqs() during the subsequent system resume. Also 82the PM core is notified about the event which causes the system suspend in 83progress to be aborted (that doesn't have to happen immediately, but at one 84of the points where the suspend thread looks for pending wakeup events). 85 86This way every interrupt from a wakeup interrupt source will either cause the 87system suspend currently in progress to be aborted or wake up the system if 88already suspended. However, after suspend_device_irqs() interrupt handlers are 89not executed for system wakeup IRQs. They are only executed for IRQF_NO_SUSPEND 90IRQs at that time, but those IRQs should not be configured for system wakeup 91using enable_irq_wake(). 92 93 94Interrupts and Suspend-to-Idle 95------------------------------ 96 97Suspend-to-idle (also known as the "freeze" sleep state) is a relatively new 98system sleep state that works by idling all of the processors and waiting for 99interrupts right after the "noirq" phase of suspending devices. 100 101Of course, this means that all of the interrupts with the IRQF_NO_SUSPEND flag 102set will bring CPUs out of idle while in that state, but they will not cause the 103IRQ subsystem to trigger a system wakeup. 104 105System wakeup interrupts, in turn, will trigger wakeup from suspend-to-idle in 106analogy with what they do in the full system suspend case. The only difference 107is that the wakeup from suspend-to-idle is signaled using the usual working 108state interrupt delivery mechanisms and doesn't require the platform to use 109any special interrupt handling logic for it to work. 110 111 112IRQF_NO_SUSPEND and enable_irq_wake() 113------------------------------------- 114 115There are very few valid reasons to use both enable_irq_wake() and the 116IRQF_NO_SUSPEND flag on the same IRQ, and it is never valid to use both for the 117same device. 118 119First of all, if the IRQ is not shared, the rules for handling IRQF_NO_SUSPEND 120interrupts (interrupt handlers are invoked after suspend_device_irqs()) are 121directly at odds with the rules for handling system wakeup interrupts (interrupt 122handlers are not invoked after suspend_device_irqs()). 123 124Second, both enable_irq_wake() and IRQF_NO_SUSPEND apply to entire IRQs and not 125to individual interrupt handlers, so sharing an IRQ between a system wakeup 126interrupt source and an IRQF_NO_SUSPEND interrupt source does not generally 127make sense. 128 129In rare cases an IRQ can be shared between a wakeup device driver and an 130IRQF_NO_SUSPEND user. In order for this to be safe, the wakeup device driver 131must be able to discern spurious IRQs from genuine wakeup events (signalling 132the latter to the core with pm_system_wakeup()), must use enable_irq_wake() to 133ensure that the IRQ will function as a wakeup source, and must request the IRQ 134with IRQF_COND_SUSPEND to tell the core that it meets these requirements. If 135these requirements are not met, it is not valid to use IRQF_COND_SUSPEND. 136