]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/parisc/iosapic.c
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci
[linux-2.6.git] / drivers / parisc / iosapic.c
index 7a57c1b8373f04438a996f05242c8070651c481b..95930d016235ae3a39fdfe71e1b409291d21d370 100644 (file)
 **
 ** PA Firmware
 ** -----------
-** PA-RISC platforms have two fundementally different types of firmware.
+** PA-RISC platforms have two fundamentally different types of firmware.
 ** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
 ** and BARs similar to a traditional PC BIOS.
 ** The newer "PAT" firmware supports PDC calls which return tables.
-** PAT firmware only initializes PCI Console and Boot interface.
-** With these tables, the OS can progam all other PCI devices.
+** PAT firmware only initializes the PCI Console and Boot interface.
+** With these tables, the OS can program all other PCI devices.
 **
 ** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
 ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
 #include <asm/superio.h>
 #endif
 
-#include <asm/iosapic.h>
+#include <asm/ropes.h>
 #include "./iosapic_private.h"
 
 #define MODULE_NAME "iosapic"
@@ -244,7 +244,7 @@ static struct irt_entry *iosapic_alloc_irt(int num_entries)
         * 4-byte alignment on 32-bit kernels
         */
        a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
-       a = (a + 7) & ~7;
+       a = (a + 7UL) & ~7UL;
        return (struct irt_entry *)a;
 }
 
@@ -487,7 +487,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
        }
 
        /* Check if pcidev behind a PPB */
-       if (NULL != pcidev->bus->self) {
+       if (pcidev->bus->parent) {
                /* Convert pcidev INTR_PIN into something we
                ** can lookup in the IRT.
                */
@@ -519,15 +519,13 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
                **
                ** Advantage is it's really easy to implement.
                */
-               intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
-               intr_pin++;     /* convert back to INTA-D (1-4) */
+               intr_pin = pci_swizzle_interrupt_pin(pcidev, intr_pin);
 #endif /* PCI_BRIDGE_FUNCS */
 
                /*
-               ** Locate the host slot the PPB nearest the Host bus
-               ** adapter.
-               */
-               while (NULL != p->parent->self)
+                * Locate the host slot of the PPB.
+                */
+               while (p->parent->parent)
                        p = p->parent;
 
                intr_slot = PCI_SLOT(p->self->devfn);
@@ -617,15 +615,10 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
 }
 
 
-static struct vector_info *iosapic_get_vector(unsigned int irq)
-{
-       return irq_desc[irq].handler_data;
-}
-
-static void iosapic_disable_irq(unsigned int irq)
+static void iosapic_mask_irq(struct irq_data *d)
 {
        unsigned long flags;
-       struct vector_info *vi = iosapic_get_vector(irq);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
        u32 d0, d1;
 
        spin_lock_irqsave(&iosapic_lock, flags);
@@ -635,9 +628,9 @@ static void iosapic_disable_irq(unsigned int irq)
        spin_unlock_irqrestore(&iosapic_lock, flags);
 }
 
-static void iosapic_enable_irq(unsigned int irq)
+static void iosapic_unmask_irq(struct irq_data *d)
 {
-       struct vector_info *vi = iosapic_get_vector(irq);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
        u32 d0, d1;
 
        /* data is initialized by fixup_irq */
@@ -673,42 +666,56 @@ printk("\n");
         * enables their IRQ. It can lead to "interesting" race conditions
         * in the driver initialization sequence.
         */
-       DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq,
+       DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq,
                        vi->eoi_addr, vi->eoi_data);
        iosapic_eoi(vi->eoi_addr, vi->eoi_data);
 }
 
-/*
- * PARISC only supports PCI devices below I/O SAPIC.
- * PCI only supports level triggered in order to share IRQ lines.
- * ergo I/O SAPIC must always issue EOI on parisc.
- *
- * i386/ia64 support ISA devices and have to deal with
- * edge-triggered interrupts too.
- */
-static void iosapic_end_irq(unsigned int irq)
+static void iosapic_eoi_irq(struct irq_data *d)
 {
-       struct vector_info *vi = iosapic_get_vector(irq);
-       DBG(KERN_DEBUG "end_irq(%d): eoi(%p, 0x%x)\n", irq,
-                       vi->eoi_addr, vi->eoi_data);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
+
        iosapic_eoi(vi->eoi_addr, vi->eoi_data);
+       cpu_eoi_irq(d);
 }
 
-static unsigned int iosapic_startup_irq(unsigned int irq)
+#ifdef CONFIG_SMP
+static int iosapic_set_affinity_irq(struct irq_data *d,
+                                   const struct cpumask *dest, bool force)
 {
-       iosapic_enable_irq(irq);
+       struct vector_info *vi = irq_data_get_irq_chip_data(d);
+       u32 d0, d1, dummy_d0;
+       unsigned long flags;
+       int dest_cpu;
+
+       dest_cpu = cpu_check_affinity(d, dest);
+       if (dest_cpu < 0)
+               return -1;
+
+       cpumask_copy(d->affinity, cpumask_of(dest_cpu));
+       vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu);
+
+       spin_lock_irqsave(&iosapic_lock, flags);
+       /* d1 contains the destination CPU, so only want to set that
+        * entry */
+       iosapic_rd_irt_entry(vi, &d0, &d1);
+       iosapic_set_irt_data(vi, &dummy_d0, &d1);
+       iosapic_wr_irt_entry(vi, d0, d1);
+       spin_unlock_irqrestore(&iosapic_lock, flags);
+
        return 0;
 }
+#endif
 
-static struct hw_interrupt_type iosapic_interrupt_type = {
-       .typename =     "IO-SAPIC-level",
-       .startup =      iosapic_startup_irq,
-       .shutdown =     iosapic_disable_irq,
-       .enable =       iosapic_enable_irq,
-       .disable =      iosapic_disable_irq,
-       .ack =          no_ack_irq,
-       .end =          iosapic_end_irq,
-//     .set_affinity = iosapic_set_affinity_irq,
+static struct irq_chip iosapic_interrupt_type = {
+       .name           =       "IO-SAPIC-level",
+       .irq_unmask     =       iosapic_unmask_irq,
+       .irq_mask       =       iosapic_mask_irq,
+       .irq_ack        =       cpu_ack_irq,
+       .irq_eoi        =       iosapic_eoi_irq,
+#ifdef CONFIG_SMP
+       .irq_set_affinity =     iosapic_set_affinity_irq,
+#endif
 };
 
 int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
@@ -849,28 +856,24 @@ void *iosapic_register(unsigned long hpa)
                return NULL;
        }
 
-       isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+       isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
        if (!isi) {
                BUG();
                return NULL;
        }
 
-       memset(isi, 0, sizeof(struct iosapic_info));
-
-       isi->addr = ioremap(hpa, 4096);
+       isi->addr = ioremap_nocache(hpa, 4096);
        isi->isi_hpa = hpa;
        isi->isi_version = iosapic_rd_version(isi);
        isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
 
-       vip = isi->isi_vector = (struct vector_info *)
-               kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
+       vip = isi->isi_vector = kcalloc(isi->isi_num_vectors,
+                                       sizeof(struct vector_info), GFP_KERNEL);
        if (vip == NULL) {
                kfree(isi);
                return NULL;
        }
 
-       memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
-
        for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
                vip->irqline = (unsigned char) cnt;
                vip->iosapic = isi;