linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / acpi / scan.c
index 698a154..9271e52 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/kernel.h>
 #include <linux/acpi.h>
 
 #include <acpi/acpi_drivers.h>
@@ -24,6 +23,7 @@ static LIST_HEAD(acpi_device_list);
 DEFINE_SPINLOCK(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
 
+static int acpi_bus_trim(struct acpi_device *start, int rmdevice);
 
 static void acpi_device_release(struct kobject *kobj)
 {
@@ -114,8 +114,6 @@ static struct kset acpi_namespace_kset = {
 static void acpi_device_register(struct acpi_device *device,
                                 struct acpi_device *parent)
 {
-       int err;
-
        /*
         * Linkage
         * -------
@@ -141,14 +139,11 @@ static void acpi_device_register(struct acpi_device *device,
                device->kobj.parent = &parent->kobj;
        device->kobj.ktype = &ktype_acpi_ns;
        device->kobj.kset = &acpi_namespace_kset;
-       err = kobject_register(&device->kobj);
-       if (err < 0)
-               printk(KERN_WARNING "%s: kobject_register error: %d\n",
-                       __FUNCTION__, err);
+       kobject_register(&device->kobj);
        create_sysfs_device_files(device);
 }
 
-static void acpi_device_unregister(struct acpi_device *device, int type)
+static int acpi_device_unregister(struct acpi_device *device, int type)
 {
        spin_lock(&acpi_device_lock);
        if (device->parent) {
@@ -164,14 +159,16 @@ static void acpi_device_unregister(struct acpi_device *device, int type)
        acpi_detach_data(device->handle, acpi_bus_data_handler);
        remove_sysfs_device_files(device);
        kobject_unregister(&device->kobj);
+       return 0;
 }
 
 void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context)
 {
+       ACPI_FUNCTION_TRACE("acpi_bus_data_handler");
 
        /* TBD */
 
-       return;
+       return_VOID;
 }
 
 static int acpi_bus_get_power_flags(struct acpi_device *device)
@@ -180,6 +177,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
        acpi_handle handle = NULL;
        u32 i = 0;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_get_power_flags");
 
        /*
         * Power Management Flags
@@ -232,14 +230,17 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
 
        device->power.state = ACPI_STATE_UNKNOWN;
 
-       return 0;
+       return_VALUE(0);
 }
 
 int acpi_match_ids(struct acpi_device *device, char *ids)
 {
+       int error = 0;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
        if (device->flags.hardware_id)
                if (strstr(ids, device->pnp.hardware_id))
-                       return 0;
+                       goto Done;
 
        if (device->flags.compatible_ids) {
                struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
@@ -248,10 +249,15 @@ int acpi_match_ids(struct acpi_device *device, char *ids)
                /* compare multiple _CID entries against driver ids */
                for (i = 0; i < cid_list->count; i++) {
                        if (strstr(ids, cid_list->id[i].value))
-                               return 0;
+                               goto Done;
                }
        }
-       return -ENOENT;
+       error = -ENOENT;
+
+      Done:
+       if (buffer.pointer)
+               acpi_os_free(buffer.pointer);
+       return error;
 }
 
 static acpi_status
@@ -310,22 +316,24 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *package = NULL;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_get_wakeup_flags");
 
        /* _PRW */
        status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
        if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRW\n"));
                goto end;
        }
 
        package = (union acpi_object *)buffer.pointer;
        status = acpi_bus_extract_wakeup_device_power_package(device, package);
        if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Error extracting _PRW package\n"));
                goto end;
        }
 
-       kfree(buffer.pointer);
+       acpi_os_free(buffer.pointer);
 
        device->wakeup.flags.valid = 1;
        /* Power button, Lid switch always enable wakeup */
@@ -335,7 +343,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
       end:
        if (ACPI_FAILURE(status))
                device->flags.wake_capable = 0;
