From: Prarit Bhargava <prarit@redhat.com> Date: Fri, 17 Oct 2008 10:44:23 -0400 Subject: [pci] set domain/node to 0 in PCI BIOS enum code path Message-id: 48F8A4C7.90802@redhat.com O-Subject: Re: [RHEL5.3 PATCH] Set domain & node to 0 in PCI BIOS enumeration code path Bugzilla: 463418 RH-Acked-by: Neil Horman <nhorman@redhat.com> RH-Acked-by: Jeff Garzik <jgarzik@redhat.com> PCI Domain support requires that calls to pci_scan_bus() now have a non-NULL sysdata struct. On systems where ACPI tables are not available, or on systems that kdump, PCI is enumerated in a different manner than that of the bare-metal kernel. In those cases we do: (all of his code is in arch/i386/pci/irq.c which is included in x86_64 builds) pcibios_irq_init() -> pirq_peer_trick() -> pci_scan_bus() However, in pirq_peer_trick() for(i = 1; i < 256; i++) { if (!busmap[i] || pci_find_bus(0, i)) continue; if (pci_scan_bus(i, &pci_root_ops, NULL)) ^^^^^^^^ CAUSES NULL POINTER PANIC printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i); } After some quick code examination I decided the best thing to do is to further hack pirq_peer_trick, which is a self-described "gross hack" anyway. My patch makes the assumption that the domain and node number is 0 for the entire PCI subsystem. AFAICT, that is no worse than what happens when we go down the pcibios_irq_init() route anyway. Resolves BZ 463418. Successfully compiled and tested by me. diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 8763033..482ddf0 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -136,10 +136,20 @@ static void __init pirq_peer_trick(void) busmap[e->bus] = 1; } for(i = 1; i < 256; i++) { + struct pci_sysdata *sd; if (!busmap[i] || pci_find_bus(0, i)) continue; - if (pci_scan_bus(i, &pci_root_ops, NULL)) + /* Continuation of the gross hack. + sysdata cannot be NULL here because of PCI_DOMAIN support. + Let's assume we're part of the same domain and node */ + sd = kzalloc(sizeof(*sd), GFP_KERNEL); + if (!sd) + panic("Cannot allocate PCI domain sysdata"); + if (pci_scan_bus(i, &pci_root_ops, sd)) printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i); + else + kfree(sd); + } pcibios_last_bus = -1; }