• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
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: */
27 static DECLARE_BITMAP(irqs_resend, IRQ_BITMAP_BITS);
28 
29 /*
30  * Run software resends of IRQ's
31  */
resend_irqs(unsigned long arg)32 static void resend_irqs(unsigned long arg)
33 {
34 	struct irq_desc *desc;
35 	int irq;
36 
37 	while (!bitmap_empty(irqs_resend, nr_irqs)) {
38 		irq = find_first_bit(irqs_resend, nr_irqs);
39 		clear_bit(irq, irqs_resend);
40 		desc = irq_to_desc(irq);
41 		if (!desc)
42 			continue;
43 		local_irq_disable();
44 		desc->handle_irq(desc);
45 		local_irq_enable();
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  */
check_irq_resend(struct irq_desc * desc)59 void check_irq_resend(struct irq_desc *desc)
60 {
61 	/*
62 	 * We do not resend level type interrupts. Level type
63 	 * interrupts are resent by hardware when they are still
64 	 * active. Clear the pending bit so suspend/resume does not
65 	 * get confused.
66 	 */
67 	if (irq_settings_is_level(desc)) {
68 		desc->istate &= ~IRQS_PENDING;
69 		return;
70 	}
71 	if (desc->istate & IRQS_REPLAY)
72 		return;
73 	if (desc->istate & IRQS_PENDING) {
74 		desc->istate &= ~IRQS_PENDING;
75 		desc->istate |= IRQS_REPLAY;
76 
77 		if (!desc->irq_data.chip->irq_retrigger ||
78 		    !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
79 #ifdef CONFIG_HARDIRQS_SW_RESEND
80 			unsigned int irq = irq_desc_get_irq(desc);
81 
82 			/*
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.
87 			 */
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;
96 				irq = desc->parent_irq;
97 			}
98 			/* Set it pending and activate the softirq: */
99 			set_bit(irq, irqs_resend);
100 			tasklet_schedule(&resend_tasklet);
101 #endif
102 		}
103 	}
104 }
105