aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:26:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:26:51 -0400
commit5f78e4d33945b291d12765cdd7e4304f437b9361 (patch)
tree113cea729de15a98bb941cc4afb8d13301534ca7 /arch/x86/kernel
parent867a89e0b73af48838c7987e80899a1ff26dd6ff (diff)
parent5f0b2976cb2b62668a076f54419c24b8ab677167 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-bigbox-pci
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-bigbox-pci: x86: add pci=check_enable_amd_mmconf and dmi check x86: work around io allocation overlap of HT links acpi: get boot_cpu_id as early for k8_scan_nodes x86_64: don't need set default res if only have one root bus x86: double check the multi root bus with fam10h mmconf x86: multi pci root bus with different io resource range, on 64-bit x86: use bus conf in NB conf fun1 to get bus range on, on 64-bit x86: get mp_bus_to_node early x86 pci: remove checking type for mmconfig probe x86: remove unneeded check in mmconf reject driver core: try parent numa_node at first before using default x86: seperate mmconf for fam10h out from setup_64.c x86: if acpi=off, force setting the mmconf for fam10h x86_64: check MSR to get MMCONFIG for AMD Family 10h x86_64: check and enable MMCONFIG for AMD Family 10h x86_64: set cfg_size for AMD Family 10h in case MMCONFIG x86: mmconf enable mcfg early x86: clear pci_mmcfg_virt when mmcfg get rejected x86: validate against acpi motherboard resources Fixed up fairly trivial conflicts in arch/x86/pci/{init.c,pci.h} due to OLPC support manually.
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/acpi/boot.c70
-rw-r--r--arch/x86/kernel/mmconf-fam10h_64.c243
-rw-r--r--arch/x86/kernel/setup_64.c20
4 files changed, 335 insertions, 0 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 350eb1b2a208..30d54ed27e55 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -103,4 +103,6 @@ ifeq ($(CONFIG_X86_64),y)
103 obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o 103 obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o
104 obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o 104 obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o
105 obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o 105 obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o
106
107 obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
106endif 108endif
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 977ed5cdeaa3..c49ebcc6c41e 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -771,6 +771,32 @@ static void __init acpi_register_lapic_address(unsigned long address)
771 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); 771 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
772} 772}
773 773
774static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
775{
776 int count;
777
778 if (!cpu_has_apic)
779 return -ENODEV;
780
781 /*
782 * Note that the LAPIC address is obtained from the MADT (32-bit value)
783 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
784 */
785
786 count =
787 acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
788 acpi_parse_lapic_addr_ovr, 0);
789 if (count < 0) {
790 printk(KERN_ERR PREFIX
791 "Error parsing LAPIC address override entry\n");
792 return count;
793 }
794
795 acpi_register_lapic_address(acpi_lapic_addr);
796
797 return count;
798}
799
774static int __init acpi_parse_madt_lapic_entries(void) 800static int __init acpi_parse_madt_lapic_entries(void)
775{ 801{
776 int count; 802 int count;
@@ -901,6 +927,33 @@ static inline int acpi_parse_madt_ioapic_entries(void)
901} 927}
902#endif /* !CONFIG_X86_IO_APIC */ 928#endif /* !CONFIG_X86_IO_APIC */
903 929
930static void __init early_acpi_process_madt(void)
931{
932#ifdef CONFIG_X86_LOCAL_APIC
933 int error;
934
935 if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
936
937 /*
938 * Parse MADT LAPIC entries
939 */
940 error = early_acpi_parse_madt_lapic_addr_ovr();
941 if (!error) {
942 acpi_lapic = 1;
943 smp_found_config = 1;
944 }
945 if (error == -EINVAL) {
946 /*
947 * Dell Precision Workstation 410, 610 come here.
948 */
949 printk(KERN_ERR PREFIX
950 "Invalid BIOS MADT, disabling ACPI\n");
951 disable_acpi();
952 }
953 }
954#endif
955}
956
904static void __init acpi_process_madt(void) 957static void __init acpi_process_madt(void)
905{ 958{
906#ifdef CONFIG_X86_LOCAL_APIC 959#ifdef CONFIG_X86_LOCAL_APIC
@@ -1233,6 +1286,23 @@ int __init acpi_boot_table_init(void)
1233 return 0; 1286 return 0;
1234} 1287}
1235 1288
1289int __init early_acpi_boot_init(void)
1290{
1291 /*
1292 * If acpi_disabled, bail out
1293 * One exception: acpi=ht continues far enough to enumerate LAPICs
1294 */
1295 if (acpi_disabled && !acpi_ht)
1296 return 1;
1297
1298 /*
1299 * Process the Multiple APIC Description Table (MADT), if present
1300 */
1301 early_acpi_process_madt();
1302
1303 return 0;
1304}
1305
1236int __init acpi_boot_init(void) 1306int __init acpi_boot_init(void)
1237{ 1307{
1238 /* 1308 /*
diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c
new file mode 100644
index 000000000000..edc5fbfe85c0
--- /dev/null
+++ b/arch/x86/kernel/mmconf-fam10h_64.c
@@ -0,0 +1,243 @@
1/*
2 * AMD Family 10h mmconfig enablement
3 */
4
5#include <linux/types.h>
6#include <linux/mm.h>
7#include <linux/string.h>
8#include <linux/pci.h>
9#include <linux/dmi.h>
10#include <asm/pci-direct.h>
11#include <linux/sort.h>
12#include <asm/io.h>
13#include <asm/msr.h>
14#include <asm/acpi.h>
15
16#include "../pci/pci.h"
17
18struct pci_hostbridge_probe {
19 u32 bus;
20 u32 slot;
21 u32 vendor;
22 u32 device;
23};
24
25static u64 __cpuinitdata fam10h_pci_mmconf_base;
26static int __cpuinitdata fam10h_pci_mmconf_base_status;
27
28static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = {
29 { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
30 { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
31};
32
33struct range {
34 u64 start;
35 u64 end;
36};
37
38static int __cpuinit cmp_range(const void *x1, const void *x2)
39{
40 const struct range *r1 = x1;
41 const struct range *r2 = x2;
42 int start1, start2;
43
44 start1 = r1->start >> 32;
45 start2 = r2->start >> 32;
46
47 return start1 - start2;
48}
49
50/*[47:0] */
51/* need to avoid (0xfd<<32) and (0xfe<<32), ht used space */
52#define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32)
53#define BASE_VALID(b) ((b != (0xfdULL << 32)) && (b != (0xfeULL << 32)))
54static void __cpuinit get_fam10h_pci_mmconf_base(void)
55{
56 int i;
57 unsigned bus;
58 unsigned slot;
59 int found;
60
61 u64 val;
62 u32 address;
63 u64 tom2;
64 u64 base = FAM10H_PCI_MMCONF_BASE;
65
66 int hi_mmio_num;
67 struct range range[8];
68
69 /* only try to get setting from BSP */
70 /* -1 or 1 */
71 if (fam10h_pci_mmconf_base_status)
72 return;
73
74 if (!early_pci_allowed())
75 goto fail;
76
77 found = 0;
78 for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
79 u32 id;
80 u16 device;
81 u16 vendor;
82
83 bus = pci_probes[i].bus;
84 slot = pci_probes[i].slot;
85 id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
86
87 vendor = id & 0xffff;
88 device = (id>>16) & 0xffff;
89 if (pci_probes[i].vendor == vendor &&
90 pci_probes[i].device == device) {
91 found = 1;
92 break;
93 }
94 }
95
96 if (!found)
97 goto fail;
98
99 /* SYS_CFG */
100 address = MSR_K8_SYSCFG;
101 rdmsrl(address, val);
102
103 /* TOP_MEM2 is not enabled? */
104 if (!(val & (1<<21))) {
105 tom2 = 0;
106 } else {
107 /* TOP_MEM2 */
108 address = MSR_K8_TOP_MEM2;
109 rdmsrl(address, val);
110 tom2 = val & (0xffffULL<<32);
111 }
112
113 if (base <= tom2)
114 base = tom2 + (1ULL<<32);
115
116 /*
117 * need to check if the range is in the high mmio range that is
118 * above 4G
119 */
120 hi_mmio_num = 0;
121 for (i = 0; i < 8; i++) {
122 u32 reg;
123 u64 start;
124 u64 end;
125 reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
126 if (!(reg & 3))
127 continue;
128
129 start = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
130 reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
131 end = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
132
133 if (!end)
134 continue;
135
136 range[hi_mmio_num].start = start;
137 range[hi_mmio_num].end = end;
138 hi_mmio_num++;
139 }
140
141 if (!hi_mmio_num)
142 goto out;
143
144 /* sort the range */
145 sort(range, hi_mmio_num, sizeof(struct range), cmp_range, NULL);
146
147 if (range[hi_mmio_num - 1].end < base)
148 goto out;
149 if (range[0].start > base)
150 goto out;
151
152 /* need to find one window */
153 base = range[0].start - (1ULL << 32);
154 if ((base > tom2) && BASE_VALID(base))
155 goto out;
156 base = range[hi_mmio_num - 1].end + (1ULL << 32);
157 if ((base > tom2) && BASE_VALID(base))
158 goto out;
159 /* need to find window between ranges */
160 if (hi_mmio_num > 1)
161 for (i = 0; i < hi_mmio_num - 1; i++) {
162 if (range[i + 1].start > (range[i].end + (1ULL << 32))) {
163 base = range[i].end + (1ULL << 32);
164 if ((base > tom2) && BASE_VALID(base))
165 goto out;
166 }
167 }
168
169fail:
170 fam10h_pci_mmconf_base_status = -1;
171 return;
172out:
173 fam10h_pci_mmconf_base = base;
174 fam10h_pci_mmconf_base_status = 1;
175}
176
177void __cpuinit fam10h_check_enable_mmcfg(void)
178{
179 u64 val;
180 u32 address;
181
182 if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
183 return;
184
185 address = MSR_FAM10H_MMIO_CONF_BASE;
186 rdmsrl(address, val);
187
188 /* try to make sure that AP's setting is identical to BSP setting */
189 if (val & FAM10H_MMIO_CONF_ENABLE) {
190 unsigned busnbits;
191 busnbits = (val >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
192 FAM10H_MMIO_CONF_BUSRANGE_MASK;
193
194 /* only trust the one handle 256 buses, if acpi=off */
195 if (!acpi_pci_disabled || busnbits >= 8) {
196 u64 base;
197 base = val & (0xffffULL << 32);
198 if (fam10h_pci_mmconf_base_status <= 0) {
199 fam10h_pci_mmconf_base = base;
200 fam10h_pci_mmconf_base_status = 1;
201 return;
202 } else if (fam10h_pci_mmconf_base == base)
203 return;
204 }
205 }
206
207 /*
208 * if it is not enabled, try to enable it and assume only one segment
209 * with 256 buses
210 */
211 get_fam10h_pci_mmconf_base();
212 if (fam10h_pci_mmconf_base_status <= 0)
213 return;
214
215 printk(KERN_INFO "Enable MMCONFIG on AMD Family 10h\n");
216 val &= ~((FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT) |
217 (FAM10H_MMIO_CONF_BUSRANGE_MASK<<FAM10H_MMIO_CONF_BUSRANGE_SHIFT));
218 val |= fam10h_pci_mmconf_base | (8 << FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
219 FAM10H_MMIO_CONF_ENABLE;
220 wrmsrl(address, val);
221}
222
223static int __devinit set_check_enable_amd_mmconf(const struct dmi_system_id *d)
224{
225 pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
226 return 0;
227}
228
229static struct dmi_system_id __devinitdata mmconf_dmi_table[] = {
230 {
231 .callback = set_check_enable_amd_mmconf,
232 .ident = "Sun Microsystems Machine",
233 .matches = {
234 DMI_MATCH(DMI_SYS_VENDOR, "Sun Microsystems"),
235 },
236 },
237 {}
238};
239
240void __init check_enable_amd_mmconf_dmi(void)
241{
242 dmi_check_system(mmconf_dmi_table);
243}
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index a94fb959a87a..22c14e21c97c 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -29,6 +29,7 @@
29#include <linux/crash_dump.h> 29#include <linux/crash_dump.h>
30#include <linux/root_dev.h> 30#include <linux/root_dev.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <asm/pci-direct.h>
32#include <linux/efi.h> 33#include <linux/efi.h>
33#include <linux/acpi.h> 34#include <linux/acpi.h>
34#include <linux/kallsyms.h> 35#include <linux/kallsyms.h>
@@ -40,6 +41,7 @@
40#include <linux/dmi.h> 41#include <linux/dmi.h>
41#include <linux/dma-mapping.h> 42#include <linux/dma-mapping.h>
42#include <linux/ctype.h> 43#include <linux/ctype.h>
44#include <linux/sort.h>
43#include <linux/uaccess.h> 45#include <linux/uaccess.h>
44#include <linux/init_ohci1394_dma.h> 46#include <linux/init_ohci1394_dma.h>
45#include <linux/kvm_para.h> 47#include <linux/kvm_para.h>
@@ -288,6 +290,18 @@ static void __init parse_setup_data(void)
288 } 290 }
289} 291}
290 292
293#ifdef CONFIG_PCI_MMCONFIG
294extern void __cpuinit fam10h_check_enable_mmcfg(void);
295extern void __init check_enable_amd_mmconf_dmi(void);
296#else
297void __cpuinit fam10h_check_enable_mmcfg(void)
298{
299}
300void __init check_enable_amd_mmconf_dmi(void)
301{
302}
303#endif
304
291/* 305/*
292 * setup_arch - architecture-specific boot-time initializations 306 * setup_arch - architecture-specific boot-time initializations
293 * 307 *
@@ -515,6 +529,9 @@ void __init setup_arch(char **cmdline_p)
515 conswitchp = &dummy_con; 529 conswitchp = &dummy_con;
516#endif 530#endif
517#endif 531#endif
532
533 /* do this before identify_cpu for boot cpu */
534 check_enable_amd_mmconf_dmi();
518} 535}
519 536
520static int __cpuinit get_model_name(struct cpuinfo_x86 *c) 537static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
@@ -767,6 +784,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
767 /* MFENCE stops RDTSC speculation */ 784 /* MFENCE stops RDTSC speculation */
768 set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); 785 set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
769 786
787 if (c->x86 == 0x10)
788 fam10h_check_enable_mmcfg();
789
770 if (amd_apic_timer_broken()) 790 if (amd_apic_timer_broken())
771 disable_apic_timer = 1; 791 disable_apic_timer = 1;
772 792