Sophie

Sophie

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

kernel-2.6.18-194.11.1.el5.src.rpm

From: Prarit Bhargava <prarit@redhat.com>
Date: Tue, 7 Apr 2009 08:56:19 -0400
Subject: [x86] general pci_scan_bus fix for baremetal and xen
Message-id: 20090407125618.8459.36812.sendpatchset@prarit.bos.redhat.com
O-Subject: [RHEL5.4 PATCH] general pci_scan_bus(..., ..., NULL) fix for baremetal and xen
Bugzilla: 494114
RH-Acked-by: Chris Lalancette <clalance@redhat.com>
RH-Acked-by: Don Dutile <ddutile@redhat.com>
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

Booting the i386 kernel, i386 PAE kernel, i386 xen dom0 with "acpi=off" all
resulted in the same panic on a baremetal kernel on an xw9400.  Similar panics
are seen on xen kernels.

This panic is very similar to the panic that was fixed by commit
1c7e4e6b8497b9feaf6e88294e5f5fd328ddefe1 which resolved BZ 463418.

This patch is a general fix for the overall issue; return 0 in pci_domain_nr()
if sysdata == NULL.

Successfully compiled and tested by me on 32-bit and 64-bit x86 on HP and IBM
systems.  The xen kernel was successfully tested by the BZ reporter.

Resolves BZ 494114.

diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index c60c574..d4b19d2 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -136,20 +136,10 @@ 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;
-		/* 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))
+		if (pci_scan_bus(i, &pci_root_ops, NULL))
 			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
-		else
-			kfree(sd);
-
 	}
 	pcibios_last_bus = -1;
 }
diff --git a/include/asm-i386/mach-xen/asm/pci.h b/include/asm-i386/mach-xen/asm/pci.h
index c991436..39b71cc 100644
--- a/include/asm-i386/mach-xen/asm/pci.h
+++ b/include/asm-i386/mach-xen/asm/pci.h
@@ -12,8 +12,14 @@ struct pci_sysdata {
 #ifdef CONFIG_PCI_DOMAINS
 static inline int pci_domain_nr(struct pci_bus *bus)
 {
-        struct pci_sysdata *sd = bus->sysdata;
-        return sd->domain;
+	struct pci_sysdata *sd = bus->sysdata;
+	if (!sd) {
+		/* Many systems call pci_scan_bus() which calls pci_domain_nr()
+		   with a NULL sysdata pointer.  It appears safe to return 0
+		   in these cases (ie, assume a single domain) */
+		return 0;
+	}
+	return sd->domain;
 }
 extern struct pci_sysdata pci_default_sysdata;
 
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h
index d1c293b..e397426 100644
--- a/include/asm-i386/pci.h
+++ b/include/asm-i386/pci.h
@@ -13,6 +13,12 @@ struct pci_sysdata {
 static inline int pci_domain_nr(struct pci_bus *bus)
 {
 	struct pci_sysdata *sd = bus->sysdata;
+	if (!sd) {
+		/* Many systems call pci_scan_bus() which calls pci_domain_nr()
+		   with a NULL sysdata pointer.  It appears safe to return 0
+		   in these cases (ie, assume a single domain) */
+		return 0;
+	}
 	return sd->domain;
 }
 extern struct pci_sysdata pci_default_sysdata;
diff --git a/include/asm-x86_64/mach-xen/asm/pci.h b/include/asm-x86_64/mach-xen/asm/pci.h
index 6d88d4b..ca4e2ec 100644
--- a/include/asm-x86_64/mach-xen/asm/pci.h
+++ b/include/asm-x86_64/mach-xen/asm/pci.h
@@ -14,8 +14,14 @@ extern struct pci_sysdata pci_default_sysdata;
 #ifdef CONFIG_PCI_DOMAINS
 static inline int pci_domain_nr(struct pci_bus *bus)
 {
-       struct pci_sysdata *sd = bus->sysdata;
-       return sd->domain;
+	struct pci_sysdata *sd = bus->sysdata;
+	if (!sd) {
+		/* Many systems call pci_scan_bus() which calls pci_domain_nr()
+		   with a NULL sysdata pointer.  It appears safe to return 0
+		   in these cases (ie, assume a single domain) */
+		return 0;
+	}
+	return sd->domain;
 }
 
 static inline int pci_proc_domain(struct pci_bus *bus)
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index e0af482..b0b88aa 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -19,6 +19,12 @@ extern struct pci_sysdata pci_default_sysdata;
 static inline int pci_domain_nr(struct pci_bus *bus)
 {
 	struct pci_sysdata *sd = bus->sysdata;
+	if (!sd) {
+		/* Many systems call pci_scan_bus() which calls pci_domain_nr()
+		   with a NULL sysdata pointer.  It appears safe to return 0
+		   in these cases (ie, assume a single domain) */
+		return 0;
+	}
 	return sd->domain;
 }