Commit 87cf25a1 authored by David S. Miller's avatar David S. Miller

Merge 2.4.x sparc64 PCI IRQ routing fixes into 2.5

parent a19ece58
...@@ -571,7 +571,7 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt ...@@ -571,7 +571,7 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt
struct pci_pbm_info *pbm = dev_pcp->pbm; struct pci_pbm_info *pbm = dev_pcp->pbm;
struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs; struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs;
unsigned int hi, mid, lo, irq; unsigned int hi, mid, lo, irq;
int i, num_intmap; int i, num_intmap, map_slot;
if (pbm->num_pbm_intmap == 0) if (pbm->num_pbm_intmap == 0)
return 0; return 0;
...@@ -579,6 +579,7 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt ...@@ -579,6 +579,7 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt
intmap = &pbm->pbm_intmap[0]; intmap = &pbm->pbm_intmap[0];
intmask = &pbm->pbm_intmask; intmask = &pbm->pbm_intmask;
num_intmap = pbm->num_pbm_intmap; num_intmap = pbm->num_pbm_intmap;
map_slot = 0;
/* If we are underneath a PCI bridge, use PROM register /* If we are underneath a PCI bridge, use PROM register
* property of the parent bridge which is closest to * property of the parent bridge which is closest to
...@@ -639,11 +640,21 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt ...@@ -639,11 +640,21 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt
printk("pci_intmap_match: Trying to recover.\n"); printk("pci_intmap_match: Trying to recover.\n");
return 0; return 0;
} }
if (pdev->bus->self != bus_dev)
map_slot = 1;
} else { } else {
pregs = bus_pcp->prom_regs; pregs = bus_pcp->prom_regs;
map_slot = 1;
} }
} }
if (map_slot) {
*interrupt = ((*interrupt
- 1
+ PCI_SLOT(pdev->devfn)) & 0x3) + 1;
}
hi = pregs->phys_hi & intmask->phys_hi; hi = pregs->phys_hi & intmask->phys_hi;
mid = pregs->phys_mid & intmask->phys_mid; mid = pregs->phys_mid & intmask->phys_mid;
lo = pregs->phys_lo & intmask->phys_lo; lo = pregs->phys_lo & intmask->phys_lo;
...@@ -655,6 +666,9 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt ...@@ -655,6 +666,9 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt
intmap[i].phys_lo == lo && intmap[i].phys_lo == lo &&
intmap[i].interrupt == irq) { intmap[i].interrupt == irq) {
*interrupt = intmap[i].cinterrupt; *interrupt = intmap[i].cinterrupt;
printk("PCI-IRQ: Routing bus[%2x] slot[%2x] map[%d] to INO[%02x]\n",
pdev->bus->number, PCI_SLOT(pdev->devfn),
map_slot, *interrupt);
return 1; return 1;
} }
} }
...@@ -720,20 +734,6 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev) ...@@ -720,20 +734,6 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev)
goto have_irq; goto have_irq;
} }
/* Firmware gets quad-hme interrupts property totally
* wrong. It is 4 EBUS+HME devices behind a Digital bridge.
* For each of the 4 instances the EBUS has interrupt property
* '1' and the HME has interrupt property '2'. So we have to
* fix this up.
*/
if (!strcmp(pcp->prom_name, "SUNW,qfe") ||
!strcmp(pcp->prom_name, "qfe")) {
if (PCI_SLOT(pdev->devfn) & ~3)
BUG();
prom_irq = PCI_SLOT(pdev->devfn) + 1;
}
/* Can we find a matching entry in the interrupt-map? */ /* Can we find a matching entry in the interrupt-map? */
if (pci_intmap_match(pdev, &prom_irq)) { if (pci_intmap_match(pdev, &prom_irq)) {
pdev->irq = p->irq_build(pbm, pdev, (portid << 6) | prom_irq); pdev->irq = p->irq_build(pbm, pdev, (portid << 6) | prom_irq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment