]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
a4633adc TG |
2 | /* |
3 | * linux/kernel/irq/resend.c | |
4 | * | |
5 | * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar | |
6 | * Copyright (C) 2005-2006, Thomas Gleixner | |
7 | * | |
8 | * This file contains the IRQ-resend code | |
9 | * | |
10 | * If the interrupt is waiting to be processed, we try to re-run it. | |
11 | * We can't directly run it from here since the caller might be in an | |
12 | * interrupt-protected region. Not all irq controller chips can | |
13 | * retrigger interrupts at the hardware level, so in those cases | |
14 | * we allow the resending of IRQs via a tasklet. | |
15 | */ | |
16 | ||
17 | #include <linux/irq.h> | |
18 | #include <linux/module.h> | |
19 | #include <linux/random.h> | |
20 | #include <linux/interrupt.h> | |
21 | ||
22 | #include "internals.h" | |
23 | ||
24 | #ifdef CONFIG_HARDIRQS_SW_RESEND | |
25 | ||
26 | /* Bitmap to handle software resend of interrupts: */ | |
c1ee6264 | 27 | static DECLARE_BITMAP(irqs_resend, IRQ_BITMAP_BITS); |
a4633adc TG |
28 | |
29 | /* | |
30 | * Run software resends of IRQ's | |
31 | */ | |
32 | static void resend_irqs(unsigned long arg) | |
33 | { | |
34 | struct irq_desc *desc; | |
35 | int irq; | |
36 | ||
85c0f909 YL |
37 | while (!bitmap_empty(irqs_resend, nr_irqs)) { |
38 | irq = find_first_bit(irqs_resend, nr_irqs); | |
a4633adc | 39 | clear_bit(irq, irqs_resend); |
08678b08 | 40 | desc = irq_to_desc(irq); |
1cd54d37 YY |
41 | if (!desc) |
42 | continue; | |
6a6de9ef | 43 | local_irq_disable(); |
bd0b9ac4 | 44 | desc->handle_irq(desc); |
6a6de9ef | 45 | local_irq_enable(); |
a4633adc TG |
46 | } |
47 | } | |
48 | ||
49 | /* Tasklet to handle resend: */ | |
50 | static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0); | |
51 | ||
52 | #endif | |
53 | ||
54 | /* | |
55 | * IRQ resend | |
56 | * | |
57 | * Is called with interrupts disabled and desc->lock held. | |
58 | */ | |
0798abeb | 59 | void check_irq_resend(struct irq_desc *desc) |
a4633adc | 60 | { |
2464286a TG |
61 | /* |
62 | * We do not resend level type interrupts. Level type | |
63 | * interrupts are resent by hardware when they are still | |
d4dc0f90 TG |
64 | * active. Clear the pending bit so suspend/resume does not |
65 | * get confused. | |
2464286a | 66 | */ |
d4dc0f90 TG |
67 | if (irq_settings_is_level(desc)) { |
68 | desc->istate &= ~IRQS_PENDING; | |
87923470 | 69 | return; |
d4dc0f90 | 70 | } |
163ef309 TG |
71 | if (desc->istate & IRQS_REPLAY) |
72 | return; | |
2a0d6fb3 | 73 | if (desc->istate & IRQS_PENDING) { |
2a0d6fb3 | 74 | desc->istate &= ~IRQS_PENDING; |
163ef309 | 75 | desc->istate |= IRQS_REPLAY; |
a4633adc | 76 | |
21e2b8c6 TG |
77 | if (!desc->irq_data.chip->irq_retrigger || |
78 | !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) { | |
a4633adc | 79 | #ifdef CONFIG_HARDIRQS_SW_RESEND |
0798abeb JL |
80 | unsigned int irq = irq_desc_get_irq(desc); |
81 | ||
293a7a0a | 82 | /* |
75a06189 TG |
83 | * If the interrupt is running in the thread |
84 | * context of the parent irq we need to be | |
85 | * careful, because we cannot trigger it | |
86 | * directly. | |
293a7a0a | 87 | */ |
75a06189 TG |
88 | if (irq_settings_is_nested_thread(desc)) { |
89 | /* | |
90 | * If the parent_irq is valid, we | |
91 | * retrigger the parent, otherwise we | |
92 | * do nothing. | |
93 | */ | |
94 | if (!desc->parent_irq) | |
95 | return; | |
293a7a0a | 96 | irq = desc->parent_irq; |
75a06189 | 97 | } |
a4633adc TG |
98 | /* Set it pending and activate the softirq: */ |
99 | set_bit(irq, irqs_resend); | |
100 | tasklet_schedule(&resend_tasklet); | |
101 | #endif | |
102 | } | |
103 | } | |
104 | } |