-       return 0;
+       return_VALUE(0);
 }
 
 /* --------------------------------------------------------------------------
@@ -434,7 +442,10 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
        islockable = device->flags.lockable;
        handle = device->handle;
 
-       result = acpi_bus_trim(device, 1);
+       if (type == ACPI_TYPE_PROCESSOR)
+               result = acpi_bus_trim(device, 0);
+       else
+               result = acpi_bus_trim(device, 1);
 
        if (!result)
                result = acpi_eject_operation(handle, islockable);
@@ -461,6 +472,7 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device)
    -------------------------------------------------------------------------- */
 
 static LIST_HEAD(acpi_bus_drivers);
+static DECLARE_MUTEX(acpi_bus_drivers_lock);
 
 /**
  * acpi_bus_match - match device IDs to driver's supported IDs
@@ -491,18 +503,19 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
 {
        int result = 0;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_driver_init");
 
        if (!device || !driver)
-               return -EINVAL;
+               return_VALUE(-EINVAL);
 
        if (!driver->ops.add)
-               return -ENOSYS;
+               return_VALUE(-ENOSYS);
 
        result = driver->ops.add(device);
        if (result) {
                device->driver = NULL;
                acpi_driver_data(device) = NULL;
-               return result;
+               return_VALUE(result);
        }
 
        device->driver = driver;
@@ -514,7 +527,7 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "Driver successfully bound to device\n"));
-       return 0;
+       return_VALUE(0);
 }
 
 static int acpi_start_single_object(struct acpi_device *device)
@@ -522,9 +535,10 @@ static int acpi_start_single_object(struct acpi_device *device)
        int result = 0;
        struct acpi_driver *driver;
 
+       ACPI_FUNCTION_TRACE("acpi_start_single_object");
 
        if (!(driver = device->driver))
-               return 0;
+               return_VALUE(0);
 
        if (driver->ops.start) {
                result = driver->ops.start(device);
@@ -532,13 +546,15 @@ static int acpi_start_single_object(struct acpi_device *device)
                        driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
        }
 
-       return result;
+       return_VALUE(result);
 }
 
-static void acpi_driver_attach(struct acpi_driver *drv)
+static int acpi_driver_attach(struct acpi_driver *drv)
 {
        struct list_head *node, *next;
+       int count = 0;
 
+       ACPI_FUNCTION_TRACE("acpi_driver_attach");
 
        spin_lock(&acpi_device_lock);
        list_for_each_safe(node, next, &acpi_device_list) {
@@ -553,6 +569,7 @@ static void acpi_driver_attach(struct acpi_driver *drv)
                        if (!acpi_bus_driver_init(dev, drv)) {
                                acpi_start_single_object(dev);
                                atomic_inc(&drv->references);
+                               count++;
                                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                                  "Found driver [%s] for device [%s]\n",
                                                  drv->name, dev->pnp.bus_id));
@@ -561,12 +578,14 @@ static void acpi_driver_attach(struct acpi_driver *drv)
                spin_lock(&acpi_device_lock);
        }
        spin_unlock(&acpi_device_lock);
+       return_VALUE(count);
 }
 
-static void acpi_driver_detach(struct acpi_driver *drv)
+static int acpi_driver_detach(struct acpi_driver *drv)
 {
        struct list_head *node, *next;
 
+       ACPI_FUNCTION_TRACE("acpi_driver_detach");
 
        spin_lock(&acpi_device_lock);
        list_for_each_safe(node, next, &acpi_device_list) {
@@ -584,6 +603,7 @@ static void acpi_driver_detach(struct acpi_driver *drv)
                }
        }
        spin_unlock(&acpi_device_lock);
+       return_VALUE(0);
 }
 
 /**
@@ -591,21 +611,28 @@ static void acpi_driver_detach(struct acpi_driver *drv)
  * @driver: driver being registered
  *
  * Registers a driver with the ACPI bus.  Searches the namespace for all
- * devices that match the driver's criteria and binds.  Returns zero for
- * success or a negative error status for failure.
+ * devices that match the driver's criteria and binds.  Returns the
+ * number of devices that were claimed by the driver, or a negative
+ * error status for failure.
  */
 int acpi_bus_register_driver(struct acpi_driver *driver)
 {
+       int count;
+
+       ACPI_FUNCTION_TRACE("acpi_bus_register_driver");
 
        if (acpi_disabled)
-               return -ENODEV;
+               return_VALUE(-ENODEV);
+
+       if (!driver)
+               return_VALUE(-EINVAL);
 
        spin_lock(&acpi_device_lock);
        list_add_tail(&driver->node, &acpi_bus_drivers);
        spin_unlock(&acpi_device_lock);
-       acpi_driver_attach(driver);
+       count = acpi_driver_attach(driver);
 
-       return 0;
+       return_VALUE(count);
 }
 
 EXPORT_SYMBOL(acpi_bus_register_driver);
