vserver 1.9.5.x5
[linux-2.6.git] / arch / ia64 / sn / kernel / irq.c
index 6bcf70e..3be4472 100644 (file)
@@ -5,97 +5,83 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
 #include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/bootmem.h>
-#include <linux/cpumask.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sn/sgi.h>
-#include <asm/sn/hcl.h>
-#include <asm/sn/types.h>
-#include <asm/sn/pci/pciio.h>
-#include <asm/sn/pci/pciio_private.h>
-#include <asm/sn/pci/pcibr.h>
-#include <asm/sn/pci/pcibr_private.h>
-#include <asm/sn/sn_cpuid.h>
-#include <asm/sn/io.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/addrs.h>
-#include <asm/sn/driver.h>
 #include <asm/sn/arch.h>
-#include <asm/sn/pda.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/sn/sn2/shub_mmr.h>
+#include "xtalk/xwidgetdev.h"
+#include "pci/pcibus_provider_defs.h"
+#include "pci/pcidev.h"
+#include "pci/pcibr_provider.h"
+#include <asm/sn/shub_mmr.h>
+#include <asm/sn/sn_sal.h>
 
 static void force_interrupt(int irq);
-extern void pcibr_force_interrupt(pcibr_intr_t intr);
-extern int sn_force_interrupt_flag;
-struct irq_desc * sn_irq_desc(unsigned int irq);
-extern cpumask_t    __cacheline_aligned pending_irq_cpumask[NR_IRQS];
-
-struct sn_intr_list_t {
-       struct sn_intr_list_t *next;
-       pcibr_intr_t intr;
-};
+static void register_intr_pda(struct sn_irq_info *sn_irq_info);
+static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
 
-static struct sn_intr_list_t *sn_intr_list[NR_IRQS];
+extern int sn_force_interrupt_flag;
+extern int sn_ioif_inited;
+struct sn_irq_info **sn_irq;
 
+static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget,
+                                    u64 sn_irq_info,
+                                    int req_irq, nasid_t req_nasid,
+                                    int req_slice)
+{
+       struct ia64_sal_retval ret_stuff;
+       ret_stuff.status = 0;
+       ret_stuff.v0 = 0;
+
+       SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
+                       (u64) SAL_INTR_ALLOC, (u64) local_nasid,
+                       (u64) local_widget, (u64) sn_irq_info, (u64) req_irq,
+                       (u64) req_nasid, (u64) req_slice);
+       return ret_stuff.status;
+}
 
-static unsigned int
-sn_startup_irq(unsigned int irq)
+static inline void sn_intr_free(nasid_t local_nasid, int local_widget,
+                               struct sn_irq_info *sn_irq_info)
 {
-        return(0);
+       struct ia64_sal_retval ret_stuff;
+       ret_stuff.status = 0;
+       ret_stuff.v0 = 0;
+
+       SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
+                       (u64) SAL_INTR_FREE, (u64) local_nasid,
+                       (u64) local_widget, (u64) sn_irq_info->irq_irq,
+                       (u64) sn_irq_info->irq_cookie, 0, 0);
 }
 
-static void
-sn_shutdown_irq(unsigned int irq)
+static unsigned int sn_startup_irq(unsigned int irq)
 {
+       return 0;
 }
 
-static void
-sn_disable_irq(unsigned int irq)
+static void sn_shutdown_irq(unsigned int irq)
 {
 }
 
-static void
-sn_enable_irq(unsigned int irq)
+static void sn_disable_irq(unsigned int irq)
 {
 }
 
-static inline void sn_move_irq(int irq)
+static void sn_enable_irq(unsigned int irq)
 {
-       /* note - we hold desc->lock */
-       cpumask_t tmp;
-       irq_desc_t *desc = irq_descp(irq);
-
-       if (!cpus_empty(pending_irq_cpumask[irq])) {
-               cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
-               if (unlikely(!cpus_empty(tmp))) {
-                       desc->handler->set_affinity(irq, pending_irq_cpumask[irq]);
-               }
-               cpus_clear(pending_irq_cpumask[irq]);
-       }
 }
 
