Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 253971
b: refs/heads/master
c: 143e859
h: refs/heads/master
i:
  253969: 8d506b1
  253967: 634f52c
v: v3
  • Loading branch information
Linus Torvalds committed Jun 24, 2011
1 parent fe5bfa0 commit 32546dd
Show file tree
Hide file tree
Showing 21 changed files with 79 additions and 100 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1190f6a067bf27b2ee7e06ec0776a17fe0f6c4d8
refs/heads/master: 143e859d05d0abf4c3b67c64c93695d59fd41342
67 changes: 14 additions & 53 deletions trunk/Documentation/power/devices.txt
Original file line number Diff line number Diff line change
Expand Up @@ -520,59 +520,20 @@ Support for power domains is provided through the pwr_domain field of struct
device. This field is a pointer to an object of type struct dev_power_domain,
defined in include/linux/pm.h, providing a set of power management callbacks
analogous to the subsystem-level and device driver callbacks that are executed
for the given device during all power transitions, in addition to the respective
subsystem-level callbacks. Specifically, the power domain "suspend" callbacks
(i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are
executed after the analogous subsystem-level callbacks, while the power domain
"resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore,
etc.) are executed before the analogous subsystem-level callbacks. Error codes
returned by the "suspend" and "resume" power domain callbacks are ignored.

Power domain ->runtime_idle() callback is executed before the subsystem-level
->runtime_idle() callback and the result returned by it is not ignored. Namely,
if it returns error code, the subsystem-level ->runtime_idle() callback will not
be called and the helper function rpm_idle() executing it will return error
code. This mechanism is intended to help platforms where saving device state
is a time consuming operation and should only be carried out if all devices
in the power domain are idle, before turning off the shared power resource(s).
Namely, the power domain ->runtime_idle() callback may return error code until
the pm_runtime_idle() helper (or its asychronous version) has been called for
all devices in the power domain (it is recommended that the returned error code
be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle()
callback from being run prematurely.

The support for device power domains is only relevant to platforms needing to
use the same subsystem-level (e.g. platform bus type) and device driver power
management callbacks in many different power domain configurations and wanting
to avoid incorporating the support for power domains into the subsystem-level
callbacks. The other platforms need not implement it or take it into account
in any way.


System Devices
--------------
System devices (sysdevs) follow a slightly different API, which can be found in

include/linux/sysdev.h
drivers/base/sys.c

System devices will be suspended with interrupts disabled, and after all other
devices have been suspended. On resume, they will be resumed before any other
devices, and also with interrupts disabled. These things occur in special
"sysdev_driver" phases, which affect only system devices.

Thus, after the suspend_noirq (or freeze_noirq or poweroff_noirq) phase, when
the non-boot CPUs are all offline and IRQs are disabled on the remaining online
CPU, then a sysdev_driver.suspend phase is carried out, and the system enters a
sleep state (or a system image is created). During resume (or after the image
has been created or loaded) a sysdev_driver.resume phase is carried out, IRQs
are enabled on the only online CPU, the non-boot CPUs are enabled, and the
resume_noirq (or thaw_noirq or restore_noirq) phase begins.

Code to actually enter and exit the system-wide low power state sometimes
involves hardware details that are only known to the boot firmware, and
may leave a CPU running software (from SRAM or flash memory) that monitors
the system and manages its wakeup sequence.
for the given device during all power transitions, instead of the respective
subsystem-level callbacks. Specifically, if a device's pm_domain pointer is
not NULL, the ->suspend() callback from the object pointed to by it will be
executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and
anlogously for all of the remaining callbacks. In other words, power management
domain callbacks, if defined for the given device, always take precedence over
the callbacks provided by the device's subsystem (e.g. bus type).

The support for device power management domains is only relevant to platforms
needing to use the same device driver power management callbacks in many
different power domain configurations and wanting to avoid incorporating the
support for power domains into subsystem-level callbacks, for example by
modifying the platform bus type. Other platforms need not implement it or take
it into account in any way.


Device Low Power (suspend) States
Expand Down
5 changes: 0 additions & 5 deletions trunk/Documentation/power/runtime_pm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -566,11 +566,6 @@ to do this is:
pm_runtime_set_active(dev);
pm_runtime_enable(dev);

The PM core always increments the run-time usage counter before calling the
->prepare() callback and decrements it after calling the ->complete() callback.
Hence disabling run-time PM temporarily like this will not cause any run-time
suspend callbacks to be lost.

7. Generic subsystem callbacks

Subsystems may wish to conserve code space by using the set of generic power
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/mn10300/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* User space memory access functions
*/
#include <linux/thread_info.h>
#include <linux/kernel.h>
#include <asm/page.h>
#include <asm/errno.h>

Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/base/power/clock_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,15 +387,15 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
clknb = container_of(nb, struct pm_clk_notifier_block, nb);

switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
case BUS_NOTIFY_BIND_DRIVER:
if (clknb->con_ids[0]) {
for (con_id = clknb->con_ids; *con_id; con_id++)
enable_clock(dev, *con_id);
} else {
enable_clock(dev, NULL);
}
break;
case BUS_NOTIFY_DEL_DEVICE:
case BUS_NOTIFY_UNBOUND_DRIVER:
if (clknb->con_ids[0]) {
for (con_id = clknb->con_ids; *con_id; con_id++)
disable_clock(dev, *con_id);
Expand Down
28 changes: 21 additions & 7 deletions trunk/drivers/base/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ static int async_error;
*/
void device_pm_init(struct device *dev)
{
dev->power.in_suspend = false;
dev->power.is_prepared = false;
dev->power.is_suspended = false;
init_completion(&dev->power.completion);
complete_all(&dev->power.completion);
dev->power.wakeup = NULL;
Expand Down Expand Up @@ -91,7 +92,7 @@ void device_pm_add(struct device *dev)
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
mutex_lock(&dpm_list_mtx);
if (dev->parent && dev->parent->power.in_suspend)
if (dev->parent && dev->parent->power.is_prepared)
dev_warn(dev, "parent %s should not be sleeping\n",
dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list);
Expand Down Expand Up @@ -511,7 +512,14 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
dpm_wait(dev->parent, async);
device_lock(dev);

dev->power.in_suspend = false;
/*
* This is a fib. But we'll allow new children to be added below
* a resumed device, even if the device hasn't been completed yet.
*/
dev->power.is_prepared = false;

if (!dev->power.is_suspended)
goto Unlock;

if (dev->pwr_domain) {
pm_dev_dbg(dev, state, "power domain ");
Expand Down Expand Up @@ -548,6 +556,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
}

End:
dev->power.is_suspended = false;

Unlock:
device_unlock(dev);
complete_all(&dev->power.completion);

Expand Down Expand Up @@ -670,7 +681,7 @@ void dpm_complete(pm_message_t state)
struct device *dev = to_device(dpm_prepared_list.prev);

get_device(dev);
dev->power.in_suspend = false;
dev->power.is_prepared = false;
list_move(&dev->power.entry, &list);
mutex_unlock(&dpm_list_mtx);

Expand Down Expand Up @@ -835,11 +846,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
device_lock(dev);

if (async_error)
goto End;
goto Unlock;

if (pm_wakeup_pending()) {
async_error = -EBUSY;
goto End;
goto Unlock;
}

if (dev->pwr_domain) {
Expand Down Expand Up @@ -877,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
}

End:
dev->power.is_suspended = !error;

Unlock:
device_unlock(dev);
complete_all(&dev->power.completion);

Expand Down Expand Up @@ -1042,7 +1056,7 @@ int dpm_prepare(pm_message_t state)
put_device(dev);
break;
}
dev->power.in_suspend = true;
dev->power.is_prepared = true;
if (!list_empty(&dev->power.entry))
list_move_tail(&dev->power.entry, &dpm_prepared_list);
put_device(dev);
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/pci/pci-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ static int pci_pm_prepare(struct device *dev)
* system from the sleep state, we'll have to prevent it from signaling
* wake-up.
*/
pm_runtime_resume(dev);
pm_runtime_get_sync(dev);

if (drv && drv->pm && drv->pm->prepare)
error = drv->pm->prepare(dev);
Expand All @@ -638,6 +638,8 @@ static void pci_pm_complete(struct device *dev)

if (drv && drv->pm && drv->pm->complete)
drv->pm->complete(dev);

pm_runtime_put_sync(dev);
}

#else /* !CONFIG_PM_SLEEP */
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/tty/serial/mrst_max3110.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,6 @@ static int max3110_main_thread(void *_max)
int ret = 0;
struct circ_buf *xmit = &max->con_xmit;

init_waitqueue_head(wq);
pr_info(PR_FMT "start main thread\n");

do {
Expand Down Expand Up @@ -823,7 +822,7 @@ static int __devinit serial_m3110_probe(struct spi_device *spi)
res = RC_TAG;
ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0);
if (ret < 0 || res == 0 || res == 0xffff) {
printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)",
dev_dbg(&spi->dev, "MAX3111 deemed not present (conf reg %04x)",
res);
ret = -ENODEV;
goto err_get_page;
Expand All @@ -838,6 +837,8 @@ static int __devinit serial_m3110_probe(struct spi_device *spi)
max->con_xmit.head = 0;
max->con_xmit.tail = 0;

init_waitqueue_head(&max->wq);

max->main_thread = kthread_run(max3110_main_thread,
max, "max3110_main");
if (IS_ERR(max->main_thread)) {
Expand Down
6 changes: 3 additions & 3 deletions trunk/drivers/usb/core/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ static int usb_unbind_interface(struct device *dev)
* Just re-enable it without affecting the endpoint toggles.
*/
usb_enable_interface(udev, intf, false);
} else if (!error && !intf->dev.power.in_suspend) {
} else if (!error && !intf->dev.power.is_prepared) {
r = usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
if (r < 0)
Expand Down Expand Up @@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf)
}

