]> err.no Git - linux-2.6/blobdiff - arch/sparc64/kernel/irq.c
[ARM] 4652/1: pxa: fix a typo of pxa27x usb host clk definition
[linux-2.6] / arch / sparc64 / kernel / irq.c
index 2be6bcbe50ca69532ce35b60a8e0a51d5d1299dc..30431bd24e1efbe7ea2153043d2d06605433febe 100644 (file)
@@ -122,19 +122,16 @@ static void bucket_set_virt_irq(unsigned long bucket_pa,
                               "i" (ASI_PHYS_USE_EC));
 }
 
-#define __irq(bucket) ((unsigned long)(bucket))
-
 #define irq_work_pa(__cpu)     &(trap_block[(__cpu)].irq_worklist_pa)
 
 static struct {
-       unsigned long irq;
        unsigned int dev_handle;
        unsigned int dev_ino;
-} virt_to_real_irq_table[NR_IRQS];
+       unsigned int in_use;
+} virt_irq_table[NR_IRQS];
 static DEFINE_SPINLOCK(virt_irq_alloc_lock);
 
-unsigned char virt_irq_alloc(unsigned long real_irq,
-                            unsigned int dev_handle,
+unsigned char virt_irq_alloc(unsigned int dev_handle,
                             unsigned int dev_ino)
 {
        unsigned long flags;
@@ -145,16 +142,16 @@ unsigned char virt_irq_alloc(unsigned long real_irq,
        spin_lock_irqsave(&virt_irq_alloc_lock, flags);
 
        for (ent = 1; ent < NR_IRQS; ent++) {
-               if (!virt_to_real_irq_table[ent].irq)
+               if (!virt_irq_table[ent].in_use)
                        break;
        }
        if (ent >= NR_IRQS) {
                printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
                ent = 0;
        } else {
-               virt_to_real_irq_table[ent].irq = real_irq;
-               virt_to_real_irq_table[ent].dev_handle = dev_handle;
-               virt_to_real_irq_table[ent].dev_ino = dev_ino;
+               virt_irq_table[ent].dev_handle = dev_handle;
+               virt_irq_table[ent].dev_ino = dev_ino;
+               virt_irq_table[ent].in_use = 1;
        }
 
        spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);
@@ -172,7 +169,7 @@ void virt_irq_free(unsigned int virt_irq)
 
        spin_lock_irqsave(&virt_irq_alloc_lock, flags);
 
-       virt_to_real_irq_table[virt_irq].irq = 0;
+       virt_irq_table[virt_irq].in_use = 0;
 
        spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);
 }
@@ -260,8 +257,8 @@ struct irq_handler_data {
        unsigned long   imap;
 
        void            (*pre_handler)(unsigned int, void *, void *);
-       void            *pre_handler_arg1;
-       void            *pre_handler_arg2;
+       void            *arg1;
+       void            *arg2;
 };
 
 #ifdef CONFIG_SMP
@@ -349,7 +346,7 @@ static void sun4u_irq_disable(unsigned int virt_irq)
        }
 }
 
-static void sun4u_irq_end(unsigned int virt_irq)
+static void sun4u_irq_eoi(unsigned int virt_irq)
 {
        struct irq_handler_data *data = get_irq_chip_data(virt_irq);
        struct irq_desc *desc = irq_desc + virt_irq;
@@ -363,7 +360,7 @@ static void sun4u_irq_end(unsigned int virt_irq)
 
 static void sun4v_irq_enable(unsigned int virt_irq)
 {
-       unsigned int ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       unsigned int ino = virt_irq_table[virt_irq].dev_ino;
        unsigned long cpuid = irq_choose_cpu(virt_irq);
        int err;
 
@@ -383,7 +380,7 @@ static void sun4v_irq_enable(unsigned int virt_irq)
 
 static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask)
 {
-       unsigned int ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       unsigned int ino = virt_irq_table[virt_irq].dev_ino;
        unsigned long cpuid = irq_choose_cpu(virt_irq);
        int err;
 
@@ -395,7 +392,7 @@ static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask)
 
 static void sun4v_irq_disable(unsigned int virt_irq)
 {
-       unsigned int ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       unsigned int ino = virt_irq_table[virt_irq].dev_ino;
        int err;
 
        err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
@@ -404,9 +401,9 @@ static void sun4v_irq_disable(unsigned int virt_irq)
                       "err(%d)\n", ino, err);
 }
 
