Commit 79e453d4 authored by Linus Torvalds's avatar Linus Torvalds

Revert mmiocfg heuristics and blacklist changes

This reverts commits 11012d41 and
40dd2d20, which allowed us to use the
MMIO accesses for PCI config cycles even without the area being marked
reserved in the e820 memory tables.

Those changes were needed for EFI-environment Intel macs, but broke some
newer Intel 965 boards, so for now it's better to revert to our old
2.6.17 behaviour and at least avoid introducing any new breakage.

Andi Kleen has a set of patches that work with both EFI and the broken
Intel 965 boards, which will be applied once they get wider testing.

Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Edgar Hucek <hostmaster@ed-soft.at>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ab5cfd2a
...@@ -1189,8 +1189,6 @@ running once the system is up. ...@@ -1189,8 +1189,6 @@ running once the system is up.
Mechanism 2. Mechanism 2.
nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI
Configuration Configuration
mmconf [IA-32,X86_64] Force MMCONFIG. This is useful
to override the builtin blacklist.
nomsi [MSI] If the PCI_MSI kernel config parameter is nomsi [MSI] If the PCI_MSI kernel config parameter is
enabled, this kernel boot option can be used to enabled, this kernel boot option can be used to
disable the use of MSI interrupts system-wide. disable the use of MSI interrupts system-wide.
......
...@@ -956,6 +956,38 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) ...@@ -956,6 +956,38 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
return 0; return 0;
} }
/*
* This function checks if the entire range <start,end> is mapped with type.
*
* Note: this function only works correct if the e820 table is sorted and
* not-overlapping, which is the case
*/
int __init
e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
{
u64 start = s;
u64 end = e;
int i;
for (i = 0; i < e820.nr_map; i++) {
struct e820entry *ei = &e820.map[i];
if (type && ei->type != type)
continue;
/* is the region (part) in overlap with the current region ?*/
if (ei->addr >= end || ei->addr + ei->size <= start)
continue;
/* if the region is at the beginning of <start,end> we move
* start to the end of the region since it's ok until there
*/
if (ei->addr <= start)
start = ei->addr + ei->size;
/* if start is now at or beyond end, we're done, full
* coverage */
if (start >= end)
return 1; /* we're done */
}
return 0;
}
/* /*
* Find the highest page frame number we have available * Find the highest page frame number we have available
*/ */
......
...@@ -237,11 +237,6 @@ char * __devinit pcibios_setup(char *str) ...@@ -237,11 +237,6 @@ char * __devinit pcibios_setup(char *str)
pci_probe &= ~PCI_PROBE_MMCONF; pci_probe &= ~PCI_PROBE_MMCONF;
return NULL; return NULL;
} }
/* override DMI blacklist */
else if (!strcmp(str, "mmconf")) {
pci_probe |= PCI_PROBE_MMCONF_FORCE;
return NULL;
}
#endif #endif
else if (!strcmp(str, "noacpi")) { else if (!strcmp(str, "noacpi")) {
acpi_noirq_set(); acpi_noirq_set();
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h>
#include <asm/e820.h> #include <asm/e820.h>
#include "pci.h" #include "pci.h"
...@@ -188,31 +187,9 @@ static __init void unreachable_devices(void) ...@@ -188,31 +187,9 @@ static __init void unreachable_devices(void)
} }
} }
static int disable_mcfg(struct dmi_system_id *d)
{
printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
pci_probe &= ~PCI_PROBE_MMCONF;
return 0;
}
static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
/* Has broken MCFG table that makes the system hang when used */
{
.callback = disable_mcfg,
.ident = "Intel D3C5105 SDV",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
DMI_MATCH(DMI_BOARD_NAME, "D26928"),
},
},
{}
};
void __init pci_mmcfg_init(void) void __init pci_mmcfg_init(void)
{ {
dmi_check_system(dmi_bad_mcfg); if ((pci_probe & PCI_PROBE_MMCONF) == 0)
if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
return; return;
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
...@@ -221,6 +198,15 @@ void __init pci_mmcfg_init(void) ...@@ -221,6 +198,15 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0)) (pci_mmcfg_config[0].base_address == 0))
return; return;
if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
E820_RESERVED)) {
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
pci_mmcfg_config[0].base_address);
printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
return;
}
printk(KERN_INFO "PCI: Using MMCONFIG\n"); printk(KERN_INFO "PCI: Using MMCONFIG\n");
raw_pci_ops = &pci_mmcfg; raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
......
...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
#define PCI_PROBE_CONF1 0x0002 #define PCI_PROBE_CONF1 0x0002
#define PCI_PROBE_CONF2 0x0004 #define PCI_PROBE_CONF2 0x0004
#define PCI_PROBE_MMCONF 0x0008 #define PCI_PROBE_MMCONF 0x0008
#define PCI_PROBE_MMCONF_FORCE 0x0010 #define PCI_PROBE_MASK 0x000f
#define PCI_PROBE_MASK 0x00ff
#define PCI_NO_SORT 0x0100 #define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200 #define PCI_BIOS_SORT 0x0200
......
...@@ -108,6 +108,35 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type) ...@@ -108,6 +108,35 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
return 0; return 0;
} }
/*
* This function checks if the entire range <start,end> is mapped with type.
*
* Note: this function only works correct if the e820 table is sorted and
* not-overlapping, which is the case
*/
int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
{
int i;
for (i = 0; i < e820.nr_map; i++) {
struct e820entry *ei = &e820.map[i];
if (type && ei->type != type)
continue;
/* is the region (part) in overlap with the current region ?*/
if (ei->addr >= end || ei->addr + ei->size <= start)
continue;
/* if the region is at the beginning of <start,end> we move
* start to the end of the region since it's ok until there
*/
if (ei->addr <= start)
start = ei->addr + ei->size;
/* if start is now at or beyond end, we're done, full coverage */
if (start >= end)
return 1; /* we're done */
}
return 0;
}
/* /*
* Find a free area in a specific range. * Find a free area in a specific range.
*/ */
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/dmi.h>
#include <asm/e820.h> #include <asm/e820.h>
#include "pci.h" #include "pci.h"
...@@ -165,33 +164,11 @@ static __init void unreachable_devices(void) ...@@ -165,33 +164,11 @@ static __init void unreachable_devices(void)
} }
} }
static int disable_mcfg(struct dmi_system_id *d)
{
printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
pci_probe &= ~PCI_PROBE_MMCONF;
return 0;
}
static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
/* Has broken MCFG table that makes the system hang when used */
{
.callback = disable_mcfg,
.ident = "Intel D3C5105 SDV",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
DMI_MATCH(DMI_BOARD_NAME, "D26928"),
},
},
{}
};
void __init pci_mmcfg_init(void) void __init pci_mmcfg_init(void)
{ {
int i; int i;
dmi_check_system(dmi_bad_mcfg); if ((pci_probe & PCI_PROBE_MMCONF) == 0)
if ((pci_probe & (PCI_PROBE_MMCONF|PCI_PROBE_MMCONF_FORCE)) == 0)
return; return;
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
...@@ -200,6 +177,15 @@ void __init pci_mmcfg_init(void) ...@@ -200,6 +177,15 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0)) (pci_mmcfg_config[0].base_address == 0))
return; return;
if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
E820_RESERVED)) {
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
pci_mmcfg_config[0].base_address);
printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
return;
}
/* RED-PEN i386 doesn't do _nocache right now */ /* RED-PEN i386 doesn't do _nocache right now */
pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
if (pci_mmcfg_virt == NULL) { if (pci_mmcfg_virt == NULL) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment