Automatic merge of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6.git/
This commit is contained in:
commit
05d3794aa8
|
@ -7,7 +7,6 @@ that support it. For example, a given bus might look like this:
|
|||
|-- 0000:17:00.0
|
||||
| |-- class
|
||||
| |-- config
|
||||
| |-- detach_state
|
||||
| |-- device
|
||||
| |-- irq
|
||||
| |-- local_cpus
|
||||
|
@ -19,7 +18,7 @@ that support it. For example, a given bus might look like this:
|
|||
| |-- subsystem_device
|
||||
| |-- subsystem_vendor
|
||||
| `-- vendor
|
||||
`-- detach_state
|
||||
`-- ...
|
||||
|
||||
The topmost element describes the PCI domain and bus number. In this case,
|
||||
the domain number is 0000 and the bus number is 17 (both values are in hex).
|
||||
|
@ -31,7 +30,6 @@ files, each with their own function.
|
|||
---- --------
|
||||
class PCI class (ascii, ro)
|
||||
config PCI config space (binary, rw)
|
||||
detach_state connection status (bool, rw)
|
||||
device PCI device (ascii, ro)
|
||||
irq IRQ number (ascii, ro)
|
||||
local_cpus nearby CPU mask (cpumask, ro)
|
||||
|
|
|
@ -207,27 +207,6 @@ SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
|
|||
#READY_AFTER_RESUME
|
||||
#
|
||||
|
||||
Driver Detach Power Management
|
||||
|
||||
The kernel now supports the ability to place a device in a low-power
|
||||
state when it is detached from its driver, which happens when its
|
||||
module is removed.
|
||||
|
||||
Each device contains a 'detach_state' file in its sysfs directory
|
||||
which can be used to control this state. Reading from this file
|
||||
displays what the current detach state is set to. This is 0 (On) by
|
||||
default. A user may write a positive integer value to this file in the
|
||||
range of 1-4 inclusive.
|
||||
|
||||
A value of 1-3 will indicate the device should be placed in that
|
||||
low-power state, which will cause ->suspend() to be called for that
|
||||
device. A value of 4 indicates that the device should be shutdown, so
|
||||
->shutdown() will be called for that device.
|
||||
|
||||
The driver is responsible for reinitializing the device when the
|
||||
module is re-inserted during it's ->probe() (or equivalent) method.
|
||||
The driver core will not call any extra functions when binding the
|
||||
device to the driver.
|
||||
|
||||
pm_message_t meaning
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ looks like the following:
|
|||
|
||||
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
|
||||
. current_vty devspec name partner_vtys
|
||||
.. detach_state index partner_clcs vterm_state
|
||||
.. index partner_clcs vterm_state
|
||||
|
||||
Each entry is provided, by default with a "name" attribute. Reading the
|
||||
"name" attribute will reveal the device type as shown in the following
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Makefile for the Linux device tree
|
||||
|
||||
obj-y := core.o sys.o interface.o bus.o \
|
||||
obj-y := core.o sys.o bus.o \
|
||||
driver.o class.o class_simple.o platform.o \
|
||||
cpu.o firmware.o init.o map.o dmapool.o \
|
||||
attribute_container.o transport_class.o
|
||||
|
|
|
@ -390,7 +390,6 @@ void device_release_driver(struct device * dev)
|
|||
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
|
||||
sysfs_remove_link(&dev->kobj, "driver");
|
||||
list_del_init(&dev->driver_list);
|
||||
device_detach_shutdown(dev);
|
||||
if (drv->remove)
|
||||
drv->remove(dev);
|
||||
dev->driver = NULL;
|
||||
|
|
|
@ -31,8 +31,6 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
|
|||
#define to_dev(obj) container_of(obj, struct device, kobj)
|
||||
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
|
||||
|
||||
extern struct attribute * dev_default_attrs[];
|
||||
|
||||
static ssize_t
|
||||
dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
|
||||
{
|
||||
|
@ -89,7 +87,6 @@ static void device_release(struct kobject * kobj)
|
|||
static struct kobj_type ktype_device = {
|
||||
.release = device_release,
|
||||
.sysfs_ops = &dev_sysfs_ops,
|
||||
.default_attrs = dev_default_attrs,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* drivers/base/interface.c - common driverfs interface that's exported to
|
||||
* the world for all devices.
|
||||
*
|
||||
* Copyright (c) 2002-3 Patrick Mochel
|
||||
* Copyright (c) 2002-3 Open Source Development Labs
|
||||
*
|
||||
* This file is released under the GPLv2
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
/**
|
||||
* detach_state - control the default power state for the device.
|
||||
*
|
||||
* This is the state the device enters when it's driver module is
|
||||
* unloaded. The value is an unsigned integer, in the range of 0-4.
|
||||
* '0' indicates 'On', so no action will be taken when the driver is
|
||||
* unloaded. This is the default behavior.
|
||||
* '4' indicates 'Off', meaning the driver core will call the driver's
|
||||
* shutdown method to quiesce the device.
|
||||
* 1-3 indicate a low-power state for the device to enter via the
|
||||
* driver's suspend method.
|
||||
*/
|
||||
|
||||
static ssize_t detach_show(struct device * dev, char * buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", dev->detach_state);
|
||||
}
|
||||
|
||||
static ssize_t detach_store(struct device * dev, const char * buf, size_t n)
|
||||
{
|
||||
u32 state;
|
||||
state = simple_strtoul(buf, NULL, 10);
|
||||
if (state > 4)
|
||||
return -EINVAL;
|
||||
dev->detach_state = state;
|
||||
return n;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store);
|
||||
|
||||
|
||||
struct attribute * dev_default_attrs[] = {
|
||||
&dev_attr_detach_state.attr,
|
||||
NULL,
|
||||
};
|
|
@ -1,18 +1,7 @@
|
|||
|
||||
|
||||
enum {
|
||||
DEVICE_PM_ON,
|
||||
DEVICE_PM1,
|
||||
DEVICE_PM2,
|
||||
DEVICE_PM3,
|
||||
DEVICE_PM_OFF,
|
||||
};
|
||||
|
||||
/*
|
||||
* shutdown.c
|
||||
*/
|
||||
|
||||
extern int device_detach_shutdown(struct device *);
|
||||
extern void device_shutdown(void);
|
||||
|
||||
|
||||
|
|
|
@ -22,8 +22,17 @@ extern int sysdev_resume(void);
|
|||
|
||||
int resume_device(struct device * dev)
|
||||
{
|
||||
if (dev->bus && dev->bus->resume)
|
||||
if (dev->power.pm_parent
|
||||
&& dev->power.pm_parent->power.power_state) {
|
||||
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
|
||||
dev->power.power_state,
|
||||
dev->power.pm_parent->bus_id,
|
||||
dev->power.pm_parent->power.power_state);
|
||||
}
|
||||
if (dev->bus && dev->bus->resume) {
|
||||
dev_dbg(dev,"resuming\n");
|
||||
return dev->bus->resume(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,20 +19,6 @@
|
|||
extern struct subsystem devices_subsys;
|
||||
|
||||
|
||||
int device_detach_shutdown(struct device * dev)
|
||||
{
|
||||
if (!dev->detach_state)
|
||||
return 0;
|
||||
|
||||
if (dev->detach_state == DEVICE_PM_OFF) {
|
||||
if (dev->driver && dev->driver->shutdown)
|
||||
dev->driver->shutdown(dev);
|
||||
return 0;
|
||||
}
|
||||
return dpm_runtime_suspend(dev, dev->detach_state);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We handle system devices differently - we suspend and shut them
|
||||
* down last and resume them first. That way, we don't do anything stupid like
|
||||
|
@ -52,13 +38,12 @@ void device_shutdown(void)
|
|||
struct device * dev;
|
||||
|
||||
down_write(&devices_subsys.rwsem);
|
||||
list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) {
|
||||
pr_debug("shutting down %s: ", dev->bus_id);
|
||||
list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
|
||||
kobj.entry) {
|
||||
if (dev->driver && dev->driver->shutdown) {
|
||||
pr_debug("Ok\n");
|
||||
dev_dbg(dev, "shutdown\n");
|
||||
dev->driver->shutdown(dev);
|
||||
} else
|
||||
pr_debug("Ignored.\n");
|
||||
}
|
||||
}
|
||||
up_write(&devices_subsys.rwsem);
|
||||
|
||||
|
|
|
@ -39,12 +39,25 @@ int suspend_device(struct device * dev, pm_message_t state)
|
|||
{
|
||||
int error = 0;
|
||||
|
||||
dev_dbg(dev, "suspending\n");
|
||||
if (dev->power.power_state) {
|
||||
dev_dbg(dev, "PM: suspend %d-->%d\n",
|
||||
dev->power.power_state, state);
|
||||
}
|
||||
if (dev->power.pm_parent
|
||||
&& dev->power.pm_parent->power.power_state) {
|
||||
dev_err(dev,
|
||||
"PM: suspend %d->%d, parent %s already %d\n",
|
||||
dev->power.power_state, state,
|
||||
dev->power.pm_parent->bus_id,
|
||||
dev->power.pm_parent->power.power_state);
|
||||
}
|
||||
|
||||
dev->power.prev_state = dev->power.power_state;
|
||||
|
||||
if (dev->bus && dev->bus->suspend && !dev->power.power_state)
|
||||
if (dev->bus && dev->bus->suspend && !dev->power.power_state) {
|
||||
dev_dbg(dev, "suspending\n");
|
||||
error = dev->bus->suspend(dev, state);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -273,9 +273,6 @@ struct device {
|
|||
BIOS data relevant to device) */
|
||||
struct dev_pm_info power;
|
||||
|
||||
u32 detach_state; /* State to enter when device is
|
||||
detached from its driver. */
|
||||
|
||||
u64 *dma_mask; /* dma mask (if dma'able device) */
|
||||
u64 coherent_dma_mask;/* Like dma_mask, but for
|
||||
alloc_coherent mappings as
|
||||
|
|
|
@ -156,14 +156,14 @@ static int enter_state(suspend_state_t state)
|
|||
goto Unlock;
|
||||
}
|
||||
|
||||
pr_debug("PM: Preparing system for suspend\n");
|
||||
pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
|
||||
if ((error = suspend_prepare(state)))
|
||||
goto Unlock;
|
||||
|
||||
pr_debug("PM: Entering state.\n");
|
||||
pr_debug("PM: Entering %s sleep\n", pm_states[state]);
|
||||
error = suspend_enter(state);
|
||||
|
||||
pr_debug("PM: Finishing up.\n");
|
||||
pr_debug("PM: Finishing wakeup.\n");
|
||||
suspend_finish(state);
|
||||
Unlock:
|
||||
up(&pm_sem);
|
||||
|
|
Loading…
Reference in New Issue