Merge branch 'linus' into core/iommu
[deliverable/linux.git] / arch / x86 / kernel / irq.c
index bce53e1352a087b5841f9998b4fa63cbf40b8c2a..f13ca1650aafce84b1ecf5c1e665f1bbf4a9f5c6 100644 (file)
@@ -5,11 +5,13 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
+#include <linux/smp.h>
+#include <linux/ftrace.h>
 
 #include <asm/apic.h>
 #include <asm/io_apic.h>
-#include <asm/smp.h>
 #include <asm/irq.h>
+#include <asm/idle.h>
 
 atomic_t irq_err_count;
 
@@ -36,11 +38,7 @@ void ack_bad_irq(unsigned int irq)
 #endif
 }
 
-#ifdef CONFIG_X86_32
-# define irq_stats(x)          (&per_cpu(irq_stat, x))
-#else
-# define irq_stats(x)          cpu_pda(x)
-#endif
+#define irq_stats(x)           (&per_cpu(irq_stat, x))
 /*
  * /proc/interrupts printing:
  */
@@ -192,4 +190,40 @@ u64 arch_irq_stat(void)
        return sum;
 }
 
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs = set_irq_regs(regs);
+
+       /* high bit used in ret_from_ code  */
+       unsigned vector = ~regs->orig_ax;
+       unsigned irq;
+
+       exit_idle();
+       irq_enter();
+
+       irq = __get_cpu_var(vector_irq)[vector];
+
+       if (!handle_irq(irq, regs)) {
+#ifdef CONFIG_X86_64
+               if (!disable_apic)
+                       ack_APIC_irq();
+#endif
+
+               if (printk_ratelimit())
+                       printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
+                              __func__, smp_processor_id(), vector, irq);
+       }
+
+       irq_exit();
+
+       set_irq_regs(old_regs);
+       return 1;
+}
+
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
This page took 0.025138 seconds and 5 git commands to generate.