1 /* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Code to handle x86 style IRQs plus some generic interrupt stuff. 7 * 8 * Copyright (C) 1992 Linus Torvalds 9 * Copyright (C) 1994 - 2000 Ralf Baechle 10 */ 11 #include <linux/kernel.h> 12 #include <linux/delay.h> 13 #include <linux/init.h> 14 #include <linux/interrupt.h> 15 #include <linux/kernel_stat.h> 16 #include <linux/module.h> 17 #include <linux/proc_fs.h> 18 #include <linux/slab.h> 19 #include <linux/mm.h> 20 #include <linux/random.h> 21 #include <linux/sched.h> 22 #include <linux/seq_file.h> 23 #include <linux/kallsyms.h> 24 #include <linux/kgdb.h> 25 #include <linux/ftrace.h> 26 27 #include <asm/atomic.h> 28 #include <asm/system.h> 29 #include <asm/uaccess.h> 30 31 #ifdef CONFIG_KGDB 32 int kgdb_early_setup; 33 #endif 34 35 static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; 36 37 int allocate_irqno(void) 38 { 39 int irq; 40 41 again: 42 irq = find_first_zero_bit(irq_map, NR_IRQS); 43 44 if (irq >= NR_IRQS) 45 return -ENOSPC; 46 47 if (test_and_set_bit(irq, irq_map)) 48 goto again; 49 50 return irq; 51 } 52 53 /* 54 * Allocate the 16 legacy interrupts for i8259 devices. This happens early 55 * in the kernel initialization so treating allocation failure as BUG() is 56 * ok. 57 */ 58 void __init alloc_legacy_irqno(void) 59 { 60 int i; 61 62 for (i = 0; i <= 16; i++) 63 BUG_ON(test_and_set_bit(i, irq_map)); 64 } 65 66 void free_irqno(unsigned int irq) 67 { 68 smp_mb__before_clear_bit(); 69 clear_bit(irq, irq_map); 70 smp_mb__after_clear_bit(); 71 } 72 73 /* 74 * 'what should we do if we get a hw irq event on an illegal vector'. 75 * each architecture has to answer this themselves. 76 */ 77 void ack_bad_irq(unsigned int irq) 78 { 79 smtc_im_ack_irq(irq); 80 printk("unexpected IRQ # %d\n", irq); 81 } 82 83 atomic_t irq_err_count; 84 85 /* 86 * Generic, controller-independent functions: 87 */ 88 89 int show_interrupts(struct seq_file *p, void *v) 90 { 91 int i = *(loff_t *) v, j; 92 struct irqaction * action; 93 unsigned long flags; 94 95 if (i == 0) { 96 seq_printf(p, " "); 97 for_each_online_cpu(j) 98 seq_printf(p, "CPU%d ", j); 99 seq_putc(p, '\n'); 100 } 101 102 if (i < NR_IRQS) { 103 raw_spin_lock_irqsave(&irq_desc[i].lock, flags); 104 action = irq_desc[i].action; 105 if (!action) 106 goto skip; 107 seq_printf(p, "%3d: ", i); 108 #ifndef CONFIG_SMP 109 seq_printf(p, "%10u ", kstat_irqs(i)); 110 #else 111 for_each_online_cpu(j) 112 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); 113 #endif 114 seq_printf(p, " %14s", irq_desc[i].chip->name); 115 seq_printf(p, " %s", action->name); 116 117 for (action=action->next; action; action = action->next) 118 seq_printf(p, ", %s", action->name); 119 120 seq_putc(p, '\n'); 121 skip: 122 raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); 123 } else if (i == NR_IRQS) { 124 seq_putc(p, '\n'); 125 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); 126 } 127 return 0; 128 } 129 130 asmlinkage void spurious_interrupt(void) 131 { 132 atomic_inc(&irq_err_count); 133 } 134 135 void __init init_IRQ(void) 136 { 137 int i; 138 139 #ifdef CONFIG_KGDB 140 if (kgdb_early_setup) 141 return; 142 #endif 143 144 for (i = 0; i < NR_IRQS; i++) 145 set_irq_noprobe(i); 146 147 arch_init_irq(); 148 149 #ifdef CONFIG_KGDB 150 if (!kgdb_early_setup) 151 kgdb_early_setup = 1; 152 #endif 153 } 154 155 /* 156 * do_IRQ handles all normal device IRQ's (the special 157 * SMP cross-CPU interrupts have their own specific 158 * handlers). 159 */ 160 void __irq_entry do_IRQ(unsigned int irq) 161 { 162 irq_enter(); 163 __DO_IRQ_SMTC_HOOK(irq); 164 generic_handle_irq(irq); 165 irq_exit(); 166 } 167 168 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF 169 /* 170 * To avoid inefficient and in some cases pathological re-checking of 171 * IRQ affinity, we have this variant that skips the affinity check. 172 */ 173 174 void __irq_entry do_IRQ_no_affinity(unsigned int irq) 175 { 176 irq_enter(); 177 __NO_AFFINITY_IRQ_SMTC_HOOK(irq); 178 generic_handle_irq(irq); 179 irq_exit(); 180 } 181 182 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ 183