Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[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>

+38 -2
+38 -2
arch/sparc64/kernel/of_device.c
··· 708 708 unsigned int irq) 709 709 { 710 710 struct linux_prom_pci_registers *regs; 711 - unsigned int devfn, slot, ret; 711 + unsigned int bus, devfn, slot, ret; 712 712 713 713 if (irq < 1 || irq > 4) 714 714 return irq; ··· 717 717 if (!regs) 718 718 return irq; 719 719 720 + bus = (regs->phys_hi >> 16) & 0xff; 720 721 devfn = (regs->phys_hi >> 8) & 0xff; 721 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 761 return ret; 726 762 }