aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci/acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/pci/acpi.c')
-rw-r--r--arch/x86/pci/acpi.c128
1 files changed, 72 insertions, 56 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index ed2835e148b5..fc09c2754e08 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -9,11 +9,11 @@
9 9
10struct pci_root_info { 10struct pci_root_info {
11 struct acpi_device *bridge; 11 struct acpi_device *bridge;
12 char *name; 12 char name[16];
13 unsigned int res_num; 13 unsigned int res_num;
14 struct resource *res; 14 struct resource *res;
15 struct list_head *resources;
16 int busnum; 15 int busnum;
16 struct pci_sysdata sd;
17}; 17};
18 18
19static bool pci_use_crs = true; 19static bool pci_use_crs = true;
@@ -245,13 +245,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
245 return AE_OK; 245 return AE_OK;
246} 246}
247 247
248static bool resource_contains(struct resource *res, resource_size_t point)
249{
250 if (res->start <= point && point <= res->end)
251 return true;
252 return false;
253}
254
255static void coalesce_windows(struct pci_root_info *info, unsigned long type) 248static void coalesce_windows(struct pci_root_info *info, unsigned long type)
256{ 249{
257 int i, j; 250 int i, j;
@@ -272,10 +265,7 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
272 * our resources no longer match the ACPI _CRS, but 265 * our resources no longer match the ACPI _CRS, but
273 * the kernel resource tree doesn't allow overlaps. 266 * the kernel resource tree doesn't allow overlaps.
274 */ 267 */
275 if (resource_contains(res1, res2->start) || 268 if (resource_overlaps(res1, res2)) {
276 resource_contains(res1, res2->end) ||
277 resource_contains(res2, res1->start) ||
278 resource_contains(res2, res1->end)) {
279 res1->start = min(res1->start, res2->start); 269 res1->start = min(res1->start, res2->start);
280 res1->end = max(res1->end, res2->end); 270 res1->end = max(res1->end, res2->end);
281 dev_info(&info->bridge->dev, 271 dev_info(&info->bridge->dev,
@@ -287,7 +277,8 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
287 } 277 }
288} 278}
289 279
290static void add_resources(struct pci_root_info *info) 280static void add_resources(struct pci_root_info *info,
281 struct list_head *resources)
291{ 282{
292 int i; 283 int i;
293 struct resource *res, *root, *conflict; 284 struct resource *res, *root, *conflict;
@@ -311,53 +302,74 @@ static void add_resources(struct pci_root_info *info)
311 "ignoring host bridge window %pR (conflicts with %s %pR)\n", 302 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
312 res, conflict->name, conflict); 303 res, conflict->name, conflict);
313 else 304 else
314 pci_add_resource(info->resources, res); 305 pci_add_resource(resources, res);
315 } 306 }
316} 307}
317 308
309static void free_pci_root_info_res(struct pci_root_info *info)
310{
311 kfree(info->res);
312 info->res = NULL;
313 info->res_num = 0;
314}
315
316static void __release_pci_root_info(struct pci_root_info *info)
317{
318 int i;
319 struct resource *res;
320
321 for (i = 0; i < info->res_num; i++) {
322 res = &info->res[i];
323
324 if (!res->parent)
325 continue;
326
327 if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
328 continue;
329
330 release_resource(res);
331 }
332
333 free_pci_root_info_res(info);
334
335 kfree(info);
336}
337static void release_pci_root_info(struct pci_host_bridge *bridge)
338{
339 struct pci_root_info *info = bridge->release_data;
340
341 __release_pci_root_info(info);
342}
343
318static void 344static void
319get_current_resources(struct acpi_device *device, int busnum, 345probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
320 int domain, struct list_head *resources) 346 int busnum, int domain)
321{ 347{
322 struct pci_root_info info;
323 size_t size; 348 size_t size;
324 349
325 info.bridge = device; 350 info->bridge = device;
326 info.res_num = 0; 351 info->res_num = 0;
327 info.resources = resources;
328 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, 352 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
329 &info); 353 info);
330 if (!info.res_num) 354 if (!info->res_num)
331 return; 355 return;
332 356
333 size = sizeof(*info.res) * info.res_num; 357 size = sizeof(*info->res) * info->res_num;
334 info.res = kmalloc(size, GFP_KERNEL); 358 info->res_num = 0;
335 if (!info.res) 359 info->res = kmalloc(size, GFP_KERNEL);
360 if (!info->res)
336 return; 361 return;
337 362
338 info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum); 363 sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
339 if (!info.name)
340 goto name_alloc_fail;
341 364
342 info.res_num = 0;
343 acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, 365 acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
344 &info); 366 info);
345
346 if (pci_use_crs) {
347 add_resources(&info);
348
349 return;
350 }
351
352 kfree(info.name);
353
354name_alloc_fail:
355 kfree(info.res);
356} 367}
357 368
358struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) 369struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
359{ 370{
360 struct acpi_device *device = root->device; 371 struct acpi_device *device = root->device;
372 struct pci_root_info *info = NULL;
361 int domain = root->segment; 373 int domain = root->segment;
362 int busnum = root->secondary.start; 374 int busnum = root->secondary.start;
363 LIST_HEAD(resources); 375 LIST_HEAD(resources);
@@ -389,17 +401,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
389 if (node != -1 && !node_online(node)) 401 if (node != -1 && !node_online(node))
390 node = -1; 402 node = -1;
391 403
392 /* Allocate per-root-bus (not per bus) arch-specific data. 404 info = kzalloc(sizeof(*info), GFP_KERNEL);
393 * TODO: leak; this memory is never freed. 405 if (!info) {
394 * It's arguable whether it's worth the trouble to care.
395 */
396 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
397 if (!sd) {
398 printk(KERN_WARNING "pci_bus %04x:%02x: " 406 printk(KERN_WARNING "pci_bus %04x:%02x: "
399 "ignored (out of memory)\n", domain, busnum); 407 "ignored (out of memory)\n", domain, busnum);
400 return NULL; 408 return NULL;
401 } 409 }
402 410
411 sd = &info->sd;
403 sd->domain = domain; 412 sd->domain = domain;
404 sd->node = node; 413 sd->node = node;
405 /* 414 /*
@@ -413,22 +422,32 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
413 * be replaced by sd. 422 * be replaced by sd.
414 */ 423 */
415 memcpy(bus->sysdata, sd, sizeof(*sd)); 424 memcpy(bus->sysdata, sd, sizeof(*sd));
416 kfree(sd); 425 kfree(info);
417 } else { 426 } else {
418 get_current_resources(device, busnum, domain, &resources); 427 probe_pci_root_info(info, device, busnum, domain);
419 428
420 /* 429 /*
421 * _CRS with no apertures is normal, so only fall back to 430 * _CRS with no apertures is normal, so only fall back to
422 * defaults or native bridge info if we're ignoring _CRS. 431 * defaults or native bridge info if we're ignoring _CRS.
423 */ 432 */
424 if (!pci_use_crs) 433 if (pci_use_crs)
434 add_resources(info, &resources);
435 else {
436 free_pci_root_info_res(info);
425 x86_pci_root_bus_resources(busnum, &resources); 437 x86_pci_root_bus_resources(busnum, &resources);
438 }
439
426 bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, 440 bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
427 &resources); 441 &resources);
428 if (bus) 442 if (bus) {
429 bus->subordinate = pci_scan_child_bus(bus); 443 bus->subordinate = pci_scan_child_bus(bus);
430 else 444 pci_set_host_bridge_release(
445 to_pci_host_bridge(bus->bridge),
446 release_pci_root_info, info);
447 } else {
431 pci_free_resource_list(&resources); 448 pci_free_resource_list(&resources);
449 __release_pci_root_info(info);
450 }
432 } 451 }
433 452
434 /* After the PCI-E bus has been walked and all devices discovered, 453 /* After the PCI-E bus has been walked and all devices discovered,
@@ -445,9 +464,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
445 } 464 }
446 } 465 }
447 466
448 if (!bus)
449 kfree(sd);
450
451 if (bus && node != -1) { 467 if (bus && node != -1) {
452#ifdef CONFIG_ACPI_NUMA 468#ifdef CONFIG_ACPI_NUMA
453 if (pxm >= 0) 469 if (pxm >= 0)