@@ -617,16 +644,23 @@ EXPORT_SYMBOL(acpi_bus_register_driver);
  * Unregisters a driver with the ACPI bus.  Searches the namespace for all
  * devices that match the driver's criteria and unbinds.
  */
-void acpi_bus_unregister_driver(struct acpi_driver *driver)
+int acpi_bus_unregister_driver(struct acpi_driver *driver)
 {
-       acpi_driver_detach(driver);
+       int error = 0;
 
-       if (!atomic_read(&driver->references)) {
-               spin_lock(&acpi_device_lock);
-               list_del_init(&driver->node);
-               spin_unlock(&acpi_device_lock);
-       }
-       return;
+       ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver");
+
+       if (driver) {
+               acpi_driver_detach(driver);
+
+               if (!atomic_read(&driver->references)) {
+                       spin_lock(&acpi_device_lock);
+                       list_del_init(&driver->node);
+                       spin_unlock(&acpi_device_lock);
+               }
+       } else
+               error = -EINVAL;
+       return_VALUE(error);
 }
 
 EXPORT_SYMBOL(acpi_bus_unregister_driver);
@@ -643,6 +677,7 @@ static int acpi_bus_find_driver(struct acpi_device *device)
        int result = 0;
        struct list_head *node, *next;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_find_driver");
 
        spin_lock(&acpi_device_lock);
        list_for_each_safe(node, next, &acpi_bus_drivers) {
@@ -662,41 +697,19 @@ static int acpi_bus_find_driver(struct acpi_device *device)
        spin_unlock(&acpi_device_lock);
 
       Done:
-       return result;
+       return_VALUE(result);
 }
 
 /* --------------------------------------------------------------------------
                                  Device Enumeration
    -------------------------------------------------------------------------- */
 
-acpi_status
-acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
-{
-       acpi_status status;
-       acpi_handle tmp;
-       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-       union acpi_object *obj;
-
-       status = acpi_get_handle(handle, "_EJD", &tmp);
-       if (ACPI_FAILURE(status))
-               return status;
-
-       status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);
-       if (ACPI_SUCCESS(status)) {
-               obj = buffer.pointer;
-               status = acpi_get_handle(NULL, obj->string.pointer, ejd);
-               kfree(buffer.pointer);
-       }
-       return status;
-}
-EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
-
-
 static int acpi_bus_get_flags(struct acpi_device *device)
 {
        acpi_status status = AE_OK;
        acpi_handle temp = NULL;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_get_flags");
 
        /* Presence of _STA indicates 'dynamic_status' */
        status = acpi_get_handle(device->handle, "_STA", &temp);
@@ -742,7 +755,7 @@ static int acpi_bus_get_flags(struct acpi_device *device)
 
        /* TBD: Peformance management */
 
-       return 0;
+       return_VALUE(0);
 }
 
 static void acpi_device_get_busid(struct acpi_device *device,
@@ -860,7 +873,7 @@ static void acpi_device_set_id(struct acpi_device *device,
                        printk(KERN_ERR "Memory allocation error\n");
        }
 
-       kfree(buffer.pointer);
+       acpi_os_free(buffer.pointer);
 }
 
 static int acpi_device_set_context(struct acpi_device *device, int type)
@@ -936,9 +949,10 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
        int result = 0;
        struct acpi_driver *driver;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_remove");
 
        if (!dev)
-               return -EINVAL;
+               return_VALUE(-EINVAL);
 
        driver = dev->driver;
 
