[IA64-SGI] abstract force_interrupt() mechanism
Mark Maule [Wed, 3 Aug 2005 21:06:00 +0000 (14:06 -0700)]
Altix patch to abstract the force_interrupt() mechanism away from the
pcibr provider.

Signed-off-by: Mark Maule <maule@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

arch/ia64/sn/kernel/irq.c
arch/ia64/sn/pci/pcibr/pcibr_provider.c
arch/ia64/sn/pci/tioca_provider.c
include/asm-ia64/sn/pcibus_provider_defs.h
include/asm-ia64/sn/pda.h

index 84d276a..af061db 100644 (file)
@@ -317,6 +317,16 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)
        pci_dev_put(pci_dev);
 }
 
+static inline void
+sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
+{
+       struct sn_pcibus_provider *pci_provider;
+
+       pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
+       if (pci_provider && pci_provider->force_interrupt)
+               (*pci_provider->force_interrupt)(sn_irq_info);
+}
+
 static void force_interrupt(int irq)
 {
        struct sn_irq_info *sn_irq_info;
@@ -325,11 +335,9 @@ static void force_interrupt(int irq)
                return;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) {
-               if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
-                   (sn_irq_info->irq_bridge != NULL))
-                       pcibr_force_interrupt(sn_irq_info);
-       }
+       list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list)
+               sn_call_force_intr_provider(sn_irq_info);
+
        rcu_read_unlock();
 }
 
@@ -351,6 +359,14 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
        struct pcidev_info *pcidev_info;
        struct pcibus_info *pcibus_info;
 
+       /*
+        * Bridge types attached to TIO (anything but PIC) do not need this WAR
+        * since they do not target Shub II interrupt registers.  If that
+        * ever changes, this check needs to accomodate.
+        */
+       if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC)
+               return;
+
        pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
        if (!pcidev_info)
                return;
@@ -377,16 +393,12 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
                break;
        }
        if (!test_bit(irr_bit, &irr_reg)) {
-               if (!test_bit(irq, pda->sn_soft_irr)) {
-                       if (!test_bit(irq, pda->sn_in_service_ivecs)) {
-                               regval &= 0xff;
-                               if (sn_irq_info->irq_int_bit & regval &
-                                   sn_irq_info->irq_last_intr) {
-                                       regval &=
-                                           ~(sn_irq_info->
-                                             irq_int_bit & regval);
-                                       pcibr_force_interrupt(sn_irq_info);
-                               }
+               if (!test_bit(irq, pda->sn_in_service_ivecs)) {
+                       regval &= 0xff;
+                       if (sn_irq_info->irq_int_bit & regval &
+                           sn_irq_info->irq_last_intr) {
+                               regval &= ~(sn_irq_info->irq_int_bit & regval);
+                               sn_call_force_intr_provider(sn_irq_info);
                        }
                }
        }
@@ -404,13 +416,7 @@ void sn_lb_int_war_check(void)
        rcu_read_lock();
        for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
                list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) {
-                       /*
-                        * Only call for PCI bridges that are fully
-                        * initialized.
-                        */
-                       if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
-                           (sn_irq_info->irq_bridge != NULL))
-                               sn_check_intr(i, sn_irq_info);
+                       sn_check_intr(i, sn_irq_info);
                }
        }
        rcu_read_unlock();
index f8cfe8a..ff9c7de 100644 (file)
@@ -178,6 +178,9 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
        struct pcibus_info *pcibus_info;
        int bit = sn_irq_info->irq_int_bit;
 
+       if (! sn_irq_info->irq_bridge)
+               return;
+
        pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
        if (pcidev_info) {
                pcibus_info =
@@ -222,6 +225,7 @@ struct sn_pcibus_provider pcibr_provider = {
        .dma_map_consistent = pcibr_dma_map_consistent,
        .dma_unmap = pcibr_dma_unmap,
        .bus_fixup = pcibr_bus_fixup,
+       .force_interrupt = pcibr_force_interrupt
 };
 
 int
index 2fef7c1..4ea04cf 100644 (file)
@@ -657,6 +657,7 @@ static struct sn_pcibus_provider tioca_pci_interfaces = {
        .dma_map_consistent = tioca_dma_map,
        .dma_unmap = tioca_dma_unmap,
        .bus_fixup = tioca_bus_fixup,
+       .force_interrupt = NULL
 };
 
 /**
index b01b21e..5c3ba57 100644 (file)
@@ -48,6 +48,7 @@ struct sn_pcibus_provider {
        dma_addr_t      (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t);
        void            (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
        void *          (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
+       void            (*force_interrupt)(struct sn_irq_info *);
 };
 
 extern struct sn_pcibus_provider *sn_pci_provider[];
index ea5590c..1c5108d 100644 (file)
@@ -39,7 +39,6 @@ typedef struct pda_s {
        unsigned long pio_write_status_val;
        volatile unsigned long *pio_shub_war_cam_addr;
 
-       unsigned long   sn_soft_irr[4];
        unsigned long   sn_in_service_ivecs[4];
        int             sn_lb_int_war_ticks;
        int             sn_last_irq;