diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-09-30 14:46:13 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-09-30 14:46:13 -0400 |
| commit | e4cb0c9e92f7b16db7a1e892ac6bcf2f736dfd50 (patch) | |
| tree | 35d66a4fc97aa642c14483966f050b5663ff02ca | |
| parent | 905563ff47db35dcb3f69e69d434207270ad1966 (diff) | |
| parent | 27f3d18630cd7fbb03b62bd78a74303cb8c88069 (diff) | |
Merge branch 'pm-genirq' into acpi-pm
| -rw-r--r-- | Documentation/power/suspend-and-interrupts.txt | 123 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 5 | ||||
| -rw-r--r-- | drivers/base/power/wakeup.c | 16 | ||||
| -rw-r--r-- | drivers/base/syscore.c | 7 | ||||
| -rw-r--r-- | drivers/pci/pcie/pme.c | 61 | ||||
| -rw-r--r-- | include/linux/interrupt.h | 5 | ||||
| -rw-r--r-- | include/linux/irq.h | 8 | ||||
| -rw-r--r-- | include/linux/irqdesc.h | 10 | ||||
| -rw-r--r-- | include/linux/suspend.h | 4 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 85 | ||||
| -rw-r--r-- | kernel/irq/internals.h | 16 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 32 | ||||
| -rw-r--r-- | kernel/irq/pm.c | 159 | ||||
| -rw-r--r-- | kernel/power/process.c | 1 |
14 files changed, 415 insertions, 117 deletions
diff --git a/Documentation/power/suspend-and-interrupts.txt b/Documentation/power/suspend-and-interrupts.txt new file mode 100644 index 000000000000..69663640dea5 --- /dev/null +++ b/Documentation/power/suspend-and-interrupts.txt | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | System Suspend and Device Interrupts | ||
| 2 | |||
| 3 | Copyright (C) 2014 Intel Corp. | ||
| 4 | Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
| 5 | |||
| 6 | |||
| 7 | Suspending and Resuming Device IRQs | ||
| 8 | ----------------------------------- | ||
| 9 | |||
| 10 | Device interrupt request lines (IRQs) are generally disabled during system | ||
| 11 | suspend 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 | ||
| 13 | devices). That is done by suspend_device_irqs(). | ||
| 14 | |||
| 15 | The rationale for doing so is that after the "late" phase of device suspend | ||
| 16 | there is no legitimate reason why any interrupts from suspended devices should | ||
| 17 | trigger and if any devices have not been suspended properly yet, it is better to | ||
| 18 | block interrupts from them anyway. Also, in the past we had problems with | ||
| 19 | interrupt handlers for shared IRQs that device drivers implementing them were | ||
| 20 | not prepared for interrupts triggering after their devices had been suspended. | ||
| 21 | In some cases they would attempt to access, for example, memory address spaces | ||
| 22 | of suspended devices and cause unpredictable behavior to ensue as a result. | ||
| 23 | Unfortunately, such problems are very difficult to debug and the introduction | ||
| 24 | of suspend_device_irqs(), along with the "noirq" phase of device suspend and | ||
| 25 | resume, was the only practical way to mitigate them. | ||
| 26 | |||
| 27 | Device IRQs are re-enabled during system resume, right before the "early" phase | ||
| 28 | of resuming devices (that is, before starting to execute ->resume_early | ||
| 29 | callbacks for devices). The function doing that is resume_device_irqs(). | ||
| 30 | |||
| 31 | |||
| 32 | The IRQF_NO_SUSPEND Flag | ||
| 33 | ------------------------ | ||
| 34 | |||
| 35 | There are interrupts that can legitimately trigger during the entire system | ||
| 36 | suspend-resume cycle, including the "noirq" phases of suspending and resuming | ||
| 37 | devices as well as during the time when nonboot CPUs are taken offline and | ||
| 38 | brought back online. That applies to timer interrupts in the first place, | ||
| 39 | but also to IPIs and to some other special-purpose interrupts. | ||
| 40 | |||
| 41 | The IRQF_NO_SUSPEND flag is used to indicate that to the IRQ subsystem when | ||
| 42 | requesting a special-purpose interrupt. It causes suspend_device_irqs() to | ||
| 43 | leave the corresponding IRQ enabled so as to allow the interrupt to work all | ||
| 44 | the time as expected. | ||
| 45 | |||
| 46 | Note that the IRQF_NO_SUSPEND flag affects the entire IRQ and not just one | ||
| 47 | user of it. Thus, if the IRQ is shared, all of the interrupt handlers installed | ||
| 48 | for it will be executed as usual after suspend_device_irqs(), even if the | ||
| 49 | IRQF_NO_SUSPEND flag was not passed to request_irq() (or equivalent) by some of | ||
| 50 | the IRQ's users. For this reason, using IRQF_NO_SUSPEND and IRQF_SHARED at the | ||
| 51 | same time should be avoided. | ||
| 52 | |||
| 53 | |||
| 54 | System Wakeup Interrupts, enable_irq_wake() and disable_irq_wake() | ||
| 55 | ------------------------------------------------------------------ | ||
| 56 | |||
| 57 | System wakeup interrupts generally need to be configured to wake up the system | ||
| 58 | from sleep states, especially if they are used for different purposes (e.g. as | ||
| 59 | I/O interrupts) in the working state. | ||
| 60 | |||
| 61 | That 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 | ||
| 63 | during system sleep so as to trigger a system wakeup when needed. For example, | ||
| 64 | the platform may include a dedicated interrupt controller used specifically for | ||
| 65 | handling system wakeup events. Then, if a given interrupt line is supposed to | ||
| 66 | wake up the system from sleep sates, the corresponding input of that interrupt | ||
| 67 | controller needs to be enabled to receive signals from the line in question. | ||
| 68 | After wakeup, it generally is better to disable that input to prevent the | ||
| 69 | dedicated controller from triggering interrupts unnecessarily. | ||
| 70 | |||
| 71 | The IRQ subsystem provides two helper functions to be used by device drivers for | ||
| 72 | those purposes. Namely, enable_irq_wake() turns on the platform's logic for | ||
| 73 | handling the given IRQ as a system wakeup interrupt line and disable_irq_wake() | ||
| 74 | turns that logic off. | ||
| 75 | |||
| 76 | Calling enable_irq_wake() causes suspend_device_irqs() to treat the given IRQ | ||
| 77 | in a special way. Namely, the IRQ remains enabled, by on the first interrupt | ||
| 78 | it will be disabled, marked as pending and "suspended" so that it will be | ||
| 79 | re-enabled by resume_device_irqs() during the subsequent system resume. Also | ||
| 80 | the PM core is notified about the event which casues the system suspend in | ||
| 81 | progress to be aborted (that doesn't have to happen immediately, but at one | ||
| 82 | of the points where the suspend thread looks for pending wakeup events). | ||
| 83 | |||
| 84 | This way every interrupt from a wakeup interrupt source will either cause the | ||
| 85 | system suspend currently in progress to be aborted or wake up the system if | ||
| 86 | already suspended. However, after suspend_device_irqs() interrupt handlers are | ||
| 87 | not executed for system wakeup IRQs. They are only executed for IRQF_NO_SUSPEND | ||
| 88 | IRQs at that time, but those IRQs should not be configured for system wakeup | ||
| 89 | using enable_irq_wake(). | ||
| 90 | |||
| 91 | |||
| 92 | Interrupts and Suspend-to-Idle | ||
| 93 | ------------------------------ | ||
| 94 | |||
| 95 | Suspend-to-idle (also known as the "freeze" sleep state) is a relatively new | ||
| 96 | system sleep state that works by idling all of the processors and waiting for | ||
| 97 | interrupts right after the "noirq" phase of suspending devices. | ||
| 98 | |||
| 99 | Of course, this means that all of the interrupts with the IRQF_NO_SUSPEND flag | ||
| 100 | set will bring CPUs out of idle while in that state, but they will not cause the | ||
| 101 | IRQ subsystem to trigger a system wakeup. | ||
| 102 | |||
| 103 | System wakeup interrupts, in turn, will trigger wakeup from suspend-to-idle in | ||
| 104 | analogy with what they do in the full system suspend case. The only difference | ||
| 105 | is that the wakeup from suspend-to-idle is signaled using the usual working | ||
| 106 | state interrupt delivery mechanisms and doesn't require the platform to use | ||
| 107 | any special interrupt handling logic for it to work. | ||
| 108 | |||
| 109 | |||
| 110 | IRQF_NO_SUSPEND and enable_irq_wake() | ||
| 111 | ------------------------------------- | ||
| 112 | |||
| 113 | There are no valid reasons to use both enable_irq_wake() and the IRQF_NO_SUSPEND | ||
| 114 | flag on the same IRQ. | ||
| 115 | |||
| 116 | First of all, if the IRQ is not shared, the rules for handling IRQF_NO_SUSPEND | ||
| 117 | interrupts (interrupt handlers are invoked after suspend_device_irqs()) are | ||
| 118 | directly at odds with the rules for handling system wakeup interrupts (interrupt | ||
| 119 | handlers are not invoked after suspend_device_irqs()). | ||
| 120 | |||
| 121 | Second, both enable_irq_wake() and IRQF_NO_SUSPEND apply to entire IRQs and not | ||
| 122 | to individual interrupt handlers, so sharing an IRQ between a system wakeup | ||
| 123 | interrupt source and an IRQF_NO_SUSPEND interrupt source does not make sense. | ||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 337ce5a9b15c..1183d545da1e 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -2623,6 +2623,7 @@ static struct irq_chip ioapic_chip __read_mostly = { | |||
| 2623 | .irq_eoi = ack_apic_level, | 2623 | .irq_eoi = ack_apic_level, |
| 2624 | .irq_set_affinity = native_ioapic_set_affinity, | 2624 | .irq_set_affinity = native_ioapic_set_affinity, |
| 2625 | .irq_retrigger = ioapic_retrigger_irq, | 2625 | .irq_retrigger = ioapic_retrigger_irq, |
| 2626 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
| 2626 | }; | 2627 | }; |
| 2627 | 2628 | ||
| 2628 | static inline void init_IO_APIC_traps(void) | 2629 | static inline void init_IO_APIC_traps(void) |
| @@ -3173,6 +3174,7 @@ static struct irq_chip msi_chip = { | |||
| 3173 | .irq_ack = ack_apic_edge, | 3174 | .irq_ack = ack_apic_edge, |
| 3174 | .irq_set_affinity = msi_set_affinity, | 3175 | .irq_set_affinity = msi_set_affinity, |
| 3175 | .irq_retrigger = ioapic_retrigger_irq, | 3176 | .irq_retrigger = ioapic_retrigger_irq, |
| 3177 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
| 3176 | }; | 3178 | }; |
| 3177 | 3179 | ||
| 3178 | int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 3180 | int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
| @@ -3271,6 +3273,7 @@ static struct irq_chip dmar_msi_type = { | |||
| 3271 | .irq_ack = ack_apic_edge, | 3273 | .irq_ack = ack_apic_edge, |
| 3272 | .irq_set_affinity = dmar_msi_set_affinity, | 3274 | .irq_set_affinity = dmar_msi_set_affinity, |
| 3273 | .irq_retrigger = ioapic_retrigger_irq, | 3275 | .irq_retrigger = ioapic_retrigger_irq, |
| 3276 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
| 3274 | }; | 3277 | }; |
| 3275 | 3278 | ||
