aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci/k8-bus_64.c
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel@gmail.com>2008-03-06 04:15:31 -0500
committerIngo Molnar <mingo@elte.hu>2008-04-26 17:41:04 -0400
commit6e184f299d696203bc40545b9db216089d88bef7 (patch)
treef43932f58c05038f948c46ac023b0a017d676a7f /arch/x86/pci/k8-bus_64.c
parent30a18d6c3f1e774de656ebd8ff219d53e2ba4029 (diff)
x86: double check the multi root bus with fam10h mmconf
some bioses give same range to mmconf for fam10h msr, and mmio for node/link. fam10h msr will overide mmio for node/link. so we can not assign range to devices under node/link for unassigned resources. this patch will take range out from the mmio for node/link Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/pci/k8-bus_64.c')
-rw-r--r--arch/x86/pci/k8-bus_64.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/arch/x86/pci/k8-bus_64.c b/arch/x86/pci/k8-bus_64.c
index 5e8a9d105edd..84b2030fc2f0 100644
--- a/arch/x86/pci/k8-bus_64.c
+++ b/arch/x86/pci/k8-bus_64.c
@@ -191,6 +191,34 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
191 { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 }, 191 { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
192}; 192};
193 193
194static u64 __initdata fam10h_mmconf_start;
195static u64 __initdata fam10h_mmconf_end;
196static void __init get_pci_mmcfg_amd_fam10h_range(void)
197{
198 u32 address;
199 u64 base, msr;
200 unsigned segn_busn_bits;
201
202 /* assume all cpus from fam10h have mmconf */
203 if (boot_cpu_data.x86 < 0x10)
204 return;
205
206 address = MSR_FAM10H_MMIO_CONF_BASE;
207 rdmsrl(address, msr);
208
209 /* mmconfig is not enable */
210 if (!(msr & FAM10H_MMIO_CONF_ENABLE))
211 return;
212
213 base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
214
215 segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
216 FAM10H_MMIO_CONF_BUSRANGE_MASK;
217
218 fam10h_mmconf_start = base;
219 fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
220}
221
194/** 222/**
195 * early_fill_mp_bus_to_node() 223 * early_fill_mp_bus_to_node()
196 * called before pcibios_scan_root and pci_scan_bus 224 * called before pcibios_scan_root and pci_scan_bus
@@ -305,6 +333,8 @@ static int __init early_fill_mp_bus_info(void)
305 continue; /* not found */ 333 continue; /* not found */
306 334
307 info = &pci_root_info[j]; 335 info = &pci_root_info[j];
336 printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
337 node, link, (u64)start, (u64)end);
308 update_res(info, start, end, IORESOURCE_IO, 0); 338 update_res(info, start, end, IORESOURCE_IO, 0);
309 update_range(range, start, end); 339 update_range(range, start, end);
310 } 340 }
@@ -328,8 +358,7 @@ static int __init early_fill_mp_bus_info(void)
328 358
329 memset(range, 0, sizeof(range)); 359 memset(range, 0, sizeof(range));
330 /* 0xfd00000000-0xffffffffff for HT */ 360 /* 0xfd00000000-0xffffffffff for HT */
331 /* 0xfc00000000-0xfcffffffff for Family 10h mmconfig*/ 361 range[0].end = (0xfdULL<<32) - 1;
332 range[0].end = 0xfbffffffffULL;
333 362
334 /* need to take out [0, TOM) for RAM*/ 363 /* need to take out [0, TOM) for RAM*/
335 address = MSR_K8_TOP_MEM1; 364 address = MSR_K8_TOP_MEM1;
@@ -339,6 +368,14 @@ static int __init early_fill_mp_bus_info(void)
339 if (end < (1ULL<<32)) 368 if (end < (1ULL<<32))
340 update_range(range, 0, end - 1); 369 update_range(range, 0, end - 1);
341 370
371 /* get mmconfig */
372 get_pci_mmcfg_amd_fam10h_range();
373 /* need to take out mmconf range */
374 if (fam10h_mmconf_end) {
375 printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end);
376 update_range(range, fam10h_mmconf_start, fam10h_mmconf_end);
377 }
378
342 /* mmio resource */ 379 /* mmio resource */
343 for (i = 0; i < 8; i++) { 380 for (i = 0; i < 8; i++) {
344 reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3)); 381 reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
@@ -364,8 +401,51 @@ static int __init early_fill_mp_bus_info(void)
364 continue; /* not found */ 401 continue; /* not found */
365 402
366 info = &pci_root_info[j]; 403 info = &pci_root_info[j];
404
405 printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
406 node, link, (u64)start, (u64)end);
407 /*
408 * some sick allocation would have range overlap with fam10h
409 * mmconf range, so need to update start and end.
410 */
411 if (fam10h_mmconf_end) {
412 int changed = 0;
413 u64 endx = 0;
414 if (start >= fam10h_mmconf_start &&
415 start <= fam10h_mmconf_end) {
416 start = fam10h_mmconf_end + 1;
417 changed = 1;
418 }
419
420 if (end >= fam10h_mmconf_start &&
421 end <= fam10h_mmconf_end) {
422 end = fam10h_mmconf_start - 1;
423 changed = 1;
424 }
425
426 if (start < fam10h_mmconf_start &&
427 end > fam10h_mmconf_end) {
428 /* we got a hole */
429 endx = fam10h_mmconf_start - 1;
430 update_res(info, start, endx, IORESOURCE_MEM, 0);
431 update_range(range, start, endx);
432 printk(KERN_CONT " ==> [%llx, %llx]", (u64)start, endx);
433 start = fam10h_mmconf_end + 1;
434 changed = 1;
435 }
436 if (changed) {
437 if (start <= end) {
438 printk(KERN_CONT " %s [%llx, %llx]", endx?"and":"==>", (u64)start, (u64)end);
439 } else {
440 printk(KERN_CONT "%s\n", endx?"":" ==> none");
441 continue;
442 }
443 }
444 }
445
367 update_res(info, start, end, IORESOURCE_MEM, 0); 446 update_res(info, start, end, IORESOURCE_MEM, 0);
368 update_range(range, start, end); 447 update_range(range, start, end);
448 printk(KERN_CONT "\n");
369 } 449 }
370 450
371 /* need to take out [4G, TOM2) for RAM*/ 451 /* need to take out [4G, TOM2) for RAM*/