/* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). */ 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 irq; exit_idle(); irq_enter(); irq = __get_cpu_var(vector_irq)[vector]; #ifdef CONFIG_DEBUG_STACKOVERFLOW stack_overflow_check(regs); #endif if (likely(irq < NR_IRQS)) generic_handle_irq(irq); else { if (!disable_apic) ack_APIC_irq(); if (printk_ratelimit()) printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n", __func__, smp_processor_id(), vector); } irq_exit(); set_irq_regs(old_regs); return 1; }
bool handle_irq(struct irq_desc *desc, struct pt_regs *regs) { stack_overflow_check(regs); if (IS_ERR_OR_NULL(desc)) return false; generic_handle_irq_desc(desc); return true; }
bool handle_irq(unsigned irq, struct pt_regs *regs) { struct irq_desc *desc; stack_overflow_check(regs); desc = irq_to_desc(irq); if (unlikely(!desc)) return false; generic_handle_irq_desc(irq, desc); return true; }
/* ONLY called from entry.S:intr_extint() */ void do_cpu_irq_mask(struct pt_regs *regs) { struct pt_regs *old_regs; unsigned long eirr_val; int irq, cpu = smp_processor_id(); #ifdef CONFIG_SMP struct irq_desc *desc; cpumask_t dest; #endif old_regs = set_irq_regs(regs); local_irq_disable(); irq_enter(); eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu); if (!eirr_val) goto set_out; irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP desc = irq_to_desc(irq); cpumask_copy(&dest, desc->irq_data.affinity); if (irqd_is_per_cpu(&desc->irq_data) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n", irq, smp_processor_id(), cpu); gsc_writel(irq + CPU_IRQ_BASE, per_cpu(cpu_data, cpu).hpa); goto set_out; } #endif stack_overflow_check(regs); #ifdef CONFIG_IRQSTACKS execute_on_irq_stack(&generic_handle_irq, irq); #else generic_handle_irq(irq); #endif /* CONFIG_IRQSTACKS */ out: irq_exit(); set_irq_regs(old_regs); return; set_out: set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu)); goto out; }