-static void sun4v_irq_end(unsigned int virt_irq)
+static void sun4v_irq_eoi(unsigned int virt_irq)
 {
-       unsigned int ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       unsigned int ino = virt_irq_table[virt_irq].dev_ino;
        struct irq_desc *desc = irq_desc + virt_irq;
        int err;
 
@@ -426,8 +423,8 @@ static void sun4v_virq_enable(unsigned int virt_irq)
 
        cpuid = irq_choose_cpu(virt_irq);
 
-       dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
-       dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       dev_handle = virt_irq_table[virt_irq].dev_handle;
+       dev_ino = virt_irq_table[virt_irq].dev_ino;
 
        err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
        if (err != HV_EOK)
@@ -455,8 +452,8 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
 
        cpuid = irq_choose_cpu(virt_irq);
 
-       dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
-       dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       dev_handle = virt_irq_table[virt_irq].dev_handle;
+       dev_ino = virt_irq_table[virt_irq].dev_ino;
 
        err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
        if (err != HV_EOK)
@@ -470,8 +467,8 @@ static void sun4v_virq_disable(unsigned int virt_irq)
        unsigned long dev_handle, dev_ino;
        int err;
 
-       dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
-       dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       dev_handle = virt_irq_table[virt_irq].dev_handle;
+       dev_ino = virt_irq_table[virt_irq].dev_ino;
 
        err = sun4v_vintr_set_valid(dev_handle, dev_ino,
                                    HV_INTR_DISABLED);
@@ -481,7 +478,7 @@ static void sun4v_virq_disable(unsigned int virt_irq)
                       dev_handle, dev_ino, err);
 }
 
-static void sun4v_virq_end(unsigned int virt_irq)
+static void sun4v_virq_eoi(unsigned int virt_irq)
 {
        struct irq_desc *desc = irq_desc + virt_irq;
        unsigned long dev_handle, dev_ino;
@@ -490,8 +487,8 @@ static void sun4v_virq_end(unsigned int virt_irq)
        if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
                return;
 
-       dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
-       dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       dev_handle = virt_irq_table[virt_irq].dev_handle;
+       dev_ino = virt_irq_table[virt_irq].dev_ino;
 
        err = sun4v_vintr_set_state(dev_handle, dev_ino,
                                    HV_INTR_STATE_IDLE);
@@ -501,33 +498,11 @@ static void sun4v_virq_end(unsigned int virt_irq)
                       dev_handle, dev_ino, err);
 }
 
-static void run_pre_handler(unsigned int virt_irq)
-{
-       struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-       unsigned int ino;
-
-       ino = virt_to_real_irq_table[virt_irq].dev_ino;
-       if (likely(data->pre_handler)) {
-               data->pre_handler(ino,
-                                 data->pre_handler_arg1,
-                                 data->pre_handler_arg2);
-       }
-}
-
 static struct irq_chip sun4u_irq = {
        .typename       = "sun4u",
        .enable         = sun4u_irq_enable,
        .disable        = sun4u_irq_disable,
-       .end            = sun4u_irq_end,
-       .set_affinity   = sun4u_set_affinity,
-};
-
-static struct irq_chip sun4u_irq_ack = {
-       .typename       = "sun4u+ack",
-       .enable         = sun4u_irq_enable,
-       .disable        = sun4u_irq_disable,
-       .ack            = run_pre_handler,
-       .end            = sun4u_irq_end,
+       .eoi            = sun4u_irq_eoi,
        .set_affinity   = sun4u_set_affinity,
 };
 
@@ -535,7 +510,7 @@ static struct irq_chip sun4v_irq = {
        .typename       = "sun4v",
        .enable         = sun4v_irq_enable,
        .disable        = sun4v_irq_disable,
-       .end            = sun4v_irq_end,
+       .eoi            = sun4v_irq_eoi,
        .set_affinity   = sun4v_set_affinity,
 };
 
@@ -543,31 +518,33 @@ static struct irq_chip sun4v_virq = {
        .typename       = "vsun4v",
        .enable         = sun4v_virq_enable,
        .disable        = sun4v_virq_disable,
-       .end            = sun4v_virq_end,
+       .eoi            = sun4v_virq_eoi,
        .set_affinity   = sun4v_virt_set_affinity,
 };
 
+static void fastcall pre_flow_handler(unsigned int virt_irq,
+                                     struct irq_desc *desc)
+{
+       struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+       unsigned int ino = virt_irq_table[virt_irq].dev_ino;
+
+       data->pre_handler(ino, data->arg1, data->arg2);
+
+       handle_fasteoi_irq(virt_irq, desc);
+}
+
 void irq_install_pre_handler(int virt_irq,
                             void (*func)(unsigned int, void *, void *),
                             void *arg1, void *arg2)
 {
        struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-       struct irq_chip *chip = get_irq_chip(virt_irq);
-
-       if (WARN_ON(chip == &sun4v_irq || chip == &sun4v_virq)) {
-               printk(KERN_ERR "IRQ: Trying to install pre-handler on "
-                      "sun4v irq %u\n", virt_irq);
-               return;
-       }
+       struct irq_desc *desc = irq_desc + virt_irq;
 
        data->pre_handler = func;
-       data->pre_handler_arg1 = arg1;
-       data->pre_handler_arg2 = arg2;
-
-       if (chip == &sun4u_irq_ack)
-               return;
+       data->arg1 = arg1;
+       data->arg2 = arg2;
 
-       set_irq_chip(virt_irq, &sun4u_irq_ack);
+       desc->handle_irq = pre_flow_handler;
 }
 
 unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
