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 | |
| 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')
| -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 5e8a9d105e..84b2030fc2 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*/ |