@@ -947,12 +961,12 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
                if (driver->ops.stop) {
                        result = driver->ops.stop(dev, ACPI_BUS_REMOVAL_EJECT);
                        if (result)
-                               return result;
+                               return_VALUE(result);
                }
 
                result = dev->driver->ops.remove(dev, ACPI_BUS_REMOVAL_EJECT);
                if (result) {
-                       return result;
+                       return_VALUE(result);
                }
 
                atomic_dec(&dev->driver->references);
@@ -961,7 +975,7 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
        }
 
        if (!rmdevice)
-               return 0;
+               return_VALUE(0);
 
        if (dev->flags.bus_address) {
                if ((dev->parent) && (dev->parent->ops.unbind))
@@ -970,7 +984,7 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
 
        acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);
 
-       return 0;
+       return_VALUE(0);
 }
 
 static int
@@ -980,14 +994,15 @@ acpi_add_single_object(struct acpi_device **child,
        int result = 0;
        struct acpi_device *device = NULL;
 
+       ACPI_FUNCTION_TRACE("acpi_add_single_object");
 
        if (!child)
-               return -EINVAL;
+               return_VALUE(-EINVAL);
 
        device = kmalloc(sizeof(struct acpi_device), GFP_KERNEL);
        if (!device) {
-               printk(KERN_ERR PREFIX "Memory allocation error\n");
-               return -ENOMEM;
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n"));
+               return_VALUE(-ENOMEM);
        }
        memset(device, 0, sizeof(struct acpi_device));
 
@@ -1112,7 +1127,7 @@ acpi_add_single_object(struct acpi_device **child,
                kfree(device);
        }
 
-       return result;
+       return_VALUE(result);
 }
 
 static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
@@ -1125,9 +1140,10 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
        acpi_object_type type = 0;
        u32 level = 1;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_scan");
 
        if (!start)
-               return -EINVAL;
+               return_VALUE(-EINVAL);
 
        parent = start;
        phandle = start->handle;
@@ -1224,7 +1240,7 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
                }
        }
 
-       return 0;
+       return_VALUE(0);
 }
 
 int
@@ -1234,6 +1250,7 @@ acpi_bus_add(struct acpi_device **child,
        int result;
        struct acpi_bus_ops ops;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_add");
 
        result = acpi_add_single_object(child, parent, handle, type);
        if (!result) {
@@ -1241,7 +1258,7 @@ acpi_bus_add(struct acpi_device **child,
                ops.acpi_op_add = 1;
                result = acpi_bus_scan(*child, &ops);
        }
-       return result;
+       return_VALUE(result);
 }
 
 EXPORT_SYMBOL(acpi_bus_add);
@@ -1251,9 +1268,10 @@ int acpi_bus_start(struct acpi_device *device)
        int result;
        struct acpi_bus_ops ops;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_start");
 
        if (!device)
-               return -EINVAL;
+               return_VALUE(-EINVAL);
 
        result = acpi_start_single_object(device);
        if (!result) {
@@ -1261,12 +1279,12 @@ int acpi_bus_start(struct acpi_device *device)
                ops.acpi_op_start = 1;
                result = acpi_bus_scan(device, &ops);
        }
-       return result;
+       return_VALUE(result);
 }
 
 EXPORT_SYMBOL(acpi_bus_start);
 
-int acpi_bus_trim(struct acpi_device *start, int rmdevice)
+static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
 {
        acpi_status status;
        struct acpi_device *parent, *child;
@@ -1319,17 +1337,16 @@ int acpi_bus_trim(struct acpi_device *start, int rmdevice)
        }
        return err;
 }
