x86: add debug info for 32bit sparse_irq
[sfrench/cifs-2.6.git] / arch / x86 / kernel / irq_32.c
index 1cf8c1fcc0889c5a066ddb2b7e150ece69dc1729..cc929f2f84f1d36312e3d926faf4c47f5fc56b1e 100644 (file)
@@ -223,20 +223,25 @@ unsigned int do_IRQ(struct pt_regs *regs)
 {
        struct pt_regs *old_regs;
        /* high bit used in ret_from_ code */
-       int overflow, irq = ~regs->orig_ax;
-       struct irq_desc *desc = irq_desc + irq;
+       int overflow;
+       unsigned vector = ~regs->orig_ax;
+       struct irq_desc *desc;
+       unsigned irq;
 
-       if (unlikely((unsigned)irq >= NR_IRQS)) {
-               printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
-                                       __func__, irq);
-               BUG();
-       }
 
        old_regs = set_irq_regs(regs);
        irq_enter();
+       irq = __get_cpu_var(vector_irq)[vector];
 
        overflow = check_stack_overflow();
 
+       desc = irq_to_desc(irq);
+       if (unlikely(!desc)) {
+               printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n",
+                                       __func__, irq, vector, smp_processor_id());
+               BUG();
+       }
+
        if (!execute_on_irq_stack(overflow, desc, irq)) {
                if (unlikely(overflow))
                        print_stack_overflow();
@@ -263,6 +268,24 @@ int show_interrupts(struct seq_file *p, void *v)
        int i = *(loff_t *) v, j;
        struct irqaction * action;
        unsigned long flags;
+       unsigned int entries;
+       struct irq_desc *desc;
+       int tail = 0;
+
+#ifdef CONFIG_HAVE_SPARSE_IRQ
+       desc = (struct irq_desc *)v;
+       entries = -1U;
+       i = desc->irq;
+       if (!desc->next)
+               tail = 1;
+#else
+       entries = nr_irqs - 1;
+       i = *(loff_t *) v;
+       if (i == nr_irqs)
+               tail = 1;
+       else
+               desc = irq_to_desc(i);
+#endif
 
        if (i == 0) {
                seq_printf(p, "           ");
@@ -271,28 +294,28 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_putc(p, '\n');
        }
 
-       if (i < NR_IRQS) {
+       if (i <= entries) {
                unsigned any_count = 0;
 
-               spin_lock_irqsave(&irq_desc[i].lock, flags);
+               spin_lock_irqsave(&desc->lock, flags);
 #ifndef CONFIG_SMP
                any_count = kstat_irqs(i);
 #else
                for_each_online_cpu(j)
-                       any_count |= kstat_cpu(j).irqs[i];
+                       any_count |= kstat_irqs_cpu(i, j);
 #endif
-               action = irq_desc[i].action;
+               action = desc->action;
                if (!action && !any_count)
                        goto skip;
-               seq_printf(p, "%3d: ",i);
+               seq_printf(p, "%#x: ",i);
 #ifndef CONFIG_SMP
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-               seq_printf(p, " %8s", irq_desc[i].chip->name);
-               seq_printf(p, "-%-8s", irq_desc[i].name);
+               seq_printf(p, " %8s", desc->chip->name);
+               seq_printf(p, "-%-8s", desc->name);
 
                if (action) {
                        seq_printf(p, "  %s", action->name);
@@ -302,8 +325,10 @@ int show_interrupts(struct seq_file *p, void *v)
 
                seq_putc(p, '\n');
 skip:
-               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == NR_IRQS) {
+               spin_unlock_irqrestore(&desc->lock, flags);
+       }
+
+       if (tail) {
                seq_printf(p, "NMI: ");
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", nmi_count(j));
@@ -325,7 +350,7 @@ skip:
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ",
                                per_cpu(irq_stat,j).irq_call_count);
-               seq_printf(p, "  function call interrupts\n");
+               seq_printf(p, "  Function call interrupts\n");
                seq_printf(p, "TLB: ");
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ",
@@ -395,20 +420,22 @@ void fixup_irqs(cpumask_t map)
 {
        unsigned int irq;
        static int warned;
+       struct irq_desc *desc;
 
-       for (irq = 0; irq < NR_IRQS; irq++) {
+       for_each_irq_desc(irq, desc) {
                cpumask_t mask;
+
                if (irq == 2)
                        continue;
 
-               cpus_and(mask, irq_desc[irq].affinity, map);
+               cpus_and(mask, desc->affinity, map);
                if (any_online_cpu(mask) == NR_CPUS) {
                        printk("Breaking affinity for irq %i\n", irq);
                        mask = map;
                }
-               if (irq_desc[irq].chip->set_affinity)
-                       irq_desc[irq].chip->set_affinity(irq, mask);
-               else if (irq_desc[irq].action && !(warned++))
+               if (desc->chip->set_affinity)
+                       desc->chip->set_affinity(irq, mask);
+               else if (desc->action && !(warned++))
                        printk("Cannot set affinity for irq %i\n", irq);
        }