1
2
3
4
5
6
7
8
9
10
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
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
28
29
30
31
32
33static void __init unreachable_devices(void)
34{
35 int i, bus;
36
37 for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
38 for (i = 0; i < 32; i++) {
39 unsigned int devfn = PCI_DEVFN(i, 0);
40 u32 val1, val2;
41
42 pci_conf1_read(0, bus, devfn, 0, 4, &val1);
43 if (val1 == 0xffffffff)
44 continue;
45
46 if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
47 raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
48 if (val1 == val2)
49 continue;
50 }
51 set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
52 printk(KERN_NOTICE "PCI: No mmconfig possible on device"
53 " %02x:%02x\n", bus, i);
54 }
55 }
56}
57
58static const char __init *pci_mmcfg_e7520(void)
59{
60 u32 win;
61 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
62
63 win = win & 0xf000;
64 if(win == 0x0000 || win == 0xf000)
65 pci_mmcfg_config_num = 0;
66 else {
67 pci_mmcfg_config_num = 1;
68 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
69 if (!pci_mmcfg_config)
70 return NULL;
71 pci_mmcfg_config[0].address = win << 16;
72 pci_mmcfg_config[0].pci_segment = 0;
73 pci_mmcfg_config[0].start_bus_number = 0;
74 pci_mmcfg_config[0].end_bus_number = 255;
75 }
76
77 return "Intel Corporation E7520 Memory Controller Hub";
78}
79
80static const char __init *pci_mmcfg_intel_945(void)
81{
82 u32 pciexbar, mask = 0, len = 0;
83
84 pci_mmcfg_config_num = 1;
85
86 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
87
88
89 if (!(pciexbar & 1))
90 pci_mmcfg_config_num = 0;
91
92
93 switch ((pciexbar >> 1) & 3) {
94 case 0:
95 mask = 0xf0000000U;
96 len = 0x10000000U;
97 break;
98 case 1:
99 mask = 0xf8000000U;
100 len = 0x08000000U;
101 break;
102 case 2:
103 mask = 0xfc000000U;
104 len = 0x04000000U;
105 break;
106 default:
107 pci_mmcfg_config_num = 0;
108 }
109
110
111
112
113 if ((pciexbar & mask) & 0x0fffffffU)
114 pci_mmcfg_config_num = 0;
115
116
117 if ((pciexbar & mask) >= 0xf0000000U)
118 pci_mmcfg_config_num = 0;
119
120 if (pci_mmcfg_config_num) {
121 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
122 if (!pci_mmcfg_config)
123 return NULL;
124 pci_mmcfg_config[0].address = pciexbar & mask;
125 pci_mmcfg_config[0].pci_segment = 0;
126 pci_mmcfg_config[0].start_bus_number = 0;
127 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
128 }
129
130 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
131}
132
133struct pci_mmcfg_hostbridge_probe {
134 u32 vendor;
135 u32 device;
136 const char *(*probe)(void);
137};
138
139static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
140 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
141 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
142};
143
144static int __init pci_mmcfg_check_hostbridge(void)
145{
146 u32 l;
147 u16 vendor, device;
148 int i;
149 const char *name;
150
151 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
152 vendor = l & 0xffff;
153 device = (l >> 16) & 0xffff;
154
155 pci_mmcfg_config_num = 0;
156 pci_mmcfg_config = NULL;
157 name = NULL;
158
159 for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
160 if (pci_mmcfg_probes[i].vendor == vendor &&
161 pci_mmcfg_probes[i].device == device)
162 name = pci_mmcfg_probes[i].probe();
163 }
164
165 if (name) {
166 printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
167 name, pci_mmcfg_config_num ? "with" : "without");
168 }
169
170 return name != NULL;
171}
172
173static void __init pci_mmcfg_insert_resources(void)
174{
175#define PCI_MMCFG_RESOURCE_NAME_LEN 19
176 int i;
177 struct resource *res;
178 char *names;
179 unsigned num_buses;
180
181 res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
182 pci_mmcfg_config_num, GFP_KERNEL);
183 if (!res) {
184 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
185 return;
186 }
187
188 names = (void *)&res[pci_mmcfg_config_num];
189 for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
190 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
191 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
192 res->name = names;
193 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
194 cfg->pci_segment);
195 res->start = cfg->address;
196 res->end = res->start + (num_buses << 20) - 1;
197 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
198 insert_resource(&iomem_resource, res);
199 names += PCI_MMCFG_RESOURCE_NAME_LEN;
200 }
201}
202
203static void __init pci_mmcfg_reject_broken(int type)
204{
205 typeof(pci_mmcfg_config[0]) *cfg;
206
207 if ((pci_mmcfg_config_num == 0) ||
208 (pci_mmcfg_config == NULL) ||
209 (pci_mmcfg_config[0].address == 0))
210 return;
211
212 cfg = &pci_mmcfg_config[0];
213
214
215
216
217
218 if (pci_mmcfg_config_num == 1 &&
219 cfg->pci_segment == 0 &&
220 (cfg->start_bus_number | cfg->end_bus_number) == 0) {
221 printk(KERN_ERR "PCI: start and end of bus number is 0. "
222 "Rejected as broken MCFG.\n");
223 goto reject;
224 }
225
226
227
228
229
230 if (type == 1 && !e820_all_mapped(cfg->address,
231 cfg->address + MMCONFIG_APER_MIN,
232 E820_RESERVED)) {
233 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
234 " E820-reserved\n", cfg->address);
235 goto reject;
236 }
237 return;
238
239reject:
240 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
241 kfree(pci_mmcfg_config);
242 pci_mmcfg_config = NULL;
243 pci_mmcfg_config_num = 0;
244}
245
246void __init pci_mmcfg_init(int type)
247{
248 int known_bridge = 0;
249
250 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
251 return;
252
253 if (type == 1 && pci_mmcfg_check_hostbridge())
254 known_bridge = 1;
255
256 if (!known_bridge) {
257 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
258 pci_mmcfg_reject_broken(type);
259 }
260
261 if ((pci_mmcfg_config_num == 0) ||
262 (pci_mmcfg_config == NULL) ||
263 (pci_mmcfg_config[0].address == 0))
264 return;
265
266 if (pci_mmcfg_arch_init()) {
267 if (type == 1)
268 unreachable_devices();
269 if (known_bridge)
270 pci_mmcfg_insert_resources();
271 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
272 }
273}
274