diff options
author | Yijing Wang <wangyijing@huawei.com> | 2013-06-06 03:34:52 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2013-06-18 12:48:34 -0400 |
commit | 3a72af09bca1666d53ddb0b05a9bdeef39e3f154 (patch) | |
tree | 4a616306b24211726aabbb299f742c5651ae9ccd /arch/ia64/pci/pci.c | |
parent | 2932239fb485931b82c50e4876a0c2d14b7711ac (diff) |
PCI/IA64: introduce probe_pci_root_info() to manage _CRS resource
Currently, initialize _CRS resource code in IA64 make pci_acpi_scan_root()
some lengthiness. Introduce probe_pci_root_info() to manage it like in X86,
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-ia64@vger.kernel.org
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/pci/pci.c')
-rw-r--r-- | arch/ia64/pci/pci.c | 100 |
1 files changed, 57 insertions, 43 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 72a1957dfff3..586cac1f47bb 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -376,6 +376,50 @@ static void release_pci_root_info(struct pci_host_bridge *bridge) | |||
376 | __release_pci_root_info(info); | 376 | __release_pci_root_info(info); |
377 | } | 377 | } |
378 | 378 | ||
379 | static int | ||
380 | probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, | ||
381 | int busnum, int domain) | ||
382 | { | ||
383 | char *name; | ||
384 | |||
385 | name = kmalloc(16, GFP_KERNEL); | ||
386 | if (!name) | ||
387 | return -ENOMEM; | ||
388 | |||
389 | sprintf(name, "PCI Bus %04x:%02x", domain, busnum); | ||
390 | info->bridge = device; | ||
391 | info->name = name; | ||
392 | |||
393 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, | ||
394 | &info->res_num); | ||
395 | if (info->res_num) { | ||
396 | info->res = | ||
397 | kzalloc_node(sizeof(*info->res) * info->res_num, | ||
398 | GFP_KERNEL, info->controller->node); | ||
399 | if (!info->res) { | ||
400 | kfree(name); | ||
401 | return -ENOMEM; | ||
402 | } | ||
403 | |||
404 | info->res_offset = | ||
405 | kzalloc_node(sizeof(*info->res_offset) * info->res_num, | ||
406 | GFP_KERNEL, info->controller->node); | ||
407 | if (!info->res_offset) { | ||
408 | kfree(name); | ||
409 | kfree(info->res); | ||
410 | info->res = NULL; | ||
411 | return -ENOMEM; | ||
412 | } | ||
413 | |||
414 | info->res_num = 0; | ||
415 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, | ||
416 | add_window, info); | ||
417 | } else | ||
418 | kfree(name); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
379 | struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | 423 | struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) |
380 | { | 424 | { |
381 | struct acpi_device *device = root->device; | 425 | struct acpi_device *device = root->device; |
@@ -385,12 +429,11 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
385 | struct pci_root_info *info = NULL; | 429 | struct pci_root_info *info = NULL; |
386 | int busnum = root->secondary.start; | 430 | int busnum = root->secondary.start; |
387 | struct pci_bus *pbus; | 431 | struct pci_bus *pbus; |
388 | char *name; | 432 | int pxm, ret; |
389 | int pxm; | ||
390 | 433 | ||
391 | controller = alloc_pci_controller(domain); | 434 | controller = alloc_pci_controller(domain); |
392 | if (!controller) | 435 | if (!controller) |
393 | goto out1; | 436 | return NULL; |
394 | 437 | ||
395 | controller->acpi_handle = device->handle; | 438 | controller->acpi_handle = device->handle; |
396 | 439 | ||
@@ -404,41 +447,23 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
404 | if (!info) { | 447 | if (!info) { |
405 | printk(KERN_WARNING | 448 | printk(KERN_WARNING |
406 | "pci_bus %04x:%02x: ignored (out of memory)\n", | 449 | "pci_bus %04x:%02x: ignored (out of memory)\n", |
407 | root->segment, busnum); | 450 | domain, busnum); |
408 | goto out2; | 451 | kfree(controller); |
452 | return NULL; | ||
409 | } | 453 | } |
410 | 454 | ||
455 | info->controller = controller; | ||
411 | INIT_LIST_HEAD(&info->io_resources); | 456 | INIT_LIST_HEAD(&info->io_resources); |
412 | INIT_LIST_HEAD(&info->resources); | 457 | INIT_LIST_HEAD(&info->resources); |
413 | /* insert busn resource at first */ | ||
414 | pci_add_resource(&info->resources, &root->secondary); | ||
415 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, | ||
416 | &info->res_num); | ||
417 | if (info->res_num) { | ||
418 | info->res = | ||
419 | kzalloc_node(sizeof(*info->res) * info->res_num, | ||
420 | GFP_KERNEL, controller->node); | ||
421 | if (!info->res) | ||
422 | goto out3; | ||
423 | 458 | ||
424 | info->res_offset = | 459 | ret = probe_pci_root_info(info, device, busnum, domain); |
425 | kzalloc_node(sizeof(*info->res_offset) * info->res_num, | 460 | if (ret) { |
426 | GFP_KERNEL, controller->node); | 461 | kfree(info->controller); |
427 | if (!info->res_offset) | 462 | kfree(info); |
428 | goto out4; | 463 | return NULL; |
429 | |||
430 | name = kmalloc(16, GFP_KERNEL); | ||
431 | if (!name) | ||
432 | goto out5; | ||
433 | |||
434 | sprintf(name, "PCI Bus %04x:%02x", domain, bus); | ||
435 | info->bridge = device; | ||
436 | info->controller = controller; | ||
437 | info->name = name; | ||
438 | info->res_num = 0; | ||
439 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, | ||
440 | add_window, info); | ||
441 | } | 464 | } |
465 | /* insert busn resource at first */ | ||
466 | pci_add_resource(&info->resources, &root->secondary); | ||
442 | /* | 467 | /* |
443 | * See arch/x86/pci/acpi.c. | 468 | * See arch/x86/pci/acpi.c. |
444 | * The desired pci bus might already be scanned in a quirk. We | 469 | * The desired pci bus might already be scanned in a quirk. We |
@@ -457,17 +482,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
457 | release_pci_root_info, info); | 482 | release_pci_root_info, info); |
458 | pci_scan_child_bus(pbus); | 483 | pci_scan_child_bus(pbus); |
459 | return pbus; | 484 | return pbus; |
460 | |||
461 | out5: | ||
462 | kfree(info->res_offset); | ||
463 | out4: | ||
464 | kfree(info->res); | ||
465 | out3: | ||
466 | kfree(info); | ||
467 | out2: | ||
468 | kfree(controller); | ||
469 | out1: | ||
470 | return NULL; | ||
471 | } | 485 | } |
472 | 486 | ||
473 | int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) | 487 | int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) |