aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt2
-rw-r--r--arch/i386/kernel/setup.c32
-rw-r--r--arch/i386/pci/common.c5
-rw-r--r--arch/i386/pci/mmconfig.c34
-rw-r--r--arch/i386/pci/pci.h3
-rw-r--r--arch/x86_64/kernel/e820.c29
-rw-r--r--arch/x86_64/pci/mmconfig.c34
7 files changed, 82 insertions, 57 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 87a17337c7f6..71d05f481727 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1189,8 +1189,6 @@ running once the system is up.
1189 Mechanism 2. 1189 Mechanism 2.
1190 nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI 1190 nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI
1191 Configuration 1191 Configuration
1192 mmconf [IA-32,X86_64] Force MMCONFIG. This is useful
1193 to override the builtin blacklist.
1194 nomsi [MSI] If the PCI_MSI kernel config parameter is 1192 nomsi [MSI] If the PCI_MSI kernel config parameter is
1195 enabled, this kernel boot option can be used to 1193 enabled, this kernel boot option can be used to
1196 disable the use of MSI interrupts system-wide. 1194 disable the use of MSI interrupts system-wide.
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 345ffb7d904d..f1682206d304 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -956,6 +956,38 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
956 return 0; 956 return 0;
957} 957}
958 958
959 /*
960 * This function checks if the entire range <start,end> is mapped with type.
961 *
962 * Note: this function only works correct if the e820 table is sorted and
963 * not-overlapping, which is the case
964 */
965int __init
966e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
967{
968 u64 start = s;
969 u64 end = e;
970 int i;
971 for (i = 0; i < e820.nr_map; i++) {
972 struct e820entry *ei = &e820.map[i];
973 if (type && ei->type != type)
974 continue;
975 /* is the region (part) in overlap with the current region ?*/
976 if (ei->addr >= end || ei->addr + ei->size <= start)
977 continue;
978 /* if the region is at the beginning of <start,end> we move
979 * start to the end of the region since it's ok until there
980 */
981 if (ei->addr <= start)
982 start = ei->addr + ei->size;
983 /* if start is now at or beyond end, we're done, full
984 * coverage */
985 if (start >= end)
986 return 1; /* we're done */
987 }
988 return 0;
989}
990
959/* 991/*
960 * Find the highest page frame number we have available 992 * Find the highest page frame number we have available
961 */ 993 */
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 1220dd828ce3..0a362e3aeac5 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -237,11 +237,6 @@ char * __devinit pcibios_setup(char *str)
237 pci_probe &= ~PCI_PROBE_MMCONF; 237 pci_probe &= ~PCI_PROBE_MMCONF;
238 return NULL; 238 return NULL;
239 } 239 }
240 /* override DMI blacklist */
241 else if (!strcmp(str, "mmconf")) {
242 pci_probe |= PCI_PROBE_MMCONF_FORCE;
243 return NULL;
244 }
245#endif 240#endif
246 else if (!strcmp(str, "noacpi")) { 241 else if (!strcmp(str, "noacpi")) {
247 acpi_noirq_set(); 242 acpi_noirq_set();
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index ef5a2faa7d82..972180f738d9 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -12,7 +12,6 @@
12#include <linux/pci.h> 12#include <linux/pci.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/acpi.h> 14#include <linux/acpi.h>
15#include <linux/dmi.h>
16#include <asm/e820.h> 15#include <asm/e820.h>
17#include "pci.h" 16#include "pci.h"
18 17
@@ -188,31 +187,9 @@ static __init void unreachable_devices(void)
188 } 187 }
189} 188}
190 189
191static int disable_mcfg(struct dmi_system_id *d)
192{
193 printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
194 pci_probe &= ~PCI_PROBE_MMCONF;
195 return 0;
196}
197
198static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
199 /* Has broken MCFG table that makes the system hang when used */
200 {
201 .callback = disable_mcfg,
202 .ident = "Intel D3C5105 SDV",
203 .matches = {
204 DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
205 DMI_MATCH(DMI_BOARD_NAME, "D26928"),
206 },
207 },
208 {}
209};
210
211void __init pci_mmcfg_init(void) 190void __init pci_mmcfg_init(void)
212{ 191{
213 dmi_check_system(dmi_bad_mcfg); 192 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
214
215 if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
216 return; 193 return;
217 194
218 acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); 195 acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -221,6 +198,15 @@ void __init pci_mmcfg_init(void)
221 (pci_mmcfg_config[0].base_address == 0)) 198 (pci_mmcfg_config[0].base_address == 0))
222 return; 199 return;
223 200
201 if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
202 pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
203 E820_RESERVED)) {
204 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
205 pci_mmcfg_config[0].base_address);
206 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
207 return;
208 }
209
224 printk(KERN_INFO "PCI: Using MMCONFIG\n"); 210 printk(KERN_INFO "PCI: Using MMCONFIG\n");
225 raw_pci_ops = &pci_mmcfg; 211 raw_pci_ops = &pci_mmcfg;
226 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; 212 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index 49a849b3a241..bf4e79335388 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -16,8 +16,7 @@
16#define PCI_PROBE_CONF1 0x0002 16#define PCI_PROBE_CONF1 0x0002
17#define PCI_PROBE_CONF2 0x0004 17#define PCI_PROBE_CONF2 0x0004
18#define PCI_PROBE_MMCONF 0x0008 18#define PCI_PROBE_MMCONF 0x0008
19#define PCI_PROBE_MMCONF_FORCE 0x0010 19#define PCI_PROBE_MASK 0x000f
20#define PCI_PROBE_MASK 0x00ff
21 20
22#define PCI_NO_SORT 0x0100 21#define PCI_NO_SORT 0x0100
23#define PCI_BIOS_SORT 0x0200 22#define PCI_BIOS_SORT 0x0200
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 764bf23c7103..d6d7f731f6f0 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -108,6 +108,35 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
108 return 0; 108 return 0;
109} 109}
110 110
111/*
112 * This function checks if the entire range <start,end> is mapped with type.
113 *
114 * Note: this function only works correct if the e820 table is sorted and
115 * not-overlapping, which is the case
116 */
117int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
118{
119 int i;
120 for (i = 0; i < e820.nr_map; i++) {
121 struct e820entry *ei = &e820.map[i];
122 if (type && ei->type != type)
123 continue;
124 /* is the region (part) in overlap with the current region ?*/
125 if (ei->addr >= end || ei->addr + ei->size <= start)
126 continue;
127
128 /* if the region is at the beginning of <start,end> we move
129 * start to the end of the region since it's ok until there
130 */
131 if (ei->addr <= start)
132 start = ei->addr + ei->size;
133 /* if start is now at or beyond end, we're done, full coverage */
134 if (start >= end)
135 return 1; /* we're done */
136 }
137 return 0;
138}
139
111/* 140/*
112 * Find a free area in a specific range. 141 * Find a free area in a specific range.
113 */ 142 */
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 2d48a7941d48..3c55c76c6fd5 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,7 +9,6 @@
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/acpi.h> 10#include <linux/acpi.h>
11#include <linux/bitmap.h> 11#include <linux/bitmap.h>
12#include <linux/dmi.h>
13#include <asm/e820.h> 12#include <asm/e820.h>
14 13
15#include "pci.h" 14#include "pci.h"
@@ -165,33 +164,11 @@ static __init void unreachable_devices(void)
165 } 164 }
166} 165}
167 166
168static int disable_mcfg(struct dmi_system_id *d)
169{
170 printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
171 pci_probe &= ~PCI_PROBE_MMCONF;
172 return 0;
173}
174
175static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
176 /* Has broken MCFG table that makes the system hang when used */
177 {
178 .callback = disable_mcfg,
179 .ident = "Intel D3C5105 SDV",
180 .matches = {
181 DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
182 DMI_MATCH(DMI_BOARD_NAME, "D26928"),
183 },
184 },
185 {}
186};
187
188void __init pci_mmcfg_init(void) 167void __init pci_mmcfg_init(void)
189{ 168{
190 int i; 169 int i;
191 170
192 dmi_check_system(dmi_bad_mcfg); 171 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
193
194 if ((pci_probe & (PCI_PROBE_MMCONF|PCI_PROBE_MMCONF_FORCE)) == 0)
195 return; 172 return;
196 173
197 acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); 174 acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -200,6 +177,15 @@ void __init pci_mmcfg_init(void)
200 (pci_mmcfg_config[0].base_address == 0)) 177 (pci_mmcfg_config[0].base_address == 0))
201 return; 178 return;
202 179
180 if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
181 pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
182 E820_RESERVED)) {
183 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
184 pci_mmcfg_config[0].base_address);
185 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
186 return;
187 }
188
203 /* RED-PEN i386 doesn't do _nocache right now */ 189 /* RED-PEN i386 doesn't do _nocache right now */
204 pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); 190 pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
205 if (pci_mmcfg_virt == NULL) { 191 if (pci_mmcfg_virt == NULL) {