Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2823

kernel-2.6.18-194.11.1.el5.src.rpm

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;
 }