aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-02-26 17:55:06 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-02-27 12:46:52 -0500
commitbb4c18cbba474ae20c84171819255598cf975158 (patch)
tree4c370809b4dffdadd59314e86c97d0fca48e9978
parentd3dcc2cb2cd86b1db68f0d87d610f1f14406f928 (diff)
[SPARC64]: Fix PCI interrupts on E450 et al.
When the PCI controller OBP node lacks an interrupt-map and interrupt-map-mask property, we need to form the INO by hand. The PCI swizzle logic was not doing that properly. This was a regression added by the of_device code. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/of_device.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index b0f3e0082a0d..ad74e5e8778e 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -708,7 +708,7 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
708 unsigned int irq) 708 unsigned int irq)
709{ 709{
710 struct linux_prom_pci_registers *regs; 710 struct linux_prom_pci_registers *regs;
711 unsigned int devfn, slot, ret; 711 unsigned int bus, devfn, slot, ret;
712 712
713 if (irq < 1 || irq > 4) 713 if (irq < 1 || irq > 4)
714 return irq; 714 return irq;
@@ -717,10 +717,46 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
717 if (!regs) 717 if (!regs)
718 return irq; 718 return irq;
719 719
720 bus = (regs->phys_hi >> 16) & 0xff;
720 devfn = (regs->phys_hi >> 8) & 0xff; 721 devfn = (regs->phys_hi >> 8) & 0xff;
721 slot = (devfn >> 3) & 0x1f; 722 slot = (devfn >> 3) & 0x1f;
722 723
723 ret = ((irq - 1 + (slot & 3)) & 3) + 1; 724 if (pp->irq_trans) {
725 /* Derived from Table 8-3, U2P User's Manual. This branch
726 * is handling a PCI controller that lacks a proper set of
727 * interrupt-map and interrupt-map-mask properties. The
728 * Ultra-E450 is one example.
729 *
730 * The bit layout is BSSLL, where:
731 * B: 0 on bus A, 1 on bus B
732 * D: 2-bit slot number, derived from PCI device number as
733 * (dev - 1) for bus A, or (dev - 2) for bus B
734 * L: 2-bit line number
735 *
736 * Actually, more "portable" way to calculate the funky
737 * slot number is to subtract pbm->pci_first_slot from the
738 * device number, and that's exactly what the pre-OF
739 * sparc64 code did, but we're building this stuff generically
740 * using the OBP tree, not in the PCI controller layer.
741 */
742 if (bus & 0x80) {
743 /* PBM-A */
744 bus = 0x00;
745 slot = (slot - 1) << 2;
746 } else {
747 /* PBM-B */
748 bus = 0x10;
749 slot = (slot - 2) << 2;
750 }
751 irq -= 1;
752
753 ret = (bus | slot | irq);
754 } else {
755 /* Going through a PCI-PCI bridge that lacks a set of
756 * interrupt-map and interrupt-map-mask properties.
757 */
758 ret = ((irq - 1 + (slot & 3)) & 3) + 1;
759 }
724 760
725 return ret; 761 return ret;
726} 762}