aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/pci/acpi.c294
1 files changed, 87 insertions, 207 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 5bc018559cc4..3cd69832d7f4 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -4,16 +4,15 @@
4#include <linux/irq.h> 4#include <linux/irq.h>
5#include <linux/dmi.h> 5#include <linux/dmi.h>
6#include <linux/slab.h> 6#include <linux/slab.h>
7#include <linux/pci-acpi.h>
7#include <asm/numa.h> 8#include <asm/numa.h>
8#include <asm/pci_x86.h> 9#include <asm/pci_x86.h>
9 10
10struct pci_root_info { 11struct pci_root_info {
11 struct acpi_device *bridge; 12 struct acpi_pci_root_info common;
12 char name[16];
13 struct pci_sysdata sd; 13 struct pci_sysdata sd;
14#ifdef CONFIG_PCI_MMCONFIG 14#ifdef CONFIG_PCI_MMCONFIG
15 bool mcfg_added; 15 bool mcfg_added;
16 u16 segment;
17 u8 start_bus; 16 u8 start_bus;
18 u8 end_bus; 17 u8 end_bus;
19#endif 18#endif
@@ -178,15 +177,18 @@ static int check_segment(u16 seg, struct device *dev, char *estr)
178 return 0; 177 return 0;
179} 178}
180 179
181static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start, 180static int setup_mcfg_map(struct acpi_pci_root_info *ci)
182 u8 end, phys_addr_t addr)
183{ 181{
184 int result; 182 int result, seg;
185 struct device *dev = &info->bridge->dev; 183 struct pci_root_info *info;
184 struct acpi_pci_root *root = ci->root;
185 struct device *dev = &ci->bridge->dev;
186 186
187 info->start_bus = start; 187 info = container_of(ci, struct pci_root_info, common);
188 info->end_bus = end; 188 info->start_bus = (u8)root->secondary.start;
189 info->end_bus = (u8)root->secondary.end;
189 info->mcfg_added = false; 190 info->mcfg_added = false;
191 seg = info->sd.domain;
190 192
191 /* return success if MMCFG is not in use */ 193 /* return success if MMCFG is not in use */
192 if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg) 194 if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
@@ -195,7 +197,8 @@ static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
195 if (!(pci_probe & PCI_PROBE_MMCONF)) 197 if (!(pci_probe & PCI_PROBE_MMCONF))
196 return check_segment(seg, dev, "MMCONFIG is disabled,"); 198 return check_segment(seg, dev, "MMCONFIG is disabled,");
197 199
198 result = pci_mmconfig_insert(dev, seg, start, end, addr); 200 result = pci_mmconfig_insert(dev, seg, info->start_bus, info->end_bus,
201 root->mcfg_addr);
199 if (result == 0) { 202 if (result == 0) {
200 /* enable MMCFG if it hasn't been enabled yet */ 203 /* enable MMCFG if it hasn't been enabled yet */
201 if (raw_pci_ext_ops == NULL) 204 if (raw_pci_ext_ops == NULL)
@@ -208,134 +211,55 @@ static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
208 return 0; 211 return 0;
209} 212}
210 213
211static void teardown_mcfg_map(struct pci_root_info *info) 214static void teardown_mcfg_map(struct acpi_pci_root_info *ci)
212{ 215{
216 struct pci_root_info *info;
217
218 info = container_of(ci, struct pci_root_info, common);
213 if (info->mcfg_added) { 219 if (info->mcfg_added) {
214 pci_mmconfig_delete(info->segment, info->start_bus, 220 pci_mmconfig_delete(info->sd.domain,
215 info->end_bus); 221 info->start_bus, info->end_bus);
216 info->mcfg_added = false; 222 info->mcfg_added = false;
217 } 223 }
218} 224}
219#else 225#else
220static int setup_mcfg_map(struct pci_root_info *info, 226static int setup_mcfg_map(struct acpi_pci_root_info *ci)
221 u16 seg, u8 start, u8 end,
222 phys_addr_t addr)
223{ 227{
224 return 0; 228 return 0;
225} 229}
226static void teardown_mcfg_map(struct pci_root_info *info) 230
231static void teardown_mcfg_map(struct acpi_pci_root_info *ci)
227{ 232{
228} 233}
229#endif 234#endif
230 235
231static void validate_resources(struct device *dev, struct list_head *crs_res, 236static int pci_acpi_root_get_node(struct acpi_pci_root *root)
232 unsigned long type)
233{ 237{
234 LIST_HEAD(list); 238 int busnum = root->secondary.start;
235 struct resource *res1, *res2, *root = NULL; 239 struct acpi_device *device = root->device;
236 struct resource_entry *tmp, *entry, *entry2; 240 int node = acpi_get_node(device->handle);
237
238 BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
239 root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
240
241 list_splice_init(crs_res, &list);
242 resource_list_for_each_entry_safe(entry, tmp, &list) {
243 bool free = false;
244 resource_size_t end;
245
246 res1 = entry->res;
247 if (!(res1->flags & type))
248 goto next;
249
250 /* Exclude non-addressable range or non-addressable portion */
251 end = min(res1->end, root->end);
252 if (end <= res1->start) {
253 dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
254 res1);
255 free = true;
256 goto next;
257 } else if (res1->end != end) {
258 dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
259 res1, (unsigned long long)end + 1,
260 (unsigned long long)res1->end);
261 res1->end = end;
262 }
263
264 resource_list_for_each_entry(entry2, crs_res) {
265 res2 = entry2->res;
266 if (!(res2->flags & type))
267 continue;
268
269 /*
270 * I don't like throwing away windows because then
271 * our resources no longer match the ACPI _CRS, but
272 * the kernel resource tree doesn't allow overlaps.
273 */
274 if (resource_overlaps(res1, res2)) {
275 res2->start = min(res1->start, res2->start);
276 res2->end = max(res1->end, res2->end);
277 dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
278 res2, res1);
279 free = true;
280 goto next;
281 }
282 }
283 241
284next: 242 if (node == NUMA_NO_NODE) {
285 resource_list_del(entry); 243 node = x86_pci_root_bus_node(busnum);
286 if (free) 244 if (node != 0 && node != NUMA_NO_NODE)
287 resource_list_free_entry(entry); 245 dev_info(&device->dev, FW_BUG "no _PXM; falling back to node %d from hardware (may be inconsistent with ACPI node numbers)\n",
288 else 246 node);
289 resource_list_add_tail(entry, crs_res);
290 } 247 }
248 if (node != NUMA_NO_NODE && !node_online(node))
249 node = NUMA_NO_NODE;
250
251 return node;
291} 252}
292 253
293static void add_resources(struct pci_root_info *info, 254static int pci_acpi_root_init_info(struct acpi_pci_root_info *ci)
294 struct list_head *resources,
295 struct list_head *crs_res)
296{ 255{
297 struct resource_entry *entry, *tmp; 256 return setup_mcfg_map(ci);
298 struct resource *res, *conflict, *root = NULL;
299
300 validate_resources(&info->bridge->dev, crs_res, IORESOURCE_MEM);
301 validate_resources(&info->bridge->dev, crs_res, IORESOURCE_IO);
302
303 resource_list_for_each_entry_safe(entry, tmp, crs_res) {
304 res = entry->res;
305 if (res->flags & IORESOURCE_MEM)
306 root = &iomem_resource;
307 else if (res->flags & IORESOURCE_IO)
308 root = &ioport_resource;
309 else
310 BUG_ON(res);
311
312 conflict = insert_resource_conflict(root, res);
313 if (conflict) {
314 dev_info(&info->bridge->dev,
315 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
316 res, conflict->name, conflict);
317 resource_list_destroy_entry(entry);
318 }
319 }
320
321 list_splice_tail(crs_res, resources);
322} 257}
323 258
324static void release_pci_root_info(struct pci_host_bridge *bridge) 259static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
325{ 260{
326 struct resource *res; 261 teardown_mcfg_map(ci);
327 struct resource_entry *entry; 262 kfree(container_of(ci, struct pci_root_info, common));
328 struct pci_root_info *info = bridge->release_data;
329
330 resource_list_for_each_entry(entry, &bridge->windows) {
331 res = entry->res;
332 if (res->parent &&
333 (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
334 release_resource(res);
335 }
336
337 teardown_mcfg_map(info);
338 kfree(info);
339} 263}
340 264
341/* 265/*
@@ -358,47 +282,44 @@ static bool resource_is_pcicfg_ioport(struct resource *res)
358 res->start == 0xCF8 && res->end == 0xCFF; 282 res->start == 0xCF8 && res->end == 0xCFF;
359} 283}
360 284
361static void probe_pci_root_info(struct pci_root_info *info, 285static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
362 struct acpi_device *device,
363 int busnum, int domain,
364 struct list_head *list)
365{ 286{
366 int ret; 287 struct acpi_device *device = ci->bridge;
288 int busnum = ci->root->secondary.start;
367 struct resource_entry *entry, *tmp; 289 struct resource_entry *entry, *tmp;
290 int status;
368 291
369 sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum); 292 status = acpi_pci_probe_root_resources(ci);
370 info->bridge = device; 293 if (pci_use_crs) {
371 ret = acpi_dev_get_resources(device, list, 294 resource_list_for_each_entry_safe(entry, tmp, &ci->resources)
372 acpi_dev_filter_resource_type_cb, 295 if (resource_is_pcicfg_ioport(entry->res))
373 (void *)(IORESOURCE_IO | IORESOURCE_MEM));
374 if (ret < 0)
375 dev_warn(&device->dev,
376 "failed to parse _CRS method, error code %d\n", ret);
377 else if (ret == 0)
378 dev_dbg(&device->dev,
379 "no IO and memory resources present in _CRS\n");
380 else
381 resource_list_for_each_entry_safe(entry, tmp, list) {
382 if ((entry->res->flags & IORESOURCE_DISABLED) ||
383 resource_is_pcicfg_ioport(entry->res))
384 resource_list_destroy_entry(entry); 296 resource_list_destroy_entry(entry);
385 else 297 return status;
386 entry->res->name = info->name; 298 }
387 } 299
300 resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
301 dev_printk(KERN_DEBUG, &device->dev,
302 "host bridge window %pR (ignored)\n", entry->res);
303 resource_list_destroy_entry(entry);
304 }
305 x86_pci_root_bus_resources(busnum, &ci->resources);
306
307 return 0;
388} 308}
389 309
310static struct acpi_pci_root_ops acpi_pci_root_ops = {
311 .pci_ops = &pci_root_ops,
312 .init_info = pci_acpi_root_init_info,
313 .release_info = pci_acpi_root_release_info,
314 .prepare_resources = pci_acpi_root_prepare_resources,
315};
316
390struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) 317struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
391{ 318{
392 struct acpi_device *device = root->device;
393 struct pci_root_info *info;
394 int domain = root->segment; 319 int domain = root->segment;
395 int busnum = root->secondary.start; 320 int busnum = root->secondary.start;
396 struct resource_entry *res_entry; 321 int node = pci_acpi_root_get_node(root);
397 LIST_HEAD(crs_res);
398 LIST_HEAD(resources);
399 struct pci_bus *bus; 322 struct pci_bus *bus;
400 struct pci_sysdata *sd;
401 int node;
402 323
403 if (pci_ignore_seg) 324 if (pci_ignore_seg)
404 root->segment = domain = 0; 325 root->segment = domain = 0;
@@ -410,71 +331,33 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
410 return NULL; 331 return NULL;
411 } 332 }
412 333
413 node = acpi_get_node(device->handle);
414 if (node == NUMA_NO_NODE) {
415 node = x86_pci_root_bus_node(busnum);
416 if (node != 0 && node != NUMA_NO_NODE)
417 dev_info(&device->dev, FW_BUG "no _PXM; falling back to node %d from hardware (may be inconsistent with ACPI node numbers)\n",
418 node);
419 }
420
421 if (node != NUMA_NO_NODE && !node_online(node))
422 node = NUMA_NO_NODE;
423
424 info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
425 if (!info) {
426 printk(KERN_WARNING "pci_bus %04x:%02x: "
427 "ignored (out of memory)\n", domain, busnum);
428 return NULL;
429 }
430
431 sd = &info->sd;
432 sd->domain = domain;
433 sd->node = node;
434 sd->companion = device;
435
436 bus = pci_find_bus(domain, busnum); 334 bus = pci_find_bus(domain, busnum);
437 if (bus) { 335 if (bus) {
438 /* 336 /*
439 * If the desired bus has been scanned already, replace 337 * If the desired bus has been scanned already, replace
440 * its bus->sysdata. 338 * its bus->sysdata.
441 */ 339 */
442 memcpy(bus->sysdata, sd, sizeof(*sd)); 340 struct pci_sysdata sd = {
443 kfree(info); 341 .domain = domain,
444 } else { 342 .node = node,
445 /* insert busn res at first */ 343 .companion = root->device
446 pci_add_resource(&resources, &root->secondary); 344 };
447 345
448 /* 346 memcpy(bus->sysdata, &sd, sizeof(sd));
449 * _CRS with no apertures is normal, so only fall back to 347 } else {
450 * defaults or native bridge info if we're ignoring _CRS. 348 struct pci_root_info *info;
451 */ 349
452 probe_pci_root_info(info, device, busnum, domain, &crs_res); 350 info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
453 if (pci_use_crs) { 351 if (!info)
454 add_resources(info, &resources, &crs_res); 352 dev_err(&root->device->dev,
455 } else { 353 "pci_bus %04x:%02x: ignored (out of memory)\n",
456 resource_list_for_each_entry(res_entry, &crs_res) 354 domain, busnum);
457 dev_printk(KERN_DEBUG, &device->dev, 355 else {
458 "host bridge window %pR (ignored)\n", 356 info->sd.domain = domain;
459 res_entry->res); 357 info->sd.node = node;
460 resource_list_free(&crs_res); 358 info->sd.companion = root->device;
461 x86_pci_root_bus_resources(busnum, &resources); 359 bus = acpi_pci_root_create(root, &acpi_pci_root_ops,
462 } 360 &info->common, &info->sd);
463
464 if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
465 (u8)root->secondary.end, root->mcfg_addr))
466 bus = pci_create_root_bus(NULL, busnum, &pci_root_ops,
467 sd, &resources);
468
469 if (bus) {
470 pci_scan_child_bus(bus);
471 pci_set_host_bridge_release(
472 to_pci_host_bridge(bus->bridge),
473 release_pci_root_info, info);
474 } else {
475 resource_list_free(&resources);
476 teardown_mcfg_map(info);
477 kfree(info);
478 } 361 }
479 } 362 }
480 363
@@ -487,9 +370,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
487 pcie_bus_configure_settings(child); 370 pcie_bus_configure_settings(child);
488 } 371 }
489 372
490 if (bus && node != NUMA_NO_NODE)
491 dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
492
493 return bus; 373 return bus;
494} 374}
495 375