diff --git a/[refs] b/[refs] index 2db16bc29f9c..51f1653a8ce2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 46e4edbf7ea9cf26665eb9f90c0fc7688d1a51ed +refs/heads/master: 446b23a75804d7ffa4cca2d4d8f0afb822108c7e diff --git a/trunk/Documentation/power/devices.txt b/trunk/Documentation/power/devices.txt index 64565aac6e40..88880839ece4 100644 --- a/trunk/Documentation/power/devices.txt +++ b/trunk/Documentation/power/devices.txt @@ -520,20 +520,59 @@ 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, 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. +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. Device Low Power (suspend) States diff --git a/trunk/Documentation/power/runtime_pm.txt b/trunk/Documentation/power/runtime_pm.txt index 22accb3eb40e..654097b130b4 100644 --- a/trunk/Documentation/power/runtime_pm.txt +++ b/trunk/Documentation/power/runtime_pm.txt @@ -566,6 +566,11 @@ 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 diff --git a/trunk/arch/mn10300/include/asm/uaccess.h b/trunk/arch/mn10300/include/asm/uaccess.h index 780560b330d9..3d6e60dad9d9 100644 --- a/trunk/arch/mn10300/include/asm/uaccess.h +++ b/trunk/arch/mn10300/include/asm/uaccess.h @@ -15,7 +15,6 @@ * User space memory access functions */ #include -#include #include #include diff --git a/trunk/drivers/base/power/clock_ops.c b/trunk/drivers/base/power/clock_ops.c index ad367c4139b1..eaa8a854af03 100644 --- a/trunk/drivers/base/power/clock_ops.c +++ b/trunk/drivers/base/power/clock_ops.c @@ -387,7 +387,7 @@ 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_BIND_DRIVER: + case BUS_NOTIFY_ADD_DEVICE: if (clknb->con_ids[0]) { for (con_id = clknb->con_ids; *con_id; con_id++) enable_clock(dev, *con_id); @@ -395,7 +395,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, enable_clock(dev, NULL); } break; - case BUS_NOTIFY_UNBOUND_DRIVER: + case BUS_NOTIFY_DEL_DEVICE: if (clknb->con_ids[0]) { for (con_id = clknb->con_ids; *con_id; con_id++) disable_clock(dev, *con_id); diff --git a/trunk/drivers/base/power/main.c b/trunk/drivers/base/power/main.c index 06f09bf89cb2..aa6320207745 100644 --- a/trunk/drivers/base/power/main.c +++ b/trunk/drivers/base/power/main.c @@ -57,8 +57,7 @@ static int async_error; */ void device_pm_init(struct device *dev) { - dev->power.is_prepared = false; - dev->power.is_suspended = false; + dev->power.in_suspend = false; init_completion(&dev->power.completion); complete_all(&dev->power.completion); dev->power.wakeup = NULL; @@ -92,7 +91,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.is_prepared) + if (dev->parent && dev->parent->power.in_suspend) dev_warn(dev, "parent %s should not be sleeping\n", dev_name(dev->parent)); list_add_tail(&dev->power.entry, &dpm_list); @@ -512,14 +511,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) dpm_wait(dev->parent, async); device_lock(dev); - /* - * 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; + dev->power.in_suspend = false; if (dev->pwr_domain) { pm_dev_dbg(dev, state, "power domain "); @@ -556,9 +548,6 @@ 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); @@ -681,7 +670,7 @@ void dpm_complete(pm_message_t state) struct device *dev = to_device(dpm_prepared_list.prev); get_device(dev); - dev->power.is_prepared = false; + dev->power.in_suspend = false; list_move(&dev->power.entry, &list); mutex_unlock(&dpm_list_mtx); @@ -846,11 +835,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) device_lock(dev); if (async_error) - goto Unlock; + goto End; if (pm_wakeup_pending()) { async_error = -EBUSY; - goto Unlock; + goto End; } if (dev->pwr_domain) { @@ -888,9 +877,6 @@ 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); @@ -1056,7 +1042,7 @@ int dpm_prepare(pm_message_t state) put_device(dev); break; } - dev->power.is_prepared = true; + dev->power.in_suspend = true; if (!list_empty(&dev->power.entry)) list_move_tail(&dev->power.entry, &dpm_prepared_list); put_device(dev); diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index 46767c53917a..135df164a4c1 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -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_get_sync(dev); + pm_runtime_resume(dev); if (drv && drv->pm && drv->pm->prepare) error = drv->pm->prepare(dev); @@ -638,8 +638,6 @@ 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 */ diff --git a/trunk/drivers/tty/serial/mrst_max3110.c b/trunk/drivers/tty/serial/mrst_max3110.c index a764bf99743b..1bd28450ca40 100644 --- a/trunk/drivers/tty/serial/mrst_max3110.c +++ b/trunk/drivers/tty/serial/mrst_max3110.c @@ -421,6 +421,7 @@ 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 { @@ -822,7 +823,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) { - dev_dbg(&spi->dev, "MAX3111 deemed not present (conf reg %04x)", + printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)", res); ret = -ENODEV; goto err_get_page; @@ -837,8 +838,6 @@ 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)) { diff --git a/trunk/drivers/usb/core/driver.c b/trunk/drivers/usb/core/driver.c index aa3cc465a601..e35a17687c05 100644 --- a/trunk/drivers/usb/core/driver.c +++ b/trunk/drivers/usb/core/driver.c @@ -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.is_prepared) { + } else if (!error && !intf->dev.power.in_suspend) { r = usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); if (r < 0) @@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf) } /* Try to rebind the interface */ - if (!intf->dev.power.is_prepared) { + if (!intf->dev.power.in_suspend) { intf->needs_binding = 0; rc = device_attach(&intf->dev); if (rc < 0) @@ -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.is_prepared) { + if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) { usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); intf->needs_altsetting0 = 0; diff --git a/trunk/fs/btrfs/ctree.h b/trunk/fs/btrfs/ctree.h index f30ac05dbda7..300628795fdb 100644 --- a/trunk/fs/btrfs/ctree.h +++ b/trunk/fs/btrfs/ctree.h @@ -19,6 +19,7 @@ #ifndef __BTRFS_CTREE__ #define __BTRFS_CTREE__ +#include #include #include #include diff --git a/trunk/fs/cifs/connect.c b/trunk/fs/cifs/connect.c index 12cf72dd0c42..19fdbda7aa95 100644 --- a/trunk/fs/cifs/connect.c +++ b/trunk/fs/cifs/connect.c @@ -2937,7 +2937,11 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, if (volume_info->nullauth) { cFYI(1, "null user"); - volume_info->username = ""; + volume_info->username = kzalloc(1, GFP_KERNEL); + if (volume_info->username == NULL) { + rc = -ENOMEM; + goto out; + } } else if (volume_info->username) { /* BB fixme parse for domain name here */ cFYI(1, "Username: %s", volume_info->username); diff --git a/trunk/fs/jfs/file.c b/trunk/fs/jfs/file.c index 2f3f531f3606..c5ce6c1d1ff4 100644 --- a/trunk/fs/jfs/file.c +++ b/trunk/fs/jfs/file.c @@ -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) { - 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]); + ji->active_ag = ji->agno; + atomic_inc( + &JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]); } spin_unlock_irq(&ji->ag_lock); } diff --git a/trunk/fs/jfs/jfs_imap.c b/trunk/fs/jfs/jfs_imap.c index b78b2f978f04..ed53a4740168 100644 --- a/trunk/fs/jfs/jfs_imap.c +++ b/trunk/fs/jfs/jfs_imap.c @@ -397,7 +397,7 @@ int diRead(struct inode *ip) release_metapage(mp); /* set the ag for the inode */ - JFS_IP(ip)->agstart = agstart; + JFS_IP(ip)->agno = BLKTOAG(agstart, sbi); JFS_IP(ip)->active_ag = -1; return (rc); @@ -901,7 +901,7 @@ int diFree(struct inode *ip) /* get the allocation group for this ino. */ - agno = BLKTOAG(JFS_IP(ip)->agstart, JFS_SBI(ip->i_sb)); + agno = JFS_IP(ip)->agno; /* Lock the AG specific inode map information */ @@ -1315,11 +1315,12 @@ 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->agstart = le64_to_cpu(iagp->agstart); + jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi); jfs_ip->active_ag = -1; } @@ -1378,7 +1379,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip) */ /* get the ag number of this iag */ - agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb)); + agno = JFS_IP(pip)->agno; if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { /* @@ -2920,9 +2921,10 @@ 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)) diff --git a/trunk/fs/jfs/jfs_incore.h b/trunk/fs/jfs/jfs_incore.h index 584a4a1a6e81..1439f119ec83 100644 --- a/trunk/fs/jfs/jfs_incore.h +++ b/trunk/fs/jfs/jfs_incore.h @@ -50,9 +50,8 @@ 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 pad; + unchar agno; /* ag number */ signed char active_ag; /* ag currently allocating from */ lid_t blid; /* lid of pseudo buffer? */ lid_t atlhead; /* anonymous tlock list head */ diff --git a/trunk/fs/jfs/resize.c b/trunk/fs/jfs/resize.c index 8d0c1c7c0820..8ea5efb5a34e 100644 --- a/trunk/fs/jfs/resize.c +++ b/trunk/fs/jfs/resize.c @@ -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; - s64 old_agsize; + uint old_agsize; int agsizechanged = 0; struct buffer_head *bh, *bh2; diff --git a/trunk/fs/omfs/file.c b/trunk/fs/omfs/file.c index 2c6d95257a4d..d738a7e493dd 100644 --- a/trunk/fs/omfs/file.c +++ b/trunk/fs/omfs/file.c @@ -4,6 +4,7 @@ * Released under GPL v2. */ +#include #include #include #include diff --git a/trunk/include/linux/device.h b/trunk/include/linux/device.h index 553fd37b173b..c66111affca9 100644 --- a/trunk/include/linux/device.h +++ b/trunk/include/linux/device.h @@ -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.is_prepared) + if (!dev->power.in_suspend) dev->power.async_suspend = true; } static inline void device_disable_async_suspend(struct device *dev) { - if (!dev->power.is_prepared) + if (!dev->power.in_suspend) dev->power.async_suspend = false; } diff --git a/trunk/include/linux/pm.h b/trunk/include/linux/pm.h index 411e4f4be52b..3160648ccdda 100644 --- a/trunk/include/linux/pm.h +++ b/trunk/include/linux/pm.h @@ -425,8 +425,7 @@ struct dev_pm_info { pm_message_t power_state; unsigned int can_wakeup:1; unsigned int async_suspend:1; - bool is_prepared:1; /* Owned by the PM core */ - bool is_suspended:1; /* Ditto */ + unsigned int in_suspend:1; /* Owned by the PM core */ spinlock_t lock; #ifdef CONFIG_PM_SLEEP struct list_head entry; diff --git a/trunk/init/calibrate.c b/trunk/init/calibrate.c index aae2f40fea4c..2568d22a304e 100644 --- a/trunk/init/calibrate.c +++ b/trunk/init/calibrate.c @@ -245,32 +245,30 @@ static unsigned long __cpuinit calibrate_delay_converge(void) void __cpuinit calibrate_delay(void) { - unsigned long lpj; static bool printed; if (preset_lpj) { - lpj = preset_lpj; + loops_per_jiffy = preset_lpj; if (!printed) pr_info("Calibrating delay loop (skipped) " "preset value.. "); } else if ((!printed) && lpj_fine) { - lpj = lpj_fine; + loops_per_jiffy = lpj_fine; pr_info("Calibrating delay loop (skipped), " "value calculated using timer frequency.. "); - } else if ((lpj = calibrate_delay_direct()) != 0) { + } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) { if (!printed) pr_info("Calibrating delay using timer " "specific routine.. "); } else { if (!printed) pr_info("Calibrating delay loop... "); - lpj = calibrate_delay_converge(); + loops_per_jiffy = calibrate_delay_converge(); } if (!printed) pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", - lpj/(500000/HZ), - (lpj/(5000/HZ)) % 100, lpj); + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy); - loops_per_jiffy = lpj; printed = true; } diff --git a/trunk/kernel/power/user.c b/trunk/kernel/power/user.c index 42ddbc6f0de6..7d02d33be699 100644 --- a/trunk/kernel/power/user.c +++ b/trunk/kernel/power/user.c @@ -113,10 +113,8 @@ static int snapshot_open(struct inode *inode, struct file *filp) if (error) pm_notifier_call_chain(PM_POST_RESTORE); } - if (error) { - free_basic_memory_bitmaps(); + if (error) atomic_inc(&snapshot_device_available); - } data->frozen = 0; data->ready = 0; data->platform_support = 0; diff --git a/trunk/mm/memory_hotplug.c b/trunk/mm/memory_hotplug.c index c46887b5a11e..02159c755136 100644 --- a/trunk/mm/memory_hotplug.c +++ b/trunk/mm/memory_hotplug.c @@ -498,9 +498,7 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) * The node we allocated has no zone fallback lists. For avoiding * to access not-initialized zonelist, build here. */ - mutex_lock(&zonelists_mutex); build_all_zonelists(NULL); - mutex_unlock(&zonelists_mutex); return pgdat; } @@ -523,7 +521,7 @@ int mem_online_node(int nid) lock_memory_hotplug(); pgdat = hotadd_new_pgdat(nid, 0); - if (!pgdat) { + if (pgdat) { ret = -ENOMEM; goto out; } diff --git a/trunk/security/keys/request_key.c b/trunk/security/keys/request_key.c index 82465328c39b..8e319a416eec 100644 --- a/trunk/security/keys/request_key.c +++ b/trunk/security/keys/request_key.c @@ -469,7 +469,7 @@ static struct key *construct_key_and_link(struct key_type *type, } else if (ret == -EINPROGRESS) { ret = 0; } else { - goto couldnt_alloc_key; + key = ERR_PTR(ret); } key_put(dest_keyring); @@ -479,7 +479,6 @@ static struct key *construct_key_and_link(struct key_type *type, construction_failed: key_negate_and_link(key, key_negative_timeout, NULL, NULL); key_put(key); -couldnt_alloc_key: key_put(dest_keyring); kleave(" = %d", ret); return ERR_PTR(ret);