ソースを参照

ACPI: create acpi_device_suspend()/acpi_device_resume()

updated and tested by Konstantin Karasyov

http://bugzilla.kernel.org/show_bug.cgi?id=5000

Signed-off-by: Patrick Mochel <patrick.mochel@intel.com>
Signed-off-by: Konstantin Karasyov <konstantin.karasyov @intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Patrick Mochel 19 年 前
コミット
5b3272655a
2 ファイル変更120 行追加1 行削除
  1. 118 0
      drivers/acpi/scan.c
  2. 2 1
      include/acpi/acpi_bus.h

+ 118 - 0
drivers/acpi/scan.c

@@ -1371,6 +1371,108 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
 	return_VALUE(result);
 	return_VALUE(result);
 }
 }
 
 
+
+static 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)
+{
+	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);
+
+			/* TBD: What suspend state should be passed
+			 * to device?
+			 */
+			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);
+	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);
+
+			/* TBD: What suspend state should be passed
+			 * to device?
+			 */
+			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)
 static int __init acpi_scan_init(void)
 {
 {
 	int result;
 	int result;
@@ -1383,6 +1485,12 @@ static int __init acpi_scan_init(void)
 
 
 	kset_register(&acpi_namespace_kset);
 	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
 	 * Create the root device in the bus's device tree
 	 */
 	 */
@@ -1392,6 +1500,16 @@ static int __init acpi_scan_init(void)
 		goto Done;
 		goto Done;
 
 
 	result = acpi_start_single_object(acpi_root);
 	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.
 	 * Enumerate devices in the ACPI namespace.

+ 2 - 1
include/acpi/acpi_bus.h

@@ -26,7 +26,7 @@
 #ifndef __ACPI_BUS_H__
 #ifndef __ACPI_BUS_H__
 #define __ACPI_BUS_H__
 #define __ACPI_BUS_H__
 
 
-#include <linux/kobject.h>
+#include <linux/device.h>
 
 
 #include <acpi/acpi.h>
 #include <acpi/acpi.h>
 
 
@@ -296,6 +296,7 @@ struct acpi_device {
 	struct acpi_driver *driver;
 	struct acpi_driver *driver;
 	void *driver_data;
 	void *driver_data;
 	struct kobject kobj;
 	struct kobject kobj;
+	struct device dev;
 };
 };
 
 
 #define acpi_driver_data(d)	((d)->driver_data)
 #define acpi_driver_data(d)	((d)->driver_data)