summaryrefslogtreecommitdiff
path: root/drivers/acpi/pci_root.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r--drivers/acpi/pci_root.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index a860efa2c562..ad4145a37786 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -36,17 +36,16 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_root")
+ACPI_MODULE_NAME("pci_root");
#define ACPI_PCI_ROOT_CLASS "pci_bridge"
#define ACPI_PCI_ROOT_HID "PNP0A03"
-#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver"
#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
static int acpi_pci_root_add(struct acpi_device *device);
static int acpi_pci_root_remove(struct acpi_device *device, int type);
static int acpi_pci_root_start(struct acpi_device *device);
static struct acpi_driver acpi_pci_root_driver = {
- .name = ACPI_PCI_ROOT_DRIVER_NAME,
+ .name = "pci_root",
.class = ACPI_PCI_ROOT_CLASS,
.ids = ACPI_PCI_ROOT_HID,
.ops = {
@@ -117,6 +116,19 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
EXPORT_SYMBOL(acpi_pci_unregister_driver);
+acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
+{
+ struct acpi_pci_root *tmp;
+
+ list_for_each_entry(tmp, &acpi_pci_roots, node) {
+ if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus))
+ return tmp->device->handle;
+ }
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
+
static acpi_status
get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
@@ -152,6 +164,21 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
return AE_OK;
}
+static void acpi_pci_bridge_scan(struct acpi_device *device)
+{
+ int status;
+ struct acpi_device *child = NULL;
+
+ if (device->flags.bus_address)
+ if (device->parent && device->parent->ops.bind) {
+ status = device->parent->ops.bind(device);
+ if (!status) {
+ list_for_each_entry(child, &device->children, node)
+ acpi_pci_bridge_scan(child);
+ }
+ }
+}
+
static int acpi_pci_root_add(struct acpi_device *device)
{
int result = 0;
@@ -160,6 +187,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
acpi_status status = AE_OK;
unsigned long value = 0;
acpi_handle handle = NULL;
+ struct acpi_device *child;
if (!device)
@@ -175,9 +203,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
acpi_driver_data(device) = root;
- /*
- * TBD: Doesn't the bus driver automatically set this?
- */
device->ops.bind = acpi_pci_bind;
/*
@@ -299,6 +324,12 @@ static int acpi_pci_root_add(struct acpi_device *device)
result = acpi_pci_irq_add_prt(device->handle, root->id.segment,
root->id.bus);
+ /*
+ * Scan and bind all _ADR-Based Devices
+ */
+ list_for_each_entry(child, &device->children, node)
+ acpi_pci_bridge_scan(child);
+
end:
if (result) {
if (!list_empty(&root->node))