Messages in this thread Patch in this message | | | Date | Thu, 1 May 2008 21:54:27 -0500 | From | Matt Domsch <> | Subject | [PATCH] fix x86 DMI checks for PCI quirks |
| |
fix x86 DMI checks for PCI quirks
http://bugzilla.kernel.org/show_bug.cgi?id=10583 https://bugzilla.redhat.com/show_bug.cgi?id=444791
Since git commit 08f1c192c3c32797068bfe97738babb3295bbf42 (between kernels 2.6.22 and 2.6.23), arch/x86/pci/acpi.c has not called pcibios_scan_root(), which would have called arch/x86/pci/common.c:dmi_check_system(). This has prevented the quirks listed in pciprobe_dmi_table[] from being checked and appropriate action taken.
This manifests itself in several Dell and HP servers not automatically having the pci=bfsort option be applied, as well as Samsung X20 and Compaq EVO N800c systems needing pci=assign-all-busses was no longer automatically applied.
This patch moves the DMI tests into its own file, arch/x86/pci/dmi.c, and invokes them via subsys_initcall() before pci_acpi_init(), pci_legacy_init(), and pcibios_init() are called, which may rely upon these tests having been executed.
Signed-off-by: Matt Domsch <Matt_Domsch@dell.com> --- arch/x86/pci/Makefile_32 | 1 + arch/x86/pci/Makefile_64 | 1 + arch/x86/pci/common.c | 219 +-------------------------------------------- arch/x86/pci/dmi.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++ arch/x86/pci/pci.h | 1 + 5 files changed, 232 insertions(+), 218 deletions(-) create mode 100644 arch/x86/pci/dmi.c
diff --git a/arch/x86/pci/Makefile_32 b/arch/x86/pci/Makefile_32 index cdd6828..d5232ee 100644 --- a/arch/x86/pci/Makefile_32 +++ b/arch/x86/pci/Makefile_32 @@ -5,6 +5,7 @@ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_32.o direct.o mmconfig-shared.o obj-$(CONFIG_PCI_DIRECT) += direct.o pci-y := fixup.o +pci-y += dmi.o pci-$(CONFIG_ACPI) += acpi.o pci-y += legacy.o irq.o diff --git a/arch/x86/pci/Makefile_64 b/arch/x86/pci/Makefile_64 index 7d8c467..654568f 100644 --- a/arch/x86/pci/Makefile_64 +++ b/arch/x86/pci/Makefile_64 @@ -8,6 +8,7 @@ EXTRA_CFLAGS += -Iarch/x86/pci obj-y := i386.o obj-$(CONFIG_PCI_DIRECT)+= direct.o obj-y += fixup.o init.o +obj-y += dmi.o obj-$(CONFIG_ACPI) += acpi.o obj-y += legacy.o irq.o common.o early.o # mmconfig has a 64bit special diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 7b6e3bb..dfc4d6b 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -8,7 +8,6 @@ #include <linux/pci.h> #include <linux/ioport.h> #include <linux/init.h> -#include <linux/dmi.h> #include <asm/acpi.h> #include <asm/segment.h> @@ -19,8 +18,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF; - -static int pci_bf_sort; +int pci_bf_sort; int pci_routeirq; int pcibios_last_bus = -1; unsigned long pirq_table_addr; @@ -158,227 +156,12 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b) pcibios_fixup_device_resources(dev); } -/* - * Only use DMI information to set this if nothing was passed - * on the kernel command line (which was parsed earlier). - */ - -static int __devinit set_bf_sort(const struct dmi_system_id *d) -{ - if (pci_bf_sort == pci_bf_sort_default) { - pci_bf_sort = pci_dmi_bf; - printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); - } - return 0; -} - -/* - * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) - */ -#ifdef __i386__ -static int __devinit assign_all_busses(const struct dmi_system_id *d) -{ - pci_probe |= PCI_ASSIGN_ALL_BUSSES; - printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" - " (pci=assign-busses)\n", d->ident); - return 0; -} -#endif - -static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { -#ifdef __i386__ -/* - * Laptops which need pci=assign-busses to see Cardbus cards - */ - { - .callback = assign_all_busses, - .ident = "Samsung X20 Laptop", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), - DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), - }, - }, -#endif /* __i386__ */ - { - .callback = set_bf_sort, - .ident = "Dell PowerEdge 1950", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell"), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), - }, - }, - { - .callback = set_bf_sort, - .ident = "Dell PowerEdge 1955", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell"), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), - }, - }, - { - .callback = set_bf_sort, - .ident = "Dell PowerEdge 2900", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell"), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), - }, - }, - { - .callback = set_bf_sort, - .ident = "Dell PowerEdge 2950", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell"), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), - }, - }, - { - .callback = set_bf_sort, - .ident = "Dell PowerEdge R900", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell"), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL20p G3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL20p G4", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL30p G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL25p G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL35p G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL45p G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL45p G2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL460c G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL465c G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL480c G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant BL685c G1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant DL385 G2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant DL585 G2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), - }, - }, -#ifdef __i386__ - { - .callback = assign_all_busses, - .ident = "Compaq EVO N800c", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), - DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"), - }, - }, -#endif - { - .callback = set_bf_sort, - .ident = "HP ProLiant DL385 G2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), - }, - }, - { - .callback = set_bf_sort, - .ident = "HP ProLiant DL585 G2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), - }, - }, - {} -}; struct pci_bus * __devinit pcibios_scan_root(int busnum) { struct pci_bus *bus = NULL; struct pci_sysdata *sd; - dmi_check_system(pciprobe_dmi_table); - while ((bus = pci_find_next_bus(bus)) != NULL) { if (bus->number == busnum) { /* Already scanned */ diff --git a/arch/x86/pci/dmi.c b/arch/x86/pci/dmi.c new file mode 100644 index 0000000..46ad227 --- /dev/null +++ b/arch/x86/pci/dmi.c @@ -0,0 +1,228 @@ +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/dmi.h> +#include "pci.h" + +/* + * Only use DMI information to set this if nothing was passed + * on the kernel command line (which was parsed earlier). + */ + +static int __devinit set_bf_sort(const struct dmi_system_id *d) +{ + if (pci_bf_sort == pci_bf_sort_default) { + pci_bf_sort = pci_dmi_bf; + printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); + } + return 0; +} + +/* + * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) + */ +#ifdef __i386__ +static int __devinit assign_all_busses(const struct dmi_system_id *d) +{ + pci_probe |= PCI_ASSIGN_ALL_BUSSES; + printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" + " (pci=assign-busses)\n", d->ident); + return 0; +} +#endif + +static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { +#ifdef __i386__ +/* + * Laptops which need pci=assign-busses to see Cardbus cards + */ + { + .callback = assign_all_busses, + .ident = "Samsung X20 Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), + }, + }, +#endif /* __i386__ */ + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 1950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), + }, + }, + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 1955", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), + }, + }, + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 2900", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), + }, + }, + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 2950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), + }, + }, + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge R900", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL20p G3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL20p G4", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL30p G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL25p G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL35p G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL45p G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL45p G2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL460c G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL465c G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL480c G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant BL685c G1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant DL385 G2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant DL585 G2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), + }, + }, +#ifdef __i386__ + { + .callback = assign_all_busses, + .ident = "Compaq EVO N800c", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), + DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"), + }, + }, +#endif + { + .callback = set_bf_sort, + .ident = "HP ProLiant DL385 G2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant DL585 G2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), + }, + }, + {} +}; + + +static int __init pciprobe_dmi_init(void) +{ + dmi_check_system(pciprobe_dmi_table); + return 0; +} + +subsys_initcall(pciprobe_dmi_init); + diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h index 3431518..98fc872 100644 --- a/arch/x86/pci/pci.h +++ b/arch/x86/pci/pci.h @@ -31,6 +31,7 @@ extern unsigned int pci_probe; extern unsigned long pirq_table_addr; +extern int pci_bf_sort; enum pci_bf_sort_state { pci_bf_sort_default, -- 1.5.2.4
-- Matt Domsch Linux Technology Strategist, Dell Office of the CTO linux.dell.com & www.dell.com/linux
| |