diff options
author | jhb <jhb@FreeBSD.org> | 2005-11-21 22:01:16 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-11-21 22:01:16 +0000 |
commit | a6da623025dcec2e0e4fcb5f210ca741274546bf (patch) | |
tree | 65d18a508949361669ea59bddaa4d1f696790745 /sys | |
parent | 26ea846ce92cc9968c0389039966c0d8b1c358cf (diff) | |
download | FreeBSD-src-a6da623025dcec2e0e4fcb5f210ca741274546bf.zip FreeBSD-src-a6da623025dcec2e0e4fcb5f210ca741274546bf.tar.gz |
Fix the code to look up the BIOS IRQ for a given link device by reading
the IRQ set by the BIOS in existing devices to actually get the correct
bus number of the child PCI bus. I was not reading the bus number from
the bridge device correctly. The __BUS_ACCESSOR() macros (from which
pcib_get_bus() is built) assume that the passed in argument is a child
device. However, at the time I'm reading the bus there is no child
device yet, so I was passing in the pcib device as the child device.
The parent of the pcib device probably returned an error in the case of
a host bridge, thus resulting in random stack garbage for the bus number.
For PCI-PCI bridges, the bus number being used was actually the subvendor
of the PCI-PCI bridge device itself.
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/acpica/acpi_pci_link.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/sys/dev/acpica/acpi_pci_link.c b/sys/dev/acpica/acpi_pci_link.c index 8041f78..57d27f7 100644 --- a/sys/dev/acpica/acpi_pci_link.c +++ b/sys/dev/acpica/acpi_pci_link.c @@ -608,7 +608,19 @@ acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot, { struct link *link; uint8_t bios_irq; + uintptr_t bus; + /* + * Look up the PCI bus for the specified PCI bridge device. Note + * that the PCI bridge device might not have any children yet. + * However, looking up its bus number doesn't require a valid child + * device, so we just pass NULL. + */ + if (BUS_READ_IVAR(pcib, NULL, PCIB_IVAR_BUS, &bus) != 0) { + device_printf(pcib, "Unable to read PCI bus number"); + panic("this is bad"); + } + /* Bump the reference count. */ ACPI_SERIAL_BEGIN(pci_link); link = acpi_pci_link_lookup(dev, index); @@ -619,7 +631,7 @@ acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot, pci_link_interrupt_weights[link->l_irq]++; /* Try to find a BIOS IRQ setting from any matching devices. */ - bios_irq = acpi_pci_link_search_irq(pcib_get_bus(pcib), slot, pin); + bios_irq = acpi_pci_link_search_irq(bus, slot, pin); if (!PCI_INTERRUPT_VALID(bios_irq)) { ACPI_SERIAL_END(pci_link); return; @@ -628,7 +640,7 @@ acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot, /* Validate the BIOS IRQ. */ if (!link_valid_irq(link, bios_irq)) { device_printf(dev, "BIOS IRQ %u for %d.%d.INT%c is invalid\n", - bios_irq, pcib_get_bus(pcib), slot, pin + 'A'); + bios_irq, (int)bus, slot, pin + 'A'); } else if (!PCI_INTERRUPT_VALID(link->l_bios_irq)) { link->l_bios_irq = bios_irq; if (bios_irq < NUM_ISA_INTERRUPTS) @@ -641,7 +653,7 @@ acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot, } else if (bios_irq != link->l_bios_irq) device_printf(dev, "BIOS IRQ %u for %d.%d.INT%c does not match previous BIOS IRQ %u\n", - bios_irq, pcib_get_bus(pcib), slot, pin + 'A', + bios_irq, (int)bus, slot, pin + 'A', link->l_bios_irq); ACPI_SERIAL_END(pci_link); } |