@@ -583,9 +560,12 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
        bucket = &ivector_table[ino];
        virt_irq = bucket_get_virt_irq(__pa(bucket));
        if (!virt_irq) {
-               virt_irq = virt_irq_alloc(__irq(bucket), 0, ino);
+               virt_irq = virt_irq_alloc(0, ino);
                bucket_set_virt_irq(__pa(bucket), virt_irq);
-               set_irq_chip(virt_irq, &sun4u_irq);
+               set_irq_chip_and_handler_name(virt_irq,
+                                             &sun4u_irq,
+                                             handle_fasteoi_irq,
+                                             "IVEC");
        }
 
        data = get_irq_chip_data(virt_irq);
@@ -618,9 +598,11 @@ static unsigned int sun4v_build_common(unsigned long sysino,
        bucket = &ivector_table[sysino];
        virt_irq = bucket_get_virt_irq(__pa(bucket));
        if (!virt_irq) {
-               virt_irq = virt_irq_alloc(__irq(bucket), 0, sysino);
+               virt_irq = virt_irq_alloc(0, sysino);
                bucket_set_virt_irq(__pa(bucket), virt_irq);
-               set_irq_chip(virt_irq, chip);
+               set_irq_chip_and_handler_name(virt_irq, chip,
+                                             handle_fasteoi_irq,
+                                             "IVEC");
        }
 
        data = get_irq_chip_data(virt_irq);
@@ -666,9 +648,12 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
                             ((unsigned long) bucket +
                              sizeof(struct ino_bucket)));
 
-       virt_irq = virt_irq_alloc(__irq(bucket), devhandle, devino);
+       virt_irq = virt_irq_alloc(devhandle, devino);
        bucket_set_virt_irq(__pa(bucket), virt_irq);
-       set_irq_chip(virt_irq, &sun4v_virq);
+
+       set_irq_chip_and_handler_name(virt_irq, &sun4v_virq,
+                                     handle_fasteoi_irq,
+                                     "IVEC");
 
        data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
        if (unlikely(!data))
@@ -696,7 +681,7 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 
 void ack_bad_irq(unsigned int virt_irq)
 {
-       unsigned int ino = virt_to_real_irq_table[virt_irq].dev_ino;
+       unsigned int ino = virt_irq_table[virt_irq].dev_ino;
 
        if (!ino)
                ino = 0xdeadbeef;
@@ -727,6 +712,7 @@ void handler_irq(int irq, struct pt_regs *regs)
                             : "memory");
 
        while (bucket_pa) {
+               struct irq_desc *desc;
                unsigned long next_pa;
                unsigned int virt_irq;
 
@@ -734,7 +720,9 @@ void handler_irq(int irq, struct pt_regs *regs)
                virt_irq = bucket_get_virt_irq(bucket_pa);
                bucket_clear_chain_pa(bucket_pa);
 
-               __do_IRQ(virt_irq);
+               desc = irq_desc + virt_irq;
+
+               desc->handle_irq(virt_irq, desc);
 
                bucket_pa = next_pa;
        }
@@ -880,7 +868,7 @@ void __cpuinit sun4v_register_mondo_queues(int this_cpu)
 static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask)
 {
        unsigned long size = PAGE_ALIGN(qmask + 1);
-       void *p = __alloc_bootmem_low(size, size, 0);
+       void *p = __alloc_bootmem(size, size, 0);
        if (!p) {
                prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
                prom_halt();
@@ -892,7 +880,7 @@ static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask)
 static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask)
 {
        unsigned long size = PAGE_ALIGN(qmask + 1);
-       void *p = __alloc_bootmem_low(size, size, 0);
+       void *p = __alloc_bootmem(size, size, 0);
 
        if (!p) {
                prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
@@ -909,7 +897,7 @@ static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb)
 
        BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
 
-       page = alloc_bootmem_low_pages(PAGE_SIZE);
+       page = alloc_bootmem_pages(PAGE_SIZE);
        if (!page) {
                prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
                prom_halt();
@@ -956,7 +944,7 @@ void __init init_IRQ(void)
        kill_prom_timer();
 
        size = sizeof(struct ino_bucket) * NUM_IVECS;
-       ivector_table = alloc_bootmem_low(size);
+       ivector_table = alloc_bootmem(size);
        if (!ivector_table) {
                prom_printf("Fatal error, cannot allocate ivector_table\n");
                prom_halt();