Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / arch / x86 / kernel / irq_64.c
index 6b5c730..1f78b23 100644 (file)
 
 atomic_t irq_err_count;
 
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+       printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
+       /*
+        * Currently unexpected vectors happen only on SMP and APIC.
+        * We _must_ ack these because every local APIC has only N
+        * irq slots per priority level, and a 'hanging, unacked' IRQ
+        * holds up an irq slot - in excessive cases (when multiple
+        * unexpected vectors occur) that might lock up the APIC
+        * completely.
+        * But don't ack when the APIC is disabled. -AK
+        */
+       if (!disable_apic)
+               ack_APIC_irq();
+}
+
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 /*
  * Probabilistic stack overflow check:
@@ -33,11 +53,11 @@ static inline void stack_overflow_check(struct pt_regs *regs)
        u64 curbase = (u64)task_stack_page(current);
        static unsigned long warned = -60*HZ;
 
-       if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
-           regs->rsp <  curbase + sizeof(struct thread_info) + 128 &&
+       if (regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE &&
+           regs->sp <  curbase + sizeof(struct thread_info) + 128 &&
            time_after(jiffies, warned + 60*HZ)) {
-               printk("do_IRQ: %s near stack overflow (cur:%Lx,rsp:%lx)\n",
-                      current->comm, curbase, regs->rsp);
+               printk("do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
+                      current->comm, curbase, regs->sp);
                show_stack(NULL,NULL);
                warned = jiffies;
        }
@@ -115,6 +135,7 @@ skip:
                        seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count);
                seq_printf(p, "  TLB shootdowns\n");
 #endif
+#ifdef CONFIG_X86_MCE
                seq_printf(p, "TRM: ");
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", cpu_pda(j)->irq_thermal_count);
@@ -123,6 +144,7 @@ skip:
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", cpu_pda(j)->irq_threshold_count);
                seq_printf(p, "  Threshold APIC interrupts\n");
+#endif
                seq_printf(p, "SPU: ");
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", cpu_pda(j)->irq_spurious_count);
@@ -132,6 +154,32 @@ skip:
        return 0;
 }
 
+/*
+ * /proc/stat helpers
+ */
+u64 arch_irq_stat_cpu(unsigned int cpu)
+{
+       u64 sum = cpu_pda(cpu)->__nmi_count;
+
+       sum += cpu_pda(cpu)->apic_timer_irqs;
+#ifdef CONFIG_SMP
+       sum += cpu_pda(cpu)->irq_resched_count;
+       sum += cpu_pda(cpu)->irq_call_count;
+       sum += cpu_pda(cpu)->irq_tlb_count;
+#endif
+#ifdef CONFIG_X86_MCE
+       sum += cpu_pda(cpu)->irq_thermal_count;
+       sum += cpu_pda(cpu)->irq_threshold_count;
+#endif
+       sum += cpu_pda(cpu)->irq_spurious_count;
+       return sum;
+}
+
+u64 arch_irq_stat(void)
+{
+       return atomic_read(&irq_err_count);
+}
+
 /*
  * do_IRQ handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
@@ -142,7 +190,7 @@ asmlinkage unsigned int 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_rax;
+       unsigned vector = ~regs->orig_ax;
        unsigned irq;
 
        exit_idle();