-static void
-sn_ack_irq(unsigned int irq)
+static void sn_ack_irq(unsigned int irq)
 {
-       unsigned long event_occurred, mask = 0;
+       uint64_t event_occurred, mask = 0;
        int nasid;
 
        irq = irq & 0xff;
-       nasid = smp_physical_node_id();
-       event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
+       nasid = get_nasid();
+       event_occurred =
+           HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED));
        if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
                mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
        }
@@ -108,272 +94,338 @@ sn_ack_irq(unsigned int irq)
        if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) {
                mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
        }
-       HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask );
+       HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS),
+             mask);
        __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
-       sn_move_irq(irq);
+
+       move_irq(irq);
 }
 
-static void
-sn_end_irq(unsigned int irq)
+static void sn_end_irq(unsigned int irq)
 {
        int nasid;
        int ivec;
-       unsigned long event_occurred;
-       irq_desc_t *desc = sn_irq_desc(irq);
-       unsigned int status = desc->status;
+       uint64_t event_occurred;
 
        ivec = irq & 0xff;
        if (ivec == SGI_UART_VECTOR) {
-               nasid = smp_physical_node_id();
-               event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) );
-               // If the UART bit is set here, we may have received an interrupt from the
-               // UART that the driver missed.  To make sure, we IPI ourselves to force us
-               // to look again.
+               nasid = get_nasid();
+               event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR
+                                      (nasid, SH_EVENT_OCCURRED));
+               /* If the UART bit is set here, we may have received an 
+                * interrupt from the UART that the driver missed.  To
+                * make sure, we IPI ourselves to force us to look again.
+                */
                if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
-                               platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0);
+                       platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR,
+                                         IA64_IPI_DM_INT, 0);
                }
        }
        __clear_bit(ivec, (volatile void *)pda->sn_in_service_ivecs);
        if (sn_force_interrupt_flag)
-               if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-                       force_interrupt(irq);
+               force_interrupt(irq);
 }
 
-static void
-sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
 {
+       struct sn_irq_info *sn_irq_info = sn_irq[irq];
+       struct sn_irq_info *tmp_sn_irq_info;
+       int cpuid, cpuphys;
+       nasid_t t_nasid;        /* nasid to target */
+       int t_slice;            /* slice to target */
+
+       /* allocate a temp sn_irq_info struct to get new target info */
+       tmp_sn_irq_info = kmalloc(sizeof(*tmp_sn_irq_info), GFP_KERNEL);
+       if (!tmp_sn_irq_info)
+               return;
+
+       cpuid = first_cpu(mask);
+       cpuphys = cpu_physical_id(cpuid);
+       t_nasid = cpuid_to_nasid(cpuid);
+       t_slice = cpuid_to_slice(cpuid);
+
+       while (sn_irq_info) {
+               int status;
+               int local_widget;
+               uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
+               nasid_t local_nasid = NASID_GET(bridge);
+
+               if (!bridge)
+                       break;  /* irq is not a device interrupt */
+
+               if (local_nasid & 1)
+                       local_widget = TIO_SWIN_WIDGETNUM(bridge);
+               else
+                       local_widget = SWIN_WIDGETNUM(bridge);
+
+               /* Free the old PROM sn_irq_info structure */
+               sn_intr_free(local_nasid, local_widget, sn_irq_info);
+
+               /* allocate a new PROM sn_irq_info struct */
+               status = sn_intr_alloc(local_nasid, local_widget,
+                                      __pa(tmp_sn_irq_info), irq, t_nasid,
+                                      t_slice);
+
+               if (status == 0) {
+                       /* Update kernels sn_irq_info with new target info */
+                       unregister_intr_pda(sn_irq_info);
+                       sn_irq_info->irq_cpuid = cpuid;
+                       sn_irq_info->irq_nasid = t_nasid;
+                       sn_irq_info->irq_slice = t_slice;
+                       sn_irq_info->irq_xtalkaddr =
+                           tmp_sn_irq_info->irq_xtalkaddr;
+                       sn_irq_info->irq_cookie = tmp_sn_irq_info->irq_cookie;
+                       register_intr_pda(sn_irq_info);
+
+                       if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type)) {
+                               pcibr_change_devices_irq(sn_irq_info);
+                       }
+
+                       sn_irq_info = sn_irq_info->irq_next;
+
 #ifdef CONFIG_SMP
-       int redir = 0;
-       int cpu;
-       struct sn_intr_list_t *p = sn_intr_list[irq];
-       pcibr_intr_t intr;
-       extern void sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
-       extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
-
-       if (p == NULL)
-               return; 
-        
-       intr = p->intr;
-
-       if (intr == NULL)
-               return; 
-
-       cpu = first_cpu(mask);
-       sn_shub_redirect_intr(intr, cpu);
-       irq = irq & 0xff;  /* strip off redirect bit, if someone stuck it on. */
-       (void) set_irq_affinity_info(irq, cpu_physical_id(intr->bi_cpu), redir);
-#endif /* CONFIG_SMP */
+                       set_irq_affinity_info((irq & 0xff), cpuphys, 0);
+#endif
+               } else {
+                       break;  /* snp_affinity failed the intr_alloc */
+               }
+       }
+       kfree(tmp_sn_irq_info);
 }
 
