kernel-ark/drivers/base/power/resume.c
Rafael J. Wysocki 43a49f8baa PM: Do not check parent state in suspend and resume core code
The checks if the device's parent is in the right state done in
drivers/base/power/suspend.c and drivers/base/power/resume.c serve no particular
purpose, since if the parent is in a wrong power state, the device's suspend or
resume callbacks are supposed to return an error anyway.  Moreover, they are
also useless from the sanity checking point of view, because they rely on the
code being checked to set dev->parent->power.power_state.event appropriately,
which need not happen if that code is buggy.  For these reasons they can be
removed.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2007-07-11 16:09:02 -07:00

150 lines
2.8 KiB
C

/*
* resume.c - Functions for waking devices up.
*
* Copyright (c) 2003 Patrick Mochel
* Copyright (c) 2003 Open Source Development Labs
*
* This file is released under the GPLv2
*
*/
#include <linux/device.h>
#include <linux/resume-trace.h>
#include "../base.h"
#include "power.h"
/**
* resume_device - Restore state for one device.
* @dev: Device.
*
*/
int resume_device(struct device * dev)
{
int error = 0;
TRACE_DEVICE(dev);
TRACE_RESUME(0);
down(&dev->sem);
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
error = dev->bus->resume(dev);
}
if (!error && dev->type && dev->type->resume) {
dev_dbg(dev,"resuming\n");
error = dev->type->resume(dev);
}
if (!error && dev->class && dev->class->resume) {
dev_dbg(dev,"class resume\n");
error = dev->class->resume(dev);
}
up(&dev->sem);
TRACE_RESUME(error);
return error;
}
static int resume_device_early(struct device * dev)
{
int error = 0;
TRACE_DEVICE(dev);
TRACE_RESUME(0);
if (dev->bus && dev->bus->resume_early) {
dev_dbg(dev,"EARLY resume\n");
error = dev->bus->resume_early(dev);
}
TRACE_RESUME(error);
return error;
}
/*
* Resume the devices that have either not gone through
* the late suspend, or that did go through it but also
* went through the early resume
*/
void dpm_resume(void)
{
mutex_lock(&dpm_list_mtx);
while(!list_empty(&dpm_off)) {
struct list_head * entry = dpm_off.next;
struct device * dev = to_device(entry);
get_device(dev);
list_move_tail(entry, &dpm_active);
mutex_unlock(&dpm_list_mtx);
resume_device(dev);
mutex_lock(&dpm_list_mtx);
put_device(dev);
}
mutex_unlock(&dpm_list_mtx);
}
/**
* device_resume - Restore state of each device in system.
*
* Walk the dpm_off list, remove each entry, resume the device,
* then add it to the dpm_active list.
*/
void device_resume(void)
{
might_sleep();
mutex_lock(&dpm_mtx);
dpm_resume();
mutex_unlock(&dpm_mtx);
}
EXPORT_SYMBOL_GPL(device_resume);
/**
* dpm_power_up - Power on some devices.
*
* Walk the dpm_off_irq list and power each device up. This
* is used for devices that required they be powered down with
* interrupts disabled. As devices are powered on, they are moved
* to the dpm_active list.
*
* Interrupts must be disabled when calling this.
*/
void dpm_power_up(void)
{
while(!list_empty(&dpm_off_irq)) {
struct list_head * entry = dpm_off_irq.next;
struct device * dev = to_device(entry);
list_move_tail(entry, &dpm_off);
resume_device_early(dev);
}
}
/**
* device_power_up - Turn on all devices that need special attention.
*
* Power on system devices then devices that required we shut them down
* with interrupts disabled.
* Called with interrupts disabled.
*/
void device_power_up(void)
{
sysdev_resume();
dpm_power_up();
}
EXPORT_SYMBOL_GPL(device_power_up);