]> err.no Git - linux-2.6/blobdiff - drivers/acpi/scan.c
ACPI: pass pm_message_t from acpi_device_suspend() to root_suspend()
[linux-2.6] / drivers / acpi / scan.c
index 31218e1d2a18313a8ea9410c3bbab5934bb7b396..eee58393eb469fe92c7195e8525687d1846b844c 100644 (file)
@@ -23,7 +23,6 @@ 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)
 {
@@ -78,7 +77,7 @@ static struct kobj_type ktype_acpi_ns = {
        .release = acpi_device_release,
 };
 
-static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
+static int namespace_uevent(struct kset *kset, struct kobject *kobj,
                             char **envp, int num_envp, char *buffer,
                             int buffer_size)
 {
@@ -89,8 +88,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
        if (!dev->driver)
                return 0;
 
-       if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
-                               "PHYSDEVDRIVER=%s", dev->driver->name))
+       if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+                          "PHYSDEVDRIVER=%s", dev->driver->name))
                return -ENOMEM;
 
        envp[i] = NULL;
@@ -98,8 +97,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
        return 0;
 }
 
-static struct kset_hotplug_ops namespace_hotplug_ops = {
-       .hotplug = &namespace_hotplug,
+static struct kset_uevent_ops namespace_uevent_ops = {
+       .uevent = &namespace_uevent,
 };
 
 static struct kset acpi_namespace_kset = {
@@ -108,7 +107,7 @@ static struct kset acpi_namespace_kset = {
                 },
        .subsys = &acpi_subsys,
        .ktype = &ktype_acpi_ns,
-       .hotplug_ops = &namespace_hotplug_ops,
+       .uevent_ops = &namespace_uevent_ops,
 };
 
 static void acpi_device_register(struct acpi_device *device,
@@ -347,7 +346,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 }
 
 /* --------------------------------------------------------------------------
-               ACPI hotplug sysfs device file support
+               ACPI sysfs device file support
    -------------------------------------------------------------------------- */
 static ssize_t acpi_eject_store(struct acpi_device *device,
                                const char *buf, size_t count);
@@ -475,8 +474,10 @@ static LIST_HEAD(acpi_bus_drivers);
 static DECLARE_MUTEX(acpi_bus_drivers_lock);
 
 /**
- * acpi_bus_match 
- * --------------
+ * acpi_bus_match - match device IDs to driver's supported IDs
+ * @device: the device that we are trying to match to a driver
+ * @driver: driver whose device id table is being checked
+ *
  * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
  * matches the specified driver's criteria.
  */
@@ -489,8 +490,10 @@ acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver)
 }
 
 /**
- * acpi_bus_driver_init 
- * --------------------
+ * acpi_bus_driver_init - add a device to a driver
+ * @device: the device to add and initialize
+ * @driver: driver for the device
+ *
  * Used to initialize a device via its device driver.  Called whenever a 
  * driver is bound to a device.  Invokes the driver's add() and start() ops.
  */
@@ -603,8 +606,9 @@ static int acpi_driver_detach(struct acpi_driver *drv)
 }
 
 /**
- * acpi_bus_register_driver 
- * ------------------------ 
+ * acpi_bus_register_driver - register a driver with the ACPI bus
+ * @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 the
  * number of devices that were claimed by the driver, or a negative
@@ -633,8 +637,9 @@ int acpi_bus_register_driver(struct acpi_driver *driver)
 EXPORT_SYMBOL(acpi_bus_register_driver);
 
 /**
- * acpi_bus_unregister_driver 
- * --------------------------
+ * acpi_bus_unregister_driver - unregisters a driver with the APIC bus
+ * @driver: driver to unregister
+ *
  * Unregisters a driver with the ACPI bus.  Searches the namespace for all
  * devices that match the driver's criteria and unbinds.
  */
@@ -660,8 +665,9 @@ int acpi_bus_unregister_driver(struct acpi_driver *driver)
 EXPORT_SYMBOL(acpi_bus_unregister_driver);
 
 /**
- * acpi_bus_find_driver 
- * --------------------
+ * acpi_bus_find_driver - check if there is a driver installed for the device
+ * @device: device that we are trying to find a supporting driver for
+ *
  * Parses the list of registered drivers looking for a driver applicable for
  * the specified device.
  */
@@ -844,7 +850,7 @@ static void acpi_device_set_id(struct acpi_device *device,
         * ----
         * Fix for the system root bus device -- the only root-level device.
         */
-       if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
+       if (((acpi_handle)parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
                hid = ACPI_BUS_HID;
                strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
                strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
@@ -1277,7 +1283,7 @@ int acpi_bus_start(struct acpi_device *device)
 
 EXPORT_SYMBOL(acpi_bus_start);
 
-static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
+int acpi_bus_trim(struct acpi_device *start, int rmdevice)
 {
        acpi_status status;
        struct acpi_device *parent, *child;
@@ -1330,6 +1336,8 @@ static 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)
 {
@@ -1363,6 +1371,100 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
        return_VALUE(result);
 }
 
+
+static inline struct acpi_device * to_acpi_dev(struct device * dev)
+{
+       return container_of(dev, struct acpi_device, dev);
+}
+
+
+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;
+}
+
+
+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;
@@ -1375,6 +1477,12 @@ static int __init acpi_scan_init(void)
 
        kset_register(&acpi_namespace_kset);
 
+       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");
+       }
+
        /*
         * Create the root device in the bus's device tree
         */
@@ -1384,6 +1492,16 @@ 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.