|
@@ -15,6 +15,9 @@
|
|
|
|
|
|
atomic_t irq_err_count;
|
|
|
|
|
|
+/* Function pointer for generic interrupt vector handling */
|
|
|
+void (*generic_interrupt_extension)(void) = NULL;
|
|
|
+
|
|
|
/*
|
|
|
* 'what should we do if we get a hw irq event on an illegal vector'.
|
|
|
* each architecture has to answer this themselves.
|
|
@@ -56,6 +59,12 @@ static int show_other_interrupts(struct seq_file *p)
|
|
|
seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
|
|
|
seq_printf(p, " Local timer interrupts\n");
|
|
|
#endif
|
|
|
+ if (generic_interrupt_extension) {
|
|
|
+ seq_printf(p, "PLT: ");
|
|
|
+ for_each_online_cpu(j)
|
|
|
+ seq_printf(p, "%10u ", irq_stats(j)->generic_irqs);
|
|
|
+ seq_printf(p, " Platform interrupts\n");
|
|
|
+ }
|
|
|
#ifdef CONFIG_SMP
|
|
|
seq_printf(p, "RES: ");
|
|
|
for_each_online_cpu(j)
|
|
@@ -163,6 +172,8 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
sum += irq_stats(cpu)->apic_timer_irqs;
|
|
|
#endif
|
|
|
+ if (generic_interrupt_extension)
|
|
|
+ sum += irq_stats(cpu)->generic_irqs;
|
|
|
#ifdef CONFIG_SMP
|
|
|
sum += irq_stats(cpu)->irq_resched_count;
|
|
|
sum += irq_stats(cpu)->irq_call_count;
|
|
@@ -226,4 +237,27 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Handler for GENERIC_INTERRUPT_VECTOR.
|
|
|
+ */
|
|
|
+void smp_generic_interrupt(struct pt_regs *regs)
|
|
|
+{
|
|
|
+ struct pt_regs *old_regs = set_irq_regs(regs);
|
|
|
+
|
|
|
+ ack_APIC_irq();
|
|
|
+
|
|
|
+ exit_idle();
|
|
|
+
|
|
|
+ irq_enter();
|
|
|
+
|
|
|
+ inc_irq_stat(generic_irqs);
|
|
|
+
|
|
|
+ if (generic_interrupt_extension)
|
|
|
+ generic_interrupt_extension();
|
|
|
+
|
|
|
+ irq_exit();
|
|
|
+
|
|
|
+ set_irq_regs(old_regs);
|
|
|
+}
|
|
|
+
|
|
|
EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
|