Merge ../linux-2.6-watchdog-mm
[linux-drm-fsl-dcu.git] / arch / ia64 / kernel / irq_ia64.c
index ef9a2b49307ae756ac58a8fb7f8c360aa2aca53a..ba3ba8bc50bef1aa77758256ec818e000eb88ff4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/ia64/kernel/irq.c
+ * linux/arch/ia64/kernel/irq_ia64.c
  *
  * Copyright (C) 1998-2001 Hewlett-Packard Co
  *     Stephane Eranian <eranian@hpl.hp.com>
@@ -14,7 +14,6 @@
  *                                             Added CPU Hotplug handling for IPF.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/jiffies.h>
@@ -31,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>
@@ -106,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
@@ -119,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
@@ -160,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);
+                       generic_handle_irq(local_vector_to_irq(vector));
 
                        /*
                         * Disable interrupts and send EOI:
@@ -181,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
@@ -204,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();
 
@@ -215,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);
+                       generic_handle_irq(local_vector_to_irq(vector));
+                       set_irq_regs(old_regs);
 
                        /*
                         * Disable interrupts and send EOI
@@ -232,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 =        SA_INTERRUPT,
+       .flags =        IRQF_DISABLED,
        .name =         "IPI"
 };
+
+static struct irqaction resched_irqaction = {
+       .handler =      dummy_handler,
+       .flags =        SA_INTERRUPT,
+       .name =         "resched"
+};
 #endif
 
 void
@@ -249,9 +288,9 @@ register_percpu_irq (ia64_vector vec, struct irqaction *action)
 
        for (irq = 0; irq < NR_IRQS; ++irq)
                if (irq_to_vector(irq) == vec) {
-                       desc = irq_descp(irq);
+                       desc = irq_desc + irq;
                        desc->status |= IRQ_PER_CPU;
-                       desc->handler = &irq_type_ia64_lsapic;
+                       desc->chip = &irq_type_ia64_lsapic;
                        if (action)
                                setup_irq(irq, action);
                }
@@ -263,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();