-
 struct hw_interrupt_type irq_type_sn = {
        "SN hub",
        sn_startup_irq,
        sn_shutdown_irq,
        sn_enable_irq,
        sn_disable_irq,
-       sn_ack_irq, 
+       sn_ack_irq,
        sn_end_irq,
        sn_set_affinity_irq
 };
 
-
-struct irq_desc *
-sn_irq_desc(unsigned int irq)
-{
-
-       irq = SN_IVEC_FROM_IRQ(irq);
-
-       return(_irq_desc + irq);
-}
-
-u8
-sn_irq_to_vector(unsigned int irq)
-{
-       return(irq);
-}
-
-unsigned int
-sn_local_vector_to_irq(u8 vector)
+unsigned int sn_local_vector_to_irq(u8 vector)
 {
        return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
 }
 
-void
-sn_irq_init (void)
+void sn_irq_init(void)
 {
        int i;
-       irq_desc_t *base_desc = _irq_desc;
+       irq_desc_t *base_desc = irq_desc;
 
-       for (i=0; i<NR_IRQS; i++) {
+       for (i = 0; i < NR_IRQS; i++) {
                if (base_desc[i].handler == &no_irq_type) {
                        base_desc[i].handler = &irq_type_sn;
                }
        }
 }
 
-void
-register_pcibr_intr(int irq, pcibr_intr_t intr)
+static void register_intr_pda(struct sn_irq_info *sn_irq_info)
 {
-       struct sn_intr_list_t *p = kmalloc(sizeof(struct sn_intr_list_t), GFP_KERNEL);
-       struct sn_intr_list_t *list;
-       int cpu = intr->bi_cpu;
+       int irq = sn_irq_info->irq_irq;
+       int cpu = sn_irq_info->irq_cpuid;
 
        if (pdacpu(cpu)->sn_last_irq < irq) {
                pdacpu(cpu)->sn_last_irq = irq;
        }
-       if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq;
-       if (!p) panic("Could not allocate memory for sn_intr_list_t\n");
-       if ((list = sn_intr_list[irq])) {
-               while (list->next) list = list->next;
-               list->next = p;
-               p->next = NULL;
-               p->intr = intr;
-       } else {
-               sn_intr_list[irq] = p;
-               p->next = NULL;
-               p->intr = intr;
+
+       if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) {
+               pdacpu(cpu)->sn_first_irq = irq;
        }
 }
 
-void
-unregister_pcibr_intr(int irq, pcibr_intr_t intr)
+static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
 {
-
-       struct sn_intr_list_t **prev, *curr;
-       int cpu = intr->bi_cpu;
-       int i;
-
-       if (sn_intr_list[irq] == NULL)
-               return;
-
-       prev = &sn_intr_list[irq];
-       curr = sn_intr_list[irq];
-       while (curr) {
-               if (curr->intr == intr)  {
-                       *prev = curr->next;
-                       break;
+       int irq = sn_irq_info->irq_irq;
+       int cpu = sn_irq_info->irq_cpuid;
+       struct sn_irq_info *tmp_irq_info;
+       int i, foundmatch;
+
+       if (pdacpu(cpu)->sn_last_irq == irq) {
+               foundmatch = 0;
+               for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--) {
+                       tmp_irq_info = sn_irq[i];
+                       while (tmp_irq_info) {
+                               if (tmp_irq_info->irq_cpuid == cpu) {
+                                       foundmatch++;
+                                       break;
+                               }
+                               tmp_irq_info = tmp_irq_info->irq_next;
+                       }
+                       if (foundmatch) {
+                               break;
+                       }
                }
-               prev = &curr->next;
-               curr = curr->next;
+               pdacpu(cpu)->sn_last_irq = i;
        }
 
-       if (curr)
-               kfree(curr);
-
-       if (!sn_intr_list[irq]) {
-               if (pdacpu(cpu)->sn_last_irq == irq) {
-                       for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--)
-                               if (sn_intr_list[i])
+       if (pdacpu(cpu)->sn_first_irq == irq) {
+               foundmatch = 0;
+               for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++) {
+                       tmp_irq_info = sn_irq[i];
+                       while (tmp_irq_info) {
+                               if (tmp_irq_info->irq_cpuid == cpu) {
+                                       foundmatch++;
                                        break;
-                       pdacpu(cpu)->sn_last_irq = i;
+                               }
+                               tmp_irq_info = tmp_irq_info->irq_next;
+                       }
+                       if (foundmatch) {
+                               break;
+                       }
                }
+               pdacpu(cpu)->sn_first_irq = ((i == NR_IRQS) ? 0 : i);
+       }
+}
 
-               if (pdacpu(cpu)->sn_first_irq == irq) {
-                       pdacpu(cpu)->sn_first_irq = 0;
-                       for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++)
-                               if (sn_intr_list[i])
-                                       pdacpu(cpu)->sn_first_irq = i;
-               }
+struct sn_irq_info *sn_irq_alloc(nasid_t local_nasid, int local_widget, int irq,
+                                nasid_t nasid, int slice)
+{
+       struct sn_irq_info *sn_irq_info;
+       int status;
+
+       sn_irq_info = kmalloc(sizeof(*sn_irq_info), GFP_KERNEL);
+       if (sn_irq_info == NULL)
+               return NULL;
+
+       memset(sn_irq_info, 0x0, sizeof(*sn_irq_info));
+
+       status =
+           sn_intr_alloc(local_nasid, local_widget, __pa(sn_irq_info), irq,
+                         nasid, slice);
+
+       if (status) {
+               kfree(sn_irq_info);
+               return NULL;
+       } else {
+               return sn_irq_info;
        }
+}
 
+void sn_irq_free(struct sn_irq_info *sn_irq_info)
+{
+       uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
+       nasid_t local_nasid = NASID_GET(bridge);
+       int local_widget;
+
+       if (local_nasid & 1)    /* tio check */
+               local_widget = TIO_SWIN_WIDGETNUM(bridge);
+       else
+               local_widget = SWIN_WIDGETNUM(bridge);
+
+       sn_intr_free(local_nasid, local_widget, sn_irq_info);
+
+       kfree(sn_irq_info);
 }
 
-void
-force_polled_int(void)
+void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
 {
-       int i;
-       struct sn_intr_list_t *p;
+       nasid_t nasid = sn_irq_info->irq_nasid;
+       int slice = sn_irq_info->irq_slice;
+       int cpu = nasid_slice_to_cpuid(nasid, slice);
 
-       for (i=0; i<NR_IRQS;i++) {
-               p = sn_intr_list[i];
-               while (p) {
-                       if (p->intr){
-                               pcibr_force_interrupt(p->intr);
-                       }
-                       p = p->next;
-               }
-       }
+       sn_irq_info->irq_cpuid = cpu;
+       sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev);
+
+       /* link it into the sn_irq[irq] list */
+       sn_irq_info->irq_next = sn_irq[sn_irq_info->irq_irq];
+       sn_irq[sn_irq_info->irq_irq] = sn_irq_info;
+
+       (void)register_intr_pda(sn_irq_info);
 }
 
