|
@@ -376,6 +376,50 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
|
|
|
__release_pci_root_info(info);
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
|
|
|
+ int busnum, int domain)
|
|
|
+{
|
|
|
+ char *name;
|
|
|
+
|
|
|
+ name = kmalloc(16, GFP_KERNEL);
|
|
|
+ if (!name)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ sprintf(name, "PCI Bus %04x:%02x", domain, busnum);
|
|
|
+ info->bridge = device;
|
|
|
+ info->name = name;
|
|
|
+
|
|
|
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
|
|
|
+ &info->res_num);
|
|
|
+ if (info->res_num) {
|
|
|
+ info->res =
|
|
|
+ kzalloc_node(sizeof(*info->res) * info->res_num,
|
|
|
+ GFP_KERNEL, info->controller->node);
|
|
|
+ if (!info->res) {
|
|
|
+ kfree(name);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ info->res_offset =
|
|
|
+ kzalloc_node(sizeof(*info->res_offset) * info->res_num,
|
|
|
+ GFP_KERNEL, info->controller->node);
|
|
|
+ if (!info->res_offset) {
|
|
|
+ kfree(name);
|
|
|
+ kfree(info->res);
|
|
|
+ info->res = NULL;
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ info->res_num = 0;
|
|
|
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS,
|
|
|
+ add_window, info);
|
|
|
+ } else
|
|
|
+ kfree(name);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
|
|
{
|
|
|
struct acpi_device *device = root->device;
|
|
@@ -385,12 +429,11 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
|
|
struct pci_root_info *info = NULL;
|
|
|
int busnum = root->secondary.start;
|
|
|
struct pci_bus *pbus;
|
|
|
- char *name;
|
|
|
- int pxm;
|
|
|
+ int pxm, ret;
|
|
|
|
|
|
controller = alloc_pci_controller(domain);
|
|
|
if (!controller)
|
|
|
- goto out1;
|
|
|
+ return NULL;
|
|
|
|
|
|
controller->acpi_handle = device->handle;
|
|
|
|
|
@@ -404,41 +447,23 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
|
|
if (!info) {
|
|
|
printk(KERN_WARNING
|
|
|
"pci_bus %04x:%02x: ignored (out of memory)\n",
|
|
|
- root->segment, busnum);
|
|
|
- goto out2;
|
|
|
+ domain, busnum);
|
|
|
+ kfree(controller);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
+ info->controller = controller;
|
|
|
INIT_LIST_HEAD(&info->io_resources);
|
|
|
INIT_LIST_HEAD(&info->resources);
|
|
|
- /* insert busn resource at first */
|
|
|
- pci_add_resource(&info->resources, &root->secondary);
|
|
|
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
|
|
|
- &info->res_num);
|
|
|
- if (info->res_num) {
|
|
|
- info->res =
|
|
|
- kzalloc_node(sizeof(*info->res) * info->res_num,
|
|
|
- GFP_KERNEL, controller->node);
|
|
|
- if (!info->res)
|
|
|
- goto out3;
|
|
|
|
|
|
- info->res_offset =
|
|
|
- kzalloc_node(sizeof(*info->res_offset) * info->res_num,
|
|
|
- GFP_KERNEL, controller->node);
|
|
|
- if (!info->res_offset)
|
|
|
- goto out4;
|
|
|
-
|
|
|
- name = kmalloc(16, GFP_KERNEL);
|
|
|
- if (!name)
|
|
|
- goto out5;
|
|
|
-
|
|
|
- sprintf(name, "PCI Bus %04x:%02x", domain, bus);
|
|
|
- info->bridge = device;
|
|
|
- info->controller = controller;
|
|
|
- info->name = name;
|
|
|
- info->res_num = 0;
|
|
|
- acpi_walk_resources(device->handle, METHOD_NAME__CRS,
|
|
|
- add_window, info);
|
|
|
+ ret = probe_pci_root_info(info, device, busnum, domain);
|
|
|
+ if (ret) {
|
|
|
+ kfree(info->controller);
|
|
|
+ kfree(info);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
+ /* insert busn resource at first */
|
|
|
+ pci_add_resource(&info->resources, &root->secondary);
|
|
|
/*
|
|
|
* See arch/x86/pci/acpi.c.
|
|
|
* 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)
|
|
|
release_pci_root_info, info);
|
|
|
pci_scan_child_bus(pbus);
|
|
|
return pbus;
|
|
|
-
|
|
|
-out5:
|
|
|
- kfree(info->res_offset);
|
|
|
-out4:
|
|
|
- kfree(info->res);
|
|
|
-out3:
|
|
|
- kfree(info);
|
|
|
-out2:
|
|
|
- kfree(controller);
|
|
|
-out1:
|
|
|
- return NULL;
|
|
|
}
|
|
|
|
|
|
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
|