Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
a4633adc | 2 | /* |
a4633adc TG |
3 | * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar |
4 | * Copyright (C) 2005-2006, Thomas Gleixner | |
5 | * | |
6 | * This file contains the IRQ-resend code | |
7 | * | |
8 | * If the interrupt is waiting to be processed, we try to re-run it. | |
9 | * We can't directly run it from here since the caller might be in an | |
10 | * interrupt-protected region. Not all irq controller chips can | |
11 | * retrigger interrupts at the hardware level, so in those cases | |
12 | * we allow the resending of IRQs via a tasklet. | |
13 | */ | |
14 | ||
15 | #include <linux/irq.h> | |
16 | #include <linux/module.h> | |
17 | #include <linux/random.h> | |
18 | #include <linux/interrupt.h> | |
19 | ||
20 | #include "internals.h" | |
21 | ||
22 | #ifdef CONFIG_HARDIRQS_SW_RESEND | |
23 | ||
bc06a9e0 SD |
24 | /* hlist_head to handle software resend of interrupts: */ |
25 | static HLIST_HEAD(irq_resend_list); | |
26 | static DEFINE_RAW_SPINLOCK(irq_resend_lock); | |
a4633adc TG |
27 | |
28 | /* | |
29 | * Run software resends of IRQ's | |
30 | */ | |
c2609541 | 31 | static void resend_irqs(struct tasklet_struct *unused) |
a4633adc | 32 | { |
4bcdf074 | 33 | guard(raw_spinlock_irq)(&irq_resend_lock); |
bc06a9e0 | 34 | while (!hlist_empty(&irq_resend_list)) { |
4bcdf074 TG |
35 | struct irq_desc *desc; |
36 | ||
37 | desc = hlist_entry(irq_resend_list.first, struct irq_desc, resend_node); | |
bc06a9e0 | 38 | hlist_del_init(&desc->resend_node); |
4bcdf074 | 39 | |
bc06a9e0 | 40 | raw_spin_unlock(&irq_resend_lock); |
bd0b9ac4 | 41 | desc->handle_irq(desc); |
bc06a9e0 | 42 | raw_spin_lock(&irq_resend_lock); |
a4633adc TG |
43 | } |
44 | } | |
45 | ||
46 | /* Tasklet to handle resend: */ | |
c2609541 | 47 | static DECLARE_TASKLET(resend_tasklet, resend_irqs); |
a4633adc | 48 | |
1f85b1f5 TG |
49 | static int irq_sw_resend(struct irq_desc *desc) |
50 | { | |
1f85b1f5 TG |
51 | /* |
52 | * Validate whether this interrupt can be safely injected from | |
53 | * non interrupt context | |
54 | */ | |
9620301c | 55 | if (irqd_is_handle_enforce_irqctx(&desc->irq_data)) |
1f85b1f5 TG |
56 | return -EINVAL; |
57 | ||
58 | /* | |
59 | * If the interrupt is running in the thread context of the parent | |
60 | * irq we need to be careful, because we cannot trigger it | |
61 | * directly. | |
62 | */ | |
63 | if (irq_settings_is_nested_thread(desc)) { | |
64 | /* | |
65 | * If the parent_irq is valid, we retrigger the parent, | |
66 | * otherwise we do nothing. | |
67 | */ | |
68 | if (!desc->parent_irq) | |
69 | return -EINVAL; | |
9f5deb55 JH |
70 | |
71 | desc = irq_to_desc(desc->parent_irq); | |
72 | if (!desc) | |
73 | return -EINVAL; | |
1f85b1f5 TG |
74 | } |
75 | ||
bc06a9e0 | 76 | /* Add to resend_list and activate the softirq: */ |
4bcdf074 TG |
77 | scoped_guard(raw_spinlock, &irq_resend_lock) { |
78 | if (hlist_unhashed(&desc->resend_node)) | |
79 | hlist_add_head(&desc->resend_node, &irq_resend_list); | |
80 | } | |
1f85b1f5 TG |
81 | tasklet_schedule(&resend_tasklet); |
82 | return 0; | |
83 | } | |
84 | ||
bc06a9e0 SD |
85 | void clear_irq_resend(struct irq_desc *desc) |
86 | { | |
4bcdf074 | 87 | guard(raw_spinlock)(&irq_resend_lock); |
bc06a9e0 | 88 | hlist_del_init(&desc->resend_node); |
bc06a9e0 SD |
89 | } |
90 | ||
91 | void irq_resend_init(struct irq_desc *desc) | |
92 | { | |
93 | INIT_HLIST_NODE(&desc->resend_node); | |
94 | } | |
1f85b1f5 | 95 | #else |
bc06a9e0 SD |
96 | void clear_irq_resend(struct irq_desc *desc) {} |
97 | void irq_resend_init(struct irq_desc *desc) {} | |
98 | ||
1f85b1f5 TG |
99 | static int irq_sw_resend(struct irq_desc *desc) |
100 | { | |
101 | return -EINVAL; | |
102 | } | |
a4633adc TG |
103 | #endif |
104 | ||
cd1752d3 MZ |
105 | static int try_retrigger(struct irq_desc *desc) |
106 | { | |
107 | if (desc->irq_data.chip->irq_retrigger) | |
108 | return desc->irq_data.chip->irq_retrigger(&desc->irq_data); | |
109 | ||
110 | #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY | |
111 | return irq_chip_retrigger_hierarchy(&desc->irq_data); | |
112 | #else | |
113 | return 0; | |
114 | #endif | |
115 | } | |
116 | ||
a4633adc TG |
117 | /* |
118 | * IRQ resend | |
119 | * | |
120 | * Is called with interrupts disabled and desc->lock held. | |
121 | */ | |
acd26bcf | 122 | int check_irq_resend(struct irq_desc *desc, bool inject) |
a4633adc | 123 | { |
da90921a TG |
124 | int err = 0; |
125 | ||
2464286a | 126 | /* |
1f85b1f5 TG |
127 | * We do not resend level type interrupts. Level type interrupts |
128 | * are resent by hardware when they are still active. Clear the | |
129 | * pending bit so suspend/resume does not get confused. | |
2464286a | 130 | */ |
d4dc0f90 TG |
131 | if (irq_settings_is_level(desc)) { |
132 | desc->istate &= ~IRQS_PENDING; | |
1f85b1f5 | 133 | return -EINVAL; |
d4dc0f90 | 134 | } |
1f85b1f5 | 135 | |
163ef309 | 136 | if (desc->istate & IRQS_REPLAY) |
1f85b1f5 TG |
137 | return -EBUSY; |
138 | ||
acd26bcf | 139 | if (!(desc->istate & IRQS_PENDING) && !inject) |
da90921a | 140 | return 0; |
a4633adc | 141 | |
da90921a TG |
142 | desc->istate &= ~IRQS_PENDING; |
143 | ||
cd1752d3 | 144 | if (!try_retrigger(desc)) |
da90921a TG |
145 | err = irq_sw_resend(desc); |
146 | ||
5c982c58 | 147 | /* If the retrigger was successful, mark it with the REPLAY bit */ |
da90921a TG |
148 | if (!err) |
149 | desc->istate |= IRQS_REPLAY; | |
150 | return err; | |
a4633adc | 151 | } |
acd26bcf TG |
152 | |
153 | #ifdef CONFIG_GENERIC_IRQ_INJECTION | |
154 | /** | |
155 | * irq_inject_interrupt - Inject an interrupt for testing/error injection | |
156 | * @irq: The interrupt number | |
157 | * | |
158 | * This function must only be used for debug and testing purposes! | |
159 | * | |
160 | * Especially on x86 this can cause a premature completion of an interrupt | |
161 | * affinity change causing the interrupt line to become stale. Very | |
162 | * unlikely, but possible. | |
163 | * | |
164 | * The injection can fail for various reasons: | |
165 | * - Interrupt is not activated | |
166 | * - Interrupt is NMI type or currently replaying | |
167 | * - Interrupt is level type | |
168 | * - Interrupt does not support hardware retrigger and software resend is | |
169 | * either not enabled or not possible for the interrupt. | |
170 | */ | |
171 | int irq_inject_interrupt(unsigned int irq) | |
172 | { | |
4bcdf074 | 173 | int err = -EINVAL; |
acd26bcf TG |
174 | |
175 | /* Try the state injection hardware interface first */ | |
176 | if (!irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true)) | |
177 | return 0; | |
178 | ||
179 | /* That failed, try via the resend mechanism */ | |
4bcdf074 TG |
180 | scoped_irqdesc_get_and_buslock(irq, 0) { |
181 | struct irq_desc *desc = scoped_irqdesc; | |
acd26bcf | 182 | |
4bcdf074 TG |
183 | /* |
184 | * Only try to inject when the interrupt is: | |
185 | * - not NMI type | |
186 | * - activated | |
187 | */ | |
188 | if (!irq_is_nmi(desc) && irqd_is_activated(&desc->irq_data)) | |
189 | err = check_irq_resend(desc, true); | |
190 | } | |
acd26bcf TG |
191 | return err; |
192 | } | |
193 | EXPORT_SYMBOL_GPL(irq_inject_interrupt); | |
194 | #endif |