Commit 081873a5 authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[PATCH] Remove code duplication in power.c

As per the FIXME. Work done by Eric Blade
parent b1c89e90
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
* *
* Kai Germaschewski contributed to the list walking routines. * Kai Germaschewski contributed to the list walking routines.
* *
* FIXME: The suspend and shutdown walks are identical. The resume walk
* is simply walking the list backward. Anyway we can combine these (cleanly)?
*/ */
#include <linux/device.h> #include <linux/device.h>
...@@ -17,13 +15,15 @@ ...@@ -17,13 +15,15 @@
#define to_dev(node) container_of(node,struct device,g_list) #define to_dev(node) container_of(node,struct device,g_list)
/** /**
* device_suspend - suspend all devices on the device tree * device_suspend - suspend/remove all devices on the device ree
* @state: state we're entering * @state: state we're entering
* @level: what stage of the suspend process we're at * @level: what stage of the suspend process we're at
* (emb: it seems that these two arguments are described backwards of what
* they actually mean .. is this correct?)
* *
* The entries in the global device list are inserted such that they're in a * The entries in the global device list are inserted such that they're in a
* depth-first ordering. So, simply iterate over the list, and call the driver's * depth-first ordering. So, simply interate over the list, and call the
* suspend callback for each device. * driver's suspend or remove callback for each device.
*/ */
int device_suspend(u32 state, u32 level) int device_suspend(u32 state, u32 level)
{ {
...@@ -31,15 +31,23 @@ int device_suspend(u32 state, u32 level) ...@@ -31,15 +31,23 @@ int device_suspend(u32 state, u32 level)
struct device * prev = NULL; struct device * prev = NULL;
int error = 0; int error = 0;
printk(KERN_EMERG "Suspending Devices\n"); if(level == SUSPEND_POWER_DOWN)
printk(KERN_EMERG "Shutting down devices\n");
else
printk(KERN_EMERG "Suspending devices\n");
spin_lock(&device_lock); spin_lock(&device_lock);
list_for_each(node,&global_device_list) { list_for_each(node,&global_device_list) {
struct device * dev = get_device_locked(to_dev(node)); struct device * dev = get_device_locked(to_dev(node));
if (dev) { if (dev) {
spin_unlock(&device_lock); spin_unlock(&device_lock);
if (dev->driver && dev->driver->suspend) if(dev->driver) {
if(level == SUSPEND_POWER_DOWN) {
if(dev->driver->remove)
dev->driver->remove(dev);
} else if(dev->driver->suspend)
error = dev->driver->suspend(dev,state,level); error = dev->driver->suspend(dev,state,level);
}
if (prev) if (prev)
put_device(prev); put_device(prev);
prev = dev; prev = dev;
...@@ -83,36 +91,12 @@ void device_resume(u32 level) ...@@ -83,36 +91,12 @@ void device_resume(u32 level)
} }
/** /**
* device_shutdown - queisce all the devices before reboot/shutdown * device_shutdown - call device_suspend with status set to shutdown, to
* * cause all devices to remove themselves cleanly
* Do depth first iteration over device tree, calling ->remove() for each
* device. This should ensure the devices are put into a sane state before
* we reboot the system.
*
*/ */
void device_shutdown(void) void device_shutdown(void)
{ {
struct list_head * node, * next; device_suspend(4, SUSPEND_POWER_DOWN);
struct device * prev = NULL;
printk(KERN_EMERG "Shutting down devices\n");
spin_lock(&device_lock);
list_for_each_safe(node,next,&global_device_list) {
struct device * dev = get_device_locked(to_dev(node));
if (dev) {
spin_unlock(&device_lock);
if (dev->driver && dev->driver->remove)
dev->driver->remove(dev);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
}
}
spin_unlock(&device_lock);
if (prev)
put_device(prev);
} }
EXPORT_SYMBOL(device_suspend); EXPORT_SYMBOL(device_suspend);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment