diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-03-06 04:15:31 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-26 17:41:04 -0400 |
commit | 6e184f299d696203bc40545b9db216089d88bef7 (patch) | |
tree | f43932f58c05038f948c46ac023b0a017d676a7f /arch/x86/pci/k8-bus_64.c | |
parent | 30a18d6c3f1e774de656ebd8ff219d53e2ba4029 (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.c | 84 |
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 | ||
194 | static u64 __initdata fam10h_mmconf_start; | ||
195 | static u64 __initdata fam10h_mmconf_end; | ||
196 | static 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*/ |