aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci/mmconfig-shared.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/pci/mmconfig-shared.c')
-rw-r--r--arch/i386/pci/mmconfig-shared.c315
1 files changed, 0 insertions, 315 deletions
diff --git a/arch/i386/pci/mmconfig-shared.c b/arch/i386/pci/mmconfig-shared.c
deleted file mode 100644
index 4df637e34f81..000000000000
--- a/arch/i386/pci/mmconfig-shared.c
+++ /dev/null
@@ -1,315 +0,0 @@
1/*
2 * mmconfig-shared.c - Low-level direct PCI config space access via
3 * MMCONFIG - common code between i386 and x86-64.
4 *
5 * This code does:
6 * - known chipset handling
7 * - ACPI decoding and validation
8 *
9 * Per-architecture code takes care of the mappings and accesses
10 * themselves.
11 */
12
13#include <linux/pci.h>
14#include <linux/init.h>
15#include <linux/acpi.h>
16#include <linux/bitmap.h>
17#include <asm/e820.h>
18
19#include "pci.h"
20
21/* aperture is up to 256MB but BIOS may reserve less */
22#define MMCONFIG_APER_MIN (2 * 1024*1024)
23#define MMCONFIG_APER_MAX (256 * 1024*1024)
24
25DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
26
27/* Indicate if the mmcfg resources have been placed into the resource table. */
28static int __initdata pci_mmcfg_resources_inserted;
29
30/* K8 systems have some devices (typically in the builtin northbridge)
31 that are only accessible using type1
32 Normally this can be expressed in the MCFG by not listing them
33 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
34 Instead try to discover all devices on bus 0 that are unreachable using MM
35 and fallback for them. */
36static void __init unreachable_devices(void)
37{
38 int i, bus;
39 /* Use the max bus number from ACPI here? */
40 for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
41 for (i = 0; i < 32; i++) {
42 unsigned int devfn = PCI_DEVFN(i, 0);
43 u32 val1, val2;
44
45 pci_conf1_read(0, bus, devfn, 0, 4, &val1);
46 if (val1 == 0xffffffff)
47 continue;
48
49 if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
50 raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
51 if (val1 == val2)
52 continue;
53 }
54 set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
55 printk(KERN_NOTICE "PCI: No mmconfig possible on device"
56 " %02x:%02x\n", bus, i);
57 }
58 }
59}
60
61static const char __init *pci_mmcfg_e7520(void)
62{
63 u32 win;
64 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
65
66 win = win & 0xf000;
67 if(win == 0x0000 || win == 0xf000)
68 pci_mmcfg_config_num = 0;
69 else {
70 pci_mmcfg_config_num = 1;
71 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
72 if (!pci_mmcfg_config)
73 return NULL;
74 pci_mmcfg_config[0].address = win << 16;
75 pci_mmcfg_config[0].pci_segment = 0;
76 pci_mmcfg_config[0].start_bus_number = 0;
77 pci_mmcfg_config[0].end_bus_number = 255;
78 }
79
80 return "Intel Corporation E7520 Memory Controller Hub";
81}
82
83static const char __init *pci_mmcfg_intel_945(void)
84{
85 u32 pciexbar, mask = 0, len = 0;
86
87 pci_mmcfg_config_num = 1;
88
89 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
90
91 /* Enable bit */
92 if (!(pciexbar & 1))
93 pci_mmcfg_config_num = 0;
94
95 /* Size bits */
96 switch ((pciexbar >> 1) & 3) {
97 case 0:
98 mask = 0xf0000000U;
99 len = 0x10000000U;
100 break;
101 case 1:
102 mask = 0xf8000000U;
103 len = 0x08000000U;
104 break;
105 case 2:
106 mask = 0xfc000000U;
107 len = 0x04000000U;
108 break;
109 default:
110 pci_mmcfg_config_num = 0;
111 }
112
113 /* Errata #2, things break when not aligned on a 256Mb boundary */
114 /* Can only happen in 64M/128M mode */
115
116 if ((pciexbar & mask) & 0x0fffffffU)
117 pci_mmcfg_config_num = 0;
118
119 /* Don't hit the APIC registers and their friends */
120 if ((pciexbar & mask) >= 0xf0000000U)
121 pci_mmcfg_config_num = 0;
122
123 if (pci_mmcfg_config_num) {
124 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
125 if (!pci_mmcfg_config)
126 return NULL;
127 pci_mmcfg_config[0].address = pciexbar & mask;
128 pci_mmcfg_config[0].pci_segment = 0;
129 pci_mmcfg_config[0].start_bus_number = 0;
130 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
131 }
132
133 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
134}
135
136struct pci_mmcfg_hostbridge_probe {
137 u32 vendor;
138 u32 device;
139 const char *(*probe)(void);
140};
141
142static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
143 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
144 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
145};
146
147static int __init pci_mmcfg_check_hostbridge(void)
148{
149 u32 l;
150 u16 vendor, device;
151 int i;
152 const char *name;
153
154 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
155 vendor = l & 0xffff;
156 device = (l >> 16) & 0xffff;
157
158 pci_mmcfg_config_num = 0;
159 pci_mmcfg_config = NULL;
160 name = NULL;
161
162 for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
163 if (pci_mmcfg_probes[i].vendor == vendor &&
164 pci_mmcfg_probes[i].device == device)
165 name = pci_mmcfg_probes[i].probe();
166 }
167
168 if (name) {
169 printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
170 name, pci_mmcfg_config_num ? "with" : "without");
171 }
172
173 return name != NULL;
174}
175
176static void __init pci_mmcfg_insert_resources(unsigned long resource_flags)
177{
178#define PCI_MMCFG_RESOURCE_NAME_LEN 19
179 int i;
180 struct resource *res;
181 char *names;
182 unsigned num_buses;
183
184 res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
185 pci_mmcfg_config_num, GFP_KERNEL);
186 if (!res) {
187 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
188 return;
189 }
190
191 names = (void *)&res[pci_mmcfg_config_num];
192 for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
193 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
194 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
195 res->name = names;
196 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
197 cfg->pci_segment);
198 res->start = cfg->address;
199 res->end = res->start + (num_buses << 20) - 1;
200 res->flags = IORESOURCE_MEM | resource_flags;
201 insert_resource(&iomem_resource, res);
202 names += PCI_MMCFG_RESOURCE_NAME_LEN;
203 }
204
205 /* Mark that the resources have been inserted. */
206 pci_mmcfg_resources_inserted = 1;
207}
208
209static void __init pci_mmcfg_reject_broken(int type)
210{
211 typeof(pci_mmcfg_config[0]) *cfg;
212
213 if ((pci_mmcfg_config_num == 0) ||
214 (pci_mmcfg_config == NULL) ||
215 (pci_mmcfg_config[0].address == 0))
216 return;
217
218 cfg = &pci_mmcfg_config[0];
219
220 /*
221 * Handle more broken MCFG tables on Asus etc.
222 * They only contain a single entry for bus 0-0.
223 */
224 if (pci_mmcfg_config_num == 1 &&
225 cfg->pci_segment == 0 &&
226 (cfg->start_bus_number | cfg->end_bus_number) == 0) {
227 printk(KERN_ERR "PCI: start and end of bus number is 0. "
228 "Rejected as broken MCFG.\n");
229 goto reject;
230 }
231
232 /*
233 * Only do this check when type 1 works. If it doesn't work
234 * assume we run on a Mac and always use MCFG
235 */
236 if (type == 1 && !e820_all_mapped(cfg->address,
237 cfg->address + MMCONFIG_APER_MIN,
238 E820_RESERVED)) {
239 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
240 " E820-reserved\n", cfg->address);
241 goto reject;
242 }
243 return;
244
245reject:
246 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
247 kfree(pci_mmcfg_config);
248 pci_mmcfg_config = NULL;
249 pci_mmcfg_config_num = 0;
250}
251
252void __init pci_mmcfg_init(int type)
253{
254 int known_bridge = 0;
255
256 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
257 return;
258
259 if (type == 1 && pci_mmcfg_check_hostbridge())
260 known_bridge = 1;
261
262 if (!known_bridge) {
263 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
264 pci_mmcfg_reject_broken(type);
265 }
266
267 if ((pci_mmcfg_config_num == 0) ||
268 (pci_mmcfg_config == NULL) ||
269 (pci_mmcfg_config[0].address == 0))
270 return;
271
272 if (pci_mmcfg_arch_init()) {
273 if (type == 1)
274 unreachable_devices();
275 if (known_bridge)
276 pci_mmcfg_insert_resources(IORESOURCE_BUSY);
277 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
278 } else {
279 /*
280 * Signal not to attempt to insert mmcfg resources because
281 * the architecture mmcfg setup could not initialize.
282 */
283 pci_mmcfg_resources_inserted = 1;
284 }
285}
286
287static int __init pci_mmcfg_late_insert_resources(void)
288{
289 /*
290 * If resources are already inserted or we are not using MMCONFIG,
291 * don't insert the resources.
292 */
293 if ((pci_mmcfg_resources_inserted == 1) ||
294 (pci_probe & PCI_PROBE_MMCONF) == 0 ||
295 (pci_mmcfg_config_num == 0) ||
296 (pci_mmcfg_config == NULL) ||
297 (pci_mmcfg_config[0].address == 0))
298 return 1;
299
300 /*
301 * Attempt to insert the mmcfg resources but not with the busy flag
302 * marked so it won't cause request errors when __request_region is
303 * called.
304 */
305 pci_mmcfg_insert_resources(0);
306
307 return 0;
308}
309
310/*
311 * Perform MMCONFIG resource insertion after PCI initialization to allow for
312 * misprogrammed MCFG tables that state larger sizes but actually conflict
313 * with other system resources.
314 */
315late_initcall(pci_mmcfg_late_insert_resources);