Pull bugzilla-5000 into release branch
authorLen Brown <len.brown@intel.com>
Fri, 16 Jun 2006 01:36:11 +0000 (21:36 -0400)
committerLen Brown <len.brown@intel.com>
Fri, 16 Jun 2006 01:36:11 +0000 (21:36 -0400)
drivers/acpi/bus.c
drivers/acpi/fan.c
drivers/acpi/scan.c
drivers/acpi/thermal.c
include/acpi/acpi_bus.h

index b77f03d51f0b6b7c7879612b6233fda2ccc1a7a9..dd3983cece92d7b590c6e2fce965d7fab2bbb9cc 100644 (file)
@@ -205,12 +205,14 @@ int acpi_bus_set_power(acpi_handle handle, int state)
         * Get device's current power state if it's unknown
         * This means device power state isn't initialized or previous setting failed
         */
-       if (device->power.state == ACPI_STATE_UNKNOWN)
-               acpi_bus_get_power(device->handle, &device->power.state);
-       if (state == device->power.state) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
-                                 state));
-               return_VALUE(0);
+       if (!device->flags.force_power_state) {
+               if (device->power.state == ACPI_STATE_UNKNOWN)
+                       acpi_bus_get_power(device->handle, &device->power.state);
+               if (state == device->power.state) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
+                                         state));
+                       return_VALUE(0);
+               }
        }
        if (!device->power.states[state].flags.valid) {
                ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n",
index e8165c4f162a238bb9627539e32de41e767846e0..1cd25784b7a48bee9620aadadf3d1a72e9abcdbd 100644 (file)
@@ -48,6 +48,8 @@ MODULE_LICENSE("GPL");
 
 static int acpi_fan_add(struct acpi_device *device);
 static int acpi_fan_remove(struct acpi_device *device, int type);
+static int acpi_fan_suspend(struct acpi_device *device, int state);
+static int acpi_fan_resume(struct acpi_device *device, int state);
 
 static struct acpi_driver acpi_fan_driver = {
        .name = ACPI_FAN_DRIVER_NAME,
@@ -56,6 +58,8 @@ static struct acpi_driver acpi_fan_driver = {
        .ops = {
                .add = acpi_fan_add,
                .remove = acpi_fan_remove,
+               .suspend = acpi_fan_suspend,
+               .resume = acpi_fan_resume,
                },
 };
 
@@ -206,6 +210,10 @@ static int acpi_fan_add(struct acpi_device *device)
                goto end;
        }
 
+       device->flags.force_power_state = 1;
+       acpi_bus_set_power(device->handle, state);
+       device->flags.force_power_state = 0;
+
        result = acpi_fan_add_fs(device);
        if (result)
                goto end;
@@ -239,6 +247,38 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
        return_VALUE(0);
 }
 
+static int acpi_fan_suspend(struct acpi_device *device, int state)
+{
+       if (!device)
+               return -EINVAL;
+
+       acpi_bus_set_power(device->handle, ACPI_STATE_D0);
+
+       return AE_OK;
+}
+
+static int acpi_fan_resume(struct acpi_device *device, int state)
+{
+       int result = 0;
+       int power_state = 0;
+
+       if (!device)
+               return -EINVAL;
+
+       result = acpi_bus_get_power(device->handle, &power_state);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Error reading fan power state\n"));
+               return result;
+       }
+
+       device->flags.force_power_state = 1;
+       acpi_bus_set_power(device->handle, power_state);
+       device->flags.force_power_state = 0;
+
+       return result;
+}
+
 static int __init acpi_fan_init(void)
 {
        int result = 0;
index fe3693de7ba3c3908f172550464c41623445d83c..f8316a05ede72fe459a66341343f5cd40fa6ae09 100644 (file)
@@ -1341,6 +1341,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;
@@ -1353,6 +1447,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
         */
@@ -1362,6 +1462,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.
index f003763de7bbb684ffa9b59f08d89975f2b9ada2..e7fe3a14fdafd46e88851f348657835555e7e484 100644 (file)
@@ -82,6 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
 
 static int acpi_thermal_add(struct acpi_device *device);
 static int acpi_thermal_remove(struct acpi_device *device, int type);
+static int acpi_thermal_resume(struct acpi_device *device, int state);
 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
@@ -103,6 +104,7 @@ static struct acpi_driver acpi_thermal_driver = {
        .ops = {
                .add = acpi_thermal_add,
                .remove = acpi_thermal_remove,
+               .resume = acpi_thermal_resume,
                },
 };
 
@@ -1417,6 +1419,20 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        return_VALUE(0);
 }
 
+static int acpi_thermal_resume(struct acpi_device *device, int state)
+{
+       struct acpi_thermal *tz = NULL;
+
+       if (!device || !acpi_driver_data(device))
+               return_VALUE(-EINVAL);
+
+       tz = (struct acpi_thermal *)acpi_driver_data(device);
+
+       acpi_thermal_check(tz);
+
+       return AE_OK;
+}
+
 static int __init acpi_thermal_init(void)
 {
        int result = 0;
index 8c7590fdd822531d7d1fd62f55397578350171b5..a2b3e390a503ffdad7b66464bd6881ae4df1c9ee 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef __ACPI_BUS_H__
 #define __ACPI_BUS_H__
 
-#include <linux/kobject.h>
+#include <linux/device.h>
 
 #include <acpi/acpi.h>
 
@@ -169,7 +169,8 @@ struct acpi_device_flags {
        u32 power_manageable:1;
        u32 performance_manageable:1;
        u32 wake_capable:1;     /* Wakeup(_PRW) supported? */
-       u32 reserved:20;
+       u32 force_power_state:1;
+       u32 reserved:19;
 };
 
 /* File System */
@@ -296,6 +297,7 @@ struct acpi_device {
        struct acpi_driver *driver;
        void *driver_data;
        struct kobject kobj;
+       struct device dev;
 };
 
 #define acpi_driver_data(d)    ((d)->driver_data)