|
@@ -6,10 +6,12 @@
|
|
|
#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/irq.h>
|
|
|
+#include <asm/idle.h>
|
|
|
|
|
|
atomic_t irq_err_count;
|
|
|
|
|
@@ -188,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);
|