diff options
author | David S. Miller | 2006-06-20 01:22:35 -0700 |
---|---|---|
committer | David S. Miller | 2006-06-20 01:22:35 -0700 |
commit | 8047e247c899f80c33a23ad7e9e250224f0d26a5 (patch) | |
tree | 253a7ba3c902730928214df5c2b5630d7875cc11 /arch/sparc64/kernel/pci_schizo.c | |
parent | 37cdcd9e82108f9b899f1631f66ade2e45738a6e (diff) |
[SPARC64]: Virtualize IRQ numbers.
Inspired by PowerPC XICS interrupt support code.
All IRQs are virtualized in order to keep NR_IRQS from needing
to be too large. Interrupts on sparc64 are arbitrary 11-bit
values, but we don't need to define NR_IRQS to 2048 if we
virtualize the IRQs.
As PCI and SBUS controller drivers build device IRQs, we divy
out virtual IRQ numbers incrementally starting at 1. Zero is
a special virtual IRQ used for the timer interrupt.
So device drivers all see virtual IRQs, and all the normal
interfaces such as request_irq(), enable_irq(), etc. translate
that into a real IRQ number in order to configure the IRQ.
At this point knowledge of the struct ino_bucket is almost
entirely contained within arch/sparc64/kernel/irq.c There are
a few small bits in the PCI controller drivers that need to
be swept away before we can remove ino_bucket's definition
out of asm-sparc64/irq.h and privately into kernel/irq.c
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index ca49ef08236d..0c400b5fa5bd 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -270,25 +270,33 @@ static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void } } +static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm, + unsigned int ino) +{ + ino &= PCI_IRQ_INO; + return pbm->pbm_regs + schizo_iclr_offset(ino) + 4; +} + +static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm, + unsigned int ino) +{ + ino &= PCI_IRQ_INO; + return pbm->pbm_regs + schizo_imap_offset(ino) + 4; +} + static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, struct pci_dev *pdev, unsigned int ino) { - struct ino_bucket *bucket; unsigned long imap, iclr; - unsigned long imap_off, iclr_off; int ign_fixup; + int virt_irq; ino &= PCI_IRQ_INO; - imap_off = schizo_imap_offset(ino); /* Now build the IRQ bucket. */ - imap = pbm->pbm_regs + imap_off; - imap += 4; - - iclr_off = schizo_iclr_offset(ino); - iclr = pbm->pbm_regs + iclr_off; - iclr += 4; + imap = schizo_ino_to_imap(pbm, ino); + iclr = schizo_ino_to_iclr(pbm, ino); /* On Schizo, no inofixup occurs. This is because each * INO has it's own IMAP register. On Psycho and Sabre @@ -305,19 +313,17 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, ign_fixup = (1 << 6); } - bucket = __bucket(build_irq(ign_fixup, iclr, imap)); - bucket->flags |= IBF_PCI; + virt_irq = build_irq(ign_fixup, iclr, imap, IBF_PCI); if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - struct irq_desc *p = bucket->irq_info; - - p->pre_handler = tomatillo_wsync_handler; - p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? - (void *) 1 : (void *) 0); - p->pre_handler_arg2 = (void *) pbm->sync_reg; + irq_install_pre_handler(virt_irq, + tomatillo_wsync_handler, + ((pbm->chip_version <= 4) ? + (void *) 1 : (void *) 0), + (void *) pbm->sync_reg); } - return __irq(bucket); + return virt_irq; } /* SCHIZO error handling support. */ @@ -358,7 +364,6 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) { struct pci_pbm_info *pbm; - struct ino_bucket *bucket; unsigned long iclr; /* Do not clear the interrupt for the other PCI bus. @@ -376,11 +381,11 @@ static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) else pbm = &p->pbm_A; - irq = schizo_irq_build(pbm, NULL, - (pbm->portid << 6) | (irq & IMAP_INO)); - bucket = __bucket(irq); - iclr = bucket->iclr; + schizo_irq_build(pbm, NULL, + (pbm->portid << 6) | (irq & IMAP_INO)); + iclr = schizo_ino_to_iclr(pbm, + (pbm->portid << 6) | (irq & IMAP_INO)); upa_writel(ICLR_IDLE, iclr); } @@ -1125,7 +1130,6 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) { struct pci_pbm_info *pbm; unsigned int irq; - struct ino_bucket *bucket; u64 tmp, err_mask, err_no_mask; /* Build IRQs and register handlers. */ @@ -1137,8 +1141,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); @@ -1150,8 +1153,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); @@ -1164,8 +1166,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_PCIERR_A_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); @@ -1178,8 +1180,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_PCIERR_B_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); @@ -1191,8 +1193,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_SERR_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); @@ -1263,7 +1265,6 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) { struct pci_pbm_info *pbm; unsigned int irq; - struct ino_bucket *bucket; u64 tmp, err_mask, err_no_mask; /* Build IRQs and register handlers. */ @@ -1275,8 +1276,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_CE_INO); @@ -1287,8 +1287,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); @@ -1299,8 +1298,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); @@ -1311,8 +1309,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_SERR_INO); @@ -1323,8 +1320,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); /* Enable UE and CE interrupts for controller. */ |