-static void
-force_interrupt(int irq)
+static void force_interrupt(int irq)
 {
-       struct sn_intr_list_t *p = sn_intr_list[irq];
+       struct sn_irq_info *sn_irq_info;
 
-       while (p) {
-               if (p->intr) {
-                       pcibr_force_interrupt(p->intr);
+       if (!sn_ioif_inited)
+               return;
+       sn_irq_info = sn_irq[irq];
+       while (sn_irq_info) {
+               if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
+                   (sn_irq_info->irq_bridge != NULL)) {
+                       pcibr_force_interrupt(sn_irq_info);
                }
-               p = p->next;
+               sn_irq_info = sn_irq_info->irq_next;
        }
 }
 
 /*
-Check for lost interrupts.  If the PIC int_status reg. says that
-an interrupt has been sent, but not handled, and the interrupt
-is not pending in either the cpu irr regs or in the soft irr regs,
-and the interrupt is not in service, then the interrupt may have
-been lost.  Force an interrupt on that pin.  It is possible that
-the interrupt is in flight, so we may generate a spurious interrupt,
-but we should never miss a real lost interrupt.
-*/
-
-static void
-sn_check_intr(int irq, pcibr_intr_t intr)
+ * Check for lost interrupts.  If the PIC int_status reg. says that
+ * an interrupt has been sent, but not handled, and the interrupt
+ * is not pending in either the cpu irr regs or in the soft irr regs,
+ * and the interrupt is not in service, then the interrupt may have
+ * been lost.  Force an interrupt on that pin.  It is possible that
+ * the interrupt is in flight, so we may generate a spurious interrupt,
+ * but we should never miss a real lost interrupt.
+ */
+static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
 {
-       unsigned long regval;
+       uint64_t regval;
        int irr_reg_num;
        int irr_bit;
-       unsigned long irr_reg;
+       uint64_t irr_reg;
+       struct pcidev_info *pcidev_info;
+       struct pcibus_info *pcibus_info;
+
+       pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+       if (!pcidev_info)
+               return;
 
+       pcibus_info =
+           (struct pcibus_info *)pcidev_info->pdi_host_pcidev_info->
+           pdi_pcibus_info;
+       regval = pcireg_intr_status_get(pcibus_info);
 
-       regval = pcireg_intr_status_get(intr->bi_soft);
        irr_reg_num = irq_to_vector(irq) / 64;
        irr_bit = irq_to_vector(irq) % 64;
        switch (irr_reg_num) {
-               case 0:
-                       irr_reg = ia64_getreg(_IA64_REG_CR_IRR0);
-                       break;
-               case 1:
-                       irr_reg = ia64_getreg(_IA64_REG_CR_IRR1);
-                       break;
-               case 2:
-                       irr_reg = ia64_getreg(_IA64_REG_CR_IRR2);
-                       break;
-               case 3:
-                       irr_reg = ia64_getreg(_IA64_REG_CR_IRR3);
-                       break;
+       case 0:
+               irr_reg = ia64_getreg(_IA64_REG_CR_IRR0);
+               break;
+       case 1:
+               irr_reg = ia64_getreg(_IA64_REG_CR_IRR1);
+               break;
+       case 2:
+               irr_reg = ia64_getreg(_IA64_REG_CR_IRR2);
+               break;
+       case 3:
+               irr_reg = ia64_getreg(_IA64_REG_CR_IRR3);
+               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) ) {
+       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 (intr->bi_ibits & regval & intr->bi_last_intr) {
-                                       regval &= ~(intr->bi_ibits & regval);
-                                       pcibr_force_interrupt(intr);
+                               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);
                                }
                        }
                }
        }
-       intr->bi_last_intr = regval;
+       sn_irq_info->irq_last_intr = regval;
 }
 
-void
-sn_lb_int_war_check(void)
+void sn_lb_int_war_check(void)
 {
        int i;
 
-       if (pda->sn_first_irq == 0) return;
-       for (i=pda->sn_first_irq;
-               i <= pda->sn_last_irq; i++) {
-                       struct sn_intr_list_t *p = sn_intr_list[i];
-                       if (p == NULL) {
-                               continue;
-                       }
-                       while (p) {
-                               sn_check_intr(i, p->intr);
-                               p = p->next;
+       if (!sn_ioif_inited || pda->sn_first_irq == 0)
+               return;
+       for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
+               struct sn_irq_info *sn_irq_info = sn_irq[i];
+               while (sn_irq_info) {
+                       /* 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_irq_info = sn_irq_info->irq_next;
+               }
        }
 }