diff options
Diffstat (limited to 'arch/ia64/kernel/irq_ia64.c')
-rw-r--r-- | arch/ia64/kernel/irq_ia64.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index aafca18..9c6dafa 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -30,6 +30,7 @@ #include <linux/smp_lock.h> #include <linux/threads.h> #include <linux/bitops.h> +#include <linux/irq.h> #include <asm/delay.h> #include <asm/intrinsics.h> @@ -105,6 +106,25 @@ reserve_irq_vector (int vector) return test_and_set_bit(pos, ia64_vector_mask); } +/* + * Dynamic irq allocate and deallocation for MSI + */ +int create_irq(void) +{ + int vector = assign_irq_vector(AUTO_ASSIGN); + + if (vector >= 0) + dynamic_irq_init(vector); + + return vector; +} + +void destroy_irq(unsigned int irq) +{ + dynamic_irq_cleanup(irq); + free_irq_vector(irq); +} + #ifdef CONFIG_SMP # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) #else @@ -118,6 +138,7 @@ reserve_irq_vector (int vector) void ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) { + struct pt_regs *old_regs = set_irq_regs(regs); unsigned long saved_tpr; #if IRQ_DEBUG @@ -159,11 +180,13 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (!IS_RESCHEDULE(vector)) { + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; + else { ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); - __do_IRQ(local_vector_to_irq(vector), regs); + __do_IRQ(local_vector_to_irq(vector)); /* * Disable interrupts and send EOI: @@ -180,6 +203,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) * come through until ia64_eoi() has been done. */ irq_exit(); + set_irq_regs(old_regs); } #ifdef CONFIG_HOTPLUG_CPU @@ -203,7 +227,11 @@ void ia64_process_pending_intr(void) * Perform normal interrupt style processing */ while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (!IS_RESCHEDULE(vector)) { + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; + else { + struct pt_regs *old_regs = set_irq_regs(NULL); + ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); @@ -214,7 +242,8 @@ void ia64_process_pending_intr(void) * Probably could shared code. */ vectors_in_migration[local_vector_to_irq(vector)]=0; - __do_IRQ(local_vector_to_irq(vector), NULL); + __do_IRQ(local_vector_to_irq(vector)); + set_irq_regs(old_regs); /* * Disable interrupts and send EOI @@ -231,13 +260,24 @@ void ia64_process_pending_intr(void) #ifdef CONFIG_SMP -extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t handle_IPI (int irq, void *dev_id); + +static irqreturn_t dummy_handler (int irq, void *dev_id) +{ + BUG(); +} static struct irqaction ipi_irqaction = { .handler = handle_IPI, .flags = IRQF_DISABLED, .name = "IPI" }; + +static struct irqaction resched_irqaction = { + .handler = dummy_handler, + .flags = SA_INTERRUPT, + .name = "resched" +}; #endif void @@ -262,6 +302,7 @@ init_IRQ (void) register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); + register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); #endif #ifdef CONFIG_PERFMON pfm_init_percpu(); |