libata: misc updates for AN
[safe/jmp/linux-2.6] / drivers / acpi / pci_root.c
index 5d6bc81..f14ff1f 100644 (file)
 #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_device_id root_device_ids[] = {
+       {"PNP0A03", 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, root_device_ids);
+
 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,
+       .ids = root_device_ids,
        .ops = {
                .add = acpi_pci_root_add,
                .remove = acpi_pci_root_remove,
@@ -58,7 +62,7 @@ static struct acpi_driver acpi_pci_root_driver = {
 
 struct acpi_pci_root {
        struct list_head node;
-       acpi_handle handle;
+       struct acpi_device * device;
        struct acpi_pci_id id;
        struct pci_bus *bus;
 };
@@ -83,7 +87,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
        list_for_each(entry, &acpi_pci_roots) {
                struct acpi_pci_root *root;
                root = list_entry(entry, struct acpi_pci_root, node);
-               driver->add(root->handle);
+               driver->add(root->device->handle);
                n++;
        }
 
@@ -98,11 +102,12 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 
        struct acpi_pci_driver **pptr = &sub_driver;
        while (*pptr) {
-               if (*pptr != driver)
-                       continue;
-               *pptr = (*pptr)->next;
-               break;
+               if (*pptr == driver)
+                       break;
+               pptr = &(*pptr)->next;
        }
+       BUG_ON(!*pptr);
+       *pptr = (*pptr)->next;
 
        if (!driver->remove)
                return;
@@ -110,27 +115,40 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
        list_for_each(entry, &acpi_pci_roots) {
                struct acpi_pci_root *root;
                root = list_entry(entry, struct acpi_pci_root, node);
-               driver->remove(root->handle);
+               driver->remove(root->device->handle);
        }
 }
 
 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)
 {
-       int *busnr = (int *)data;
+       int *busnr = data;
        struct acpi_resource_address64 address;
 
-       if (resource->type != ACPI_RSTYPE_ADDRESS16 &&
-           resource->type != ACPI_RSTYPE_ADDRESS32 &&
-           resource->type != ACPI_RSTYPE_ADDRESS64)
+       if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
+           resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
+           resource->type != ACPI_RESOURCE_TYPE_ADDRESS64)
                return AE_OK;
 
        acpi_resource_to_address64(resource, &address);
        if ((address.address_length > 0) &&
            (address.resource_type == ACPI_BUS_NUMBER_RANGE))
-               *busnr = address.min_address_range;
+               *busnr = address.minimum;
 
        return AE_OK;
 }
@@ -151,6 +169,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;
@@ -159,26 +192,22 @@ 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;
 
-       ACPI_FUNCTION_TRACE("acpi_pci_root_add");
 
        if (!device)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
-       root = kmalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
+       root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
        if (!root)
-               return_VALUE(-ENOMEM);
-       memset(root, 0, sizeof(struct acpi_pci_root));
+               return -ENOMEM;
        INIT_LIST_HEAD(&root->node);
 
-       root->handle = device->handle;
+       root->device = device;
        strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
        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;
 
        /* 
@@ -186,7 +215,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
         * -------
         * Obtained via _SEG, if exists, otherwise assumed to be zero (0).
         */
-       status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
+       status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
                                       &value);
        switch (status) {
        case AE_OK:
@@ -198,7 +227,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
                root->id.segment = 0;
                break;
        default:
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SEG\n"));
+               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG"));
                result = -ENODEV;
                goto end;
        }
@@ -208,7 +237,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
         * ---
         * Obtained via _BBN, if exists, otherwise assumed to be zero (0).
         */
-       status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
+       status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL,
                                       &value);
        switch (status) {
        case AE_OK:
@@ -219,7 +248,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
                root->id.bus = 0;
                break;
        default:
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BBN\n"));
+               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN"));
                result = -ENODEV;
                goto end;
        }
@@ -231,10 +260,11 @@ static int acpi_pci_root_add(struct acpi_device *device)
                        int bus = 0;
                        acpi_status status;
 
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
+                       printk(KERN_ERR PREFIX
+                                   "Wrong _BBN value, reboot"
+                                   " and use option 'pci=noacpi'\n");
 
-                       status = try_get_root_bridge_busnr(root->handle, &bus);
+                       status = try_get_root_bridge_busnr(device->handle, &bus);
                        if (ACPI_FAILURE(status))
                                break;
                        if (bus != root->id.bus) {
@@ -273,9 +303,9 @@ static int acpi_pci_root_add(struct acpi_device *device)
         */
        root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
        if (!root->bus) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Bus %04x:%02x not present in PCI namespace\n",
-                                 root->id.segment, root->id.bus));
+               printk(KERN_ERR PREFIX
+                           "Bus %04x:%02x not present in PCI namespace\n",
+                           root->id.segment, root->id.bus);
                result = -ENODEV;
                goto end;
        }
@@ -294,11 +324,17 @@ static int acpi_pci_root_add(struct acpi_device *device)
         * -----------------
         * Evaluate and parse _PRT, if exists.
         */
-       status = acpi_get_handle(root->handle, METHOD_NAME__PRT, &handle);
+       status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
        if (ACPI_SUCCESS(status))
-               result = acpi_pci_irq_add_prt(root->handle, root->id.segment,
+               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))
@@ -306,46 +342,43 @@ static int acpi_pci_root_add(struct acpi_device *device)
                kfree(root);
        }
 
-       return_VALUE(result);
+       return result;
 }
 
 static int acpi_pci_root_start(struct acpi_device *device)
 {
        struct acpi_pci_root *root;
 
-       ACPI_FUNCTION_TRACE("acpi_pci_root_start");
 
        list_for_each_entry(root, &acpi_pci_roots, node) {
-               if (root->handle == device->handle) {
+               if (root->device == device) {
                        pci_bus_add_devices(root->bus);
-                       return_VALUE(0);
+                       return 0;
                }
        }
-       return_VALUE(-ENODEV);
+       return -ENODEV;
 }
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
        struct acpi_pci_root *root = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_pci_root_remove");
 
        if (!device || !acpi_driver_data(device))
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
-       root = (struct acpi_pci_root *)acpi_driver_data(device);
+       root = acpi_driver_data(device);
 
        kfree(root);
 
-       return_VALUE(0);
+       return 0;
 }
 
 static int __init acpi_pci_root_init(void)
 {
-       ACPI_FUNCTION_TRACE("acpi_pci_root_init");
 
        if (acpi_pci_disabled)
-               return_VALUE(0);
+               return 0;
 
        /* DEBUG:
           acpi_dbg_layer = ACPI_PCI_COMPONENT;
@@ -353,9 +386,9 @@ static int __init acpi_pci_root_init(void)
         */
 
        if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
-               return_VALUE(-ENODEV);
+               return -ENODEV;
 
-       return_VALUE(0);
+       return 0;
 }
 
 subsys_initcall(acpi_pci_root_init);