-EXPORT_SYMBOL_GPL(acpi_bus_trim);
-
 
 static int acpi_bus_scan_fixed(struct acpi_device *root)
 {
        int result = 0;
        struct acpi_device *device = NULL;
 
+       ACPI_FUNCTION_TRACE("acpi_bus_scan_fixed");
 
        if (!root)
-               return -ENODEV;
+               return_VALUE(-ENODEV);
 
        /*
         * Enumerate all fixed-feature devices.
@@ -1350,121 +1367,20 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
                        result = acpi_start_single_object(device);
        }
 
-       return result;
-}
-
-
-static inline struct acpi_device * to_acpi_dev(struct device * dev)
-{
-       return container_of(dev, struct acpi_device, dev);
+       return_VALUE(result);
 }
 
-
-static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state)
-{
-       struct acpi_device * dev, * next;
-       int result;
-
-       spin_lock(&acpi_device_lock);
-       list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) {
-               if (dev->driver && dev->driver->ops.suspend) {
-                       spin_unlock(&acpi_device_lock);
-                       result = dev->driver->ops.suspend(dev, 0);
-                       if (result) {
-                               printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n",
-                                      acpi_device_name(dev),
-                                      acpi_device_bid(dev), result);
-                       }
-                       spin_lock(&acpi_device_lock);
-               }
-       }
-       spin_unlock(&acpi_device_lock);
-       return 0;
-}
-
-
-static int acpi_device_suspend(struct device * dev, pm_message_t state)
-{
-       struct acpi_device * acpi_dev = to_acpi_dev(dev);
-
-       /*
-        * For now, we should only register 1 generic device -
-        * the ACPI root device - and from there, we walk the
-        * tree of ACPI devices to suspend each one using the
-        * ACPI driver methods.
-        */
-       if (acpi_dev->handle == ACPI_ROOT_OBJECT)
-               root_suspend(acpi_dev, state);
-       return 0;
-}
-
-
-
-static int root_resume(struct acpi_device * acpi_dev)
-{
-       struct acpi_device * dev, * next;
-       int result;
-
-       spin_lock(&acpi_device_lock);
-       list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) {
-               if (dev->driver && dev->driver->ops.resume) {
-                       spin_unlock(&acpi_device_lock);
-                       result = dev->driver->ops.resume(dev, 0);
-                       if (result) {
-                               printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n",
-                                      acpi_device_name(dev),
-                                      acpi_device_bid(dev), result);
-                       }
-                       spin_lock(&acpi_device_lock);
-               }
-       }
-       spin_unlock(&acpi_device_lock);
-       return 0;
-}
-
-
-static int acpi_device_resume(struct device * dev)
-{
-       struct acpi_device * acpi_dev = to_acpi_dev(dev);
-
-       /*
-        * For now, we should only register 1 generic device -
-        * the ACPI root device - and from there, we walk the
-        * tree of ACPI devices to resume each one using the
-        * ACPI driver methods.
-        */
-       if (acpi_dev->handle == ACPI_ROOT_OBJECT)
-               root_resume(acpi_dev);
-       return 0;
-}
-
-
-static struct bus_type acpi_bus_type = {
-       .name           = "acpi",
-       .suspend        = acpi_device_suspend,
-       .resume         = acpi_device_resume,
-};
-
-
-
 static int __init acpi_scan_init(void)
 {
        int result;
        struct acpi_bus_ops ops;
 
+       ACPI_FUNCTION_TRACE("acpi_scan_init");
 
        if (acpi_disabled)
-               return 0;
-
-       result = kset_register(&acpi_namespace_kset);
-       if (result < 0)
-               printk(KERN_ERR PREFIX "kset_register error: %d\n", result);
+               return_VALUE(0);
 
-       result = bus_register(&acpi_bus_type);
-       if (result) {
-               /* We don't want to quit even if we failed to add suspend/resume */
-               printk(KERN_ERR PREFIX "Could not register bus type\n");
-       }
+       kset_register(&acpi_namespace_kset);
 
        /*
         * Create the root device in the bus's device tree
@@ -1475,16 +1391,6 @@ static int __init acpi_scan_init(void)
                goto Done;
 
        result = acpi_start_single_object(acpi_root);
-       if (result)
-               goto Done;
-
-       acpi_root->dev.bus = &acpi_bus_type;
-       snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name);
-       result = device_register(&acpi_root->dev);
-       if (result) {
-               /* We don't want to quit even if we failed to add suspend/resume */
-               printk(KERN_ERR PREFIX "Could not register device\n");
-       }
 
        /*
         * Enumerate devices in the ACPI namespace.
@@ -1501,7 +1407,7 @@ static int __init acpi_scan_init(void)
                acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
 
       Done:
-       return result;
+       return_VALUE(result);
 }
 
 subsys_initcall(acpi_scan_init);