linux/arch/mips/kernel/irq.c
<<
>>
Prefs
   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/proc_fs.h>
  17#include <linux/mm.h>
  18#include <linux/random.h>
  19#include <linux/sched.h>
  20#include <linux/seq_file.h>
  21#include <linux/kallsyms.h>
  22#include <linux/kgdb.h>
  23#include <linux/ftrace.h>
  24
  25#include <linux/atomic.h>
  26#include <asm/uaccess.h>
  27
  28#ifdef CONFIG_KGDB
  29int kgdb_early_setup;
  30#endif
  31
  32static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
  33
  34int allocate_irqno(void)
  35{
  36        int irq;
  37
  38again:
  39        irq = find_first_zero_bit(irq_map, NR_IRQS);
  40
  41        if (irq >= NR_IRQS)
  42                return -ENOSPC;
  43
  44        if (test_and_set_bit(irq, irq_map))
  45                goto again;
  46
  47        return irq;
  48}
  49
  50/*
  51 * Allocate the 16 legacy interrupts for i8259 devices.  This happens early
  52 * in the kernel initialization so treating allocation failure as BUG() is
  53 * ok.
  54 */
  55void __init alloc_legacy_irqno(void)
  56{
  57        int i;
  58
  59        for (i = 0; i <= 16; i++)
  60                BUG_ON(test_and_set_bit(i, irq_map));
  61}
  62
  63void free_irqno(unsigned int irq)
  64{
  65        smp_mb__before_atomic();
  66        clear_bit(irq, irq_map);
  67        smp_mb__after_atomic();
  68}
  69
  70/*
  71 * 'what should we do if we get a hw irq event on an illegal vector'.
  72 * each architecture has to answer this themselves.
  73 */
  74void ack_bad_irq(unsigned int irq)
  75{
  76        printk("unexpected IRQ # %d\n", irq);
  77}
  78
  79atomic_t irq_err_count;
  80
  81int arch_show_interrupts(struct seq_file *p, int prec)
  82{
  83        seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
  84        return 0;
  85}
  86
  87asmlinkage void spurious_interrupt(void)
  88{
  89        atomic_inc(&irq_err_count);
  90}
  91
  92void __init init_IRQ(void)
  93{
  94        int i;
  95
  96#ifdef CONFIG_KGDB
  97        if (kgdb_early_setup)
  98                return;
  99#endif
 100
 101        for (i = 0; i < NR_IRQS; i++)
 102                irq_set_noprobe(i);
 103
 104        arch_init_irq();
 105
 106#ifdef CONFIG_KGDB
 107        if (!kgdb_early_setup)
 108                kgdb_early_setup = 1;
 109#endif
 110}
 111
 112#ifdef DEBUG_STACKOVERFLOW
 113static inline void check_stack_overflow(void)
 114{
 115        unsigned long sp;
 116
 117        __asm__ __volatile__("move %0, $sp" : "=r" (sp));
 118        sp &= THREAD_MASK;
 119
 120        /*
 121         * Check for stack overflow: is there less than STACK_WARN free?
 122         * STACK_WARN is defined as 1/8 of THREAD_SIZE by default.
 123         */
 124        if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
 125                printk("do_IRQ: stack overflow: %ld\n",
 126                       sp - sizeof(struct thread_info));
 127                dump_stack();
 128        }
 129}
 130#else
 131static inline void check_stack_overflow(void) {}
 132#endif
 133
 134
 135/*
 136 * do_IRQ handles all normal device IRQ's (the special
 137 * SMP cross-CPU interrupts have their own specific
 138 * handlers).
 139 */
 140void __irq_entry do_IRQ(unsigned int irq)
 141{
 142        irq_enter();
 143        check_stack_overflow();
 144        generic_handle_irq(irq);
 145        irq_exit();
 146}
 147
 148