diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-11-13 19:33:53 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-11-24 18:28:51 -0500 |
commit | 7da7d360ae025158d09aab18d66f5d2fe3c02252 (patch) | |
tree | 35aaf2c1c39e17f24e89dcb0e19aa26d778b5f7e /arch/x86 | |
parent | d3578ef7aab5b9bb874d085609b3ed5d9abffc48 (diff) |
x86/PCI: MMCONFIG: centralize MCFG structure management
This patch encapsulate pci_mmcfg_config[] updates. All alloc/free is now
done in pci_mmconfig_add() and free_all_mcfg(), so all updates to
pci_mmcfg_config[] and pci_mmcfg_config_num are in those two functions.
This replaces the previous sequence of extend_mmcfg(), fill_one_mmcfg()
with the single pci_mmconfig_add() interface. This interface is currently
static but will eventually be used in the host bridge hot-add path.
Reviewed-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/pci/mmconfig-shared.c | 85 |
1 files changed, 39 insertions, 46 deletions
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 7a7b6ba3abbb..62a8ecd96980 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -26,14 +26,24 @@ | |||
26 | /* Indicate if the mmcfg resources have been placed into the resource table. */ | 26 | /* Indicate if the mmcfg resources have been placed into the resource table. */ |
27 | static int __initdata pci_mmcfg_resources_inserted; | 27 | static int __initdata pci_mmcfg_resources_inserted; |
28 | 28 | ||
29 | static __init int extend_mmcfg(int num) | 29 | static __init void free_all_mmcfg(void) |
30 | { | ||
31 | pci_mmcfg_arch_free(); | ||
32 | pci_mmcfg_config_num = 0; | ||
33 | kfree(pci_mmcfg_config); | ||
34 | pci_mmcfg_config = NULL; | ||
35 | } | ||
36 | |||
37 | static __init struct acpi_mcfg_allocation *pci_mmconfig_add(int segment, | ||
38 | int start, int end, u64 addr) | ||
30 | { | 39 | { |
31 | struct acpi_mcfg_allocation *new; | 40 | struct acpi_mcfg_allocation *new; |
32 | int new_num = pci_mmcfg_config_num + num; | 41 | int new_num = pci_mmcfg_config_num + 1; |
42 | int i = pci_mmcfg_config_num; | ||
33 | 43 | ||
34 | new = kzalloc(sizeof(pci_mmcfg_config[0]) * new_num, GFP_KERNEL); | 44 | new = kzalloc(sizeof(pci_mmcfg_config[0]) * new_num, GFP_KERNEL); |
35 | if (!new) | 45 | if (!new) |
36 | return -1; | 46 | return NULL; |
37 | 47 | ||
38 | if (pci_mmcfg_config) { | 48 | if (pci_mmcfg_config) { |
39 | memcpy(new, pci_mmcfg_config, | 49 | memcpy(new, pci_mmcfg_config, |
@@ -42,18 +52,13 @@ static __init int extend_mmcfg(int num) | |||
42 | } | 52 | } |
43 | pci_mmcfg_config = new; | 53 | pci_mmcfg_config = new; |
44 | 54 | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static __init void fill_one_mmcfg(u64 addr, int segment, int start, int end) | ||
49 | { | ||
50 | int i = pci_mmcfg_config_num; | ||
51 | |||
52 | pci_mmcfg_config_num++; | 55 | pci_mmcfg_config_num++; |
53 | pci_mmcfg_config[i].address = addr; | 56 | pci_mmcfg_config[i].address = addr; |
54 | pci_mmcfg_config[i].pci_segment = segment; | 57 | pci_mmcfg_config[i].pci_segment = segment; |
55 | pci_mmcfg_config[i].start_bus_number = start; | 58 | pci_mmcfg_config[i].start_bus_number = start; |
56 | pci_mmcfg_config[i].end_bus_number = end; | 59 | pci_mmcfg_config[i].end_bus_number = end; |
60 | |||
61 | return &pci_mmcfg_config[i]; | ||
57 | } | 62 | } |
58 | 63 | ||
59 | static const char __init *pci_mmcfg_e7520(void) | 64 | static const char __init *pci_mmcfg_e7520(void) |
@@ -65,11 +70,9 @@ static const char __init *pci_mmcfg_e7520(void) | |||
65 | if (win == 0x0000 || win == 0xf000) | 70 | if (win == 0x0000 || win == 0xf000) |
66 | return NULL; | 71 | return NULL; |
67 | 72 | ||
68 | if (extend_mmcfg(1) == -1) | 73 | if (pci_mmconfig_add(0, 0, 255, win << 16) == NULL) |
69 | return NULL; | 74 | return NULL; |
70 | 75 | ||
71 | fill_one_mmcfg(win << 16, 0, 0, 255); | ||
72 | |||
73 | return "Intel Corporation E7520 Memory Controller Hub"; | 76 | return "Intel Corporation E7520 Memory Controller Hub"; |
74 | } | 77 | } |
75 | 78 | ||
@@ -111,11 +114,9 @@ static const char __init *pci_mmcfg_intel_945(void) | |||
111 | if ((pciexbar & mask) >= 0xf0000000U) | 114 | if ((pciexbar & mask) >= 0xf0000000U) |
112 | return NULL; | 115 | return NULL; |
113 | 116 | ||
114 | if (extend_mmcfg(1) == -1) | 117 | if (pci_mmconfig_add(0, 0, (len >> 20) - 1, pciexbar & mask) == NULL) |
115 | return NULL; | 118 | return NULL; |
116 | 119 | ||
117 | fill_one_mmcfg(pciexbar & mask, 0, 0, (len >> 20) - 1); | ||
118 | |||
119 | return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; | 120 | return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; |
120 | } | 121 | } |
121 | 122 | ||
@@ -124,7 +125,7 @@ static const char __init *pci_mmcfg_amd_fam10h(void) | |||
124 | u32 low, high, address; | 125 | u32 low, high, address; |
125 | u64 base, msr; | 126 | u64 base, msr; |
126 | int i; | 127 | int i; |
127 | unsigned segnbits = 0, busnbits; | 128 | unsigned segnbits = 0, busnbits, end_bus; |
128 | 129 | ||
129 | if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) | 130 | if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) |
130 | return NULL; | 131 | return NULL; |
@@ -158,11 +159,13 @@ static const char __init *pci_mmcfg_amd_fam10h(void) | |||
158 | busnbits = 8; | 159 | busnbits = 8; |
159 | } | 160 | } |
160 | 161 | ||
161 | if (extend_mmcfg(1 << segnbits) == -1) | 162 | end_bus = (1 << busnbits) - 1; |
162 | return NULL; | ||
163 | |||
164 | for (i = 0; i < (1 << segnbits); i++) | 163 | for (i = 0; i < (1 << segnbits); i++) |
165 | fill_one_mmcfg(base + (1<<28) * i, i, 0, (1 << busnbits) - 1); | 164 | if (pci_mmconfig_add(i, 0, end_bus, |
165 | base + (1<<28) * i) == NULL) { | ||
166 | free_all_mmcfg(); | ||
167 | return NULL; | ||
168 | } | ||
166 | 169 | ||
167 | return "AMD Family 10h NB"; | 170 | return "AMD Family 10h NB"; |
168 | } | 171 | } |
@@ -210,16 +213,14 @@ static const char __init *pci_mmcfg_nvidia_mcp55(void) | |||
210 | if (!(extcfg & extcfg_enable_mask)) | 213 | if (!(extcfg & extcfg_enable_mask)) |
211 | continue; | 214 | continue; |
212 | 215 | ||
213 | if (extend_mmcfg(1) == -1) | ||
214 | continue; | ||
215 | |||
216 | size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift; | 216 | size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift; |
217 | base = extcfg & extcfg_base_mask[size_index]; | 217 | base = extcfg & extcfg_base_mask[size_index]; |
218 | /* base could > 4G */ | 218 | /* base could > 4G */ |
219 | base <<= extcfg_base_lshift; | 219 | base <<= extcfg_base_lshift; |
220 | start = (extcfg & extcfg_start_mask) >> extcfg_start_shift; | 220 | start = (extcfg & extcfg_start_mask) >> extcfg_start_shift; |
221 | end = start + extcfg_sizebus[size_index] - 1; | 221 | end = start + extcfg_sizebus[size_index] - 1; |
222 | fill_one_mmcfg(base, 0, start, end); | 222 | if (pci_mmconfig_add(0, start, end, base) == NULL) |
223 | continue; | ||
223 | mcp55_mmconf_found++; | 224 | mcp55_mmconf_found++; |
224 | } | 225 | } |
225 | 226 | ||
@@ -303,8 +304,7 @@ static int __init pci_mmcfg_check_hostbridge(void) | |||
303 | if (!raw_pci_ops) | 304 | if (!raw_pci_ops) |
304 | return 0; | 305 | return 0; |
305 | 306 | ||
306 | pci_mmcfg_config_num = 0; | 307 | free_all_mmcfg(); |
307 | pci_mmcfg_config = NULL; | ||
308 | 308 | ||
309 | for (i = 0; i < ARRAY_SIZE(pci_mmcfg_probes); i++) { | 309 | for (i = 0; i < ARRAY_SIZE(pci_mmcfg_probes); i++) { |
310 | bus = pci_mmcfg_probes[i].bus; | 310 | bus = pci_mmcfg_probes[i].bus; |
@@ -516,10 +516,7 @@ static void __init pci_mmcfg_reject_broken(int early) | |||
516 | 516 | ||
517 | reject: | 517 | reject: |
518 | printk(KERN_INFO "PCI: Not using MMCONFIG.\n"); | 518 | printk(KERN_INFO "PCI: Not using MMCONFIG.\n"); |
519 | pci_mmcfg_arch_free(); | 519 | free_all_mmcfg(); |
520 | kfree(pci_mmcfg_config); | ||
521 | pci_mmcfg_config = NULL; | ||
522 | pci_mmcfg_config_num = 0; | ||
523 | } | 520 | } |
524 | 521 | ||
525 | static int __initdata known_bridge; | 522 | static int __initdata known_bridge; |
@@ -556,7 +553,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) | |||
556 | struct acpi_table_mcfg *mcfg; | 553 | struct acpi_table_mcfg *mcfg; |
557 | struct acpi_mcfg_allocation *cfg_table, *cfg; | 554 | struct acpi_mcfg_allocation *cfg_table, *cfg; |
558 | unsigned long i; | 555 | unsigned long i; |
559 | int entries, config_size; | 556 | int entries; |
560 | 557 | ||
561 | if (!header) | 558 | if (!header) |
562 | return -EINVAL; | 559 | return -EINVAL; |
@@ -564,7 +561,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) | |||
564 | mcfg = (struct acpi_table_mcfg *)header; | 561 | mcfg = (struct acpi_table_mcfg *)header; |
565 | 562 | ||
566 | /* how many config structures do we have */ | 563 | /* how many config structures do we have */ |
567 | pci_mmcfg_config_num = 0; | 564 | free_all_mmcfg(); |
568 | entries = 0; | 565 | entries = 0; |
569 | i = header->length - sizeof(struct acpi_table_mcfg); | 566 | i = header->length - sizeof(struct acpi_table_mcfg); |
570 | while (i >= sizeof(struct acpi_mcfg_allocation)) { | 567 | while (i >= sizeof(struct acpi_mcfg_allocation)) { |
@@ -576,25 +573,21 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) | |||
576 | return -ENODEV; | 573 | return -ENODEV; |
577 | } | 574 | } |
578 | 575 | ||
579 | config_size = entries * sizeof(*pci_mmcfg_config); | ||
580 | pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); | ||
581 | if (!pci_mmcfg_config) { | ||
582 | printk(KERN_WARNING PREFIX | ||
583 | "No memory for MCFG config tables\n"); | ||
584 | return -ENOMEM; | ||
585 | } | ||
586 | |||
587 | memcpy(pci_mmcfg_config, &mcfg[1], config_size); | ||
588 | pci_mmcfg_config_num = entries; | ||
589 | |||
590 | cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1]; | 576 | cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1]; |
591 | for (i = 0; i < entries; i++) { | 577 | for (i = 0; i < entries; i++) { |
592 | cfg = &cfg_table[i]; | 578 | cfg = &cfg_table[i]; |
593 | if (acpi_mcfg_check_entry(mcfg, cfg)) { | 579 | if (acpi_mcfg_check_entry(mcfg, cfg)) { |
594 | kfree(pci_mmcfg_config); | 580 | free_all_mmcfg(); |
595 | pci_mmcfg_config_num = 0; | ||
596 | return -ENODEV; | 581 | return -ENODEV; |
597 | } | 582 | } |
583 | |||
584 | if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number, | ||
585 | cfg->end_bus_number, cfg->address) == NULL) { | ||
586 | printk(KERN_WARNING PREFIX | ||
587 | "no memory for MCFG entries\n"); | ||
588 | free_all_mmcfg(); | ||
589 | return -ENOMEM; | ||
590 | } | ||
598 | } | 591 | } |
599 | 592 | ||
600 | return 0; | 593 | return 0; |