/* Try to rebind the interface */
if (!intf->dev.power.in_suspend) {
if (!intf->dev.power.is_prepared) {
intf->needs_binding = 0;
rc = device_attach(&intf->dev);
if (rc < 0)
Expand Down Expand Up @@ -1107,7 +1107,7 @@ static int usb_resume_interface(struct usb_device *udev,
if (intf->condition == USB_INTERFACE_UNBOUND) {

/* Carry out a deferred switch to altsetting 0 */
if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) {
if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) {
usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
intf->needs_altsetting0 = 0;
Expand Down
1 change: 0 additions & 1 deletion trunk/fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#ifndef __BTRFS_CTREE__
#define __BTRFS_CTREE__

#include <linux/version.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/fs.h>
Expand Down
6 changes: 3 additions & 3 deletions trunk/fs/jfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ static int jfs_open(struct inode *inode, struct file *file)
struct jfs_inode_info *ji = JFS_IP(inode);
spin_lock_irq(&ji->ag_lock);
if (ji->active_ag == -1) {
ji->active_ag = ji->agno;
atomic_inc(
&JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]);
struct jfs_sb_info *jfs_sb = JFS_SBI(inode->i_sb);
ji->active_ag = BLKTOAG(addressPXD(&ji->ixpxd), jfs_sb);
atomic_inc( &jfs_sb->bmap->db_active[ji->active_ag]);
}
spin_unlock_irq(&ji->ag_lock);
}
Expand Down
12 changes: 5 additions & 7 deletions trunk/fs/jfs/jfs_imap.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ int diRead(struct inode *ip)
release_metapage(mp);

/* set the ag for the inode */
JFS_IP(ip)->agno = BLKTOAG(agstart, sbi);
JFS_IP(ip)->agstart = agstart;
JFS_IP(ip)->active_ag = -1;

return (rc);
Expand Down Expand Up @@ -901,7 +901,7 @@ int diFree(struct inode *ip)

/* get the allocation group for this ino.
*/
agno = JFS_IP(ip)->agno;
agno = BLKTOAG(JFS_IP(ip)->agstart, JFS_SBI(ip->i_sb));

/* Lock the AG specific inode map information
*/
Expand Down Expand Up @@ -1315,12 +1315,11 @@ int diFree(struct inode *ip)
static inline void
diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
{
struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
struct jfs_inode_info *jfs_ip = JFS_IP(ip);

ip->i_ino = (iagno << L2INOSPERIAG) + ino;
jfs_ip->ixpxd = iagp->inoext[extno];
jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);
jfs_ip->agstart = le64_to_cpu(iagp->agstart);
jfs_ip->active_ag = -1;
}

Expand Down Expand Up @@ -1379,7 +1378,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
*/

/* get the ag number of this iag */
agno = JFS_IP(pip)->agno;
agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb));

if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) {
/*
Expand Down Expand Up @@ -2921,10 +2920,9 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
continue;
}

/* agstart that computes to the same ag is treated as same; */
agstart = le64_to_cpu(iagp->agstart);
/* iagp->agstart = agstart & ~(mp->db_agsize - 1); */
n = agstart >> mp->db_agl2size;
iagp->agstart = cpu_to_le64((s64)n << mp->db_agl2size);

/* compute backed inodes */
numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts))
Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/jfs/jfs_incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ struct jfs_inode_info {
short btindex; /* btpage entry index*/
struct inode *ipimap; /* inode map */
unsigned long cflag; /* commit flags */
u64 agstart; /* agstart of the containing IAG */
u16 bxflag; /* xflag of pseudo buffer? */
unchar agno; /* ag number */
unchar pad;
signed char active_ag; /* ag currently allocating from */
lid_t blid; /* lid of pseudo buffer? */
lid_t atlhead; /* anonymous tlock list head */
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/jfs/resize.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
int log_formatted = 0;
struct inode *iplist[1];
struct jfs_superblock *j_sb, *j_sb2;
uint old_agsize;
s64 old_agsize;
int agsizechanged = 0;
struct buffer_head *bh, *bh2;

Expand Down
1 change: 0 additions & 1 deletion trunk/fs/omfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Released under GPL v2.
*/

#include <linux/version.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/buffer_head.h>
Expand Down
4 changes: 2 additions & 2 deletions trunk/include/linux/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -654,13 +654,13 @@ static inline int device_is_registered(struct device *dev)

static inline void device_enable_async_suspend(struct device *dev)
{
if (!dev->power.in_suspend)
if (!dev->power.is_prepared)
dev->power.async_suspend = true;
}

static inline void device_disable_async_suspend(struct device *dev)
{
if (!dev->power.in_suspend)
if (!dev->power.is_prepared)
dev->power.async_suspend = false;
}

Expand Down
Loading

0 comments on commit 32546dd

Please sign in to comment.