xref: /openbmc/linux/kernel/irq/handle.c (revision 1277a5325adfc53caac7dd3dac5d3d2fd2a125b4)
1 /*
2  * linux/kernel/irq/handle.c
3  *
4  * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
5  * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
6  *
7  * This file contains the core interrupt handling code.
8  *
9  * Detailed information is available in Documentation/DocBook/genericirq
10  *
11  */
12 
13 #include <linux/irq.h>
14 #include <linux/random.h>
15 #include <linux/sched.h>
16 #include <linux/interrupt.h>
17 #include <linux/kernel_stat.h>
18 
19 #include <trace/events/irq.h>
20 
21 #include "internals.h"
22 
23 /**
24  * handle_bad_irq - handle spurious and unhandled irqs
25  * @irq:       the interrupt number
26  * @desc:      description of the interrupt
27  *
28  * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
29  */
30 void handle_bad_irq(unsigned int irq, struct irq_desc *desc)
31 {
32 	print_irq_desc(irq, desc);
33 	kstat_incr_irqs_this_cpu(irq, desc);
34 	ack_bad_irq(irq);
35 }
36 
37 /*
38  * Special, empty irq handler:
39  */
40 irqreturn_t no_action(int cpl, void *dev_id)
41 {
42 	return IRQ_NONE;
43 }
44 
45 static void warn_no_thread(unsigned int irq, struct irqaction *action)
46 {
47 	if (test_and_set_bit(IRQTF_WARNED, &action->thread_flags))
48 		return;
49 
50 	printk(KERN_WARNING "IRQ %d device %s returned IRQ_WAKE_THREAD "
51 	       "but no thread function available.", irq, action->name);
52 }
53 
54 irqreturn_t
55 handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
56 {
57 	irqreturn_t ret, retval = IRQ_NONE;
58 	unsigned int status = 0, irq = desc->irq_data.irq;
59 
60 	do {
61 		trace_irq_handler_entry(irq, action);
62 		ret = action->handler(irq, action->dev_id);
63 		trace_irq_handler_exit(irq, action, ret);
64 
65 		if (WARN_ON_ONCE(!irqs_disabled()))
66 			local_irq_disable();
67 
68 		switch (ret) {
69 		case IRQ_WAKE_THREAD:
70 			/*
71 			 * Set result to handled so the spurious check
72 			 * does not trigger.
73 			 */
74 			ret = IRQ_HANDLED;
75 
76 			/*
77 			 * Catch drivers which return WAKE_THREAD but
78 			 * did not set up a thread function
79 			 */
80 			if (unlikely(!action->thread_fn)) {
81 				warn_no_thread(irq, action);
82 				break;
83 			}
84 
85 			/*
86 			 * Wake up the handler thread for this
87 			 * action. In case the thread crashed and was
88 			 * killed we just pretend that we handled the
89 			 * interrupt. The hardirq handler above has
90 			 * disabled the device interrupt, so no irq
91 			 * storm is lurking.
92 			 */
93 			if (likely(!test_bit(IRQTF_DIED,
94 					     &action->thread_flags))) {
95 				set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
96 				wake_up_process(action->thread);
97 			}
98 
99 			/* Fall through to add to randomness */
100 		case IRQ_HANDLED:
101 			status |= action->flags;
102 			break;
103 
104 		default:
105 			break;
106 		}
107 
108 		retval |= ret;
109 		action = action->next;
110 	} while (action);
111 
112 	if (status & IRQF_SAMPLE_RANDOM)
113 		add_interrupt_randomness(irq);
114 
115 	if (!noirqdebug)
116 		note_interrupt(irq, desc, ret);
117 	return retval;
118 }
119 
120 irqreturn_t handle_irq_event(struct irq_desc *desc)
121 {
122 	struct irqaction *action = desc->action;
123 	irqreturn_t ret;
124 
125 	desc->status &= ~IRQ_PENDING;
126 	desc->status |= IRQ_INPROGRESS;
127 	raw_spin_unlock(&desc->lock);
128 
129 	ret = handle_irq_event_percpu(desc, action);
130 
131 	raw_spin_lock(&desc->lock);
132 	desc->status &= ~IRQ_INPROGRESS;
133 	return ret;
134 }
135 
136 /**
137  * handle_IRQ_event - irq action chain handler
138  * @irq:	the interrupt number
139  * @action:	the interrupt action chain for this irq
140  *
141  * Handles the action chain of an irq event
142  */
143 irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
144 {
145 	return handle_irq_event_percpu(irq_to_desc(irq), action);
146 }
147