0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/irq.h>
0012 #include <linux/random.h>
0013 #include <linux/sched.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/kernel_stat.h>
0016
0017 #include <asm/irq_regs.h>
0018
0019 #include <trace/events/irq.h>
0020
0021 #include "internals.h"
0022
0023 #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
0024 void (*handle_arch_irq)(struct pt_regs *) __ro_after_init;
0025 #endif
0026
0027
0028
0029
0030
0031
0032
0033 void handle_bad_irq(struct irq_desc *desc)
0034 {
0035 unsigned int irq = irq_desc_get_irq(desc);
0036
0037 print_irq_desc(irq, desc);
0038 kstat_incr_irqs_this_cpu(desc);
0039 ack_bad_irq(irq);
0040 }
0041 EXPORT_SYMBOL_GPL(handle_bad_irq);
0042
0043
0044
0045
0046 irqreturn_t no_action(int cpl, void *dev_id)
0047 {
0048 return IRQ_NONE;
0049 }
0050 EXPORT_SYMBOL_GPL(no_action);
0051
0052 static void warn_no_thread(unsigned int irq, struct irqaction *action)
0053 {
0054 if (test_and_set_bit(IRQTF_WARNED, &action->thread_flags))
0055 return;
0056
0057 printk(KERN_WARNING "IRQ %d device %s returned IRQ_WAKE_THREAD "
0058 "but no thread function available.", irq, action->name);
0059 }
0060
0061 void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
0062 {
0063
0064
0065
0066
0067
0068 if (action->thread->flags & PF_EXITING)
0069 return;
0070
0071
0072
0073
0074
0075 if (test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags))
0076 return;
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 desc->threads_oneshot |= action->thread_mask;
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 atomic_inc(&desc->threads_active);
0135
0136 wake_up_process(action->thread);
0137 }
0138
0139 irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc)
0140 {
0141 irqreturn_t retval = IRQ_NONE;
0142 unsigned int irq = desc->irq_data.irq;
0143 struct irqaction *action;
0144
0145 record_irq_time(desc);
0146
0147 for_each_action_of_desc(desc, action) {
0148 irqreturn_t res;
0149
0150
0151
0152
0153 if (irq_settings_can_thread(desc) &&
0154 !(action->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT)))
0155 lockdep_hardirq_threaded();
0156
0157 trace_irq_handler_entry(irq, action);
0158 res = action->handler(irq, action->dev_id);
0159 trace_irq_handler_exit(irq, action, res);
0160
0161 if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pS enabled interrupts\n",
0162 irq, action->handler))
0163 local_irq_disable();
0164
0165 switch (res) {
0166 case IRQ_WAKE_THREAD:
0167
0168
0169
0170
0171 if (unlikely(!action->thread_fn)) {
0172 warn_no_thread(irq, action);
0173 break;
0174 }
0175
0176 __irq_wake_thread(desc, action);
0177 break;
0178
0179 default:
0180 break;
0181 }
0182
0183 retval |= res;
0184 }
0185
0186 return retval;
0187 }
0188
0189 irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
0190 {
0191 irqreturn_t retval;
0192
0193 retval = __handle_irq_event_percpu(desc);
0194
0195 add_interrupt_randomness(desc->irq_data.irq);
0196
0197 if (!irq_settings_no_debug(desc))
0198 note_interrupt(desc, retval);
0199 return retval;
0200 }
0201
0202 irqreturn_t handle_irq_event(struct irq_desc *desc)
0203 {
0204 irqreturn_t ret;
0205
0206 desc->istate &= ~IRQS_PENDING;
0207 irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
0208 raw_spin_unlock(&desc->lock);
0209
0210 ret = handle_irq_event_percpu(desc);
0211
0212 raw_spin_lock(&desc->lock);
0213 irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
0214 return ret;
0215 }
0216
0217 #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
0218 int __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
0219 {
0220 if (handle_arch_irq)
0221 return -EBUSY;
0222
0223 handle_arch_irq = handle_irq;
0224 return 0;
0225 }
0226
0227
0228
0229
0230
0231
0232 asmlinkage void noinstr generic_handle_arch_irq(struct pt_regs *regs)
0233 {
0234 struct pt_regs *old_regs;
0235
0236 irq_enter();
0237 old_regs = set_irq_regs(regs);
0238 handle_arch_irq(regs);
0239 set_irq_regs(old_regs);
0240 irq_exit();
0241 }
0242 #endif